static void slip_txtask(int argc, char *argv[]) { FAR struct slip_driver_s *priv; unsigned int index = *(argv[1]) - '0'; uip_lock_t flags; ndbg("index: %d\n", index); DEBUGASSERT(index < CONFIG_SLIP_NINTERFACES); /* Get our private data structure instance and wake up the waiting * initialization logic. */ priv = &g_slip[index]; slip_semgive(priv); /* Loop forever */ for (;;) { /* Wait for the timeout to expire (or until we are signaled by by */ usleep(SLIP_WDDELAY); /* Is the interface up? */ if (priv->bifup) { /* Get exclusive access to uIP (if it it is already being used * slip_rxtask, then we have to wait). */ slip_semtake(priv); /* Poll uIP for new XMIT data. BUG: We really need to calculate * 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 = uip_lock(); priv->dev.d_buf = priv->txbuf; (void)uip_timer(&priv->dev, slip_uiptxpoll, SLIP_POLLHSEC); uip_unlock(flags); slip_semgive(priv); } } }
int slip_initialize(int intf, FAR const char *devname) { FAR struct slip_driver_s *priv; char buffer[8]; FAR char *argv[2]; /* Get the interface structure associated with this interface number. */ DEBUGASSERT(intf < CONFIG_NET_SLIP_NINTERFACES); priv = &g_slip[intf]; /* Initialize the driver structure */ memset(priv, 0, sizeof(struct slip_driver_s)); priv->dev.d_ifup = slip_ifup; /* I/F up (new IP address) callback */ priv->dev.d_ifdown = slip_ifdown; /* I/F down callback */ priv->dev.d_txavail = slip_txavail; /* New TX data callback */ #ifdef CONFIG_NET_IGMP priv->dev.d_addmac = slip_addmac; /* Add multicast MAC address */ priv->dev.d_rmmac = slip_rmmac; /* Remove multicast MAC address */ #endif priv->dev.d_private = priv; /* Used to recover private state from dev */ /* Open the device */ priv->fd = open(devname, O_RDWR, 0666); if (priv->fd < 0) { nerr("ERROR: Failed to open %s: %d\n", devname, errno); return -errno; } /* Initialize the wait semaphore */ sem_init(&priv->waitsem, 0, 0); /* Put the interface in the down state. This usually amounts to resetting * the device and/or calling slip_ifdown(). */ slip_ifdown(&priv->dev); /* Start the SLIP receiver task */ snprintf(buffer, 8, "%d", intf); argv[0] = buffer; argv[1] = NULL; priv->rxpid = task_create("rxslip", CONFIG_NET_SLIP_DEFPRIO, CONFIG_NET_SLIP_STACKSIZE, (main_t)slip_rxtask, (FAR char * const *)argv); if (priv->rxpid < 0) { nerr("ERROR: Failed to start receiver task\n"); return -errno; } /* Wait and make sure that the receive task is started. */ slip_semtake(priv); /* Start the SLIP transmitter task */ priv->txpid = task_create("txslip", CONFIG_NET_SLIP_DEFPRIO, CONFIG_NET_SLIP_STACKSIZE, (main_t)slip_txtask, (FAR char * const *)argv); if (priv->txpid < 0) { nerr("ERROR: Failed to start receiver task\n"); return -errno; } /* Wait and make sure that the transmit task is started. */ slip_semtake(priv); /* Bump the semaphore count so that it can now be used as a mutex */ slip_semgive(priv); /* Register the device with the OS so that socket IOCTLs can be performed */ (void)netdev_register(&priv->dev, NET_LL_SLIP); /* When the RX and TX tasks were created, the TTY file descriptor was * dup'ed for each task. This task no longer needs the file descriptor * and we can safely close it. */ close(priv->fd); return OK; }
static int slip_rxtask(int argc, FAR char *argv[]) { FAR struct slip_driver_s *priv; unsigned int index = *(argv[1]) - '0'; net_lock_t flags; int ch; nerr("index: %d\n", index); DEBUGASSERT(index < CONFIG_NET_SLIP_NINTERFACES); /* Get our private data structure instance and wake up the waiting * initialization logic. */ priv = &g_slip[index]; slip_semgive(priv); /* Loop forever */ for (; ; ) { /* Wait for the next character to be available on the input stream. */ ninfo("Waiting...\n"); ch = slip_getc(priv); /* Ignore any input that we receive before the interface is up. */ if (!priv->bifup) { continue; } /* We have something... * * END characters may appear at packet boundaries BEFORE as well as * after the beginning of the packet. This is normal and expected. */ 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); NETDEV_RXPACKETS(&priv->dev); /* 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 >= IPv4_HDRLEN) { NETDEV_RXIPV4(&priv->dev); /* Handle the IP input. Get exclusive access to the network. */ slip_semtake(priv); priv->dev.d_buf = priv->rxbuf; priv->dev.d_len = priv->rxlen; flags = net_lock(); ipv4_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); kill(priv->txpid, SIGALRM); } net_unlock(flags); slip_semgive(priv); } else { NETDEV_RXERRORS(&priv->dev); } } /* We won't get here */ return OK; }
static void slip_txtask(int argc, FAR char *argv[]) { FAR struct slip_driver_s *priv; unsigned int index = *(argv[1]) - '0'; net_lock_t flags; systime_t msec_start; systime_t msec_now; unsigned int hsec; nerr("index: %d\n", index); DEBUGASSERT(index < CONFIG_NET_SLIP_NINTERFACES); /* Get our private data structure instance and wake up the waiting * initialization logic. */ priv = &g_slip[index]; slip_semgive(priv); /* Loop forever */ msec_start = clock_systimer() * MSEC_PER_TICK; for (; ; ) { /* Wait for the timeout to expire (or until we are signaled by by */ slip_semtake(priv); if (!priv->txnodelay) { slip_semgive(priv); usleep(SLIP_WDDELAY); } else { priv->txnodelay = false; slip_semgive(priv); } /* Is the interface up? */ if (priv->bifup) { /* Get exclusive access to the network (if it it is already being used * slip_rxtask, then we have to wait). */ slip_semtake(priv); /* Poll the networking layer for new XMIT data. */ flags = net_lock(); priv->dev.d_buf = priv->txbuf; /* Has a half second elapsed since the last timer poll? */ msec_now = clock_systimer() * MSEC_PER_TICK; hsec = (unsigned int)(msec_now - msec_start) / (MSEC_PER_SEC / 2); if (hsec) { /* Yes, perform the timer poll */ (void)devif_timer(&priv->dev, slip_txpoll); msec_start += hsec * (MSEC_PER_SEC / 2); } else { /* No, perform the normal TX poll */ (void)devif_poll(&priv->dev, slip_txpoll); } net_unlock(flags); slip_semgive(priv); } } }