Exemplo n.º 1
0
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);
        }
    }
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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);
        }
    }
}