mirror of
https://github.com/apache/nuttx.git
synced 2026-05-30 21:36:28 +08:00
Networking: SLIP interface improvements. From Macs N.
This commit is contained in:
+87
-52
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* drivers/net/slip.c
|
* drivers/net/slip.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2011-2012, 2015 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Reference: RFC 1055
|
* Reference: RFC 1055
|
||||||
@@ -56,6 +56,7 @@
|
|||||||
|
|
||||||
#include <nuttx/irq.h>
|
#include <nuttx/irq.h>
|
||||||
#include <nuttx/net/net.h>
|
#include <nuttx/net/net.h>
|
||||||
|
#include <nuttx/clock.h>
|
||||||
#include <nuttx/net/netdev.h>
|
#include <nuttx/net/netdev.h>
|
||||||
#include <nuttx/net/ip.h>
|
#include <nuttx/net/ip.h>
|
||||||
#include <nuttx/net/slip.h>
|
#include <nuttx/net/slip.h>
|
||||||
@@ -158,11 +159,12 @@ struct slip_statistics_s
|
|||||||
struct slip_driver_s
|
struct slip_driver_s
|
||||||
{
|
{
|
||||||
volatile bool bifup; /* true:ifup false:ifdown */
|
volatile bool bifup; /* true:ifup false:ifdown */
|
||||||
int fd; /* TTY file descriptor */
|
bool txnodelay; /* True: usleep() not needed */
|
||||||
|
int16_t fd; /* TTY file descriptor */
|
||||||
|
uint16_t rxlen; /* The number of bytes in rxbuf */
|
||||||
pid_t rxpid; /* Receiver thread ID */
|
pid_t rxpid; /* Receiver thread ID */
|
||||||
pid_t txpid; /* Transmitter thread ID */
|
pid_t txpid; /* Transmitter thread ID */
|
||||||
sem_t waitsem; /* Mutually exclusive access to uIP */
|
sem_t waitsem; /* Mutually exclusive access to uIP */
|
||||||
uint16_t rxlen; /* The number of bytes in rxbuf */
|
|
||||||
|
|
||||||
/* Driver statistics */
|
/* Driver statistics */
|
||||||
|
|
||||||
@@ -195,7 +197,8 @@ static void slip_semtake(FAR struct slip_driver_s *priv);
|
|||||||
|
|
||||||
/* Common TX logic */
|
/* Common TX logic */
|
||||||
|
|
||||||
static void slip_write(FAR struct slip_driver_s *priv, const uint8_t *buffer, int len);
|
static void slip_write(FAR struct slip_driver_s *priv,
|
||||||
|
FAR const uint8_t *buffer, int len);
|
||||||
static void slip_putc(FAR struct slip_driver_s *priv, int ch);
|
static void slip_putc(FAR struct slip_driver_s *priv, int ch);
|
||||||
static int slip_transmit(FAR struct slip_driver_s *priv);
|
static int slip_transmit(FAR struct slip_driver_s *priv);
|
||||||
static int slip_txpoll(FAR struct net_driver_s *dev);
|
static int slip_txpoll(FAR struct net_driver_s *dev);
|
||||||
@@ -255,7 +258,7 @@ static void slip_semtake(FAR struct slip_driver_s *priv)
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void slip_write(FAR struct slip_driver_s *priv,
|
static inline void slip_write(FAR struct slip_driver_s *priv,
|
||||||
const uint8_t *buffer, int len)
|
FAR const uint8_t *buffer, int len)
|
||||||
{
|
{
|
||||||
/* Handle the case where the write is awakened by a signal */
|
/* Handle the case where the write is awakened by a signal */
|
||||||
|
|
||||||
@@ -390,6 +393,7 @@ static int slip_transmit(FAR struct slip_driver_s *priv)
|
|||||||
/* And send the END token */
|
/* And send the END token */
|
||||||
|
|
||||||
slip_putc(priv, SLIP_END);
|
slip_putc(priv, SLIP_END);
|
||||||
|
priv->txnodelay = true;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -454,6 +458,9 @@ static void slip_txtask(int argc, FAR char *argv[])
|
|||||||
FAR struct slip_driver_s *priv;
|
FAR struct slip_driver_s *priv;
|
||||||
unsigned int index = *(argv[1]) - '0';
|
unsigned int index = *(argv[1]) - '0';
|
||||||
net_lock_t flags;
|
net_lock_t flags;
|
||||||
|
unsigned int msec_start;
|
||||||
|
unsigned int msec_now;
|
||||||
|
unsigned int hsec;
|
||||||
|
|
||||||
ndbg("index: %d\n", index);
|
ndbg("index: %d\n", index);
|
||||||
DEBUGASSERT(index < CONFIG_SLIP_NINTERFACES);
|
DEBUGASSERT(index < CONFIG_SLIP_NINTERFACES);
|
||||||
@@ -467,11 +474,22 @@ static void slip_txtask(int argc, FAR char *argv[])
|
|||||||
|
|
||||||
/* Loop forever */
|
/* Loop forever */
|
||||||
|
|
||||||
|
msec_start = clock_systimer() * MSEC_PER_TICK;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
/* Wait for the timeout to expire (or until we are signaled by by */
|
/* Wait for the timeout to expire (or until we are signaled by by */
|
||||||
|
|
||||||
usleep(SLIP_WDDELAY);
|
slip_semtake(priv);
|
||||||
|
if (!priv->txnodelay)
|
||||||
|
{
|
||||||
|
slip_semgive(priv);
|
||||||
|
usleep(SLIP_WDDELAY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
priv->txnodelay = false;
|
||||||
|
slip_semgive(priv);
|
||||||
|
}
|
||||||
|
|
||||||
/* Is the interface up? */
|
/* Is the interface up? */
|
||||||
|
|
||||||
@@ -483,15 +501,23 @@ static void slip_txtask(int argc, FAR char *argv[])
|
|||||||
|
|
||||||
slip_semtake(priv);
|
slip_semtake(priv);
|
||||||
|
|
||||||
/* Poll uIP for new XMIT data. BUG: We really need to calculate
|
/* Poll the networking layer for new XMIT data. */
|
||||||
* the number of hsecs! When we are awakened by slip_txavail, the
|
|
||||||
* number will be smaller; when we have to wait for the semaphore
|
|
||||||
* (above), it may be larger.
|
|
||||||
*/
|
|
||||||
|
|
||||||
flags = net_lock();
|
flags = net_lock();
|
||||||
priv->dev.d_buf = priv->txbuf;
|
priv->dev.d_buf = priv->txbuf;
|
||||||
(void)devif_timer(&priv->dev, slip_txpoll, SLIP_POLLHSEC);
|
|
||||||
|
msec_now = clock_systimer() * MSEC_PER_TICK;
|
||||||
|
hsec = (unsigned int)(msec_now - msec_start) / (MSEC_PER_SEC / 2);
|
||||||
|
if (hsec)
|
||||||
|
{
|
||||||
|
(void)devif_timer(&priv->dev, slip_txpoll, hsec);
|
||||||
|
msec_start += hsec * (MSEC_PER_SEC / 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(void)uip_poll(&priv->dev, slip_uiptxpoll);
|
||||||
|
}
|
||||||
|
|
||||||
net_unlock(flags);
|
net_unlock(flags);
|
||||||
slip_semgive(priv);
|
slip_semgive(priv);
|
||||||
}
|
}
|
||||||
@@ -563,19 +589,21 @@ static inline void slip_receive(FAR struct slip_driver_s *priv)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
case SLIP_END:
|
case SLIP_END:
|
||||||
nvdbg("END\n");
|
{
|
||||||
|
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,
|
||||||
* it. This is meant to avoid bothering IP with all the empty
|
* ignore it. This is meant to avoid bothering IP with all the
|
||||||
* packets generated by the duplicate END characters which are in
|
* empty packets generated by the duplicate END characters which
|
||||||
* turn sent to try to detect line noise.
|
* are in turn sent to try to detect line noise.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (priv->rxlen > 0)
|
if (priv->rxlen > 0)
|
||||||
{
|
{
|
||||||
nvdbg("Received packet size %d\n", priv->rxlen);
|
nvdbg("Received packet size %d\n", priv->rxlen);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* if it's the same code as an ESC character, wait and get another
|
/* if it's the same code as an ESC character, wait and get another
|
||||||
@@ -584,38 +612,44 @@ static inline void slip_receive(FAR struct slip_driver_s *priv)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
case SLIP_ESC:
|
case SLIP_ESC:
|
||||||
nvdbg("ESC\n");
|
{
|
||||||
ch = slip_getc(priv);
|
nvdbg("ESC\n");
|
||||||
|
ch = slip_getc(priv);
|
||||||
|
|
||||||
/* if "ch" is not one of these two, then we have a protocol
|
/* if "ch" is not one of these two, then we have a protocol
|
||||||
* violation. The best bet seems to be to leave the byte alone
|
* violation. The best bet seems to be to leave the byte alone
|
||||||
* and just stuff it into the packet
|
* and just stuff it into the packet
|
||||||
*/
|
*/
|
||||||
|
|
||||||
switch (ch)
|
switch (ch)
|
||||||
{
|
{
|
||||||
case SLIP_ESC_END:
|
case SLIP_ESC_END:
|
||||||
nvdbg("ESC-END\n");
|
nvdbg("ESC-END\n");
|
||||||
ch = SLIP_END;
|
ch = SLIP_END;
|
||||||
break;
|
break;
|
||||||
case SLIP_ESC_ESC:
|
|
||||||
nvdbg("ESC-ESC\n");
|
|
||||||
ch = SLIP_ESC;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ndbg("ERROR: Protocol violation: %02x\n", ch);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Here we fall into the default handler and let it store the
|
case SLIP_ESC_ESC:
|
||||||
* character for us
|
nvdbg("ESC-ESC\n");
|
||||||
*/
|
ch = SLIP_ESC;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ndbg("ERROR: Protocol violation: %02x\n", ch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Here we fall into the default handler and let it store the
|
||||||
|
* character for us
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (priv->rxlen < CONFIG_NET_SLIP_MTU+2)
|
{
|
||||||
{
|
if (priv->rxlen < CONFIG_NET_SLIP_MTU+2)
|
||||||
priv->rxbuf[priv->rxlen++] = ch;
|
{
|
||||||
}
|
priv->rxbuf[priv->rxlen++] = ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -724,6 +758,7 @@ static int slip_rxtask(int argc, FAR char *argv[])
|
|||||||
if (priv->dev.d_len > 0)
|
if (priv->dev.d_len > 0)
|
||||||
{
|
{
|
||||||
slip_transmit(priv);
|
slip_transmit(priv);
|
||||||
|
kill(priv->txpid, SIGALRM);
|
||||||
}
|
}
|
||||||
net_unlock(flags);
|
net_unlock(flags);
|
||||||
slip_semgive(priv);
|
slip_semgive(priv);
|
||||||
@@ -822,6 +857,7 @@ static int slip_txavail(FAR struct net_driver_s *dev)
|
|||||||
{
|
{
|
||||||
/* Wake up the TX polling thread */
|
/* Wake up the TX polling thread */
|
||||||
|
|
||||||
|
priv->txnodelay = true;
|
||||||
kill(priv->txpid, SIGALRM);
|
kill(priv->txpid, SIGALRM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -912,7 +948,7 @@ int slip_initialize(int intf, FAR const char *devname)
|
|||||||
{
|
{
|
||||||
FAR struct slip_driver_s *priv;
|
FAR struct slip_driver_s *priv;
|
||||||
char buffer[8];
|
char buffer[8];
|
||||||
FAR const char *argv[2];
|
FAR char *argv[2];
|
||||||
|
|
||||||
/* Get the interface structure associated with this interface number. */
|
/* Get the interface structure associated with this interface number. */
|
||||||
|
|
||||||
@@ -1002,4 +1038,3 @@ int slip_initialize(int intf, FAR const char *devname)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_NET && CONFIG_NET_SLIP */
|
#endif /* CONFIG_NET && CONFIG_NET_SLIP */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user