Exemple #1
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;
}
Exemple #2
0
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;
}
Exemple #3
0
void tiva_adc_lock(FAR struct tiva_adc_s *priv, int sse)
{
  struct tiva_adc_sse_s *s = g_sses[SSE_IDX(priv->devno, sse)];
  int ret;
#ifdef CONFIG_DEBUG_ANALOG
  uint16_t loop_count = 0;
#endif

  ainfo("Locking...\n");

  do
    {
      ret = nxsem_wait(&s->exclsem);

      /* This should only fail if the wait was canceled by an signal (and the
       * worker thread will receive a lot of signals).
       */

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

#ifdef CONFIG_DEBUG_ANALOG
      if (loop_count % 1000)
        {
          ainfo("loop=%d\n");
        }

      ++loop_count;
#endif
    }
  while (ret == -EINTR);
}
Exemple #4
0
static inline int syslog_dev_takesem(void)
{
  pid_t me = getpid();
  int ret;

  /* Does this thread already hold the semaphore?  That could happen if
   * we were called recursively, i.e., if the logic kicked off by
   * file_write() where to generate more debug output.  Return an
   * error in that case.
   */

  if (g_syslog_dev.sl_holder == me)
    {
      /* Return an error (instead of deadlocking) */

      return -EWOULDBLOCK;
    }

  /* Either the semaphore is available or is currently held by another
   * thread.  Wait for it to become available.
   */

  ret = nxsem_wait(&g_syslog_dev.sl_sem);
  if (ret < 0)
    {
      return ret;
    }

  /* We hold the semaphore.  We can safely mark ourself as the holder
   * of the semaphore.
   */

  g_syslog_dev.sl_holder = me;
  return OK;
}
Exemple #5
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
}
Exemple #6
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;
}
Exemple #7
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
}
Exemple #8
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;
}
Exemple #9
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;
}
Exemple #10
0
static inline int btn_takesem(sem_t *sem)
{
  int ret;

  /* Take a count from the semaphore, possibly waiting */

  ret = nxsem_wait(sem);

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

  DEBUGASSERT(ret == OK || ret == -EINTR);
  return ret;
}
Exemple #11
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
}
Exemple #12
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 */
    }
}
Exemple #13
0
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;
}
Exemple #14
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;
}
Exemple #15
0
static void _sdc_semtake(FAR sem_t *sem)
{
  int ret;

  do
    {
      /* Take the semaphore (perhaps waiting) */

      ret = nxsem_wait(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);
}
Exemple #16
0
static void pty_semtake(FAR struct pty_devpair_s *devpair)
{
  int ret;

  do
    {
      /* Take the semaphore (perhaps waiting) */

      ret = nxsem_wait(&devpair->pp_exclsem);

      /* 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);
}
Exemple #17
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
}
Exemple #18
0
static int  mtdconfig_open(FAR struct file *filep)
{
  FAR struct inode *inode = filep->f_inode;
  FAR struct mtdconfig_struct_s *dev = inode->i_private;
  int ret;

  /* Get exclusive access to the device */

  ret = nxsem_wait(&dev->exclsem);
  if (ret < 0)
    {
      ferr("ERROR: nxsem_wait failed: %d\n", ret);
      DEBUGASSERT(ret == -EINTR || ret == -ECANCELED);
      goto errout;
    }

  dev->readoff = 0;

errout:
  return ret;
}
Exemple #19
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;
}
Exemple #20
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;
}
Exemple #21
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;
}
Exemple #22
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;
}
Exemple #23
0
static int tc_poll(FAR struct file *filep, FAR struct pollfd *fds,
                        bool setup)
{
  FAR struct inode         *inode;
  FAR struct tc_dev_s *priv;
  int                       ret;
  int                       i;

  iinfo("setup: %d\n", (int)setup);
  DEBUGASSERT(filep && fds);
  inode = filep->f_inode;

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

  /* Are we setting up the poll?  Or tearing it down? */

  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;
    }

  if (setup)
    {
      /* Ignore waits that do not include POLLIN */

      if ((fds->events & POLLIN) == 0)
        {
          ierr("ERROR: Missing POLLIN: revents: %08x\n", fds->revents);
          ret = -EDEADLK;
          goto errout;
        }

      /* This is a request to set up the poll.  Find an available
       * slot for the poll structure reference
       */

      for (i = 0; i < CONFIG_TOUCHSCREEN_NPOLLWAITERS; i++)
        {
          /* Find an available slot */

          if (!priv->fds[i])
            {
              /* Bind the poll structure and this slot */

              priv->fds[i] = fds;
              fds->priv    = &priv->fds[i];
              break;
            }
        }

      if (i >= CONFIG_TOUCHSCREEN_NPOLLWAITERS)
        {
          ierr("ERROR: No availabled slot found: %d\n", i);
          fds->priv    = NULL;
          ret          = -EBUSY;
          goto errout;
        }

      /* Should we immediately notify on any of the requested events? */

      if (priv->penchange)
        {
          tc_notify(priv);
        }
    }
  else if (fds->priv)
    {
      /* This is a request to tear down the poll. */

      struct pollfd **slot = (struct pollfd **)fds->priv;
      DEBUGASSERT(slot != NULL);

      /* Remove all memory of the poll setup */

      *slot                = NULL;
      fds->priv            = NULL;
    }

