Exemplo n.º 1
0
static void tc_notify(FAR struct tc_dev_s *priv)
{
#ifndef CONFIG_DISABLE_POLL
  int i;
#endif

  /* If no threads have the driver open, then just dump the state */

#ifdef CONFIG_TOUCHSCREEN_REFCNT
  if ((priv->crefs == 0) && priv->sample.contact == CONTACT_UP)
    {
      priv->sample.contact = CONTACT_NONE;
      priv->sample.valid   = false;
      priv->id++;
      return;
    }
#endif

  /* If there are threads waiting for read data, then signal one of them
   * that the read data is available.
   */

  if (priv->nwaiters > 0)
    {
      /* After posting this semaphore, we need to exit because the touchscreen
       * is no longer available.
       */

      nxsem_post(&priv->waitsem);
    }

  /* If there are threads waiting on poll() for touchscreen data to become available,
   * then wake them up now.  NOTE: we wake up all waiting threads because we
   * do not know that they are going to do.  If they all try to read the data,
   * then some make end up blocking after all.
   */

#ifndef CONFIG_DISABLE_POLL
  for (i = 0; i < CONFIG_TOUCHSCREEN_NPOLLWAITERS; i++)
    {
      struct pollfd *fds = priv->fds[i];
      if (fds)
        {
          fds->revents |= POLLIN;
          iinfo("Report events: %02x\n", fds->revents);
          nxsem_post(fds->sem);
        }
    }
#endif
}
Exemplo n.º 2
0
void icmpv6_rnotify(FAR struct net_driver_s *dev, const net_ipv6addr_t draddr,
                    const net_ipv6addr_t prefix, unsigned int preflen)
{
  FAR struct icmpv6_rnotify_s *curr;

  ninfo("Notified\n");

  /* Find an entry with the matching device name in the list of waiters */

  for (curr = g_icmpv6_rwaiters; curr; curr = curr->rn_flink)
    {
      /* Does this entry match?  If the result is okay, then we have
       * already notified this waiter and it has not yet taken the
       * entry from the list.
       */

      if (curr->rn_result != OK &&
          strncmp(curr->rn_ifname, dev->d_ifname, IFNAMSIZ) == 0)
        {
          /* Yes.. Set the new network addresses. */

          icmpv6_setaddresses(dev, draddr, prefix, preflen);

          /* And signal the waiting, returning success */

          curr->rn_result = OK;
          nxsem_post(&curr->rn_sem);
          break;
        }
    }
}
Exemplo n.º 3
0
Arquivo: pwm.c Projeto: dagar/NuttX
void pwm_expired(FAR void *handle)
{
  FAR struct pwm_upperhalf_s *upper = (FAR struct pwm_upperhalf_s *)handle;

  pwminfo("started: %d waiting: %d\n", upper->started, upper->waiting);

  /* Make sure that the PWM is started */

  if (upper->started)
    {
      /* Is there a thread waiting for the pulse train to complete? */

      if (upper->waiting)
        {
          /* Yes.. clear the waiting flag and awakened the waiting thread */

          upper->waiting = false;
          nxsem_post(&upper->waitsem);
        }

      /* The PWM is now stopped */

      upper->started = false;
    }
}
Exemplo n.º 4
0
Arquivo: pwm.c Projeto: dagar/NuttX
static int pwm_open(FAR struct file *filep)
{
  FAR struct inode           *inode = filep->f_inode;
  FAR struct pwm_upperhalf_s *upper = inode->i_private;
  uint8_t                     tmp;
  int                         ret;

  pwminfo("crefs: %d\n", upper->crefs);

  /* Get exclusive access to the device structures */

  ret = nxsem_wait(&upper->exclsem);
  if (ret < 0)
    {
      goto errout;
    }

  /* Increment the count of references to the device.  If this the first
   * time that the driver has been opened for this device, then initialize
   * the device.
   */

  tmp = upper->crefs + 1;
  if (tmp == 0)
    {
      /* More than 255 opens; uint8_t overflows to zero */

      ret = -EMFILE;
      goto errout_with_sem;
    }

  /* Check if this is the first time that the driver has been opened. */

  if (tmp == 1)
    {
      FAR struct pwm_lowerhalf_s *lower = upper->dev;

      /* Yes.. perform one time hardware initialization. */

      DEBUGASSERT(lower->ops->setup != NULL);
      pwminfo("calling setup\n");

      ret = lower->ops->setup(lower);
      if (ret < 0)
        {
          goto errout_with_sem;
        }
    }

  /* Save the new open count on success */

  upper->crefs = tmp;
  ret = OK;

errout_with_sem:
  nxsem_post(&upper->exclsem);

errout:
  return ret;
}
Exemplo n.º 5
0
static int accept_eventhandler(FAR struct tcp_conn_s *listener,
                               FAR struct tcp_conn_s *conn)
{
  struct accept_s *pstate = (struct accept_s *)listener->accept_private;
  int ret = -EINVAL;

  if (pstate)
    {
      /* Get the connection address */

      accept_tcpsender(pstate->acpt_sock, conn, pstate->acpt_addr,
                       pstate->acpt_addrlen);

      /* Save the connection structure */

      pstate->acpt_newconn     = conn;
      pstate->acpt_result      = OK;

      /* There should be a reference of one on the new connection */

      DEBUGASSERT(conn->crefs == 1);

      /* Wake-up the waiting caller thread */

      nxsem_post(&pstate->acpt_sem);

      /* Stop any further callbacks */

      listener->accept_private = NULL;
      listener->accept         = NULL;
      ret                      = OK;
  }

  return ret;
}
Exemplo n.º 6
0
static int tc_waitsample(FAR struct tc_dev_s *priv,
                              FAR struct tc_sample_s *sample)
{
  int ret;

  /* Pre-emption must be disabled when this is called to to prevent sampled
   * data from changing until it has been reported.
   */

  sched_lock();

  /* Now release the semaphore that manages mutually exclusive access to
   * the device structure.  This may cause other tasks to become ready to
   * run, but they cannot run yet because pre-emption is disabled.
   */

  nxsem_post(&priv->devsem);

  /* Try to get the a sample... if we cannot, then wait on the semaphore
   * that is posted when new sample data is availble.
   */

  while (tc_sample(priv, sample) < 0)
    {
      /* Wait for a change in the touchscreen state */

      priv->nwaiters++;
      ret = nxsem_wait(&priv->waitsem);
      priv->nwaiters--;

      if (ret < 0)
        {
          /* If we are awakened by a signal, then we need to return
           * the failure now.
           */

          DEBUGASSERT(ret == -EINTR || ret  == -ECANCELED);
          goto errout;
        }
    }

  /* Re-acquire the semaphore that manages mutually exclusive access to
   * the device structure.  We may have to wait here.  But we have our sample.
   * Interrupts and pre-emption will be re-enabled while we wait.
   */

  ret = nxsem_wait(&priv->devsem);

errout:
  /* Restore pre-emption.  We might get suspended here but that is okay
   * because we already have our sample.  Note:  this means that if there
   * were two threads reading from the touchscreen for some reason, the data
   * might be read out of order.
   */

  sched_unlock();
  return ret;
}
Exemplo n.º 7
0
static int  mtdconfig_close(FAR struct file *filep)
{
  FAR struct inode *inode = filep->f_inode;
  FAR struct mtdconfig_struct_s *dev = inode->i_private;

  /* Release exclusive access to the device */

  nxsem_post(&dev->exclsem);
  return OK;
}
Exemplo n.º 8
0
static int ads7843e_open(FAR struct file *filep)
{
#ifdef CONFIG_ADS7843E_REFCNT
  FAR struct inode         *inode;
  FAR struct ads7843e_dev_s *priv;
  uint8_t                   tmp;
  int                       ret;

  iinfo("Opening\n");

  DEBUGASSERT(filep);
  inode = filep->f_inode;

  DEBUGASSERT(inode && inode->i_private);
  priv  = (FAR struct ads7843e_dev_s *)inode->i_private;

  /* Get exclusive access to the driver data structure */

  ret = nxsem_wait(&priv->devsem);
  if (ret < 0)
    {
      /* This should only happen if the wait was cancelled by an signal */

      DEBUGASSERT(ret == -EINTR || ret == -ECANCELED);
      return ret;
    }

  /* Increment the reference count */

  tmp = priv->crefs + 1;
  if (tmp == 0)
    {
      /* More than 255 opens; uint8_t overflows to zero */

      ret = -EMFILE;
      goto errout_with_sem;
    }

  /* When the reference increments to 1, this is the first open event
   * on the driver.. and an opportunity to do any one-time initialization.
   */

  /* Save the new open count on success */

  priv->crefs = tmp;

errout_with_sem:
  nxsem_post(&priv->devsem);
  return ret;
#else
  iinfo("Opening\n");
  return OK;
#endif
}
Exemplo n.º 9
0
static inline void syslog_dev_givesem(void)
{
#ifdef CONFIG_DEBUG_ASSERTIONS
  pid_t me = getpid();
  DEBUGASSERT(g_syslog_dev.sl_holder == me);
#endif

  /* Relinquish the semaphore */

  g_syslog_dev.sl_holder = NO_HOLDER;
  nxsem_post(&g_syslog_dev.sl_sem);
}
Exemplo n.º 10
0
static int ft80x_close(FAR struct file *filep)
{
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
  FAR struct inode *inode;
  FAR struct ft80x_dev_s *priv;
  int ret;

  DEBUGASSERT(filep != NULL);
  inode = filep->f_inode;
  DEBUGASSERT(inode != NULL && inode->i_private != NULL);
  priv  = inode->i_private;

  lcdinfo("crefs: %d\n", priv->crefs);

  /* Get exclusive access to the device structures */

  ret = nxsem_wait(&priv->exclsem);
  if (ret < 0)
    {
      goto errout;
    }

  /* Will the count decrement to zero? */

  if (priv->crefs <= 1)
    {
      /* Yes.. if the driver has been unlinked, then we need to destroy the
       * driver instance.
       */

      priv->crefs = 0;
      if (priv->unlinked)
        {
          ft80x_destroy(priv);
          return OK;
        }
    }
  else
    {
      /* NO.. decrement the number of references to the driver. */

      priv->crefs--;
    }

  ret = OK;
  nxsem_post(&priv->exclsem);

errout:
  return ret;
#else
  return OK;
#endif
}
Exemplo n.º 11
0
int bcmf_sdpcm_queue_frame(FAR struct bcmf_dev_s *priv,
                           struct bcmf_frame_s *frame, bool control)
{
  FAR struct bcmf_sdio_dev_s *sbus = (FAR struct bcmf_sdio_dev_s *)priv->bus;
  struct bcmf_sdio_frame *sframe = (struct bcmf_sdio_frame *)frame;
  struct bcmf_sdpcm_header *header = (struct bcmf_sdpcm_header *)sframe->data;

