Example #1
0
File: pwm.c Project: dagar/NuttX
int pwm_register(FAR const char *path, FAR struct pwm_lowerhalf_s *dev)
{
  FAR struct pwm_upperhalf_s *upper;

  /* Allocate the upper-half data structure */

  upper = (FAR struct pwm_upperhalf_s *)kmm_zalloc(sizeof(struct pwm_upperhalf_s));
  if (!upper)
    {
      pwmerr("Allocation failed\n");
      return -ENOMEM;
    }

  /* Initialize the PWM device structure (it was already zeroed by kmm_zalloc()) */

  nxsem_init(&upper->exclsem, 0, 1);
#ifdef CONFIG_PWM_PULSECOUNT
  nxsem_init(&upper->waitsem, 0, 0);

  /* The wait semaphore is used for signaling and, hence, should not have priority
   * inheritance enabled.
   */

  nxsem_setprotocol(&upper->waitsem, SEM_PRIO_NONE);
#endif

  upper->dev = dev;

  /* Register the PWM device */

  pwminfo("Registering %s\n", path);
  return register_driver(path, &g_pwmops, 0666, upper);
}
Example #2
0
void up_dmainitialize(void)
{
  int i;

  for (i = 0; i < DMA_CHANNEL_NUM; i++)
    {
      g_dma.phydmach[i].inprogress = 0;
      sq_init(&g_dma.phydmach[i].req_q);
    }

  nxsem_init(&g_dma.exclsem, 0, 1);

  if (irq_attach(LC823450_IRQ_DMAC, dma_interrupt, NULL) != 0)
    {
      return;
    }
  up_enable_irq(LC823450_IRQ_DMAC);

  /* Clock & Reset */

  modifyreg32(MCLKCNTBASIC, 0, MCLKCNTBASIC_DMAC_CLKEN);
  modifyreg32(MRSTCNTBASIC, 0, MRSTCNTBASIC_DMAC_RSTB);

  /* DMAC enable */

  modifyreg32(DMACCONFIG, 0, DMACCONFIG_EN);

#ifdef DMA_TEST
  lc823450_dma_test();
#endif

  /* clock disable */

  modifyreg32(MCLKCNTBASIC, MCLKCNTBASIC_DMAC_CLKEN, 0);
}
Example #3
0
File: mm_sem.c Project: dagar/NuttX
void mm_seminitialize(FAR struct mm_heap_s *heap)
{
  /* Initialize the MM semaphore to one (to support one-at-a-time access to
   * private data sets).
   */

  (void)nxsem_init(&heap->mm_semaphore, 0, 1);

  heap->mm_holder      = -1;
  heap->mm_counts_held = 0;
}
Example #4
0
int up_hrttimer_usleep(unsigned int usec)
{
  struct hrt_s hrt;

  nxsem_init(&hrt.sem, 0, 0);
  hrt.usec = usec;

  hrt_usleep_add(&hrt);
  nxsem_wait(&hrt.sem);

  return 0;
}
Example #5
0
GRAN_HANDLE gran_initialize(FAR void *heapstart, size_t heapsize,
                            uint8_t log2gran, uint8_t log2align)
{
  FAR struct gran_s *priv;
  uintptr_t          heapend;
  uintptr_t          alignedstart;
  unsigned int       mask;
  unsigned int       alignedsize;
  unsigned int       ngranules;

  /* Check parameters if debug is on.  Note the size of a granule is
   * limited to 2**31 bytes and that the size of the granule must be greater
   * than or equal to the alignment size.
   */

  DEBUGASSERT(heapstart && heapsize > 0 &&
              log2gran > 0 && log2gran < 32 &&
              log2gran >= log2align);

  /* Get the aligned start of the heap */

  mask         = (1 << log2align) - 1;
  alignedstart = ((uintptr_t)heapstart + mask) & ~mask;

  /* Determine the number of granules */

  mask         = (1 << log2gran) - 1;
  heapend      = (uintptr_t)heapstart + heapsize;
  alignedsize  = (heapend - alignedstart) & ~mask;
  ngranules    = alignedsize >> log2gran;

  /* Allocate the information structure with a granule table of the
   * correct size.
   */

  priv = (FAR struct gran_s *)kmm_zalloc(SIZEOF_GRAN_S(ngranules));
  if (priv)
    {
      /* Initialize non-zero elements of the granules heap info structure */

      priv->log2gran  = log2gran;
      priv->ngranules = ngranules;
      priv->heapstart = alignedstart;

      /* Initialize mutual exclusion support */

#ifndef CONFIG_GRAN_INTR
      nxsem_init(&priv->exclsem, 0, 1);
#endif
    }

  return (GRAN_HANDLE)priv;
}
Example #6
0
int sem_init(FAR sem_t *sem, int pshared, unsigned int value)
{
  int ret;

  ret = nxsem_init(sem, pshared, value);
  if (ret < 0)
    {
      set_errno(-ret);
      ret = ERROR;
    }

  return ret;
}
Example #7
0
int btn_register(FAR const char *devname,
                 FAR const struct btn_lowerhalf_s *lower)