errout:
  nxsem_post(&priv->devsem);
  return ret;
}
Exemple #24
0
static int pty_open(FAR struct file *filep)
{
  FAR struct inode *inode;
  FAR struct pty_dev_s *dev;
  FAR struct pty_devpair_s *devpair;
  int ret;

  DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
  inode   = filep->f_inode;
  dev     = inode->i_private;
  DEBUGASSERT(dev != NULL && dev->pd_devpair != NULL);
  devpair = dev->pd_devpair;

  /* Wait if this is an attempt to open the slave device and the slave
   * device is locked.
   */

  if (!dev->pd_master)
    {
      /* Slave... Check if the slave driver is locked.  We need to lock the
       * scheduler while we are running to prevent asyncrhonous modification
       * of pp_locked by pty_ioctl().
       */

      sched_lock();
      while (devpair->pp_locked)
        {
          /* Wait until unlocked.  We will also most certainly suspend here. */

          (void)nxsem_wait(&devpair->pp_slavesem);

          /* Get exclusive access to the device structure.  This might also
           * cause suspension.
           */

          pty_semtake(devpair);

          /* Check again in case something happened asynchronously while we
           * were suspended.
           */

          if (devpair->pp_locked)
           {
             /* This cannot suspend because we have the scheduler locked.
              * So pp_locked cannot change asyncrhonously between this test
              * and the redundant test at the top of the loop.
              */

             pty_semgive(devpair);
           }
        }

      sched_unlock();
    }
  else
    {
       /* Master ... Get exclusive access to the device structure */

       pty_semtake(devpair);
    }

#ifndef CONFIG_PSEUDOTERM_SUSV1
  /* If one side of the driver has been unlinked, then refuse further
   * opens.
   *
   * NOTE: We ignore this case in the SUSv1 case.  In the SUSv1 case, the
   * master side is always unlinked.
   */

  if (devpair->pp_unlinked)
    {
      ret = -EIDRM;
    }
  else
#endif
    {
      /* Increment the count of open references on the driver */

      devpair->pp_nopen++;
      DEBUGASSERT(devpair->pp_nopen > 0);

      ret = OK;
    }

  pty_semgive(devpair);
  return ret;
}
Exemple #25
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;
}
Exemple #26
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;
}
Exemple #27
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;
}
Exemple #28
0
static ssize_t tc_read(FAR struct file *filep, FAR char *buffer, size_t len)
{
  FAR struct inode          *inode;
  FAR struct tc_dev_s  *priv;
  FAR struct touch_sample_s *report;
  struct tc_sample_s    sample;
  int                        ret;

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

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

  /* Verify that the caller has provided a buffer large enough to receive
   * the touch data.
   */

  if (len < SIZEOF_TOUCH_SAMPLE_S(1))
    {
      /* We could provide logic to break up a touch report into segments and
       * handle smaller reads... but why?
       */

      return -ENOSYS;
    }

  /* 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;
    }

  /* Try to read sample data. */

  ret = tc_sample(priv, &sample);
  if (ret < 0)
    {
      /* Sample data is not available now.  We would ave to wait to get
       * receive sample data.  If the user has specified the O_NONBLOCK
       * option, then just return an error.
       */

      if (filep->f_oflags & O_NONBLOCK)
        {
          ret = -EAGAIN;
          goto errout;
       }

      /* Wait for sample data */

      ret = tc_waitsample(priv, &sample);
      if (ret < 0)
        {
          /* We might have been awakened by a signal */

          goto errout;
        }
    }

  /* In any event, we now have sampled touchscreen data that we can report
   * to the caller.
   */

  report = (FAR struct touch_sample_s *)buffer;
  memset(report, 0, SIZEOF_TOUCH_SAMPLE_S(1));
  report->npoints            = 1;
  report->point[0].id        = sample.id;
  report->point[0].x         = sample.x;
  report->point[0].y         = sample.y;

  /* Report the appropriate flags */

  if (sample.contact == CONTACT_UP)
    {
       /* Pen is now up.  Is the positional data valid?  This is important to
        * know because the release will be sent to the window based on its
       * last positional data.
       */

      if (sample.valid)
        {
          report->point[0].flags  = TOUCH_UP | TOUCH_ID_VALID |
                                    TOUCH_POS_VALID | TOUCH_PRESSURE_VALID;
        }
      else
        {
          report->point[0].flags  = TOUCH_UP | TOUCH_ID_VALID;
        }
    }
  else
    {
      if (sample.contact == CONTACT_DOWN)
        {
          /* First contact */

          report->point[0].flags  = TOUCH_DOWN | TOUCH_ID_VALID | TOUCH_POS_VALID;
        }
      else /* if (sample->contact == CONTACT_MOVE) */
        {
          /* Movement of the same contact */

          report->point[0].flags  = TOUCH_MOVE | TOUCH_ID_VALID | TOUCH_POS_VALID;
        }
    }

  ret = SIZEOF_TOUCH_SAMPLE_S(1);

errout:
  nxsem_post(&priv->devsem);
  return ret;
}
Exemple #29
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;
}
Exemple #30
0
static void ft80x_interrupt_work(FAR void *arg)
{
  FAR struct ft80x_dev_s *priv = (FAR struct ft80x_dev_s *)arg;
  uint32_t intflags;
  uint32_t regval;
  int ret;

  DEBUGASSERT(priv != NULL);

  /* Get exclusive access to the device structures */

  do
    {
      ret = nxsem_wait(&priv->exclsem);
      DEBUGASSERT(ret == OK || ret == -EINTR);
    }
  while (ret < 0);

  /* Get the set of pending interrupts.  Note that simply reading this
   * register is sufficient to clear all pending interrupts.
   */

  intflags = ft80x_read_word(priv, FT80X_REG_INT_FLAGS);

  /* And process each pending interrupt.
   *
   * REVISIT:  No interrupt sources are ever enabled in the current
   * implementation.
   */

   if ((intflags & FT80X_INT_SWAP) != 0)
     {
       /* Display swap occurred */

       lcdinfo("Display swap occurred\n");
       ft80x_notify(priv, FT80X_NOTIFY_SWAP, 0);
     }

   if ((intflags & FT80X_INT_TOUCH) != 0)
     {
       /* Touch-screen touch detected */

       lcdinfo("Touch-screen touch detected\n");
       ft80x_notify(priv, FT80X_NOTIFY_TOUCH, 0);
     }

   if ((intflags & FT80X_INT_TAG) != 0)
     {
       /* Touch-screen tag value change */

       lcdinfo("Touch-screen tag value change\n");
#ifdef CONFIG_LCD_FT800
       regval = ft80x_read_word(priv, FT80X_REG_TOUCH_TAG);
#else
       regval = ft80x_read_word(priv, FT80X_REG_CTOUCH_TAG);
#endif
       ft80x_notify(priv, FT80X_NOTIFY_TAG, (int)(regval & TOUCH_TAG_MASK));
     }

   if ((intflags & FT80X_INT_SOUND) != 0)
     {
       /*  Sound effect ended */

       lcdinfo(" Sound effect ended\n");
       ft80x_notify(priv, FT80X_NOTIFY_SOUND, 0);
     }

   if ((intflags & FT80X_INT_PLAYBACK) != 0)
     {
       /* Audio playback ended */

       lcdinfo("Audio playback ended\n");
       ft80x_notify(priv, FT80X_NOTIFY_PLAYBACK, 0);
     }

   if ((intflags & FT80X_INT_CMDEMPTY) != 0)
     {
       /* Command FIFO empty */

       lcdinfo("Command FIFO empty\n");
       ft80x_notify(priv, FT80X_NOTIFY_CMDEMPTY, 0);
     }

   if ((intflags & FT80X_INT_CMDFLAG) != 0)
     {
       /* Command FIFO flag */

       lcdinfo("Command FIFO flag\n");
       ft80x_notify(priv, FT80X_NOTIFY_CMDFLAG, 0);
     }

   if ((intflags & FT80X_INT_CONVCOMPLETE) != 0)
     {
       /* Touch-screen conversions completed */

       lcdinfo(" Touch-screen conversions completed\n");
       ft80x_notify(priv, FT80X_NOTIFY_CONVCOMPLETE, 0);
     }

  /* Re-enable interrupts */

  DEBUGASSERT(priv->lower != NULL && priv->lower->enable != NULL);
  priv->lower->enable(priv->lower, true);
  nxsem_post(&priv->exclsem);
}