  /* Prepare sw header */

  memset(header, 0, sizeof(struct bcmf_sdpcm_header));
  header->size = frame->len;
  header->checksum = ~header->size;
  header->data_offset = (uint8_t)(frame->data - frame->base);

  if (control)
    {
      header->channel = SDPCM_CONTROL_CHANNEL;
    }
  else
    {
      header->channel = SDPCM_DATA_CHANNEL;
    }

  /* Add frame in tx queue */

  if (nxsem_wait(&sbus->queue_mutex) < 0)
    {
      PANIC();
    }

  bcmf_dqueue_push(&sbus->tx_queue, &sframe->list_entry);

  nxsem_post(&sbus->queue_mutex);

  /* Notify bcmf thread tx frame is ready */

  nxsem_post(&sbus->thread_signal);

  return OK;
}
Exemplo n.º 12
0
static int ads7843e_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
  FAR struct inode         *inode;
  FAR struct ads7843e_dev_s *priv;
  int                       ret;

  iinfo("cmd: %d arg: %ld\n", cmd, arg);
  DEBUGASSERT(filep);
  inode = filep->f_inode;

  DEBUGASSERT(inode && inode->i_private);
  priv  = (FAR struct ads7843e_dev_s *)inode->i_private;

  /* Get exclusive access to the driver data structure */

  ret = nxsem_wait(&priv->devsem);
  if (ret < 0)
    {
      /* This should only happen if the wait was cancelled by an signal */

      DEBUGASSERT(ret == -EINTR || ret == -ECANCELED);
      return ret;
    }

  /* Process the IOCTL by command */

  switch (cmd)
    {
      case TSIOC_SETFREQUENCY:  /* arg: Pointer to uint32_t frequency value */
        {
          FAR uint32_t *ptr = (FAR uint32_t *)((uintptr_t)arg);
          DEBUGASSERT(priv->config != NULL && ptr != NULL);
          priv->config->frequency = SPI_SETFREQUENCY(priv->spi, *ptr);
        }
        break;

      case TSIOC_GETFREQUENCY:  /* arg: Pointer to uint32_t frequency value */
        {
          FAR uint32_t *ptr = (FAR uint32_t *)((uintptr_t)arg);
          DEBUGASSERT(priv->config != NULL && ptr != NULL);
          *ptr = priv->config->frequency;
        }
        break;

      default:
        ret = -ENOTTY;
        break;
    }

  nxsem_post(&priv->devsem);
  return ret;
}
Exemplo n.º 13
0
static void ads7843e_notify(FAR struct ads7843e_dev_s *priv)
{
#ifndef CONFIG_DISABLE_POLL
  int i;
#endif

  /* If there are threads waiting for read data, then signal one of them
   * that the read data is available.
   */

  if (priv->nwaiters > 0)
    {
      /* After posting this semaphore, we need to exit because the ADS7843E
       * is no longer available.
       */

      nxsem_post(&priv->waitsem);
    }

  /* If there are threads waiting on poll() for ADS7843E data to become available,
   * then wake them up now.  NOTE: we wake up all waiting threads because we
   * do not know that they are going to do.  If they all try to read the data,
   * then some make end up blocking after all.
   */

#ifndef CONFIG_DISABLE_POLL
  for (i = 0; i < CONFIG_ADS7843E_NPOLLWAITERS; i++)
    {
      struct pollfd *fds = priv->fds[i];
      if (fds)
        {
          fds->revents |= POLLIN;
          iinfo("Report events: %02x\n", fds->revents);
          nxsem_post(fds->sem);
        }
    }
#endif
}
Exemplo n.º 14
0
static int smps_open(FAR struct file *filep)
{
  FAR struct inode      *inode = filep->f_inode;
  FAR struct smps_dev_s *dev   = inode->i_private;
  uint8_t                tmp;
  int                    ret;

  /* If the port is the middle of closing, wait until the close is finished */

  ret = nxsem_wait(&dev->closesem);
  if (ret >= 0)
    {
      /* Increment the count of references to the device.  If this the first
       * time that the driver has been opened for this device, then initialize
       * the device.
       */

      tmp = dev->ocount + 1;
      if (tmp == 0)
        {
          /* More than 255 opens; uint8_t overflows to zero */

          ret = -EMFILE;
        }
      else
        {
          /* Check if this is the first time that the driver has been opened. */

          if (tmp == 1)
            {
              /* Yes.. perform one time hardware initialization. */

              irqstate_t flags = enter_critical_section();
              ret = dev->ops->setup(dev);
              if (ret == OK)
                {
                  /* Save the new open count on success */

                  dev->ocount = tmp;
                }

              leave_critical_section(flags);
            }
        }

      nxsem_post(&dev->closesem);
    }

  return OK;
}
Exemplo n.º 15
0
static void arp_send_terminate(FAR struct arp_send_s *state, int result)
{
  /* Don't allow any further call backs. */

   state->snd_sent         = true;
   state->snd_result       = (int16_t)result;
   state->snd_cb->flags    = 0;
   state->snd_cb->priv     = NULL;
   state->snd_cb->event    = NULL;

   /* Wake up the waiting thread */

   nxsem_post(&state->snd_sem);
}
Exemplo n.º 16
0
static int mtdconfig_poll(FAR struct file *filep, FAR struct pollfd *fds,
                          bool setup)
{
  if (setup)
    {
      fds->revents |= (fds->events & (POLLIN | POLLOUT));
      if (fds->revents != 0)
        {
          nxsem_post(fds->sem);
        }
    }

  return OK;
}
Exemplo n.º 17
0
static int smps_close(FAR struct file *filep)
{
  FAR struct inode     *inode  = filep->f_inode;
  FAR struct smps_dev_s *dev   = inode->i_private;
  irqstate_t            flags;
  int                   ret;

  ret = nxsem_wait(&dev->closesem);
  if (ret >= 0)
    {
      /* Decrement the references to the driver.  If the reference count will
       * decrement to 0, then uninitialize the driver.
       */

      if (dev->ocount > 1)
        {
          dev->ocount--;
          nxsem_post(&dev->closesem);
        }
      else
        {
          /* There are no more references to the port */

          dev->ocount = 0;

          /* Free the IRQ and disable the SMPS device */

          flags = enter_critical_section();       /* Disable interrupts */
          dev->ops->shutdown(dev);               /* Disable the SMPS */
          leave_critical_section(flags);

          nxsem_post(&dev->closesem);
        }
    }

  return ret;
}
Exemplo n.º 18
0
static int ft80x_open(FAR struct file *filep)
{
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
  FAR struct inode *inode;
  FAR struct ft80x_dev_s *priv;
  uint8_t tmp;
  int ret;

  DEBUGASSERT(filep != NULL);
  inode = filep->f_inode;
  DEBUGASSERT(inode != NULL && inode->i_private != NULL);
  priv  = inode->i_private;

  lcdinfo("crefs: %d\n", priv->crefs);

  /* Get exclusive access to the device structures */

  ret = nxsem_wait(&priv->exclsem);
  if (ret < 0)
    {
      goto errout;
    }

  /* Increment the count of references to the device */

  tmp = priv->crefs + 1;
  if (tmp == 0)
    {
      /* More than 255 opens; uint8_t overflows to zero */

      ret = -EMFILE;
      goto errout_with_sem;
    }

  /* Save the new open count */

  priv->crefs = tmp;
  ret = OK;

errout_with_sem:
  nxsem_post(&priv->exclsem);

errout:
  return ret;
#else
  return OK;
#endif
}
Exemplo n.º 19
0
static FAR char *unique_chardev(void)
{
  struct stat statbuf;
  char devbuf[16];
  uint32_t devno;
  int ret;

  /* Loop until we get a unique device name */

  for (; ; )
    {
      /* Get the semaphore protecting the path number */

      do
        {
          ret = nxsem_wait(&g_devno_sem);

          /* The only case that an error should occur here is if the wait
           * was awakened by a signal.
           */

          DEBUGASSERT(ret == OK || ret == -EINTR);
        }
      while (ret == -EINTR);

      /* Get the next device number and release the semaphore */

      devno = ++g_devno;
      nxsem_post(&g_devno_sem);

      /* Construct the full device number */

      devno &= 0xffffff;
      snprintf(devbuf, 16, "/dev/tmp%06lx", (unsigned long)devno);

      /* Make sure that file name is not in use */

      ret = stat(devbuf, &statbuf);
      if (ret < 0)
        {
          DEBUGASSERT(errno == ENOENT);
          return strdup(devbuf);
        }

      /* It is in use, try again */
    }
}
Exemplo n.º 20
0
Arquivo: pwm.c Projeto: dagar/NuttX
static int pwm_close(FAR struct file *filep)
{
  FAR struct inode           *inode = filep->f_inode;
  FAR struct pwm_upperhalf_s *upper = inode->i_private;
  int                         ret;

  pwminfo("crefs: %d\n", upper->crefs);

  /* Get exclusive access to the device structures */

  ret = nxsem_wait(&upper->exclsem);
  if (ret < 0)
    {
      goto errout;
    }

  /* Decrement the references to the driver.  If the reference count will
   * decrement to 0, then uninitialize the driver.
   */

  if (upper->crefs > 1)
    {
      upper->crefs--;
    }
  else
    {
      FAR struct pwm_lowerhalf_s *lower = upper->dev;

      /* There are no more references to the port */

      upper->crefs = 0;

      /* Disable the PWM device */

      DEBUGASSERT(lower->ops->shutdown != NULL);
      pwminfo("calling shutdown: %d\n");

      lower->ops->shutdown(lower);
    }

  ret = OK;
  nxsem_post(&upper->exclsem);

errout:
  return ret;
}
Exemplo n.º 21
0
static ssize_t ft80x_write(FAR struct file *filep, FAR const char *buffer,
                           size_t len)
{
  FAR struct inode *inode;
  FAR struct ft80x_dev_s *priv;
  int ret;

  lcdinfo("buffer: %p len %lu\n", buffer, (unsigned long)len);
  DEBUGASSERT(buffer != NULL && ((uintptr_t)buffer & 3) == 0 &&
              len > 0 && (len & 3) == 0 && len <= FT80X_RAM_DL_SIZE);

  DEBUGASSERT(filep != NULL);
  inode = filep->f_inode;
  DEBUGASSERT(inode != NULL && inode->i_private != NULL);
  priv  = inode->i_private;

  if (buffer == NULL || ((uintptr_t)buffer & 3) != 0 ||
      len == 0 || (len & 3) != 0 || (len + filep->f_pos) > FT80X_RAM_DL_SIZE)
    {
       return -EINVAL;
    }

  /* Get exclusive access to the device structures */

  ret = nxsem_wait(&priv->exclsem);
  if (ret < 0)
    {
      return ret;
    }

  /* Note that there is no check if the driver was opened read-only.  That
   * would be a silly thing to do.
   */

  /* The write method is functionally equivalent to the FT80X_IOC_CREATEDL
   * IOCTL command:  It simply copies the display list in the user buffer to
   * the FT80x display list memory.
   */

  ft80x_write_memory(priv, FT80X_RAM_DL + filep->f_pos, buffer, len);
  filep->f_pos += len;

  nxsem_post(&priv->exclsem);
  return len;
}
Exemplo n.º 22
0
static int tc_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
#if 1
  iinfo("cmd: %d arg: %ld\n", cmd, arg);
  return -ENOTTY; /* None yet supported */
