SLIP corrections

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3376 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo
2011-03-13 15:12:31 +00:00
parent 150b525f34
commit d146196b72
6 changed files with 154 additions and 124 deletions
+95 -91
View File
@@ -52,7 +52,6 @@
#include <fcntl.h>
#include <unistd.h>
#include <wdog.h>
#include <poll.h>
#include <errno.h>
#include <debug.h>
@@ -138,9 +137,10 @@ struct slip_driver_s
{
bool bifup; /* true:ifup false:ifdown */
WDOG_ID txpoll; /* TX poll timer */
int fd; /* File descriptor associated with stream */
FILE *stream; /* The contained serial stream */
pid_t pid; /* Receiver thread ID */
sem_t waitsem; /* Only used at start-up */
uint16_t rxlen; /* The number of bytes in rxbuf */
/* Driver statistics */
@@ -151,6 +151,8 @@ struct slip_driver_s
/* This holds the information visible to uIP/NuttX */
struct uip_driver_s dev; /* Interface understood by uIP */
uint8_t rxbuf[CONFIG_NET_BUFSIZE + 2];
uint8_t txbuf[CONFIG_NET_BUFSIZE + 2];
};
/****************************************************************************
@@ -180,7 +182,6 @@ static int slip_uiptxpoll(struct uip_driver_s *dev);
/* Packet receiver task */
static inline int slip_getc(FAR struct slip_driver_s *priv);
static inline void slip_readpacket(FAR struct slip_driver_s *priv);
static inline void slip_receive(FAR struct slip_driver_s *priv);
static int slip_rxtask(int argc, char *argv[]);
@@ -375,6 +376,7 @@ static int slip_transmit(FAR struct slip_driver_s *priv)
{
slip_write(priv, start, len);
}
fflush(priv->stream);
/* And send the END token */
@@ -448,7 +450,7 @@ static inline int slip_getc(FAR struct slip_driver_s *priv)
}
/****************************************************************************
* Function: slip_readpacket
* Function: slip_receive
*
* Description:
* Read a packet from the serial input
@@ -461,12 +463,11 @@ static inline int slip_getc(FAR struct slip_driver_s *priv)
*
****************************************************************************/
static inline void slip_readpacket(FAR struct slip_driver_s *priv)
static inline void slip_receive(FAR struct slip_driver_s *priv)
{
uint8_t ch;
int nbytes = 0;
/* Copy the data data from the hardware to priv->dev.d_buf until we
/* Copy the data data from the hardware to to the RX buffer until we
* put together a whole packet. Make sure not to copy them into the
* packet if we run out of room.
*/
@@ -474,7 +475,7 @@ static inline void slip_readpacket(FAR struct slip_driver_s *priv)
nvdbg("Receiving packet\n");
for (;;)
{
/* Get the next character in the stream */
/* Get the next character in the stream. */
ch = slip_getc(priv);
@@ -489,16 +490,15 @@ static inline void slip_readpacket(FAR struct slip_driver_s *priv)
case SLIP_END:
nvdbg("END\n");
/* a minor optimization: if there is no data in the packet, ignore
/* A minor optimization: if there is no data in the packet, ignore
* it. This is meant to avoid bothering IP with all the empty
* packets generated by the duplicate END characters which are in
* turn sent to try to detect line noise.
*/
if (nbytes > 0)
if (priv->rxlen > 0)
{
nvdbg("Received packet size %d\n", nbytes);
priv->dev.d_len = nbytes;
nvdbg("Received packet size %d\n", priv->rxlen);
return;
}
break;
@@ -523,8 +523,8 @@ static inline void slip_readpacket(FAR struct slip_driver_s *priv)
nvdbg("ESC-END\n");
ch = SLIP_END;
break;
nvdbg("ESC-ESC\n");
case SLIP_ESC_ESC:
nvdbg("ESC-ESC\n");
ch = SLIP_ESC;
break;
default:
@@ -537,57 +537,15 @@ static inline void slip_readpacket(FAR struct slip_driver_s *priv)
*/
default:
if (nbytes < priv->dev.d_len)
if (priv->rxlen < CONFIG_NET_BUFSIZE+2)
{
priv->dev.d_buf[nbytes++] = ch;
priv->rxbuf[priv->rxlen++] = ch;
}
break;
}
}
}
/****************************************************************************
* Function: slip_receive
*
* Description:
* Accept and handle an incoming packet.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
* Global interrupts are disabled by interrupt handling logic.
*
****************************************************************************/
static inline void slip_receive(FAR struct slip_driver_s *priv)
{
/* Copy the data data from the hardware to priv->dev.d_buf until we put
* together a whole packet.
*/
slip_readpacket(priv);
SLIP_STAT(priv, received);
/* All packets are assumed to be IP packets (we don't have a choice.. there
* is no Ethernet header containing the EtherType)
*/
uip_input(&priv->dev);
/* If the above function invocation resulted in data that should be
* sent out on the network, the field d_len will set to a value > 0.
*/
if (priv->dev.d_len > 0)
{
slip_transmit(priv);
}
}
/****************************************************************************
* Function: slip_rxtask
*
@@ -608,10 +566,8 @@ static inline void slip_receive(FAR struct slip_driver_s *priv)
static int slip_rxtask(int argc, char *argv[])
{
FAR struct slip_driver_s *priv;
struct pollfd fds[1];
unsigned int index = *(argv[1]) - '0';
irqstate_t flags;
int ret;
int ch;
ndbg("index: %d\n", index);
DEBUGASSERT(index < CONFIG_SLIP_NINTERFACES);
@@ -625,27 +581,79 @@ static int slip_rxtask(int argc, char *argv[])
for (;;)
{
/* Set up the poll */
/* Wait for the next character to be available on the input stream. */
memset(fds, 0, sizeof(struct pollfd));
fds[0].fd = priv->fd;
fds[0].events = POLLIN;
fds[0].revents = 0;
ch = slip_getc(priv);
/* Wait for incoming data (with no timeout) */
/* We have something... three interesting cases. First there might
* be a read error. Anything other an EINTR would indicate a serious
* device-related problem or software bug.
*/
ret = poll(fds, 1, -1);
DEBUGASSERT(ret >= 0);
if (ret > 0)
if (ch == EOF)
{
/* Call slip_receive() to handle incoming data. Interrupts must
* be disabled here to keept the POLL watchdoe from firing.
DEBUGASSERT(errno == EINTR);
continue;
}
/* END characters may appear at packet boundaries BEFORE as well as
* after the beginning of the packet. This is normal and expected.
*/
else if (ch == SLIP_END)
{
priv->rxlen = 0;
}
/* Otherwise, we are in danger of being out-of-sync. Apparently the
* leading END character is optional. Let's try to continue.
*/
else
{
priv->rxbuf[0] = (uint8_t)ch;
priv->rxlen = 1;
}
/* Copy the data data from the hardware to priv->rxbuf until we put
* together a whole packet.
*/
slip_receive(priv);
SLIP_STAT(priv, received);
/* All packets are assumed to be IP packets (we don't have a choice..
* there is no Ethernet header containing the EtherType). So pass the
* received packet on for IP processing -- but only if it is big
* enough to hold an IP header.
*/
if (priv->rxlen >= UIP_IPH_LEN)
{
/* Handle the IP input. Interrupts must be disabled here to
* keep the POLL watchdog from firing.
*/
flags = irqsave();
slip_receive(priv);
irqstate_t flags = irqsave();
priv->dev.d_buf = priv->rxbuf;
priv->dev.d_len = priv->rxlen;
uip_input(&priv->dev);
/* If the above function invocation resulted in data that should
* be sent out on the network, the field d_len will set to a
* value > 0. NOTE that we are transmitting using the RX buffer!
*/
if (priv->dev.d_len > 0)
{
slip_transmit(priv);
}
irqrestore(flags);
}
else
{
SLIP_STAT(priv, rxsmallpacket);
}
}
/* We won't get here */
@@ -677,6 +685,7 @@ static void slip_polltimer(int argc, uint32_t arg, ...)
/* If so, update TCP timing states and poll uIP for new XMIT data. */
priv->dev.d_buf = priv->txbuf;
(void)uip_timer(&priv->dev, slip_uiptxpoll, SLIP_POLLHSEC);
/* Setup the watchdog poll timer again */
@@ -791,6 +800,7 @@ static int slip_txavail(struct uip_driver_s *dev)
{
/* Poll uIP for new XMIT data */
priv->dev.d_buf = priv->txbuf;
(void)uip_poll(&priv->dev, slip_uiptxpoll);
}
@@ -881,8 +891,8 @@ static int slip_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac)
int slip_initialize(int intf, const char *devname)
{
struct slip_driver_s *priv;
char buffer[IFNAMSIZ];
pid_t pid;
char buffer[8];
const char *argv[2];
/* Get the interface structure associated with this interface number. */
@@ -903,18 +913,10 @@ int slip_initialize(int intf, const char *devname)
/* Open the device */
priv->fd = open(devname, O_RDWR, 0666);
if (priv->fd < 0)
{
ndbg("ERROR: Failed to open %s: %d\n", devname, errno);
return -errno;
}
priv->stream = fdopen(priv->fd, "rw");
priv->stream = fopen(devname, "rw");
if (priv->stream == NULL)
{
ndbg("ERROR: Failed to fdopen %s: %d\n", devname, errno);
close(priv->fd);
return -errno;
}
@@ -930,16 +932,18 @@ int slip_initialize(int intf, const char *devname)
/* Start the SLIP receiver task */
snprintf(buffer, IFNAMSIZ, "%d", intf);
snprintf(buffer, 8, "%d", intf);
argv[0] = buffer;
argv[1] = NULL;
#ifndef CONFIG_CUSTOM_STACK
pid = task_create("usbhost", CONFIG_SLIP_DEFPRIO, CONFIG_SLIP_STACKSIZE,
(main_t)slip_rxtask, (const char **)buffer);
priv->pid = task_create("usbhost", CONFIG_SLIP_DEFPRIO,
CONFIG_SLIP_STACKSIZE, (main_t)slip_rxtask, argv);
#else
pid = task_create("usbhost", CONFIG_SLIP_DEFPRIO,
(main_t)slip_rxtask, (const char **)buffer);
priv->pid = task_create("usbhost", CONFIG_SLIP_DEFPRIO,
(main_t)slip_rxtask, argv);
#endif
if (pid < 0)
if (priv->pid < 0)
{
ndbg("ERROR: Failed to start receiver task\n");
return -errno;
@@ -956,7 +960,7 @@ int slip_initialize(int intf, const char *devname)
/* Register the device with the OS so that socket IOCTLs can be performed */
#if CONFIG_NSOCKET_DESCRIPTORS > 0
snprintf(buffer, IFNAMSIZ, "slip%d", intf);
snprintf(priv->dev.d_ifname, IFNAMSIZ, "slip%d", intf);
#endif
(void)netdev_register(&priv->dev);
return OK;