{
  FAR struct btn_upperhalf_s *priv;
  int ret;

  DEBUGASSERT(devname && lower);

  /* Allocate a new button driver instance */

  priv = (FAR struct btn_upperhalf_s *)
    kmm_zalloc(sizeof(struct btn_upperhalf_s));

  if (!priv)
    {
      ierr("ERROR: Failed to allocate device structure\n");
      return -ENOMEM;
    }

  /* Make sure that all button interrupts are disabled */

  DEBUGASSERT(lower->bl_enable);
  lower->bl_enable(lower, 0, 0, NULL, NULL);

  /* Initialize the new button driver instance */

  priv->bu_lower = lower;
  nxsem_init(&priv->bu_exclsem, 0, 1);

  DEBUGASSERT(lower->bl_buttons);
  priv->bu_sample = lower->bl_buttons(lower);

  /* And register the button driver */

  ret = register_driver(devname, &btn_fops, 0666, priv);
  if (ret < 0)
    {
      ierr("ERROR: register_driver failed: %d\n", ret);
      goto errout_with_priv;
    }

  return OK;

errout_with_priv:
  nxsem_destroy(&priv->bu_exclsem);
  kmm_free(priv);
  return ret;
}
Example #8
0
int smps_register(FAR const char *path, FAR struct smps_dev_s *dev, FAR void *lower)
{
  int ret;

  DEBUGASSERT(path != NULL && dev != NULL && lower != NULL);
  DEBUGASSERT(dev->ops != NULL);

  /* For safety reason, when some necessary low-level logic is not provided,
   * system should fail before low-level hardware initialization, so:
   *   - all ops are checked here, before character driver registration
   *   - all ops must be provided, even if not used
   */

  DEBUGASSERT(dev->ops->setup != NULL);
  DEBUGASSERT(dev->ops->shutdown != NULL);
  DEBUGASSERT(dev->ops->stop != NULL);
  DEBUGASSERT(dev->ops->start != NULL);
  DEBUGASSERT(dev->ops->params_set != NULL);
  DEBUGASSERT(dev->ops->mode_set != NULL);
  DEBUGASSERT(dev->ops->limits_set != NULL);
  DEBUGASSERT(dev->ops->fault_set != NULL);
  DEBUGASSERT(dev->ops->state_get != NULL);
  DEBUGASSERT(dev->ops->fault_get != NULL);
  DEBUGASSERT(dev->ops->fault_clean != NULL);
  DEBUGASSERT(dev->ops->ioctl != NULL);

  /* Initialize the SMPS device structure */

  dev->ocount = 0;

  /* Initialize semaphores */

  nxsem_init(&dev->closesem, 0, 1);

  /* Connect SMPS driver with lower level interface */

  dev->lower = lower;

  /* Register the SMPS character driver */

  ret = register_driver(path, &smps_fops, 0444, dev);
  if (ret < 0)
    {
      nxsem_destroy(&dev->closesem);
    }

  return ret;
}
Example #9
0
void netlink_initialize(void)
{
  int i;

  /* Initialize the queues */

  dq_init(&g_free_netlink_connections);
  dq_init(&g_active_netlink_connections);
  nxsem_init(&g_free_sem, 0, 1);

  for (i = 0; i < CONFIG_NET_NETLINK_CONNS; i++)
    {
      FAR struct netlink_conn_s *conn = &g_netlink_connections[i];

      /* Mark the connection closed and move it to the free list */

      memset(conn, 0, sizeof(*conn));
      dq_addlast(&conn->node, &g_free_netlink_connections);
    }
}
Example #10
0
int apb_alloc(FAR struct audio_buf_desc_s *bufdesc)
{
  uint32_t            bufsize;
  int                 ret;
  struct ap_buffer_s  *apb;

  DEBUGASSERT(bufdesc->u.ppBuffer != NULL);

  /* Perform a user mode allocation */

  bufsize = sizeof(struct ap_buffer_s) + bufdesc->numbytes;
  apb = lib_umalloc(bufsize);
  *bufdesc->u.ppBuffer = apb;

  /* Test if the allocation was successful or not */

  if (*bufdesc->u.ppBuffer == NULL)
    {
      ret = -ENOMEM;
    }
  else
    {
      /* Populate the buffer contents */

      memset(apb, 0, bufsize);
      apb->i.channels = 1;
      apb->crefs      = 1;
      apb->nmaxbytes  = bufdesc->numbytes;
      apb->nbytes     = 0;
      apb->flags      = 0;
      apb->samp       = (FAR uint8_t *)(apb + 1);
#ifdef CONFIG_AUDIO_MULTI_SESSION
      apb->session    = bufdesc->session;
#endif

      nxsem_init(&apb->sem, 0, 1);
      ret = sizeof(struct audio_buf_desc_s);
    }

  return ret;
}
Example #11
0
int i2schar_register(FAR struct i2s_dev_s *i2s, int minor)
{
  FAR struct i2schar_dev_s *priv;
  char devname[DEVNAME_FMTLEN];
  int ret;

  /* Sanity check */

  DEBUGASSERT(i2s != NULL && (unsigned)minor < 1000);

  /* Allocate a I2S character device structure */

  priv = (FAR struct i2schar_dev_s *)kmm_zalloc(sizeof(struct i2schar_dev_s));
  if (priv)
    {
      /* Initialize the I2S character device structure */

      priv->i2s = i2s;
      nxsem_init(&priv->exclsem, 0, 1);

      /* Create the character device name */

      snprintf(devname, DEVNAME_FMTLEN, DEVNAME_FMT, minor);
      ret = register_driver(devname, &i2schar_fops, 0666, priv);
      if (ret < 0)
        {
          /* Free the device structure if we failed to create the character
           * device.
           */

          kmm_free(priv);
        }

      /* Return the result of the registration */

      return OK;
    }


  return -ENOMEM;
}
Example #12
0
int mtdconfig_register(FAR struct mtd_dev_s *mtd)
{
  int ret = OK;
  struct mtdconfig_struct_s *dev;
  struct mtd_geometry_s geo;      /* Device geometry */

  dev = (struct mtdconfig_struct_s *)kmm_malloc(sizeof(struct mtdconfig_struct_s));
  if (dev)
    {
      /* Initialize the mtdconfig device structure */

      dev->mtd = mtd;
      nxsem_init(&dev->exclsem, 0, 1);

      /* Get the device geometry. (casting to uintptr_t first eliminates
       * complaints on some architectures where the sizeof long is different
       * from the size of a pointer).
       */

      ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&geo));
      if (ret < 0)
        {
          ferr("ERROR: MTD ioctl(MTDIOC_GEOMETRY) failed: %d\n", ret);
          kmm_free(dev);
          goto errout;
        }

      dev->blocksize = geo.blocksize;
      dev->neraseblocks = geo.neraseblocks;
      dev->erasesize = geo.erasesize;
      dev->nblocks = geo.neraseblocks * geo.erasesize / geo.blocksize;

      (void)register_driver("/dev/config", &mtdconfig_fops, 0666, dev);
    }