#else
  FAR struct inode *inode;
  FAR struct tc_dev_s *priv;
  int ret;

  iinfo("cmd: %d arg: %ld\n", cmd, arg);
  DEBUGASSERT(filep);
  inode = filep->f_inode;

  DEBUGASSERT(inode && inode->i_private);
  priv  = (FAR struct tc_dev_s *)inode->i_private;

  /* Get exclusive access to the driver data structure */

  ret = nxsem_wait(&priv->devsem);
  if (ret < 0)
    {
      /* This should only happen if the wait was canceled by an signal */

      DEBUGASSERT(ret == -EINTR || ret == -ECANCELED);
      return ret;
    }

  /* Process the IOCTL by command */

  switch (cmd)
    {
      /* ADD IOCTL COMMAND CASES HERE */

      default:
        ret = -ENOTTY;
        break;
    }

  nxsem_post(&priv->devsem);
  return ret;
#endif
}
Exemplo n.º 23
0
static int ads7843e_close(FAR struct file *filep)
{
#ifdef CONFIG_ADS7843E_REFCNT
  FAR struct inode         *inode;
  FAR struct ads7843e_dev_s *priv;
  int                       ret;

  iinfo("Closing\n");
  DEBUGASSERT(filep);
  inode = filep->f_inode;

  DEBUGASSERT(inode && inode->i_private);
  priv  = (FAR struct ads7843e_dev_s *)inode->i_private;

  /* Get exclusive access to the driver data structure */

  ret = nxsem_wait(&priv->devsem);
  if (ret < 0)
    {
      /* This should only happen if the wait was canceled by an signal */

      DEBUGASSERT(ret == -EINTR || ret == -ECANCELED);
      return ret;
    }

  /* Decrement the reference count unless it would decrement a negative
   * value.  When the count decrements to zero, there are no further
   * open references to the driver.
   */

  if (priv->crefs >= 1)
    {
      priv->crefs--;
    }

  nxsem_post(&priv->devsem);
#endif
  iinfo("Closing\n");
  return OK;
}
Exemplo n.º 24
0
static void hrt_queue_refresh(void)
{
  int elapsed;
  dq_entry_t *pent;
  struct hrt_s *tmp;
  irqstate_t flags;

  flags = spin_lock_irqsave();
  elapsed = (uint64_t)getreg32(rMT20CNT) * (1000 * 1000) * 10 / XT1OSC_CLK;

  for (pent = hrt_timer_queue.head; pent; pent = dq_next(pent))
    {
      tmp = container_of(pent, struct hrt_s, ent);
      tmp->usec -= elapsed;
    }

cont:
  /* serch for expired */

  for (pent = hrt_timer_queue.head; pent; pent = dq_next(pent))
    {
      tmp = container_of(pent, struct hrt_s, ent);
      if (tmp->usec <= 0)
        {
          dq_rem(pent, &hrt_timer_queue);
          spin_unlock_irqrestore(flags);
          nxsem_post(&tmp->sem);
          flags = spin_lock_irqsave();
          goto cont;
        }
      else
        {
          break;
        }
    }

  spin_unlock_irqrestore(flags);
}
Exemplo n.º 25
0
struct bcmf_frame_s *bcmf_sdpcm_get_rx_frame(FAR struct bcmf_dev_s *priv)
{
  dq_entry_t *entry;
  struct bcmf_sdio_frame *sframe;
  FAR struct bcmf_sdio_dev_s *sbus = (FAR struct bcmf_sdio_dev_s *)priv->bus;

