int pwm_register(FAR const char *path, FAR struct pwm_lowerhalf_s *dev) { FAR struct pwm_upperhalf_s *upper; /* Allocate the upper-half data structure */ upper = (FAR struct pwm_upperhalf_s *)kmm_zalloc(sizeof(struct pwm_upperhalf_s)); if (!upper) { pwmerr("Allocation failed\n"); return -ENOMEM; } /* Initialize the PWM device structure (it was already zeroed by kmm_zalloc()) */ nxsem_init(&upper->exclsem, 0, 1); #ifdef CONFIG_PWM_PULSECOUNT nxsem_init(&upper->waitsem, 0, 0); /* The wait semaphore is used for signaling and, hence, should not have priority * inheritance enabled. */ nxsem_setprotocol(&upper->waitsem, SEM_PRIO_NONE); #endif upper->dev = dev; /* Register the PWM device */ pwminfo("Registering %s\n", path); return register_driver(path, &g_pwmops, 0666, upper); }
void up_dmainitialize(void) { int i; for (i = 0; i < DMA_CHANNEL_NUM; i++) { g_dma.phydmach[i].inprogress = 0; sq_init(&g_dma.phydmach[i].req_q); } nxsem_init(&g_dma.exclsem, 0, 1); if (irq_attach(LC823450_IRQ_DMAC, dma_interrupt, NULL) != 0) { return; } up_enable_irq(LC823450_IRQ_DMAC); /* Clock & Reset */ modifyreg32(MCLKCNTBASIC, 0, MCLKCNTBASIC_DMAC_CLKEN); modifyreg32(MRSTCNTBASIC, 0, MRSTCNTBASIC_DMAC_RSTB); /* DMAC enable */ modifyreg32(DMACCONFIG, 0, DMACCONFIG_EN); #ifdef DMA_TEST lc823450_dma_test(); #endif /* clock disable */ modifyreg32(MCLKCNTBASIC, MCLKCNTBASIC_DMAC_CLKEN, 0); }
void mm_seminitialize(FAR struct mm_heap_s *heap) { /* Initialize the MM semaphore to one (to support one-at-a-time access to * private data sets). */ (void)nxsem_init(&heap->mm_semaphore, 0, 1); heap->mm_holder = -1; heap->mm_counts_held = 0; }
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; }
GRAN_HANDLE gran_initialize(FAR void *heapstart, size_t heapsize, uint8_t log2gran, uint8_t log2align) { FAR struct gran_s *priv; uintptr_t heapend; uintptr_t alignedstart; unsigned int mask; unsigned int alignedsize; unsigned int ngranules; /* Check parameters if debug is on. Note the size of a granule is * limited to 2**31 bytes and that the size of the granule must be greater * than or equal to the alignment size. */ DEBUGASSERT(heapstart && heapsize > 0 && log2gran > 0 && log2gran < 32 && log2gran >= log2align); /* Get the aligned start of the heap */ mask = (1 << log2align) - 1; alignedstart = ((uintptr_t)heapstart + mask) & ~mask; /* Determine the number of granules */ mask = (1 << log2gran) - 1; heapend = (uintptr_t)heapstart + heapsize; alignedsize = (heapend - alignedstart) & ~mask; ngranules = alignedsize >> log2gran; /* Allocate the information structure with a granule table of the * correct size. */ priv = (FAR struct gran_s *)kmm_zalloc(SIZEOF_GRAN_S(ngranules)); if (priv) { /* Initialize non-zero elements of the granules heap info structure */ priv->log2gran = log2gran; priv->ngranules = ngranules; priv->heapstart = alignedstart; /* Initialize mutual exclusion support */ #ifndef CONFIG_GRAN_INTR nxsem_init(&priv->exclsem, 0, 1); #endif } return (GRAN_HANDLE)priv; }
int sem_init(FAR sem_t *sem, int pshared, unsigned int value) { int ret; ret = nxsem_init(sem, pshared, value); if (ret < 0) { set_errno(-ret); ret = ERROR; } return ret; }
int btn_register(FAR const char *devname, FAR const struct btn_lowerhalf_s *lower) { FAR struct btn_upperhalf_s *priv; int ret; DEBUGASSERT(devname && lower); /* Allocate a new button driver instance */ priv = (FAR struct btn_upperhalf_s *) kmm_zalloc(sizeof(struct btn_upperhalf_s)); if (!priv) { ierr("ERROR: Failed to allocate device structure\n"); return -ENOMEM; } /* Make sure that all button interrupts are disabled */ DEBUGASSERT(lower->bl_enable); lower->bl_enable(lower, 0, 0, NULL, NULL); /* Initialize the new button driver instance */ priv->bu_lower = lower; nxsem_init(&priv->bu_exclsem, 0, 1); DEBUGASSERT(lower->bl_buttons); priv->bu_sample = lower->bl_buttons(lower); /* And register the button driver */ ret = register_driver(devname, &btn_fops, 0666, priv); if (ret < 0) { ierr("ERROR: register_driver failed: %d\n", ret); goto errout_with_priv; } return OK; errout_with_priv: nxsem_destroy(&priv->bu_exclsem); kmm_free(priv); return ret; }
int smps_register(FAR const char *path, FAR struct smps_dev_s *dev, FAR void *lower) { int ret; DEBUGASSERT(path != NULL && dev != NULL && lower != NULL); DEBUGASSERT(dev->ops != NULL); /* For safety reason, when some necessary low-level logic is not provided, * system should fail before low-level hardware initialization, so: * - all ops are checked here, before character driver registration * - all ops must be provided, even if not used */ DEBUGASSERT(dev->ops->setup != NULL); DEBUGASSERT(dev->ops->shutdown != NULL); DEBUGASSERT(dev->ops->stop != NULL); DEBUGASSERT(dev->ops->start != NULL); DEBUGASSERT(dev->ops->params_set != NULL); DEBUGASSERT(dev->ops->mode_set != NULL); DEBUGASSERT(dev->ops->limits_set != NULL); DEBUGASSERT(dev->ops->fault_set != NULL); DEBUGASSERT(dev->ops->state_get != NULL); DEBUGASSERT(dev->ops->fault_get != NULL); DEBUGASSERT(dev->ops->fault_clean != NULL); DEBUGASSERT(dev->ops->ioctl != NULL); /* Initialize the SMPS device structure */ dev->ocount = 0; /* Initialize semaphores */ nxsem_init(&dev->closesem, 0, 1); /* Connect SMPS driver with lower level interface */ dev->lower = lower; /* Register the SMPS character driver */ ret = register_driver(path, &smps_fops, 0444, dev); if (ret < 0) { nxsem_destroy(&dev->closesem); } return ret; }
void netlink_initialize(void) { int i; /* Initialize the queues */ dq_init(&g_free_netlink_connections); dq_init(&g_active_netlink_connections); nxsem_init(&g_free_sem, 0, 1); for (i = 0; i < CONFIG_NET_NETLINK_CONNS; i++) { FAR struct netlink_conn_s *conn = &g_netlink_connections[i]; /* Mark the connection closed and move it to the free list */ memset(conn, 0, sizeof(*conn)); dq_addlast(&conn->node, &g_free_netlink_connections); } }
int apb_alloc(FAR struct audio_buf_desc_s *bufdesc) { uint32_t bufsize; int ret; struct ap_buffer_s *apb; DEBUGASSERT(bufdesc->u.ppBuffer != NULL); /* Perform a user mode allocation */ bufsize = sizeof(struct ap_buffer_s) + bufdesc->numbytes; apb = lib_umalloc(bufsize); *bufdesc->u.ppBuffer = apb; /* Test if the allocation was successful or not */ if (*bufdesc->u.ppBuffer == NULL) { ret = -ENOMEM; } else { /* Populate the buffer contents */ memset(apb, 0, bufsize); apb->i.channels = 1; apb->crefs = 1; apb->nmaxbytes = bufdesc->numbytes; apb->nbytes = 0; apb->flags = 0; apb->samp = (FAR uint8_t *)(apb + 1); #ifdef CONFIG_AUDIO_MULTI_SESSION apb->session = bufdesc->session; #endif nxsem_init(&apb->sem, 0, 1); ret = sizeof(struct audio_buf_desc_s); } return ret; }
int i2schar_register(FAR struct i2s_dev_s *i2s, int minor) { FAR struct i2schar_dev_s *priv; char devname[DEVNAME_FMTLEN]; int ret; /* Sanity check */ DEBUGASSERT(i2s != NULL && (unsigned)minor < 1000); /* Allocate a I2S character device structure */ priv = (FAR struct i2schar_dev_s *)kmm_zalloc(sizeof(struct i2schar_dev_s)); if (priv) { /* Initialize the I2S character device structure */ priv->i2s = i2s; nxsem_init(&priv->exclsem, 0, 1); /* Create the character device name */ snprintf(devname, DEVNAME_FMTLEN, DEVNAME_FMT, minor); ret = register_driver(devname, &i2schar_fops, 0666, priv); if (ret < 0) { /* Free the device structure if we failed to create the character * device. */ kmm_free(priv); } /* Return the result of the registration */ return OK; } return -ENOMEM; }
int mtdconfig_register(FAR struct mtd_dev_s *mtd) { int ret = OK; struct mtdconfig_struct_s *dev; struct mtd_geometry_s geo; /* Device geometry */ dev = (struct mtdconfig_struct_s *)kmm_malloc(sizeof(struct mtdconfig_struct_s)); if (dev) { /* Initialize the mtdconfig device structure */ dev->mtd = mtd; nxsem_init(&dev->exclsem, 0, 1); /* Get the device geometry. (casting to uintptr_t first eliminates * complaints on some architectures where the sizeof long is different * from the size of a pointer). */ ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&geo)); if (ret < 0) { ferr("ERROR: MTD ioctl(MTDIOC_GEOMETRY) failed: %d\n", ret); kmm_free(dev); goto errout; } dev->blocksize = geo.blocksize; dev->neraseblocks = geo.neraseblocks; dev->erasesize = geo.erasesize; dev->nblocks = geo.neraseblocks * geo.erasesize / geo.blocksize; (void)register_driver("/dev/config", &mtdconfig_fops, 0666, dev); } errout: return ret; }
int oneshot_register(FAR const char *devname, FAR struct oneshot_lowerhalf_s *lower) { FAR struct oneshot_dev_s *priv; int ret; sninfo("devname=%s lower=%p\n", devname, lower); DEBUGASSERT(devname != NULL && lower != NULL); /* Allocate a new oneshot timer driver instance */ priv = (FAR struct oneshot_dev_s *) kmm_zalloc(sizeof(struct oneshot_dev_s)); if (!priv) { snerr("ERROR: Failed to allocate device structure\n"); return -ENOMEM; } /* Initialize the new oneshot timer driver instance */ priv->od_lower = lower; nxsem_init(&priv->od_exclsem, 0, 1); /* And register the oneshot timer driver */ ret = register_driver(devname, &g_oneshot_ops, 0666, priv); if (ret < 0) { snerr("ERROR: register_driver failed: %d\n", ret); nxsem_destroy(&priv->od_exclsem); kmm_free(priv); } return ret; }
void icmpv6_rwait_setup(FAR struct net_driver_s *dev, FAR struct icmpv6_rnotify_s *notify) { irqstate_t flags; /* Initialize the wait structure */ memcpy(notify->rn_ifname, dev->d_ifname, IFNAMSIZ); notify->rn_result = -ETIMEDOUT; /* This semaphore is used for signaling and, hence, should not have * priority inheritance enabled. */ (void)nxsem_init(¬ify->rn_sem, 0, 0); nxsem_setprotocol(¬ify->rn_sem, SEM_PRIO_NONE); /* Add the wait structure to the list with interrupts disabled */ flags = enter_critical_section(); notify->rn_flink = g_icmpv6_rwaiters; g_icmpv6_rwaiters = notify; leave_critical_section(flags); }
void icmpv6_wait_setup(const net_ipv6addr_t ipaddr, FAR struct icmpv6_notify_s *notify) { irqstate_t flags; /* Initialize the wait structure */ net_ipv6addr_copy(notify->nt_ipaddr, ipaddr); notify->nt_result = -ETIMEDOUT; /* This semaphore is used for signaling and, hence, should not have * priority inheritance enabled. */ (void)nxsem_init(¬ify->nt_sem, 0, 0); nxsem_setprotocol(¬ify->nt_sem, SEM_PRIO_NONE); /* Add the wait structure to the list with interrupts disabled */ flags = enter_critical_section(); notify->nt_flink = g_icmpv6_waiters; g_icmpv6_waiters = notify; leave_critical_section(flags); }
FAR struct file_struct *fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb) { FAR struct streamlist *slist; FAR FILE *stream; int errcode = OK; int ret; int i; /* Check input parameters */ if (fd < 0) { errcode = EBADF; goto errout; } /* A NULL TCB pointer means to use this threads TCB. This is a little * hack the let's this function be called from user-space (via a syscall) * without having access to the TCB. */ if (!tcb) { tcb = sched_self(); } DEBUGASSERT(tcb && tcb->group); /* Verify that this is a valid file/socket descriptor and that the * requested access can be support. * * Is this fd in the range of valid file descriptors? Socket descriptors * lie in a different range. */ #if CONFIG_NFILE_DESCRIPTORS > 0 if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) #endif { /* No.. If networking is enabled then this might be a socket * descriptor. */ #if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 ret = net_checksd(fd, oflags); #else /* No networking... it is just a bad descriptor */ errcode = EBADF; goto errout; #endif } /* The descriptor is in a valid range to file descriptor... perform some more checks */ #if CONFIG_NFILE_DESCRIPTORS > 0 else { ret = fs_checkfd(tcb, fd, oflags); } #endif /* Do we have a good descriptor of some sort? */ if (ret < 0) { /* No... return the reported error */ errcode = -ret; goto errout; } /* Get the stream list from the TCB */ #if (defined(CONFIG_BUILD_PROTECTED) || defined(CONFIG_BUILD_KERNEL)) && \ defined(CONFIG_MM_KERNEL_HEAP) slist = tcb->group->tg_streamlist; #else slist = &tcb->group->tg_streamlist; #endif /* Find an unallocated FILE structure in the stream list */ ret = nxsem_wait(&slist->sl_sem); if (ret < 0) { errcode = -ret; goto errout; } for (i = 0 ; i < CONFIG_NFILE_STREAMS; i++) { stream = &slist->sl_streams[i]; if (stream->fs_fd < 0) { /* Zero the structure */ memset(stream, 0, sizeof(FILE)); #ifndef CONFIG_STDIO_DISABLE_BUFFERING /* Initialize the semaphore the manages access to the buffer */ (void)nxsem_init(&stream->fs_sem, 0, 1); #if CONFIG_STDIO_BUFFER_SIZE > 0 /* Allocate the IO buffer at the appropriate privilege level for * the group. */ stream->fs_bufstart = group_malloc(tcb->group, CONFIG_STDIO_BUFFER_SIZE); if (!stream->fs_bufstart) { errcode = ENOMEM; goto errout_with_sem; } /* Set up pointers */ stream->fs_bufend = &stream->fs_bufstart[CONFIG_STDIO_BUFFER_SIZE]; stream->fs_bufpos = stream->fs_bufstart; stream->fs_bufread = stream->fs_bufstart; #ifdef CONFIG_STDIO_LINEBUFFER /* Setup buffer flags */ stream->fs_flags |= __FS_FLAG_LBF; /* Line buffering */ #endif /* CONFIG_STDIO_LINEBUFFER */ #endif /* CONFIG_STDIO_BUFFER_SIZE > 0 */ #endif /* !CONFIG_STDIO_DISABLE_BUFFERING */ /* Save the file description and open flags. Setting the * file descriptor locks this stream. */ stream->fs_fd = fd; stream->fs_oflags = (uint16_t)oflags; nxsem_post(&slist->sl_sem); return stream; } } /* No free stream available.. report ENFILE */ errcode = ENFILE; #if !defined(CONFIG_STDIO_DISABLE_BUFFERING) && CONFIG_STDIO_BUFFER_SIZE > 0 errout_with_sem: #endif nxsem_post(&slist->sl_sem); errout: set_errno(errcode); return NULL; }
FAR struct nxterm_state_s * nxterm_register(NXTERM handle, FAR struct nxterm_window_s *wndo, FAR const struct nxterm_operations_s *ops, int minor) { FAR struct nxterm_state_s *priv; FAR const struct nx_font_s *fontset; char devname[NX_DEVNAME_SIZE]; NXHANDLE hfont; int ret; DEBUGASSERT(handle && wndo && ops && (unsigned)minor < 256); /* Allocate the driver structure */ priv = (FAR struct nxterm_state_s *)kmm_zalloc(sizeof(struct nxterm_state_s)); if (!priv) { gerr("ERROR: Failed to allocate the NX driver structure\n"); return NULL; } /* Initialize the driver structure */ priv->ops = ops; priv->handle = handle; priv->minor = minor; memcpy(&priv->wndo, wndo, sizeof(struct nxterm_window_s)); nxsem_init(&priv->exclsem, 0, 1); #ifdef CONFIG_DEBUG_FEATURES priv->holder = NO_HOLDER; #endif #ifdef CONFIG_NXTERM_NXKBDIN /* The waitsem semaphore is used for signaling and, hence, should not have * priority inheritance enabled. */ nxsem_init(&priv->waitsem, 0, 0); nxsem_setprotocol(&priv->waitsem, SEM_PRIO_NONE); #endif /* Connect to the font cache for the configured font characteristics */ priv->fcache = nxf_cache_connect(wndo->fontid, wndo->fcolor[0], wndo->wcolor[0], CONFIG_NXTERM_BPP, CONFIG_NXTERM_CACHESIZE); if (priv->fcache == NULL) { gerr("ERROR: Failed to connect to font cache for font ID %d: %d\n", wndo->fontid, errno); goto errout; } /* Get the handle of the font managed by the font cache */ hfont = nxf_cache_getfonthandle(priv->fcache); if (hfont == NULL) { gerr("ERROR: Failed to get handlr for font ID %d: %d\n", wndo->fontid, errno); goto errout; } /* Get information about the font set being used and save this in the * state structure */ fontset = nxf_getfontset(hfont); priv->fheight = fontset->mxheight; priv->fwidth = fontset->mxwidth; priv->spwidth = fontset->spwidth; /* Set up the text cache */ priv->maxchars = CONFIG_NXTERM_MXCHARS; /* Set the initial display position */ nxterm_home(priv); /* Show the cursor */ priv->cursor.code = CONFIG_NXTERM_CURSORCHAR; nxterm_showcursor(priv); /* Register the driver */ snprintf(devname, NX_DEVNAME_SIZE, NX_DEVNAME_FORMAT, minor); ret = register_driver(devname, &g_nxterm_drvrops, 0666, priv); if (ret < 0) { gerr("ERROR: Failed to register %s\n", devname); } return (NXTERM)priv; errout: kmm_free(priv); return NULL; }
static struct tiva_adc_s *tiva_adc_struct_init(struct tiva_adc_cfg_s *cfg) { struct tiva_adc_s *adc = g_adcs[cfg->adc]; struct tiva_adc_sse_s *sse = 0; uint8_t s = 0; /* Do not re-initialize the run-time structures, there is a chance another * process is also using this ADC. */ if (adc->cfg == true) { goto tiva_adc_struct_init_ok; } else { if (adc != NULL) { adc->ena = false; adc->devno = cfg->adc; for (s = 0; s < 4; s++) { /* Only configure selected SSEs */ if (cfg->sse[s]) { sse = g_sses[SSE_IDX(cfg->adc, s)]; if (sse != NULL) { sse->adc = cfg->adc; sse->num = s; nxsem_init(&sse->exclsem, SEM_PROCESS_PRIVATE, 1); sse->ena = false; sse->cfg = true; } else { goto tiva_adc_struct_init_error; } } } /* Initialize the public ADC device data structure */ adc->dev = g_devs[cfg->adc]; if (adc->dev != NULL) { adc->dev->ad_ops = &g_adcops; adc->dev->ad_priv = adc; } else { goto tiva_adc_struct_init_error; } goto tiva_adc_struct_init_ok; } else { goto tiva_adc_struct_init_error; } } tiva_adc_struct_init_error: ainfo("Invalid ADC device number: expected=%d actual=%d\n", 0, cfg->adc); ainfo("ADC%d (CONFIG_TIVA_ADC%d) must be enabled in Kconfig first!", cfg->adc, cfg->adc); return NULL; tiva_adc_struct_init_ok: adc->cfg = true; return adc; }
int arp_send(in_addr_t ipaddr) { FAR struct net_driver_s *dev; struct arp_notify_s notify; struct timespec delay; struct arp_send_s state; int ret; /* First check if destination is a local broadcast. */ if (ipaddr == INADDR_BROADCAST) { /* We don't need to send the ARP request */ return OK; } #ifdef CONFIG_NET_IGMP /* Check if the destination address is a multicast address * * - IPv4: multicast addresses lie in the class D group -- The address range * 224.0.0.0 to 239.255.255.255 (224.0.0.0/4) * * - IPv6 multicast addresses are have the high-order octet of the * addresses=0xff (ff00::/8.) */ if (NTOHL(ipaddr) >= 0xe0000000 && NTOHL(ipaddr) <= 0xefffffff) { /* We don't need to send the ARP request */ return OK; } #endif /* Get the device that can route this request */ dev = netdev_findby_ipv4addr(INADDR_ANY, ipaddr); if (!dev) { nerr("ERROR: Unreachable: %08lx\n", (unsigned long)ipaddr); ret = -EHOSTUNREACH; goto errout; } /* ARP support is only built if the Ethernet data link is supported. * Continue and send the ARP request only if this device uses the * Ethernet data link protocol. */ if (dev->d_lltype != NET_LL_ETHERNET) { return OK; } /* Check if the destination address is on the local network. */ if (!net_ipv4addr_maskcmp(ipaddr, dev->d_ipaddr, dev->d_netmask)) { in_addr_t dripaddr; /* Destination address is not on the local network */ #ifdef CONFIG_NET_ROUTE /* We have a routing table.. find the correct router to use in * this case (or, as a fall-back, use the device's default router * address). We will use the router IP address instead of the * destination address when determining the MAC address. */ netdev_ipv4_router(dev, ipaddr, &dripaddr); #else /* Use the device's default router IP address instead of the * destination address when determining the MAC address. */ net_ipv4addr_copy(dripaddr, dev->d_draddr); #endif ipaddr = dripaddr; } /* The destination address is on the local network. Check if it is * the sub-net broadcast address. */ else if (net_ipv4addr_broadcast(ipaddr, dev->d_netmask)) { /* Yes.. We don't need to send the ARP request */ return OK; } /* Allocate resources to receive a callback. This and the following * initialization is performed with the network lock because we don't * want anything to happen until we are ready. */ net_lock(); state.snd_cb = arp_callback_alloc(dev); if (!state.snd_cb) { nerr("ERROR: Failed to allocate a callback\n"); ret = -ENOMEM; goto errout_with_lock; } /* This semaphore is used for signaling and, hence, should not have * priority inheritance enabled. */ (void)nxsem_init(&state.snd_sem, 0, 0); /* Doesn't really fail */ nxsem_setprotocol(&state.snd_sem, SEM_PRIO_NONE); state.snd_retries = 0; /* No retries yet */ state.snd_ipaddr = ipaddr; /* IP address to query */ /* Remember the routing device name */ strncpy((FAR char *)state.snd_ifname, (FAR const char *)dev->d_ifname, IFNAMSIZ); /* Now loop, testing if the address mapping is in the ARP table and re- * sending the ARP request if it is not. */ ret = -ETIMEDOUT; /* Assume a timeout failure */ while (state.snd_retries < CONFIG_ARP_SEND_MAXTRIES) { /* Check if the address mapping is present in the ARP table. This * is only really meaningful on the first time through the loop. * * NOTE: If the ARP table is large than this could be a performance * issue. */ if (arp_find(ipaddr, NULL) >= 0) { /* We have it! Break out with success */ ret = OK; break; } /* Set up the ARP response wait BEFORE we send the ARP request */ arp_wait_setup(ipaddr, ¬ify); /* Arm/re-arm the callback */ state.snd_sent = false; state.snd_result = -EBUSY; state.snd_cb->flags = (ARP_POLL | NETDEV_DOWN); state.snd_cb->priv = (FAR void *)&state; state.snd_cb->event = arp_send_eventhandler; /* Notify the device driver that new TX data is available. * NOTES: This is in essence what netdev_ipv4_txnotify() does, which * is not possible to call since it expects a in_addr_t as * its single argument to lookup the network interface. */ if (dev->d_txavail) { dev->d_txavail(dev); } /* Wait for the send to complete or an error to occur. * net_lockedwait will also terminate if a signal is received. */ do { (void)net_lockedwait(&state.snd_sem); } while (!state.snd_sent); /* Check the result of the send operation */ ret = state.snd_result; if (ret < 0) { /* Break out on a send failure */ nerr("ERROR: Send failed: %d\n", ret); break; } /* Now wait for response to the ARP response to be received. The * optimal delay would be the work case round trip time. * NOTE: The network is locked. */ delay.tv_sec = CONFIG_ARP_SEND_DELAYSEC; delay.tv_nsec = CONFIG_ARP_SEND_DELAYNSEC; ret = arp_wait(¬ify, &delay); /* arp_wait will return OK if and only if the matching ARP response * is received. Otherwise, it will return -ETIMEDOUT. */ if (ret >= OK) { /* Break out if arp_wait() fails */ break; } /* Increment the retry count */ state.snd_retries++; nerr("ERROR: arp_wait failed: %d\n", ret); } nxsem_destroy(&state.snd_sem); arp_callback_free(dev, state.snd_cb); errout_with_lock: net_unlock(); errout: return ret; }
int stm32_tsc_setup(int minor) { FAR struct tc_dev_s *priv; char devname[DEV_NAMELEN]; #ifdef CONFIG_TOUCHSCREEN_MULTIPLE irqstate_t flags; #endif int ret; iinfo("minor: %d\n", minor); DEBUGASSERT(minor >= 0 && minor < 100); /* If we only have one touchscreen, check if we already did init */ #ifndef CONFIG_TOUCHSCREEN_MULTIPLE if (g_touchinitdone) { return OK; } #endif /* Configure the touchscreen DRIVEA and DRIVEB pins for output */ stm32_configgpio(GPIO_TP_DRIVEA); stm32_configgpio(GPIO_TP_DRIVEB); /* Configure Analog inputs for sampling X and Y coordinates */ stm32_configgpio(GPIO_TP_XL); stm32_configgpio(GPIO_TP_YD); tc_adc_init(); /* Create and initialize a touchscreen device driver instance */ #ifndef CONFIG_TOUCHSCREEN_MULTIPLE priv = &g_touchscreen; #else priv = (FAR struct tc_dev_s *)kmm_malloc(sizeof(struct tc_dev_s)); if (!priv) { ierr("ERROR: kmm_malloc(%d) failed\n", sizeof(struct tc_dev_s)); return -ENOMEM; } #endif /* Initialize the touchscreen device driver instance */ memset(priv, 0, sizeof(struct tc_dev_s)); nxsem_init(&priv->devsem, 0, 1); /* Initialize device structure semaphore */ nxsem_init(&priv->waitsem, 0, 0); /* Initialize pen event wait semaphore */ /* Register the device as an input device */ (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor); iinfo("Registering %s\n", devname); ret = register_driver(devname, &tc_fops, 0666, priv); if (ret < 0) { ierr("ERROR: register_driver() failed: %d\n", ret); goto errout_with_priv; } /* Schedule work to perform the initial sampling and to set the data * availability conditions. */ priv->state = TC_READY; ret = work_queue(HPWORK, &priv->work, tc_worker, priv, 0); if (ret != 0) { ierr("ERROR: Failed to queue work: %d\n", ret); goto errout_with_priv; } /* And return success (?) */ #ifndef CONFIG_TOUCHSCREEN_MULTIPLE g_touchinitdone = true; #endif return OK; errout_with_priv: nxsem_destroy(&priv->devsem); #ifdef CONFIG_TOUCHSCREEN_MULTIPLE kmm_free(priv); #endif return ret; }
int pty_register(int minor) { FAR struct pty_devpair_s *devpair; int pipe_a[2]; int pipe_b[2]; char devname[16]; int ret; /* Allocate a device instance */ devpair = kmm_zalloc(sizeof(struct pty_devpair_s)); if (devpair == NULL) { return -ENOMEM; } /* Initialize semaphores */ nxsem_init(&devpair->pp_slavesem, 0, 0); nxsem_init(&devpair->pp_exclsem, 0, 1); /* The pp_slavesem semaphore is used for signaling and, hence, should not * have priority inheritance enabled. */ nxsem_setprotocol(&devpair->pp_slavesem, SEM_PRIO_NONE); #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS devpair->pp_minor = minor; #endif devpair->pp_locked = true; devpair->pp_master.pd_devpair = devpair; devpair->pp_master.pd_master = true; devpair->pp_slave.pd_devpair = devpair; /* Create two pipes: * * pipe_a: Master source, slave sink (TX, slave-to-master) * pipe_b: Master sink, slave source (RX, master-to-slave) */ ret = pipe2(pipe_a, CONFIG_PSEUDOTERM_TXBUFSIZE); if (ret < 0) { goto errout_with_devpair; } ret = pipe2(pipe_b, CONFIG_PSEUDOTERM_RXBUFSIZE); if (ret < 0) { goto errout_with_pipea; } /* Detach the pipe file descriptors (closing them in the process) * * fd[0] is for reading; * fd[1] is for writing. */ ret = file_detach(pipe_a[0], &devpair->pp_master.pd_src); if (ret < 0) { goto errout_with_pipeb; } pipe_a[0] = -1; ret = file_detach(pipe_a[1], &devpair->pp_slave.pd_sink); if (ret < 0) { goto errout_with_pipeb; } pipe_a[1] = -1; ret = file_detach(pipe_b[0], &devpair->pp_slave.pd_src); if (ret < 0) { goto errout_with_pipeb; } pipe_b[0] = -1; ret = file_detach(pipe_b[1], &devpair->pp_master.pd_sink); if (ret < 0) { goto errout_with_pipeb; } pipe_b[1] = -1; /* Register the slave device * * BSD style (deprecated): /dev/ttypN * SUSv1 style: /dev/pts/N * * Where N is the minor number */ #ifdef CONFIG_PSEUDOTERM_BSD snprintf(devname, 16, "/dev/ttyp%d", minor); #else snprintf(devname, 16, "/dev/pts/%d", minor); #endif ret = register_driver(devname, &g_pty_fops, 0666, &devpair->pp_slave); if (ret < 0) { goto errout_with_pipeb; } /* Register the master device * * BSD style (deprecated): /dev/ptyN * SUSv1 style: Master: /dev/ptmx (multiplexor, see ptmx.c) * * Where N is the minor number */ snprintf(devname, 16, "/dev/pty%d", minor); ret = register_driver(devname, &g_pty_fops, 0666, &devpair->pp_master); if (ret < 0) { goto errout_with_slave; } return OK; errout_with_slave: #ifdef CONFIG_PSEUDOTERM_BSD snprintf(devname, 16, "/dev/ttyp%d", minor); #else snprintf(devname, 16, "/dev/pts/%d", minor); #endif (void)unregister_driver(devname); errout_with_pipeb: if (pipe_b[0] >= 0) { close(pipe_b[0]); } else { (void)file_close_detached(&devpair->pp_master.pd_src); } if (pipe_b[1] >= 0) { close(pipe_b[1]); } else { (void)file_close_detached(&devpair->pp_slave.pd_sink); } errout_with_pipea: if (pipe_a[0] >= 0) { close(pipe_a[0]); } else { (void)file_close_detached(&devpair->pp_slave.pd_src); } if (pipe_a[1] >= 0) { close(pipe_a[1]); } else { (void)file_close_detached(&devpair->pp_master.pd_sink); } errout_with_devpair: nxsem_destroy(&devpair->pp_exclsem); nxsem_destroy(&devpair->pp_slavesem); kmm_free(devpair); return ret; }
int syslog_dev_initialize(FAR const char *devpath, int oflags, int mode) { int fd; int ret; /* At this point, the only expected states are SYSLOG_UNINITIALIZED or * SYSLOG_REOPEN.. Not SYSLOG_INITIALIZING, SYSLOG_FAILURE, SYSLOG_OPENED. */ DEBUGASSERT(g_syslog_dev.sl_state == SYSLOG_UNINITIALIZED || g_syslog_dev.sl_state == SYSLOG_REOPEN); /* Save the path to the device in case we have to re-open it. * If we get here and sl_devpath is not equal to NULL, that is a clue * that we will are re-openingthe file. */ if (g_syslog_dev.sl_state == SYSLOG_REOPEN) { /* Re-opening: Then we should already have a copy of the path to the * device. */ DEBUGASSERT(g_syslog_dev.sl_devpath != NULL && strcmp(g_syslog_dev.sl_devpath, devpath) == 0); } else { /* Initializing. Copy the device path so that we can use it if we * have to re-open the file. */ DEBUGASSERT(g_syslog_dev.sl_devpath == NULL); g_syslog_dev.sl_oflags = oflags; g_syslog_dev.sl_mode = mode; g_syslog_dev.sl_devpath = strdup(devpath); DEBUGASSERT(g_syslog_dev.sl_devpath != NULL); } g_syslog_dev.sl_state = SYSLOG_INITIALIZING; /* Open the device driver. */ fd = open(devpath, oflags, mode); if (fd < 0) { int errcode = get_errno(); DEBUGASSERT(errcode > 0); /* We failed to open the file. Perhaps it does exist? Perhaps it * exists, but is not ready because it depends on insertion of a * removable device? * * In any case we will attempt to re-open the device repeatedly. * The assumption is that the device path is valid but that the * driver has not yet been registered or a removable device has * not yet been installed. */ g_syslog_dev.sl_state = SYSLOG_REOPEN; return -errcode; } /* Detach the file descriptor from the file structure. The file * descriptor is a task-specific concept. Detaching the file * descriptor allows us to use the device on all threads in all tasks. */ ret = file_detach(fd, &g_syslog_dev.sl_file); if (ret < 0) { /* This should not happen and means that something very bad has * occurred. */ g_syslog_dev.sl_state = SYSLOG_FAILURE; close(fd); return ret; } /* The SYSLOG device is open and ready for writing. */ nxsem_init(&g_syslog_dev.sl_sem, 0, 1); g_syslog_dev.sl_holder = NO_HOLDER; g_syslog_dev.sl_state = SYSLOG_OPENED; return OK; }
int psock_tcp_accept(FAR struct socket *psock, FAR struct sockaddr *addr, FAR socklen_t *addrlen, FAR void **newconn) { FAR struct tcp_conn_s *conn; struct accept_s state; int ret; DEBUGASSERT(psock && newconn); /* Check the backlog to see if there is a connection already pending for * this listener. */ conn = (FAR struct tcp_conn_s *)psock->s_conn; #ifdef CONFIG_NET_TCPBACKLOG state.acpt_newconn = tcp_backlogremove(conn); if (state.acpt_newconn) { /* Yes... get the address of the connected client */ ninfo("Pending conn=%p\n", state.acpt_newconn); accept_tcpsender(psock, state.acpt_newconn, addr, addrlen); } /* In general, this implementation will not support non-blocking socket * operations... except in a few cases: Here for TCP accept with * backlog enabled. If this socket is configured as non-blocking then * return EAGAIN if there is no pending connection in the backlog. */ else if (_SS_ISNONBLOCK(psock->s_flags)) { return -EAGAIN; } else #endif { /* Set the socket state to accepting */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_ACCEPT); /* Perform the TCP accept operation */ /* Initialize the state structure. This is done with the network * locked because we don't want anything to happen until we are * ready. */ state.acpt_sock = psock; state.acpt_addr = addr; state.acpt_addrlen = addrlen; state.acpt_newconn = NULL; state.acpt_result = OK; /* This semaphore is used for signaling and, hence, should not have * priority inheritance enabled. */ nxsem_init(&state.acpt_sem, 0, 0); nxsem_setprotocol(&state.acpt_sem, SEM_PRIO_NONE); /* Set up the callback in the connection */ conn->accept_private = (FAR void *)&state; conn->accept = accept_eventhandler; /* Wait for the send to complete or an error to occur: NOTES: * net_lockedwait will also terminate if a signal is received. */ ret = net_lockedwait(&state.acpt_sem); /* Make sure that no further events are processed */ conn->accept_private = NULL; conn->accept = NULL; nxsem_destroy(&state. acpt_sem); /* Set the socket state to idle */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE); /* Check for a errors. Errors are signalled by negative errno values * for the send length. */ if (state.acpt_result != 0) { DEBUGASSERT(state.acpt_result > 0); return -state.acpt_result; } /* If net_lockedwait failed, then we were probably reawakened by a * signal. In this case, net_lockedwait will have returned negated * errno appropriately. */ if (ret < 0) { return ret; } } *newconn = (FAR void *)state.acpt_newconn; return OK; }
int icmpv6_neighbor(const net_ipv6addr_t ipaddr) { FAR struct net_driver_s *dev; struct icmpv6_notify_s notify; struct timespec delay; struct icmpv6_neighbor_s state; FAR const uint16_t *lookup; int ret; /* First check if destination is a local broadcast or a multicast address. * * - IPv6 multicast addresses are have the high-order octet of the * addresses=0xff (ff00::/8.) */ if (net_ipv6addr_cmp(ipaddr, g_ipv6_unspecaddr) || net_is_addr_mcast(ipaddr)) { /* We don't need to send the Neighbor Solicitation */ return OK; } /* Get the device that can route this request */ dev = netdev_findby_ipv6addr(g_ipv6_unspecaddr, ipaddr); if (!dev) { nerr("ERROR: Unreachable: %08lx\n", (unsigned long)ipaddr); ret = -EHOSTUNREACH; goto errout; } /* Send the Neighbor Solicitation request only if this device uses the * Ethernet data link protocol. * * REVISIT: Other link layer protocols may require Neighbor Discovery * as well. */ if (dev->d_lltype != NET_LL_ETHERNET) { return OK; } /* Check if the destination address is on the local network. */ if (net_ipv6addr_maskcmp(ipaddr, dev->d_ipv6addr, dev->d_ipv6netmask)) { /* Yes.. use the input address for the lookup */ lookup = ipaddr; } else { net_ipv6addr_t dripaddr; /* Destination address is not on the local network */ #ifdef CONFIG_NET_ROUTE /* We have a routing table.. find the correct router to use in * this case (or, as a fall-back, use the device's default router * address). We will use the router IP address instead of the * destination address when determining the MAC address. */ netdev_ipv6_router(dev, ipaddr, dripaddr); #else /* Use the device's default router IP address instead of the * destination address when determining the MAC address. */ net_ipv6addr_copy(dripaddr, dev->d_ipv6draddr); #endif /* Use the router address for the lookup */ lookup = dripaddr; } /* Allocate resources to receive a callback. This and the following * initialization is performed with the network lock because we don't * want anything to happen until we are ready. */ net_lock(); state.snd_cb = icmpv6_callback_alloc(dev); if (!state.snd_cb) { nerr("ERROR: Failed to allocate a callback\n"); ret = -ENOMEM; goto errout_with_lock; } /* Initialize the state structure with the network locked. * * This semaphore is used for signaling and, hence, should not have * priority inheritance enabled. */ (void)nxsem_init(&state.snd_sem, 0, 0); /* Doesn't really fail */ nxsem_setprotocol(&state.snd_sem, SEM_PRIO_NONE); state.snd_retries = 0; /* No retries yet */ net_ipv6addr_copy(state.snd_ipaddr, lookup); /* IP address to query */ /* Remember the routing device name */ strncpy((FAR char *)state.snd_ifname, (FAR const char *)dev->d_ifname, IFNAMSIZ); /* Now loop, testing if the address mapping is in the Neighbor Table and * re-sending the Neighbor Solicitation if it is not. */ ret = -ETIMEDOUT; /* Assume a timeout failure */ while (state.snd_retries < CONFIG_ICMPv6_NEIGHBOR_MAXTRIES) { /* Check if the address mapping is present in the Neighbor Table. This * is only really meaningful on the first time through the loop. * * NOTE: If the Neighbor Table is large than this could be a performance * issue. */ if (neighbor_findentry(lookup) != NULL) { /* We have it! Break out with success */ ret = OK; break; } /* Set up the Neighbor Advertisement wait BEFORE we send the Neighbor * Solicitation. */ icmpv6_wait_setup(lookup, ¬ify); /* Arm/re-arm the callback */ state.snd_sent = false; state.snd_cb->flags = ICMPv6_POLL; state.snd_cb->priv = (FAR void *)&state; state.snd_cb->event = icmpv6_neighbor_eventhandler; /* Notify the device driver that new TX data is available. */ dev->d_txavail(dev); /* Wait for the send to complete or an error to occur. * net_lockedwait will also terminate if a signal is received. */ do { (void)net_lockedwait(&state.snd_sem); } while (!state.snd_sent); /* Now wait for response to the Neighbor Advertisement to be received. * The optimal delay would be the work case round trip time. * NOTE: The network is locked. */ delay.tv_sec = CONFIG_ICMPv6_NEIGHBOR_DELAYSEC; delay.tv_nsec = CONFIG_ICMPv6_NEIGHBOR_DELAYNSEC; ret = icmpv6_wait(¬ify, &delay); /* icmpv6_wait will return OK if and only if the matching Neighbor * Advertisement is received. Otherwise, it will return -ETIMEDOUT. */ if (ret == OK) { break; } /* Increment the retry count */ state.snd_retries++; } nxsem_destroy(&state.snd_sem); icmpv6_callback_free(dev, state.snd_cb); errout_with_lock: net_unlock(); errout: return ret; }
int ads7843e_register(FAR struct spi_dev_s *spi, FAR struct ads7843e_config_s *config, int minor) { FAR struct ads7843e_dev_s *priv; char devname[DEV_NAMELEN]; #ifdef CONFIG_ADS7843E_MULTIPLE irqstate_t flags; #endif int ret; iinfo("spi: %p minor: %d\n", spi, minor); /* Debug-only sanity checks */ DEBUGASSERT(spi != NULL && config != NULL && minor >= 0 && minor < 100); /* Create and initialize a ADS7843E device driver instance */ #ifndef CONFIG_ADS7843E_MULTIPLE priv = &g_ads7843e; #else priv = (FAR struct ads7843e_dev_s *)kmm_malloc(sizeof(struct ads7843e_dev_s)); if (!priv) { ierr("ERROR: kmm_malloc(%d) failed\n", sizeof(struct ads7843e_dev_s)); return -ENOMEM; } #endif /* Initialize the ADS7843E device driver instance */ memset(priv, 0, sizeof(struct ads7843e_dev_s)); priv->spi = spi; /* Save the SPI device handle */ priv->config = config; /* Save the board configuration */ priv->wdog = wd_create(); /* Create a watchdog timer */ priv->threshx = INVALID_THRESHOLD; /* Initialize thresholding logic */ priv->threshy = INVALID_THRESHOLD; /* Initialize thresholding logic */ /* Initialize semaphores */ nxsem_init(&priv->devsem, 0, 1); /* Initialize device structure semaphore */ nxsem_init(&priv->waitsem, 0, 0); /* Initialize pen event wait semaphore */ /* The pen event semaphore is used for signaling and, hence, should not * have priority inheritance enabled. */ nxsem_setprotocol(&priv->waitsem, SEM_PRIO_NONE); /* Make sure that interrupts are disabled */ config->clear(config); config->enable(config, false); /* Attach the interrupt handler */ ret = config->attach(config, ads7843e_interrupt); if (ret < 0) { ierr("ERROR: Failed to attach interrupt\n"); goto errout_with_priv; } iinfo("Mode: %d Bits: 8 Frequency: %d\n", CONFIG_ADS7843E_SPIMODE, CONFIG_ADS7843E_FREQUENCY); /* Lock the SPI bus so that we have exclusive access */ ads7843e_lock(spi); /* Enable the PEN IRQ */ ads7843e_sendcmd(priv, ADS7843_CMD_ENABPENIRQ); /* Unlock the bus */ ads7843e_unlock(spi); /* Register the device as an input device */ (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor); iinfo("Registering %s\n", devname); ret = register_driver(devname, &ads7843e_fops, 0666, priv); if (ret < 0) { ierr("ERROR: register_driver() failed: %d\n", ret); goto errout_with_priv; } /* If multiple ADS7843E devices are supported, then we will need to add * this new instance to a list of device instances so that it can be * found by the interrupt handler based on the received IRQ number. */ #ifdef CONFIG_ADS7843E_MULTIPLE priv->flink = g_ads7843elist; g_ads7843elist = priv; leave_critical_section(flags); #endif /* Schedule work to perform the initial sampling and to set the data * availability conditions. */ ret = work_queue(HPWORK, &priv->work, ads7843e_worker, priv, 0); if (ret != 0) { ierr("ERROR: Failed to queue work: %d\n", ret); goto errout_with_priv; } /* And return success (?) */ return OK; errout_with_priv: nxsem_destroy(&priv->devsem); #ifdef CONFIG_ADS7843E_MULTIPLE kmm_free(priv); #endif return ret; }
ssize_t ieee802154_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, int flags, FAR struct sockaddr *from, FAR socklen_t *fromlen) { FAR struct ieee802154_conn_s *conn = (FAR struct ieee802154_conn_s *)psock->s_conn; FAR struct radio_driver_s *radio; struct ieee802154_recvfrom_s state; ssize_t ret; /* If a 'from' address has been provided, verify that it is large * enough to hold this address family. */ if (from != NULL && *fromlen < sizeof(struct sockaddr_ieee802154_s)) { return -EINVAL; } if (psock->s_type != SOCK_DGRAM) { nerr("ERROR: Unsupported socket type: %d\n", psock->s_type); return -EPROTONOSUPPORT; } /* Perform the packet recvfrom() operation */ /* Initialize the state structure. This is done with the network * locked because we don't want anything to happen until we are ready. */ net_lock(); memset(&state, 0, sizeof(struct ieee802154_recvfrom_s)); state.ir_buflen = len; state.ir_buffer = buf; state.ir_sock = psock; state.ir_from = from; /* Get the device driver that will service this transfer */ radio = ieee802154_find_device(conn, &conn->laddr); if (radio == NULL) { ret = -ENODEV; goto errout_with_lock; } /* Before we wait for data, let's check if there are already frame(s) * waiting in the RX queue. */ ret = ieee802154_recvfrom_rxqueue(radio, &state); if (ret > 0) { /* Good newe! We have a frame and we are done. */ net_unlock(); return ret; } /* We will have to wait. This semaphore is used for signaling and, * hence, should not have priority inheritance enabled. */ (void)nxsem_init(&state.ir_sem, 0, 0); /* Doesn't really fail */ (void)nxsem_setprotocol(&state.ir_sem, SEM_PRIO_NONE); /* Set the socket state to receiving */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_RECV); /* Set up the callback in the connection */ state.ir_cb = ieee802154_callback_alloc(&radio->r_dev, conn); if (state.ir_cb) { state.ir_cb->flags = (IEEE802154_NEWDATA | IEEE802154_POLL); state.ir_cb->priv = (FAR void *)&state; state.ir_cb->event = ieee802154_recvfrom_eventhandler; /* Wait for either the receive to complete or for an error/timeout to * occur. NOTES: (1) net_lockedwait will also terminate if a signal * is received, (2) the network is locked! It will be un-locked while * the task sleeps and automatically re-locked when the task restarts. */ (void)net_lockedwait(&state.ir_sem); /* Make sure that no further events are processed */ ieee802154_callback_free(&radio->r_dev, conn, state.ir_cb); ret = state.ir_result; } else { ret = -EBUSY; } /* Set the socket state to idle */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE); nxsem_destroy(&state.ir_sem); errout_with_lock: net_unlock(); return ret; }