errout:
  return ret;
}
Example #13
0
int oneshot_register(FAR const char *devname,
                     FAR struct oneshot_lowerhalf_s *lower)
{
  FAR struct oneshot_dev_s *priv;
  int ret;

  sninfo("devname=%s lower=%p\n", devname, lower);
  DEBUGASSERT(devname != NULL && lower != NULL);

  /* Allocate a new oneshot timer driver instance */

  priv = (FAR struct oneshot_dev_s *)
    kmm_zalloc(sizeof(struct oneshot_dev_s));

  if (!priv)
    {
      snerr("ERROR: Failed to allocate device structure\n");
      return -ENOMEM;
    }

  /* Initialize the new oneshot timer driver instance */

  priv->od_lower = lower;
  nxsem_init(&priv->od_exclsem, 0, 1);

  /* And register the oneshot timer driver */

  ret = register_driver(devname, &g_oneshot_ops, 0666, priv);
  if (ret < 0)
    {
      snerr("ERROR: register_driver failed: %d\n", ret);
      nxsem_destroy(&priv->od_exclsem);
      kmm_free(priv);
    }

  return ret;
}
Example #14
0
void icmpv6_rwait_setup(FAR struct net_driver_s *dev,
                        FAR struct icmpv6_rnotify_s *notify)
{
  irqstate_t flags;

  /* Initialize the wait structure */

  memcpy(notify->rn_ifname, dev->d_ifname, IFNAMSIZ);
  notify->rn_result = -ETIMEDOUT;

  /* This semaphore is used for signaling and, hence, should not have
   * priority inheritance enabled.
   */

  (void)nxsem_init(&notify->rn_sem, 0, 0);
  nxsem_setprotocol(&notify->rn_sem, SEM_PRIO_NONE);

  /* Add the wait structure to the list with interrupts disabled */

  flags             = enter_critical_section();
  notify->rn_flink  = g_icmpv6_rwaiters;
  g_icmpv6_rwaiters  = notify;
  leave_critical_section(flags);
}
Example #15
0
void icmpv6_wait_setup(const net_ipv6addr_t ipaddr,
                       FAR struct icmpv6_notify_s *notify)
{
  irqstate_t flags;

  /* Initialize the wait structure */

  net_ipv6addr_copy(notify->nt_ipaddr, ipaddr);
  notify->nt_result = -ETIMEDOUT;

  /* This semaphore is used for signaling and, hence, should not have
   * priority inheritance enabled.
   */

  (void)nxsem_init(&notify->nt_sem, 0, 0);
  nxsem_setprotocol(&notify->nt_sem, SEM_PRIO_NONE);

  /* Add the wait structure to the list with interrupts disabled */

  flags             = enter_critical_section();
  notify->nt_flink  = g_icmpv6_waiters;
  g_icmpv6_waiters  = notify;
  leave_critical_section(flags);
}
Example #16
0
FAR struct file_struct *fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb)
{
  FAR struct streamlist *slist;
  FAR FILE              *stream;
  int                    errcode = OK;
  int                    ret;
  int                    i;

  /* Check input parameters */

  if (fd < 0)
    {
      errcode = EBADF;
      goto errout;
    }

  /* A NULL TCB pointer means to use this threads TCB.  This is a little
   * hack the let's this function be called from user-space (via a syscall)
   * without having access to the TCB.
   */

  if (!tcb)
    {
      tcb = sched_self();
    }

  DEBUGASSERT(tcb && tcb->group);

  /* Verify that this is a valid file/socket descriptor and that the
   * requested access can be support.
   *
   * Is this fd in the range of valid file descriptors?  Socket descriptors
   * lie in a different range.
   */

#if CONFIG_NFILE_DESCRIPTORS > 0
  if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
#endif
    {
      /* No.. If networking is enabled then this might be a socket
       * descriptor.
       */

#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
      ret = net_checksd(fd, oflags);
#else
      /* No networking... it is just a bad descriptor */

      errcode = EBADF;
      goto errout;
#endif
    }

  /* The descriptor is in a valid range to file descriptor... perform some more checks */

#if CONFIG_NFILE_DESCRIPTORS > 0
  else
    {
      ret = fs_checkfd(tcb, fd, oflags);
    }
#endif

  /* Do we have a good descriptor of some sort? */

  if (ret < 0)
    {
      /* No... return the reported error */

      errcode = -ret;
      goto errout;
    }

  /* Get the stream list from the TCB */

#if (defined(CONFIG_BUILD_PROTECTED) || defined(CONFIG_BUILD_KERNEL)) && \
     defined(CONFIG_MM_KERNEL_HEAP)
  slist = tcb->group->tg_streamlist;
#else
  slist = &tcb->group->tg_streamlist;
#endif

  /* Find an unallocated FILE structure in the stream list */

  ret = nxsem_wait(&slist->sl_sem);
  if (ret < 0)
    {
      errcode = -ret;
      goto errout;
    }

  for (i = 0 ; i < CONFIG_NFILE_STREAMS; i++)
    {
      stream = &slist->sl_streams[i];
      if (stream->fs_fd < 0)
        {
          /* Zero the structure */

          memset(stream, 0, sizeof(FILE));

#ifndef CONFIG_STDIO_DISABLE_BUFFERING
          /* Initialize the semaphore the manages access to the buffer */

          (void)nxsem_init(&stream->fs_sem, 0, 1);

#if CONFIG_STDIO_BUFFER_SIZE > 0
          /* Allocate the IO buffer at the appropriate privilege level for
           * the group.
           */

          stream->fs_bufstart =
            group_malloc(tcb->group, CONFIG_STDIO_BUFFER_SIZE);

          if (!stream->fs_bufstart)
            {
              errcode = ENOMEM;
              goto errout_with_sem;
            }

          /* Set up pointers */

          stream->fs_bufend  = &stream->fs_bufstart[CONFIG_STDIO_BUFFER_SIZE];
          stream->fs_bufpos  = stream->fs_bufstart;
          stream->fs_bufread = stream->fs_bufstart;

#ifdef CONFIG_STDIO_LINEBUFFER
          /* Setup buffer flags */

          stream->fs_flags  |= __FS_FLAG_LBF; /* Line buffering */

#endif /* CONFIG_STDIO_LINEBUFFER */
#endif /* CONFIG_STDIO_BUFFER_SIZE > 0 */
#endif /* !CONFIG_STDIO_DISABLE_BUFFERING */

          /* Save the file description and open flags.  Setting the
           * file descriptor locks this stream.
           */

          stream->fs_fd      = fd;
          stream->fs_oflags  = (uint16_t)oflags;

          nxsem_post(&slist->sl_sem);
          return stream;
        }
    }

  /* No free stream available.. report ENFILE */

  errcode = ENFILE;

#if !defined(CONFIG_STDIO_DISABLE_BUFFERING) && CONFIG_STDIO_BUFFER_SIZE > 0
errout_with_sem:
#endif
  nxsem_post(&slist->sl_sem);

errout:
  set_errno(errcode);
  return NULL;
}
Example #17
0
FAR struct nxterm_state_s *
  nxterm_register(NXTERM handle, FAR struct nxterm_window_s *wndo,
                 FAR const struct nxterm_operations_s *ops, int minor)
{
  FAR struct nxterm_state_s *priv;
  FAR const struct nx_font_s *fontset;
  char devname[NX_DEVNAME_SIZE];
  NXHANDLE hfont;
  int ret;

  DEBUGASSERT(handle && wndo && ops && (unsigned)minor < 256);

  /* Allocate the driver structure */

  priv = (FAR struct nxterm_state_s *)kmm_zalloc(sizeof(struct nxterm_state_s));
  if (!priv)
    {
      gerr("ERROR: Failed to allocate the NX driver structure\n");
      return NULL;
    }

  /* Initialize the driver structure */

  priv->ops     = ops;
  priv->handle  = handle;
  priv->minor   = minor;
  memcpy(&priv->wndo, wndo, sizeof(struct nxterm_window_s));

  nxsem_init(&priv->exclsem, 0, 1);
#ifdef CONFIG_DEBUG_FEATURES
  priv->holder  = NO_HOLDER;
#endif

#ifdef CONFIG_NXTERM_NXKBDIN
  /* The waitsem semaphore is used for signaling and, hence, should not have
   * priority inheritance enabled.
   */

  nxsem_init(&priv->waitsem, 0, 0);
  nxsem_setprotocol(&priv->waitsem, SEM_PRIO_NONE);
#endif

  /* Connect to the font cache for the configured font characteristics */

  priv->fcache = nxf_cache_connect(wndo->fontid, wndo->fcolor[0],
                                   wndo->wcolor[0], CONFIG_NXTERM_BPP,
                                   CONFIG_NXTERM_CACHESIZE);
  if (priv->fcache == NULL)
    {
      gerr("ERROR: Failed to connect to font cache for font ID %d: %d\n",
           wndo->fontid, errno);
      goto errout;
    }

  /* Get the handle of the font managed by the font cache */

  hfont = nxf_cache_getfonthandle(priv->fcache);
  if (hfont == NULL)
    {
      gerr("ERROR: Failed to get handlr for font ID %d: %d\n",
           wndo->fontid, errno);
      goto errout;
    }

  /* Get information about the font set being used and save this in the
   * state structure
   */

  fontset         = nxf_getfontset(hfont);
  priv->fheight   = fontset->mxheight;
  priv->fwidth    = fontset->mxwidth;
  priv->spwidth   = fontset->spwidth;

  /* Set up the text cache */

  priv->maxchars  = CONFIG_NXTERM_MXCHARS;

  /* Set the initial display position */

  nxterm_home(priv);

  /* Show the cursor */

  priv->cursor.code = CONFIG_NXTERM_CURSORCHAR;
  nxterm_showcursor(priv);

  /* Register the driver */

  snprintf(devname, NX_DEVNAME_SIZE, NX_DEVNAME_FORMAT, minor);
  ret = register_driver(devname, &g_nxterm_drvrops, 0666, priv);
  if (ret < 0)
    {
      gerr("ERROR: Failed to register %s\n", devname);
    }

  return (NXTERM)priv;

errout:
  kmm_free(priv);
  return NULL;
}
Example #18
0
static struct tiva_adc_s *tiva_adc_struct_init(struct tiva_adc_cfg_s *cfg)
{
  struct tiva_adc_s     *adc           = g_adcs[cfg->adc];
  struct tiva_adc_sse_s *sse           = 0;
  uint8_t                s             = 0;