  if (nxsem_wait(&sbus->queue_mutex) < 0)
    {
      PANIC();
    }

  entry = bcmf_dqueue_pop_tail(&sbus->rx_queue);

  nxsem_post(&sbus->queue_mutex);

  if (entry == NULL)
    {
      return NULL;
    }

  sframe = container_of(entry, struct bcmf_sdio_frame, list_entry);
  return &sframe->header;
}
Exemplo n.º 26
0
void icmpv6_notify(net_ipv6addr_t ipaddr)
{
  FAR struct icmpv6_notify_s *curr;

  /* Find an entry with the matching IP address in the list of waiters */

  for (curr = g_icmpv6_waiters; curr; curr = curr->nt_flink)
    {
      /* Does this entry match?  If the result is okay, then we have
       * already notified this waiter and it has not yet taken the
       * entry from the list.
       */

      if (curr->nt_result != OK && net_ipv6addr_cmp(curr->nt_ipaddr, ipaddr))
        {
          /* Yes.. Signal the waiting, returning success */

          curr->nt_result = OK;
          nxsem_post(&curr->nt_sem);
          break;
        }
    }
}
Exemplo n.º 27
0
static int ft80x_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
  FAR struct inode *inode;
  FAR struct ft80x_dev_s *priv;
  int ret;

  DEBUGASSERT(filep != NULL);
  inode = filep->f_inode;
  DEBUGASSERT(inode != NULL && inode->i_private != NULL);
  priv  = inode->i_private;

  lcdinfo("cmd: %d arg: %lu\n", cmd, arg);

  /* Get exclusive access to the device structures */

  ret = nxsem_wait(&priv->exclsem);
  if (ret < 0)
    {
      return ret;
    }

  /* Handle built-in ioctl commands */

  switch (cmd)
    {
      /* FT80X_IOC_CREATEDL:
       *   Description:  Write a display list to the FT80x display list memory
       *   Description:  Write a display list to the FT80x display list memory
       *                 starting at offset zero.  This may or may not be the
       *                 entire display list.  Display lists may be created
       *                 incrementally, starting with FT80X_IOC_CREATEDL and
       *                 finishing the display list using FT80XIO_APPENDDL
       *   Argument:     A reference to a display list structure instance.
       *                 See struct ft80x_displaylist_s.
       *   Returns:      None
       */

      case FT80X_IOC_CREATEDL:

        /* Set the file position to zero and fall through to "append" the new
         * display list data at offset 0.
         */

        filep->f_pos = 0;

        /* FALLTHROUGH */

      /* FT80X_IOC_APPENDDL:
       *   Description:  Write additional display list entries to the FT80x
       *                 display list memory at the current display list offset.
       *                 This IOCTL command permits display lists to be completed
       *                 incrementally, starting with FT80X_IOC_CREATEDL and
       *                 finishing the display list using FT80XIO_APPENDDL.
       *   Argument:     A reference to a display list structure instance.  See
       *                 struct ft80x_displaylist_s.
       *   Returns:      None
       */

      case FT80X_IOC_APPENDDL:
        {
          FAR struct ft80x_displaylist_s *dl =
            (FAR struct ft80x_displaylist_s *)((uintptr_t)arg);

          if (dl == NULL || ((uintptr_t)&dl->cmd & 3) != 0 ||
              (dl->dlsize & 3) != 0 ||
              dl->dlsize + filep->f_pos > FT80X_RAM_DL_SIZE)
            {
              ret = -EINVAL;
            }
          else
            {
              /* Check if there is a display list.  It might be useful for
               * the application to issue FT80X_IOC_CREATEDL with no data in
               * order to initialize the display list, then form all of the
               * list entries with FT80X_IOC_APPENDDL.
               */

              if (dl->dlsize > 0)
                {
                  /* This IOCTL command simply copies the display list
                   * provided into the FT80x display list memory.
                   */

                  ft80x_write_memory(priv, FT80X_RAM_DL + filep->f_pos,
                                     &dl->cmd, dl->dlsize);
                  filep->f_pos += dl->dlsize;
                }

              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_GETRAMDL:
       *   Description:  Read a 32-bit value from the display list.
       *   Argument:     A reference to an instance of struct ft80x_relmem_s.
       *   Returns:      The 32-bit value read from the display list.
       */

      case FT80X_IOC_GETRAMDL:
        {
          FAR struct ft80x_relmem_s *ramdl =
            (FAR struct ft80x_relmem_s *)((uintptr_t)arg);

          if (ramdl == NULL || ((uintptr_t)ramdl->offset & 3) != 0 ||
              ramdl->offset >= FT80X_RAM_DL_SIZE)
            {
              ret = -EINVAL;
            }
          else
            {
              ft80x_read_memory(priv, FT80X_RAM_DL + ramdl->offset,
                                ramdl->value, ramdl->nbytes);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_PUTRAMG
       *   Description:  Write byte data to FT80x graphics memory (RAM_G)
       *   Argument:     A reference to an instance of struct ft80x_relmem_s.
       *   Returns:      None.
       */

      case FT80X_IOC_PUTRAMG:
        {
          FAR struct ft80x_relmem_s *ramg =
            (FAR struct ft80x_relmem_s *)((uintptr_t)arg);

          if (ramg == NULL ||
             (ramg->offset + ramg->nbytes) >= FT80X_RAM_G_SIZE)
            {
              ret = -EINVAL;
            }
          else
            {
              ft80x_write_memory(priv, FT80X_RAM_G + ramg->offset,
                                 ramg->value, ramg->nbytes);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_PUTRAMCMD
       *   Description:  Write 32-bit aligned data to FT80x FIFO (RAM_CMD)
       *   Argument:     A reference to an instance of struct ft80x_relmem_s below.
       *   Returns:      None.
       */

      case FT80X_IOC_PUTRAMCMD:
        {
          FAR struct ft80x_relmem_s *ramcmd =
            (FAR struct ft80x_relmem_s *)((uintptr_t)arg);

          if (ramcmd == NULL || ((uintptr_t)ramcmd->offset & 3) != 0 /* ||
              ramcmd->offset >= FT80X_CMDFIFO_SIZE */ )
            {
              ret = -EINVAL;
            }
          else
            {
              ft80x_write_memory(priv, FT80X_RAM_CMD + ramcmd->offset,
                                ramcmd->value, ramcmd->nbytes);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_GETREG8:
       *   Description:  Read an 8-bit register value from the FT80x.
       *   Argument:     A reference to an instance of struct ft80x_register_s.
       *   Returns:      The 8-bit value read from the register.
       */

      case FT80X_IOC_GETREG8:
        {
          FAR struct ft80x_register_s *reg =
            (FAR struct ft80x_register_s *)((uintptr_t)arg);

          if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0)
            {
              ret = -EINVAL;
            }
          else
            {
              reg->value.u8 = ft80x_read_byte(priv, reg->addr);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_GETREG16:
       *   Description:  Read a 16-bit register value from the FT80x.
       *   Argument:     A reference to an instance of struct ft80x_register_s.
       *   Returns:      The 16-bit value read from the register.
       */

      case FT80X_IOC_GETREG16:
        {
          FAR struct ft80x_register_s *reg =
            (FAR struct ft80x_register_s *)((uintptr_t)arg);

          if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0)
            {
              ret = -EINVAL;
            }
          else
            {
              reg->value.u16 = ft80x_read_hword(priv, reg->addr);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_GETREG32:
       *   Description:  Read a 32-bit register value from the FT80x.
       *   Argument:     A reference to an instance of struct ft80x_register_s.
       *   Returns:      The 32-bit value read from the register.
       */

      case FT80X_IOC_GETREG32:
        {
          FAR struct ft80x_register_s *reg =
            (FAR struct ft80x_register_s *)((uintptr_t)arg);

          if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0)
            {
              ret = -EINVAL;
            }
          else
            {
              reg->value.u32 = ft80x_read_word(priv, reg->addr);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_GETREGS:
       *   Description:  Read multiple 32-bit register values from the FT80x.
       *   Argument:     A reference to an instance of struct ft80x_registers_s.
       *   Returns:      The 32-bit values read from the consecutive registers .
       */

      case FT80X_IOC_GETREGS:
        {
          FAR struct ft80x_registers_s *regs =
            (FAR struct ft80x_registers_s *)((uintptr_t)arg);

          if (regs == NULL || ((uintptr_t)regs->addr & 3) != 0)
            {
              ret = -EINVAL;
            }
          else
            {
              ft80x_read_memory(priv, regs->addr, regs->value,
                                (size_t)regs->nregs << 2);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_PUTREG8:
       *   Description:  Write an 8-bit register value to the FT80x.
       *   Argument:     A reference to an instance of struct ft80x_register_s.
       *   Returns:      None.
       */

      case FT80X_IOC_PUTREG8:
        {
          FAR struct ft80x_register_s *reg =
            (FAR struct ft80x_register_s *)((uintptr_t)arg);

          if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0)
            {
              ret = -EINVAL;
            }
          else
            {
              ft80x_write_byte(priv, reg->addr, reg->value.u8);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_PUTREG16:
       *   Description:  Write a 16-bit  register value to the FT80x.
       *   Argument:     A reference to an instance of struct ft80x_register_s.
       *   Returns:      None.
       */

      case FT80X_IOC_PUTREG16:
        {
          FAR struct ft80x_register_s *reg =
            (FAR struct ft80x_register_s *)((uintptr_t)arg);

          if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0)
            {
              ret = -EINVAL;
            }
          else
            {
              ft80x_write_hword(priv, reg->addr, reg->value.u16);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_PUTREG32:
       *   Description:  Write a 32-bit  register value to the FT80x.
       *   Argument:     A reference to an instance of struct ft80x_register_s.
       *   Returns:      None.
       */

      case FT80X_IOC_PUTREG32:
        {
          FAR struct ft80x_register_s *reg =
            (FAR struct ft80x_register_s *)((uintptr_t)arg);

          if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0)
            {
              ret = -EINVAL;
            }
          else
            {
              ft80x_write_word(priv, reg->addr, reg->value.u32);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_PUTREGS:
       *   Description:  Write multiple 32-bit register values to the FT80x.
       *   Argument:     A reference to an instance of struct ft80x_registers_s.
       *   Returns:      None.
       */

      case FT80X_IOC_PUTREGS:
        {
          FAR struct ft80x_registers_s *regs =
            (FAR struct ft80x_registers_s *)((uintptr_t)arg);

          if (regs == NULL || ((uintptr_t)regs->addr & 3) != 0)
            {
              ret = -EINVAL;
            }
          else
            {
              ft80x_write_memory(priv, regs->addr, regs->value,
                                 (size_t)regs->nregs << 2);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_EVENTNOTIFY:
       *   Description:  Setup to receive a signal when an event occurs.
       *   Argument:     A reference to an instance of struct ft80x_notify_s.
       *   Returns:      None
       */

      case FT80X_IOC_EVENTNOTIFY:
        {
          FAR struct ft80x_notify_s *notify =
            (FAR struct ft80x_notify_s *)((uintptr_t)arg);

          if (notify == NULL || !GOOD_SIGNO(notify->signo) || notify->pid < 0 ||
              (unsigned int)notify->event >= FT80X_INT_NEVENTS)
            {
              ret = -EINVAL;
            }
          else
            {
              FAR struct ft80x_eventinfo_s *info = &priv->notify[notify->event];
              uint32_t regval;

              /* Are we enabling or disabling */

              if (notify->enable)
                {
                  /* Make sure that arguments are valid for the enable */

                  if (notify->signo == 0 || notify->pid == 0)
                    {
                      ret = -EINVAL;
                    }
                  else
                    {
                      /* Setup the new notification information */

                      info->signo  = notify->signo;
                      info->pid    = notify->pid;
                      info->enable = true;

                      /* Enable interrupts associated with the event */

                      regval  = ft80x_read_word(priv, FT80X_REG_INT_MASK);
                      regval |= (1 << notify->event);
                      ft80x_write_word(priv, FT80X_REG_INT_MASK, regval);
                      ret = OK;
                    }
                }
              else
                {
                  /* Disable the notification */

                  info->signo  = 0;
                  info->pid    = 0;
                  info->enable = false;

                  /* Disable interrupts associated with the event */

                  regval  = ft80x_read_word(priv, FT80X_REG_INT_MASK);
                  regval &= ~(1 << notify->event);
                  ft80x_write_word(priv, FT80X_REG_INT_MASK, regval);
                  ret = OK;
                }
            }
        }
        break;

       /* FT80X_IOC_FADE:
        *   Description:  Change the backlight intensity with a controllable
        *                 fade.
        *   Argument:     A reference to an instance of struct ft80x_fade_s.
        *   Returns:      None.
        */

       case FT80X_IOC_FADE:
        {
          FAR const struct ft80x_fade_s *fade =
            (FAR const struct ft80x_fade_s *)((uintptr_t)arg);

          if (fade == NULL || fade->duty > 100 ||
              fade->delay < MIN_FADE_DELAY || fade->delay > MAX_FADE_DELAY)
            {
              ret = -EINVAL;
            }
          else
            {
              ret = ft80x_fade(priv, fade);
            }
        }
        break;

       /* FT80X_IOC_AUDIO:
        *   Description:  Enable/disable an external audio amplifer.
        *   Argument:     0=disable; 1=enable.
        *   Returns:      None.
        */

       case FT80X_IOC_AUDIO:
        {
#if defined(CONFIG_LCD_FT80X_AUDIO_MCUSHUTDOWN)
          /* Amplifier is controlled by an MCU GPIO pin */

          DEBUGASSERT(priv->lower->attach != NULL && priv->lower->audio != NULL);
          DEBUGASSERT(arg == 0 || arg == 1);

          priv->lower->audio(priv->lower, (arg != 0));
          ret = OK;

#elif defined(CONFIG_LCD_FT80X_AUDIO_GPIOSHUTDOWN)
          /* Amplifier is controlled by an FT80x GPIO pin */

          uint8_t regval8;

          DEBUGASSERT(arg == 0 || arg == 1);

          regval8  = ft80x_read_byte(priv, FT80X_REG_GPIO);

          /* Active low logic assumed */

          if (arg == 0)
            {
              regval8 |= (1 << CONFIG_LCD_FT80X_AUDIO_GPIO);
            }
          else
            {
              regval8 &= ~(1 << CONFIG_LCD_FT80X_AUDIO_GPIO);
            }

          ft80x_write_byte(priv, FT80X_REG_GPIO, regval8);
          ret = OK;

#else
          /* Amplifier is not controllable. */

          DEBUGASSERT(arg == 0 || arg == 1);
          return OK;
#endif
        }
        break;

      /* Unrecognized IOCTL command */

      default:
        lcderr("ERROR: Unrecognized cmd: %d arg: %ld\n", cmd, arg);
        ret = -ENOTTY;
        break;
    }

  nxsem_post(&priv->exclsem);
  return ret;
}
Exemplo n.º 28
0
int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
{
  int ret;
  uint16_t len, checksum;
  struct bcmf_sdpcm_header *header;
  struct bcmf_sdio_frame *sframe;
  FAR struct bcmf_sdio_dev_s *sbus = (FAR struct bcmf_sdio_dev_s *)priv->bus;

  /* Request free frame buffer */

  sframe = bcmf_sdio_allocate_frame(priv, false, false);

  if (sframe == NULL)
    {
      wlinfo("fail alloc\n");
      return -EAGAIN;
    }

  header = (struct bcmf_sdpcm_header *)sframe->data;

  /* Read header */

  ret = bcmf_transfer_bytes(sbus, false, 2, 0, (uint8_t *)header, 4);
  if (ret != OK)
    {
      wlinfo("failread size\n");
      ret = -EIO;
      goto exit_abort;
    }

  len = header->size;
  checksum = header->checksum;

  /* All zero means no more to read */

  if (!(len | checksum))
    {
      ret = -ENODATA;
      goto exit_free_frame;
    }

  if (((~len & 0xffff) ^ checksum) || len < sizeof(struct bcmf_sdpcm_header))
    {
      wlerr("Invalid header checksum or len %x %x\n", len, checksum);
      ret = -EINVAL;
      goto exit_abort;
    }

  if (len > sframe->header.len)
    {
      wlerr("Frame is too large, cancel %d %d\n", len, sframe->header.len);
      ret = -ENOMEM;
      goto exit_abort;
    }

  /* Read remaining frame data */

  ret = bcmf_transfer_bytes(sbus, false, 2, 0, (uint8_t *)header + 4, len - 4);
  if (ret != OK)
    {
      ret = -EIO;
      goto exit_abort;
    }

  // wlinfo("Receive frame %p %d\n", sframe, len);
  // bcmf_hexdump((uint8_t *)header, header->size, (unsigned int)header);

  /* Process and validate header */

  ret = bcmf_sdpcm_process_header(sbus, header);
  if (ret != OK)
    {
      wlerr("Error while processing header %d\n", ret);
      ret = -EINVAL;
      goto exit_free_frame;
    }

  /* Update frame structure */

  sframe->header.len = header->size;
  sframe->header.data += header->data_offset;

  /* Process received frame content */

  switch (header->channel & 0x0f)
    {
      case SDPCM_CONTROL_CHANNEL:
        ret = bcmf_cdc_process_control_frame(priv, &sframe->header);
        goto exit_free_frame;

      case SDPCM_EVENT_CHANNEL:
        if (header->data_offset == header->size)
          {
            /* Empty event, ignore */

            ret = OK;
          }
        else
          {
            ret = bcmf_bdc_process_event_frame(priv, &sframe->header);
          }
        goto exit_free_frame;

      case SDPCM_DATA_CHANNEL:

        /* Queue frame and notify network layer frame is available */

        if (nxsem_wait(&sbus->queue_mutex) < 0)
          {
            PANIC();
          }

        bcmf_dqueue_push(&sbus->rx_queue, &sframe->list_entry);
        nxsem_post(&sbus->queue_mutex);

        bcmf_netdev_notify_rx(priv);

        /* Upper layer have to free all received frames */

        ret = OK;
        break;

      default:
        wlerr("Got unexpected message type %d\n", header->channel);
        ret = -EINVAL;
        goto exit_free_frame;
    }

  return ret;

exit_abort:
  bcmf_sdpcm_rxfail(sbus, false);
exit_free_frame:
  bcmf_sdio_free_frame(priv, sframe);
  return ret;
}
Exemplo n.º 29
0
int bcmf_sdpcm_sendframe(FAR struct bcmf_dev_s *priv)
{
  int ret;
  bool is_txframe;
  dq_entry_t *entry;
  struct bcmf_sdio_frame *sframe;
  struct bcmf_sdpcm_header *header;
  FAR struct bcmf_sdio_dev_s *sbus = (FAR struct bcmf_sdio_dev_s *)priv->bus;

  if (sbus->tx_queue.tail == NULL)
    {
      /* No more frames to send */

      return -ENODATA;
    }

  if (sbus->tx_seq == sbus->max_seq)
    {
      // TODO handle this case
      wlerr("No credit to send frame\n");
      return -EAGAIN;
    }


  if (nxsem_wait(&sbus->queue_mutex) < 0)
    {
      PANIC();
    }

  entry = sbus->tx_queue.tail;
  sframe = container_of(entry, struct bcmf_sdio_frame, list_entry);
  header = (struct bcmf_sdpcm_header *)sframe->header.base;

  /* Set frame sequence id */

  header->sequence = sbus->tx_seq++;

  // wlinfo("Send frame %p\n", sframe);
  // bcmf_hexdump(sframe->header.base, sframe->header.len,
  //              (unsigned long)sframe->header.base);

  ret = bcmf_transfer_bytes(sbus, true, 2, 0, sframe->header.base,
                            sframe->header.len);
  if (ret != OK)
    {
      wlinfo("fail send frame %d\n", ret);
      ret = -EIO;
      goto exit_abort;
      // TODO handle retry count and remove frame from queue + abort TX
    }

  /* Frame sent, remove it from queue */

  bcmf_dqueue_pop_tail(&sbus->tx_queue);
  nxsem_post(&sbus->queue_mutex);
  is_txframe = sframe->tx;

  /* Free frame buffer */

  bcmf_sdio_free_frame(priv, sframe);

  if (is_txframe)
    {
      /* Notify upper layer at least one TX buffer is available */

      bcmf_netdev_notify_tx_done(priv);
    }

  return OK;

exit_abort:
  // bcmf_sdpcm_txfail(sbus, false);
  nxsem_post(&sbus->queue_mutex);
  return ret;
}
Exemplo n.º 30
0
static int oneshot_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
  FAR struct inode *inode;
  FAR struct oneshot_dev_s *priv;
  int ret;

  tmrinfo("cmd=%d arg=%08lx\n", cmd, (unsigned long)arg);

  DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
  inode = filep->f_inode;
  priv  = (FAR struct oneshot_dev_s *)inode->i_private;
  DEBUGASSERT(priv != NULL);

  /* Get exclusive access to the device structures */

  ret = nxsem_wait(&priv->od_exclsem);
  if (ret < 0)
    {
      return ret;
    }

  /* Handle oneshot timer ioctl commands */

  switch (cmd)
    {
      /* OSIOC_MAXDELAY - Return the maximum delay that can be supported
       *                  by this timer.
       *                  Argument: A referenct to a struct timespec in
       *                  which the maximum time will be returned.
       */

      case OSIOC_MAXDELAY:
        {
          FAR struct timespec *ts = (FAR struct timespec *)((uintptr_t)arg);
          DEBUGASSERT(ts != NULL);

          ret = ONESHOT_MAX_DELAY(priv->od_lower, ts);
        }
        break;

      /* OSIOC_START - Start the oneshot timer
       *               Argument: A reference to struct oneshot_start_s
       */

      case OSIOC_START:
        {
          FAR struct oneshot_start_s *start;
          pid_t pid;

          start = (FAR struct oneshot_start_s *)((uintptr_t)arg);
          DEBUGASSERT(start != NULL);

          /* Save signalling information */

          priv->od_signo = start->signo;
          priv->od_arg   = start->arg;

          pid = start->pid;
          if (pid == 0)
            {
              pid = getpid();
            }

          priv->od_pid = pid;

          /* Start the oneshot timer */

          ret = ONESHOT_START(priv->od_lower, oneshot_callback, priv,
                              &start->ts);
        }
        break;

      /* OSIOC_CANCEL - Stop the timer
       *                Argument: A reference to a struct timespec in
       *                which the time remaining will be returned.
       */

      case OSIOC_CANCEL:
        {
          FAR struct timespec *ts = (FAR struct timespec *)((uintptr_t)arg);

          /* Cancel the oneshot timer */

          ret = ONESHOT_CANCEL(priv->od_lower, ts);
        }
        break;

      /* OSIOC_CURRENT - Get the current time
       *                 Argument: A reference to a struct timespec in
       *                 which the current time will be returned.
       */

      case OSIOC_CURRENT:
        {
          FAR struct timespec *ts = (FAR struct timespec *)((uintptr_t)arg);

          /* Get the current time */

          ret = ONESHOT_CURRENT(priv->od_lower, ts);
        }
        break;

      default:
        {
          tmrerr("ERROR: Unrecognized cmd: %d arg: %ld\n", cmd, arg);
          ret = -ENOTTY;
        }
        break;
    }

  nxsem_post(&priv->od_exclsem);
  return ret;
}