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