  /* Do not re-initialize the run-time structures, there is a chance another
   * process is also using this ADC.
   */

  if (adc->cfg == true)
    {
      goto tiva_adc_struct_init_ok;
    }
  else
    {
      if (adc != NULL)
        {
          adc->ena = false;
          adc->devno = cfg->adc;

          for (s = 0; s < 4; s++)
            {

              /* Only configure selected SSEs */

              if (cfg->sse[s])
                {
                  sse = g_sses[SSE_IDX(cfg->adc, s)];

                  if (sse != NULL)
                    {
                      sse->adc = cfg->adc;
                      sse->num = s;
                      nxsem_init(&sse->exclsem, SEM_PROCESS_PRIVATE, 1);
                      sse->ena = false;
                      sse->cfg = true;
                    }
                  else
                    {
                      goto tiva_adc_struct_init_error;
                    }
                }
            }

          /* Initialize the public ADC device data structure */

          adc->dev = g_devs[cfg->adc];
          if (adc->dev != NULL)
            {
              adc->dev->ad_ops  = &g_adcops;
              adc->dev->ad_priv = adc;
            }
          else
            {
              goto tiva_adc_struct_init_error;
            }
          goto tiva_adc_struct_init_ok;
        }
      else
        {
          goto tiva_adc_struct_init_error;
        }
    }

tiva_adc_struct_init_error:
  ainfo("Invalid ADC device number: expected=%d actual=%d\n",
        0, cfg->adc);
  ainfo("ADC%d (CONFIG_TIVA_ADC%d) must be enabled in Kconfig first!",
        cfg->adc, cfg->adc);
  return NULL;

tiva_adc_struct_init_ok:
  adc->cfg = true;
  return adc;
}
Example #19
0
int arp_send(in_addr_t ipaddr)
{
  FAR struct net_driver_s *dev;
  struct arp_notify_s notify;
  struct timespec delay;
  struct arp_send_s state;
  int ret;

  /* First check if destination is a local broadcast. */

  if (ipaddr == INADDR_BROADCAST)
    {
      /* We don't need to send the ARP request */

      return OK;
    }

#ifdef CONFIG_NET_IGMP
  /* Check if the destination address is a multicast address
   *
   * - IPv4: multicast addresses lie in the class D group -- The address range
   *   224.0.0.0 to 239.255.255.255 (224.0.0.0/4)
   *
   * - IPv6 multicast addresses are have the high-order octet of the
   *   addresses=0xff (ff00::/8.)
   */

  if (NTOHL(ipaddr) >= 0xe0000000 && NTOHL(ipaddr) <= 0xefffffff)
    {
      /* We don't need to send the ARP request */

      return OK;
    }
#endif

  /* Get the device that can route this request */

  dev = netdev_findby_ipv4addr(INADDR_ANY, ipaddr);
  if (!dev)
    {
      nerr("ERROR: Unreachable: %08lx\n", (unsigned long)ipaddr);
      ret = -EHOSTUNREACH;
      goto errout;
    }

  /* ARP support is only built if the Ethernet data link is supported.
   * Continue and send the ARP request only if this device uses the
   * Ethernet data link protocol.
   */

  if (dev->d_lltype != NET_LL_ETHERNET)
    {
      return OK;
    }

  /* Check if the destination address is on the local network. */

  if (!net_ipv4addr_maskcmp(ipaddr, dev->d_ipaddr, dev->d_netmask))
    {
      in_addr_t dripaddr;

      /* Destination address is not on the local network */

#ifdef CONFIG_NET_ROUTE
      /* We have a routing table.. find the correct router to use in
       * this case (or, as a fall-back, use the device's default router
       * address).  We will use the router IP address instead of the
       * destination address when determining the MAC address.
       */

      netdev_ipv4_router(dev, ipaddr, &dripaddr);
#else
      /* Use the device's default router IP address instead of the
       * destination address when determining the MAC address.
       */

      net_ipv4addr_copy(dripaddr, dev->d_draddr);
#endif
      ipaddr = dripaddr;
    }

  /* The destination address is on the local network.  Check if it is
   * the sub-net broadcast address.
   */

  else if (net_ipv4addr_broadcast(ipaddr, dev->d_netmask))
    {
      /* Yes.. We don't need to send the ARP request */

      return OK;
    }

  /* Allocate resources to receive a callback.  This and the following
   * initialization is performed with the network lock because we don't
   * want anything to happen until we are ready.
   */

  net_lock();
  state.snd_cb = arp_callback_alloc(dev);
  if (!state.snd_cb)
    {
      nerr("ERROR: Failed to allocate a callback\n");
      ret = -ENOMEM;
      goto errout_with_lock;
    }

  /* This semaphore is used for signaling and, hence, should not have
   * priority inheritance enabled.
   */

  (void)nxsem_init(&state.snd_sem, 0, 0); /* Doesn't really fail */
  nxsem_setprotocol(&state.snd_sem, SEM_PRIO_NONE);

  state.snd_retries   = 0;              /* No retries yet */
  state.snd_ipaddr    = ipaddr;         /* IP address to query */

  /* Remember the routing device name */

  strncpy((FAR char *)state.snd_ifname, (FAR const char *)dev->d_ifname,
          IFNAMSIZ);

  /* Now loop, testing if the address mapping is in the ARP table and re-
   * sending the ARP request if it is not.
   */

  ret = -ETIMEDOUT; /* Assume a timeout failure */

  while (state.snd_retries < CONFIG_ARP_SEND_MAXTRIES)
    {
      /* Check if the address mapping is present in the ARP table.  This
       * is only really meaningful on the first time through the loop.
       *
       * NOTE: If the ARP table is large than this could be a performance
       * issue.
       */

      if (arp_find(ipaddr, NULL) >= 0)
        {
          /* We have it!  Break out with success */

          ret = OK;
          break;
        }

      /* Set up the ARP response wait BEFORE we send the ARP request */

      arp_wait_setup(ipaddr, &notify);

      /* Arm/re-arm the callback */

      state.snd_sent      = false;
      state.snd_result    = -EBUSY;
      state.snd_cb->flags = (ARP_POLL | NETDEV_DOWN);
      state.snd_cb->priv  = (FAR void *)&state;
      state.snd_cb->event = arp_send_eventhandler;

      /* Notify the device driver that new TX data is available.
       * NOTES: This is in essence what netdev_ipv4_txnotify() does, which
       * is not possible to call since it expects a in_addr_t as
       * its single argument to lookup the network interface.
       */

      if (dev->d_txavail)
        {
          dev->d_txavail(dev);
        }

      /* Wait for the send to complete or an error to occur.
       * net_lockedwait will also terminate if a signal is received.
       */

      do
        {
          (void)net_lockedwait(&state.snd_sem);
        }
      while (!state.snd_sent);

      /* Check the result of the send operation */

      ret = state.snd_result;
      if (ret < 0)
        {
          /* Break out on a send failure */

          nerr("ERROR: Send failed: %d\n", ret);
          break;
        }

      /* Now wait for response to the ARP response to be received.  The
       * optimal delay would be the work case round trip time.
       * NOTE: The network is locked.
       */

      delay.tv_sec  = CONFIG_ARP_SEND_DELAYSEC;
      delay.tv_nsec = CONFIG_ARP_SEND_DELAYNSEC;

      ret = arp_wait(&notify, &delay);

      /* arp_wait will return OK if and only if the matching ARP response
       * is received.  Otherwise, it will return -ETIMEDOUT.
       */

      if (ret >= OK)
        {
          /* Break out if arp_wait() fails */

          break;
        }

      /* Increment the retry count */

      state.snd_retries++;
      nerr("ERROR: arp_wait failed: %d\n", ret);
    }

  nxsem_destroy(&state.snd_sem);
  arp_callback_free(dev, state.snd_cb);
errout_with_lock:
  net_unlock();
errout:
  return ret;
}
Example #20
0
int stm32_tsc_setup(int minor)
{
  FAR struct tc_dev_s *priv;
  char devname[DEV_NAMELEN];
#ifdef CONFIG_TOUCHSCREEN_MULTIPLE
  irqstate_t flags;
#endif
  int ret;

  iinfo("minor: %d\n", minor);
  DEBUGASSERT(minor >= 0 && minor < 100);

  /* If we only have one touchscreen, check if we already did init */

#ifndef CONFIG_TOUCHSCREEN_MULTIPLE
  if (g_touchinitdone)
    {
      return OK;
    }
#endif

  /* Configure the touchscreen DRIVEA and DRIVEB pins for output */

  stm32_configgpio(GPIO_TP_DRIVEA);
  stm32_configgpio(GPIO_TP_DRIVEB);

  /* Configure Analog inputs for sampling X and Y coordinates */

  stm32_configgpio(GPIO_TP_XL);
  stm32_configgpio(GPIO_TP_YD);

  tc_adc_init();

  /* Create and initialize a touchscreen device driver instance */

#ifndef CONFIG_TOUCHSCREEN_MULTIPLE
  priv = &g_touchscreen;
#else
  priv = (FAR struct tc_dev_s *)kmm_malloc(sizeof(struct tc_dev_s));
  if (!priv)
    {
      ierr("ERROR: kmm_malloc(%d) failed\n", sizeof(struct tc_dev_s));
      return -ENOMEM;
    }
#endif

  /* Initialize the touchscreen device driver instance */

  memset(priv, 0, sizeof(struct tc_dev_s));
  nxsem_init(&priv->devsem,  0, 1); /* Initialize device structure semaphore */
  nxsem_init(&priv->waitsem, 0, 0); /* Initialize pen event wait semaphore */

  /* Register the device as an input device */

  (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor);
  iinfo("Registering %s\n", devname);

  ret = register_driver(devname, &tc_fops, 0666, priv);
  if (ret < 0)
    {
      ierr("ERROR: register_driver() failed: %d\n", ret);
      goto errout_with_priv;
    }

  /* Schedule work to perform the initial sampling and to set the data
   * availability conditions.
   */

  priv->state = TC_READY;
  ret = work_queue(HPWORK, &priv->work, tc_worker, priv, 0);
  if (ret != 0)
    {
      ierr("ERROR: Failed to queue work: %d\n", ret);
      goto errout_with_priv;
    }

  /* And return success (?) */

#ifndef CONFIG_TOUCHSCREEN_MULTIPLE
  g_touchinitdone = true;
#endif

  return OK;

errout_with_priv:
  nxsem_destroy(&priv->devsem);
#ifdef CONFIG_TOUCHSCREEN_MULTIPLE
  kmm_free(priv);
#endif
  return ret;
}
Example #21
0
int pty_register(int minor)
{
  FAR struct pty_devpair_s *devpair;
  int pipe_a[2];
  int pipe_b[2];
  char devname[16];
  int ret;

  /* Allocate a device instance */

  devpair = kmm_zalloc(sizeof(struct pty_devpair_s));
  if (devpair == NULL)
    {
      return -ENOMEM;
    }

  /* Initialize semaphores */

  nxsem_init(&devpair->pp_slavesem, 0, 0);
  nxsem_init(&devpair->pp_exclsem, 0, 1);

  /* The pp_slavesem semaphore is used for signaling and, hence, should not
   * have priority inheritance enabled.
   */

  nxsem_setprotocol(&devpair->pp_slavesem, SEM_PRIO_NONE);

#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
  devpair->pp_minor             = minor;
#endif
  devpair->pp_locked            = true;
  devpair->pp_master.pd_devpair = devpair;
  devpair->pp_master.pd_master  = true;
  devpair->pp_slave.pd_devpair  = devpair;

  /* Create two pipes:
   *
   *   pipe_a:  Master source, slave sink (TX, slave-to-master)
   *   pipe_b:  Master sink, slave source (RX, master-to-slave)
   */

  ret = pipe2(pipe_a, CONFIG_PSEUDOTERM_TXBUFSIZE);
  if (ret < 0)
    {
      goto errout_with_devpair;
    }

  ret = pipe2(pipe_b, CONFIG_PSEUDOTERM_RXBUFSIZE);
  if (ret < 0)
    {
      goto errout_with_pipea;
    }

  /* Detach the pipe file descriptors (closing them in the process)
   *
   *  fd[0] is for reading;
   *  fd[1] is for writing.
   */

  ret = file_detach(pipe_a[0], &devpair->pp_master.pd_src);
  if (ret < 0)
    {
      goto errout_with_pipeb;
    }

  pipe_a[0] = -1;

  ret = file_detach(pipe_a[1], &devpair->pp_slave.pd_sink);
  if (ret < 0)
    {
      goto errout_with_pipeb;
    }

  pipe_a[1] = -1;

  ret = file_detach(pipe_b[0], &devpair->pp_slave.pd_src);
  if (ret < 0)
    {
      goto errout_with_pipeb;
    }

  pipe_b[0] = -1;

  ret = file_detach(pipe_b[1], &devpair->pp_master.pd_sink);
  if (ret < 0)
    {
      goto errout_with_pipeb;
    }

  pipe_b[1] = -1;

  /* Register the slave device
   *
   * BSD style (deprecated): /dev/ttypN
   * SUSv1 style:  /dev/pts/N
   *
   * Where N is the minor number
   */

#ifdef CONFIG_PSEUDOTERM_BSD
  snprintf(devname, 16, "/dev/ttyp%d", minor);
#else
  snprintf(devname, 16, "/dev/pts/%d", minor);
#endif

  ret = register_driver(devname, &g_pty_fops, 0666, &devpair->pp_slave);
  if (ret < 0)
    {
      goto errout_with_pipeb;
    }

  /* Register the master device
   *
   * BSD style (deprecated):  /dev/ptyN
   * SUSv1 style: Master: /dev/ptmx (multiplexor, see ptmx.c)
   *
   * Where N is the minor number
   */

  snprintf(devname, 16, "/dev/pty%d", minor);

  ret = register_driver(devname, &g_pty_fops, 0666, &devpair->pp_master);
  if (ret < 0)
    {
      goto errout_with_slave;
    }

  return OK;

errout_with_slave:
#ifdef CONFIG_PSEUDOTERM_BSD
  snprintf(devname, 16, "/dev/ttyp%d", minor);
#else
  snprintf(devname, 16, "/dev/pts/%d", minor);
#endif
  (void)unregister_driver(devname);

errout_with_pipeb:
  if (pipe_b[0] >= 0)
    {
      close(pipe_b[0]);
    }
  else
    {
      (void)file_close_detached(&devpair->pp_master.pd_src);
    }

  if (pipe_b[1] >= 0)
    {
      close(pipe_b[1]);
    }
  else
    {
      (void)file_close_detached(&devpair->pp_slave.pd_sink);
    }

errout_with_pipea:
  if (pipe_a[0] >= 0)
    {
      close(pipe_a[0]);
    }
  else
    {
      (void)file_close_detached(&devpair->pp_slave.pd_src);
    }

  if (pipe_a[1] >= 0)
    {
      close(pipe_a[1]);
    }
  else
    {
      (void)file_close_detached(&devpair->pp_master.pd_sink);
    }

errout_with_devpair:
   nxsem_destroy(&devpair->pp_exclsem);
   nxsem_destroy(&devpair->pp_slavesem);
   kmm_free(devpair);
   return ret;
}
Example #22
0
int syslog_dev_initialize(FAR const char *devpath, int oflags, int mode)
{
  int fd;
  int ret;

  /* At this point, the only expected states are SYSLOG_UNINITIALIZED or
   * SYSLOG_REOPEN..  Not SYSLOG_INITIALIZING, SYSLOG_FAILURE, SYSLOG_OPENED.
   */

  DEBUGASSERT(g_syslog_dev.sl_state == SYSLOG_UNINITIALIZED ||
              g_syslog_dev.sl_state == SYSLOG_REOPEN);

  /* Save the path to the device in case we have to re-open it.
   * If we get here and sl_devpath is not equal to NULL, that is a clue
   * that we will are re-openingthe file.
   */

  if (g_syslog_dev.sl_state == SYSLOG_REOPEN)
    {
      /* Re-opening: Then we should already have a copy of the path to the
       * device.
       */

      DEBUGASSERT(g_syslog_dev.sl_devpath != NULL &&
                  strcmp(g_syslog_dev.sl_devpath, devpath) == 0);
    }
  else
    {
      /* Initializing.  Copy the device path so that we can use it if we
       * have to re-open the file.
       */

      DEBUGASSERT(g_syslog_dev.sl_devpath == NULL);
      g_syslog_dev.sl_oflags  = oflags;
      g_syslog_dev.sl_mode    = mode;
      g_syslog_dev.sl_devpath = strdup(devpath);
      DEBUGASSERT(g_syslog_dev.sl_devpath != NULL);
    }

  g_syslog_dev.sl_state = SYSLOG_INITIALIZING;

  /* Open the device driver. */

  fd = open(devpath, oflags, mode);
  if (fd < 0)
    {
       int errcode = get_errno();
       DEBUGASSERT(errcode > 0);

      /* We failed to open the file. Perhaps it does exist?  Perhaps it
       * exists, but is not ready because it depends on insertion of a
       * removable device?
       *
       * In any case we will attempt to re-open the device repeatedly.
       * The assumption is that the device path is valid but that the
       * driver has not yet been registered or a removable device has
       * not yet been installed.
       */

      g_syslog_dev.sl_state = SYSLOG_REOPEN;
      return -errcode;
    }

  /* Detach the file descriptor from the file structure.  The file
   * descriptor is a task-specific concept.  Detaching the file
   * descriptor allows us to use the device on all threads in all tasks.
   */

  ret = file_detach(fd, &g_syslog_dev.sl_file);
  if (ret < 0)
    {
      /* This should not happen and means that something very bad has
       * occurred.
       */

      g_syslog_dev.sl_state = SYSLOG_FAILURE;
      close(fd);
      return ret;
    }

  /* The SYSLOG device is open and ready for writing. */

  nxsem_init(&g_syslog_dev.sl_sem, 0, 1);
  g_syslog_dev.sl_holder = NO_HOLDER;
  g_syslog_dev.sl_state  = SYSLOG_OPENED;
  return OK;
}
Example #23
0
int psock_tcp_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
                     FAR socklen_t *addrlen, FAR void **newconn)
{
  FAR struct tcp_conn_s *conn;
  struct accept_s state;
  int ret;

  DEBUGASSERT(psock && newconn);

  /* Check the backlog to see if there is a connection already pending for
   * this listener.
   */

  conn = (FAR struct tcp_conn_s *)psock->s_conn;

#ifdef CONFIG_NET_TCPBACKLOG
  state.acpt_newconn = tcp_backlogremove(conn);
  if (state.acpt_newconn)
    {
      /* Yes... get the address of the connected client */

      ninfo("Pending conn=%p\n", state.acpt_newconn);
      accept_tcpsender(psock, state.acpt_newconn, addr, addrlen);
    }

  /* In general, this implementation will not support non-blocking socket
   * operations... except in a few cases:  Here for TCP accept with
   * backlog enabled.  If this socket is configured as non-blocking then
   * return EAGAIN if there is no pending connection in the backlog.
   */

  else if (_SS_ISNONBLOCK(psock->s_flags))
    {
      return -EAGAIN;
    }
  else
#endif
    {
      /* Set the socket state to accepting */

      psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_ACCEPT);

      /* Perform the TCP accept operation */

      /* Initialize the state structure.  This is done with the network
       * locked because we don't want anything to happen until we are
       * ready.
       */

      state.acpt_sock       = psock;
      state.acpt_addr       = addr;
      state.acpt_addrlen    = addrlen;
      state.acpt_newconn    = NULL;
      state.acpt_result     = OK;

      /* This semaphore is used for signaling and, hence, should not have
       * priority inheritance enabled.
       */

      nxsem_init(&state.acpt_sem, 0, 0);
      nxsem_setprotocol(&state.acpt_sem, SEM_PRIO_NONE);

      /* Set up the callback in the connection */

      conn->accept_private  = (FAR void *)&state;
      conn->accept          = accept_eventhandler;

      /* Wait for the send to complete or an error to occur:  NOTES:
       * net_lockedwait will also terminate if a signal is received.
       */

      ret = net_lockedwait(&state.acpt_sem);

      /* Make sure that no further events are processed */

      conn->accept_private = NULL;
      conn->accept         = NULL;

      nxsem_destroy(&state. acpt_sem);

      /* Set the socket state to idle */

      psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);

      /* Check for a errors.  Errors are signalled by negative errno values
       * for the send length.
       */

      if (state.acpt_result != 0)
        {
          DEBUGASSERT(state.acpt_result > 0);
          return -state.acpt_result;
        }

      /* If net_lockedwait failed, then we were probably reawakened by a
       * signal.  In this case, net_lockedwait will have returned negated
       * errno appropriately.
       */

      if (ret < 0)
        {
          return ret;
        }
    }

  *newconn = (FAR void *)state.acpt_newconn;
  return OK;
}
Example #24
0
int icmpv6_neighbor(const net_ipv6addr_t ipaddr)
{
  FAR struct net_driver_s *dev;
  struct icmpv6_notify_s notify;
  struct timespec delay;
  struct icmpv6_neighbor_s state;
  FAR const uint16_t *lookup;
  int ret;

  /* First check if destination is a local broadcast or a multicast address.
   *
   * - IPv6 multicast addresses are have the high-order octet of the
   *   addresses=0xff (ff00::/8.)
   */

  if (net_ipv6addr_cmp(ipaddr, g_ipv6_unspecaddr) ||
      net_is_addr_mcast(ipaddr))
    {
      /* We don't need to send the Neighbor Solicitation */

      return OK;
    }

  /* Get the device that can route this request */

  dev = netdev_findby_ipv6addr(g_ipv6_unspecaddr, ipaddr);
  if (!dev)
    {
      nerr("ERROR: Unreachable: %08lx\n", (unsigned long)ipaddr);
      ret = -EHOSTUNREACH;
      goto errout;
    }

  /* Send the Neighbor Solicitation request only if this device uses the
   * Ethernet data link protocol.
   *
   * REVISIT:  Other link layer protocols may require Neighbor Discovery
   * as well.
   */

  if (dev->d_lltype != NET_LL_ETHERNET)
    {
      return OK;
    }

  /* Check if the destination address is on the local network. */

  if (net_ipv6addr_maskcmp(ipaddr, dev->d_ipv6addr, dev->d_ipv6netmask))
    {
      /* Yes.. use the input address for the lookup */

      lookup = ipaddr;
    }
  else
    {
      net_ipv6addr_t dripaddr;

      /* Destination address is not on the local network */

#ifdef CONFIG_NET_ROUTE

      /* We have a routing table.. find the correct router to use in
       * this case (or, as a fall-back, use the device's default router
       * address).  We will use the router IP address instead of the
       * destination address when determining the MAC address.
       */

      netdev_ipv6_router(dev, ipaddr, dripaddr);
#else
      /* Use the device's default router IP address instead of the
       * destination address when determining the MAC address.
       */

      net_ipv6addr_copy(dripaddr, dev->d_ipv6draddr);
#endif

      /* Use the router address for the lookup */

      lookup = dripaddr;
    }

  /* Allocate resources to receive a callback.  This and the following
   * initialization is performed with the network lock because we don't
   * want anything to happen until we are ready.
   */

  net_lock();
  state.snd_cb = icmpv6_callback_alloc(dev);
  if (!state.snd_cb)
    {
      nerr("ERROR: Failed to allocate a callback\n");
      ret = -ENOMEM;
      goto errout_with_lock;
    }

  /* Initialize the state structure with the network locked.
   *
   * This semaphore is used for signaling and, hence, should not have
   * priority inheritance enabled.
   */

  (void)nxsem_init(&state.snd_sem, 0, 0);        /* Doesn't really fail */
  nxsem_setprotocol(&state.snd_sem, SEM_PRIO_NONE);

  state.snd_retries = 0;                       /* No retries yet */
  net_ipv6addr_copy(state.snd_ipaddr, lookup); /* IP address to query */

  /* Remember the routing device name */

  strncpy((FAR char *)state.snd_ifname, (FAR const char *)dev->d_ifname,
          IFNAMSIZ);

  /* Now loop, testing if the address mapping is in the Neighbor Table and
   * re-sending the Neighbor Solicitation if it is not.
   */

  ret = -ETIMEDOUT; /* Assume a timeout failure */

  while (state.snd_retries < CONFIG_ICMPv6_NEIGHBOR_MAXTRIES)
    {
      /* Check if the address mapping is present in the Neighbor Table.  This
       * is only really meaningful on the first time through the loop.
       *
       * NOTE: If the Neighbor Table is large than this could be a performance
       * issue.
       */

      if (neighbor_findentry(lookup) != NULL)
        {
          /* We have it!  Break out with success */

          ret = OK;
          break;
        }

      /* Set up the Neighbor Advertisement wait BEFORE we send the Neighbor
       * Solicitation.
       */

      icmpv6_wait_setup(lookup, &notify);

      /* Arm/re-arm the callback */

      state.snd_sent      = false;
      state.snd_cb->flags = ICMPv6_POLL;
      state.snd_cb->priv  = (FAR void *)&state;
      state.snd_cb->event = icmpv6_neighbor_eventhandler;

      /* Notify the device driver that new TX data is available. */

      dev->d_txavail(dev);

      /* Wait for the send to complete or an error to occur.
       * net_lockedwait will also terminate if a signal is received.
       */

      do
        {
          (void)net_lockedwait(&state.snd_sem);
        }
      while (!state.snd_sent);

      /* Now wait for response to the Neighbor Advertisement to be received.
       * The optimal delay would be the work case round trip time.
       * NOTE: The network is locked.
       */

      delay.tv_sec  = CONFIG_ICMPv6_NEIGHBOR_DELAYSEC;
      delay.tv_nsec = CONFIG_ICMPv6_NEIGHBOR_DELAYNSEC;

      ret = icmpv6_wait(&notify, &delay);

      /* icmpv6_wait will return OK if and only if the matching Neighbor
       * Advertisement is received.  Otherwise, it will return -ETIMEDOUT.
       */

      if (ret == OK)
        {
          break;
        }

      /* Increment the retry count */

      state.snd_retries++;
    }

  nxsem_destroy(&state.snd_sem);
  icmpv6_callback_free(dev, state.snd_cb);
errout_with_lock:
  net_unlock();
errout:
  return ret;
}
Example #25
0
int ads7843e_register(FAR struct spi_dev_s *spi,
                      FAR struct ads7843e_config_s *config, int minor)
{
  FAR struct ads7843e_dev_s *priv;
  char devname[DEV_NAMELEN];
#ifdef CONFIG_ADS7843E_MULTIPLE
  irqstate_t flags;
#endif
  int ret;

  iinfo("spi: %p minor: %d\n", spi, minor);

  /* Debug-only sanity checks */

  DEBUGASSERT(spi != NULL && config != NULL && minor >= 0 && minor < 100);

  /* Create and initialize a ADS7843E device driver instance */

#ifndef CONFIG_ADS7843E_MULTIPLE
  priv = &g_ads7843e;
#else
  priv = (FAR struct ads7843e_dev_s *)kmm_malloc(sizeof(struct ads7843e_dev_s));
  if (!priv)
    {
      ierr("ERROR: kmm_malloc(%d) failed\n", sizeof(struct ads7843e_dev_s));
      return -ENOMEM;
    }
#endif

  /* Initialize the ADS7843E device driver instance */

  memset(priv, 0, sizeof(struct ads7843e_dev_s));
  priv->spi     = spi;               /* Save the SPI device handle */
  priv->config  = config;            /* Save the board configuration */
  priv->wdog    = wd_create();       /* Create a watchdog timer */
  priv->threshx = INVALID_THRESHOLD; /* Initialize thresholding logic */
  priv->threshy = INVALID_THRESHOLD; /* Initialize thresholding logic */

  /* Initialize semaphores */

  nxsem_init(&priv->devsem,  0, 1);    /* Initialize device structure semaphore */
  nxsem_init(&priv->waitsem, 0, 0);    /* Initialize pen event wait semaphore */

  /* The pen event semaphore is used for signaling and, hence, should not
   * have priority inheritance enabled.
   */

  nxsem_setprotocol(&priv->waitsem, SEM_PRIO_NONE);

  /* Make sure that interrupts are disabled */

  config->clear(config);
  config->enable(config, false);

  /* Attach the interrupt handler */

  ret = config->attach(config, ads7843e_interrupt);
  if (ret < 0)
    {
      ierr("ERROR: Failed to attach interrupt\n");
      goto errout_with_priv;
    }

  iinfo("Mode: %d Bits: 8 Frequency: %d\n",
        CONFIG_ADS7843E_SPIMODE, CONFIG_ADS7843E_FREQUENCY);

  /* Lock the SPI bus so that we have exclusive access */

  ads7843e_lock(spi);

  /* Enable the PEN IRQ */

  ads7843e_sendcmd(priv, ADS7843_CMD_ENABPENIRQ);

  /* Unlock the bus */

  ads7843e_unlock(spi);

  /* Register the device as an input device */

  (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor);
  iinfo("Registering %s\n", devname);

  ret = register_driver(devname, &ads7843e_fops, 0666, priv);
  if (ret < 0)
    {
      ierr("ERROR: register_driver() failed: %d\n", ret);
      goto errout_with_priv;
    }

  /* If multiple ADS7843E devices are supported, then we will need to add
   * this new instance to a list of device instances so that it can be
   * found by the interrupt handler based on the received IRQ number.
   */

#ifdef CONFIG_ADS7843E_MULTIPLE
  priv->flink    = g_ads7843elist;
  g_ads7843elist = priv;
  leave_critical_section(flags);
#endif

  /* Schedule work to perform the initial sampling and to set the data
   * availability conditions.
   */

  ret = work_queue(HPWORK, &priv->work, ads7843e_worker, priv, 0);
  if (ret != 0)
    {
      ierr("ERROR: Failed to queue work: %d\n", ret);
      goto errout_with_priv;
    }

  /* And return success (?) */

  return OK;

errout_with_priv:
  nxsem_destroy(&priv->devsem);
#ifdef CONFIG_ADS7843E_MULTIPLE
  kmm_free(priv);
#endif
  return ret;
}
Example #26
0
ssize_t ieee802154_recvfrom(FAR struct socket *psock, FAR void *buf,
                            size_t len, int flags, FAR struct sockaddr *from,
                            FAR socklen_t *fromlen)
{
  FAR struct ieee802154_conn_s *conn = (FAR struct ieee802154_conn_s *)psock->s_conn;
  FAR struct radio_driver_s *radio;
  struct ieee802154_recvfrom_s state;
  ssize_t ret;

  /* If a 'from' address has been provided, verify that it is large
   * enough to hold this address family.
   */

  if (from != NULL && *fromlen < sizeof(struct sockaddr_ieee802154_s))
    {
      return -EINVAL;
    }

  if (psock->s_type != SOCK_DGRAM)
    {
      nerr("ERROR: Unsupported socket type: %d\n", psock->s_type);
      return -EPROTONOSUPPORT;
    }

  /* Perform the packet recvfrom() operation */

  /* Initialize the state structure.  This is done with the network
   * locked because we don't want anything to happen until we are ready.
   */

  net_lock();
  memset(&state, 0, sizeof(struct ieee802154_recvfrom_s));

  state.ir_buflen = len;
  state.ir_buffer = buf;
  state.ir_sock   = psock;
  state.ir_from   = from;

  /* Get the device driver that will service this transfer */

  radio = ieee802154_find_device(conn, &conn->laddr);
  if (radio == NULL)
    {
      ret = -ENODEV;
      goto errout_with_lock;
    }

  /* Before we wait for data, let's check if there are already frame(s)
   * waiting in the RX queue.
   */

  ret = ieee802154_recvfrom_rxqueue(radio, &state);
  if (ret > 0)
    {
      /* Good newe!  We have a frame and we are done. */

      net_unlock();
      return ret;
    }

  /* We will have to wait.  This semaphore is used for signaling and,
   * hence, should not have priority inheritance enabled.
   */

  (void)nxsem_init(&state.ir_sem, 0, 0); /* Doesn't really fail */
  (void)nxsem_setprotocol(&state.ir_sem, SEM_PRIO_NONE);

  /* Set the socket state to receiving */

  psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_RECV);

  /* Set up the callback in the connection */

  state.ir_cb = ieee802154_callback_alloc(&radio->r_dev, conn);
  if (state.ir_cb)
    {
      state.ir_cb->flags  = (IEEE802154_NEWDATA | IEEE802154_POLL);
      state.ir_cb->priv   = (FAR void *)&state;
      state.ir_cb->event  = ieee802154_recvfrom_eventhandler;

      /* Wait for either the receive to complete or for an error/timeout to
       * occur. NOTES:  (1) net_lockedwait will also terminate if a signal
       * is received, (2) the network is locked!  It will be un-locked while
       * the task sleeps and automatically re-locked when the task restarts.
       */

      (void)net_lockedwait(&state.ir_sem);

      /* Make sure that no further events are processed */

      ieee802154_callback_free(&radio->r_dev, conn, state.ir_cb);
      ret = state.ir_result;
    }
  else
    {
      ret = -EBUSY;
    }

  /* Set the socket state to idle */

  psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
  nxsem_destroy(&state.ir_sem);

errout_with_lock:
  net_unlock();
  return ret;
}