static int usbhost_connect(FAR struct usbhost_class_s *usbclass, FAR const uint8_t *configdesc, int desclen) { FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)usbclass; int ret; DEBUGASSERT(priv != NULL && configdesc != NULL && desclen >= sizeof(struct usb_cfgdesc_s)); /* Parse the configuration descriptor to get the endpoints */ ret = usbhost_cfgdesc(priv, configdesc, desclen); if (ret < 0) { udbg("usbhost_cfgdesc() failed: %d\n", ret); } else { /* Now configure the device and register the NuttX driver */ ret = usbhost_devinit(priv); if (ret < 0) { udbg("usbhost_devinit() failed: %d\n", ret); } } return ret; }
int sam_usbhost_initialize(void) { pid_t pid; int ret; /* First, register all of the class drivers needed to support the drivers * that we care about: */ ret = usbhost_storageinit(); if (ret != OK) { udbg("ERROR: Failed to register the mass storage class: %d\n", ret); } #ifdef CONFIG_SAMA5_OHCI /* Get an instance of the USB OHCI interface */ g_ohciconn = sam_ohci_initialize(0); if (!g_ohciconn) { udbg("ERROR: sam_ohci_initialize failed\n"); return -ENODEV; } /* Start a thread to handle device connection. */ pid = TASK_CREATE("usbhost", CONFIG_USBHOST_DEFPRIO, CONFIG_USBHOST_STACKSIZE, (main_t)ohci_waiter, (FAR char * const *)NULL); if (pid < 0) { udbg("ERROR: Failed to create ohci_waiter task: %d\n", ret); return -ENODEV; } #endif #ifdef CONFIG_SAMA5_EHCI /* Get an instance of the USB EHCI interface */ g_ehciconn = sam_ehci_initialize(0); if (!g_ehciconn) { udbg("ERROR: sam_ehci_initialize failed\n"); return -ENODEV; } /* Start a thread to handle device connection. */ pid = TASK_CREATE("usbhost", CONFIG_USBHOST_DEFPRIO, CONFIG_USBHOST_STACKSIZE, (main_t)ehci_waiter, (FAR char * const *)NULL); if (pid < 0) { udbg("ERROR: Failed to create ehci_waiter task: %d\n", ret); return -ENODEV; } #endif return OK; }
static int usbhost_connect(FAR struct usbhost_class_s *hubclass, FAR const uint8_t *configdesc, int desclen) { FAR struct usbhost_hubpriv_s *priv; FAR struct usbhost_hubport_s *hport; int ret; DEBUGASSERT(hubclass != NULL); priv = &((FAR struct usbhost_hubclass_s *)hubclass)->hubpriv; DEBUGASSERT(hubclass->hport); hport = hubclass->hport; DEBUGASSERT(configdesc != NULL && desclen >= sizeof(struct usb_cfgdesc_s)); /* Parse the configuration descriptor to get the endpoints */ ret = usbhost_cfgdesc(hubclass, configdesc, desclen); if (ret < 0) { udbg("ERROR: Failed to parse config descriptor: %d\n", ret); return ret; } /* Read the hub descriptor */ ret = usbhost_hubdesc(hubclass); if (ret < 0) { return ret; } if (priv->nports > USBHUB_MAX_PORTS) { udbg("ERROR: too many downstream ports: %d\n", priv->nports); return -ENOSYS; } /* Enable power to all downstream ports */ ret = usbhost_hubpwr(priv, hport, true); if (ret < 0) { udbg("ERROR: usbhost_hubpwr failed: %d\n", ret); return ret; } /* Begin monitoring of port status change events */ ret = DRVR_ASYNCH(hport->drvr, priv->intin, (FAR uint8_t *)priv->buffer, INTIN_BUFSIZE, usbhost_callback, hubclass); if (ret < 0) { udbg("ERROR: DRVR_ASYNCH failed: %d\n", ret); (void)usbhost_hubpwr(priv, hport, false); } return ret; }
int stm32_usbhost_initialize(void) { int pid; int ret; /* First, register all of the class drivers needed to support the drivers * that we care about: */ uvdbg("Register class drivers\n"); #ifdef CONFIG_USBHOST_HUB /* Initialize USB hub class support */ ret = usbhost_hub_initialize(); if (ret < 0) { udbg("ERROR: usbhost_hub_initialize failed: %d\n", ret); } #endif #ifdef CONFIG_USBHOST_MSC /* Register the USB mass storage class class */ ret = usbhost_msc_initialize(); if (ret != OK) { udbg("ERROR: Failed to register the mass storage class: %d\n", ret); } #endif #ifdef CONFIG_USBHOST_CDCACM /* Register the CDC/ACM serial class */ ret = usbhost_cdcacm_initialize(); if (ret != OK) { udbg("ERROR: Failed to register the CDC/ACM serial class: %d\n", ret); } #endif /* Then get an instance of the USB host interface */ uvdbg("Initialize USB host\n"); g_usbconn = stm32_otghshost_initialize(0); if (g_usbconn) { /* Start a thread to handle device connection. */ uvdbg("Start usbhost_waiter\n"); pid = task_create("usbhost", CONFIG_STM32F429IDISCO_USBHOST_PRIO, CONFIG_STM32F429IDISCO_USBHOST_STACKSIZE, (main_t)usbhost_waiter, (FAR char * const *)NULL); return pid < 0 ? -ENOEXEC : OK; } return -ENODEV; }
void sam_usbhost_vbusdrive(int rhport, bool enable) { pio_pinset_t pinset = 0; uvdbg("RHPort%d: enable=%d\n", rhport+1, enable); /* Pick the PIO configuration associated with the selected root hub port */ switch (rhport) { case SAM_RHPORT1: #ifndef CONFIG_SAMA5_UHPHS_RHPORT1 udbg("ERROR: RHPort1 is not available in this configuration\n"); return; #else pinset = PIO_USBA_VBUS_ENABLE; break; #endif case SAM_RHPORT2: #ifndef CONFIG_SAMA5_UHPHS_RHPORT2 udbg("ERROR: RHPort2 is not available in this configuration\n"); return; #else pinset = PIO_USBB_VBUS_ENABLE; break; #endif case SAM_RHPORT3: #ifndef CONFIG_SAMA5_UHPHS_RHPORT3 udbg("ERROR: RHPort3 is not available in this configuration\n"); return; #else pinset = PIO_USBC_VBUS_ENABLE; break; #endif default: udbg("ERROR: RHPort%d is not supported\n", rhport+1); return; } /* Then enable or disable VBUS power */ if (enable) { /* Enable the Power Switch by driving the enable pin low */ sam_piowrite(pinset, false); } else { /* Disable the Power Switch by driving the enable pin high */ sam_piowrite(pinset, true); } }
int usbhost_devaddr_create(FAR struct usbhost_devaddr_s *hcd, FAR void *associate) { FAR struct usbhost_devhash_s *hentry; uint8_t hvalue; int devaddr; /* Allocate a hash table entry */ hentry = (FAR struct usbhost_devhash_s *)kmalloc(sizeof(struct usbhost_devhash_s)); if (!hentry) { udbg("ERROR: Failed to allocate a hash table entry\n"); return -ENOMEM; } /* Get exclusive access to the HCD device address data */ usbhost_takesem(hcd); /* Allocate a device address */ devaddr = usbhost_devaddr_allocate(hcd); if (devaddr < 0) { udbg("ERROR: Failed to allocate a device address\n"); free(hentry); } else { /* Initialize the hash table entry */ hentry->devaddr = devaddr; hentry->payload = associate; /* Add the new device address to the hash table */ hvalue = usbhost_devaddr_hash(devaddr); hentry->flink = hcd->hashtab[hvalue]; hcd->hashtab[hvalue] = hentry; /* Try to re-use the lowest numbered device addresses */ if (hcd->next > devaddr) { hcd->next = devaddr; } } usbhost_givesem(hcd); return devaddr; }
void usbip_stop_threads(struct usbip_device *ud) { /* kill threads related to this sdev, if v.c. exists */ if (ud->tcp_rx.thread != NULL) { send_sig(SIGKILL, ud->tcp_rx.thread, 1); wait_for_completion(&ud->tcp_rx.thread_done); udbg("rx_thread for ud %p has finished\n", ud); } if (ud->tcp_tx.thread != NULL) { send_sig(SIGKILL, ud->tcp_tx.thread, 1); wait_for_completion(&ud->tcp_tx.thread_done); udbg("tx_thread for ud %p has finished\n", ud); } }
int stm32_usbhost_initialize(void) { int pid; int ret; /* First, register all of the class drivers needed to support the drivers * that we care about: */ uvdbg("Register class drivers\n"); ret = usbhost_storageinit(); if (ret != OK) { udbg("Failed to register the mass storage class\n"); } /* Then get an instance of the USB host interface */ uvdbg("Initialize USB host\n"); g_drvr = usbhost_initialize(0); if (g_drvr) { /* Start a thread to handle device connection. */ uvdbg("Start usbhost_waiter\n"); pid = TASK_CREATE("usbhost", CONFIG_USBHOST_DEFPRIO, CONFIG_USBHOST_STACKSIZE, (main_t)usbhost_waiter, (FAR char * const *)NULL); return pid < 0 ? -ENOEXEC : OK; } return -ENODEV; }
static ssize_t store_match_busid(struct device_driver *dev, const char *buf, size_t count) { int len; char busid[BUS_ID_SIZE]; if (count < 5) return -EINVAL; /* strnlen() does not include \0 */ len = strnlen(buf + 4, BUS_ID_SIZE); /* busid needs to include \0 termination */ if (!(len < BUS_ID_SIZE)) return -EINVAL; strncpy(busid, buf + 4, BUS_ID_SIZE); if (!strncmp(buf, "add ", 4)) { if (add_match_busid(busid) < 0) return -ENOMEM; else { udbg("add busid %s\n", busid); return count; } } else if (!strncmp(buf, "del ", 4)) { if (del_match_busid(busid) < 0) return -ENODEV; else { udbg("del busid %s\n", busid); return count; } } else return -EINVAL; }
static inline int usbhost_classbind(FAR struct usbhost_hubport_s *hport, const uint8_t *configdesc, int desclen, struct usbhost_id_s *id, FAR struct usbhost_class_s **usbclass) { FAR struct usbhost_class_s *devclass; FAR const struct usbhost_registry_s *reg; int ret = -EINVAL; /* Is there is a class implementation registered to support this device. */ reg = usbhost_findclass(id); uvdbg("usbhost_findclass: %p\n", reg); if (reg != NULL) { /* Yes.. there is a class for this device. Get an instance of * its interface. */ ret = -ENOMEM; devclass = CLASS_CREATE(reg, hport, id); uvdbg("CLASS_CREATE: %p\n", devclass); if (devclass != NULL) { /* Then bind the newly instantiated class instance */ ret = CLASS_CONNECT(devclass, configdesc, desclen); if (ret < 0) { /* On failures, call the class disconnect method which * should then free the allocated devclass instance. */ udbg("CLASS_CONNECT failed: %d\n", ret); CLASS_DISCONNECTED(devclass); } else { *usbclass = devclass; } } } uvdbg("Returning: %d\n", ret); return ret; }
static int usbhost_hubpwr(FAR struct usbhost_hubpriv_s *priv, FAR struct usbhost_hubport_s *hport, bool on) { FAR struct usb_ctrlreq_s *ctrlreq; uint16_t req; int port; int ret; /* Are we enabling or disabling power? */ if (on) { req = USBHUB_REQ_SETFEATURE; } else { req = USBHUB_REQ_CLEARFEATURE; } /* Enable/disable power to all downstream ports */ ctrlreq = priv->ctrlreq; DEBUGASSERT(ctrlreq); for (port = 1; port <= priv->nports; port++) { ctrlreq->type = USBHUB_REQ_TYPE_PORT; ctrlreq->req = req; usbhost_putle16(ctrlreq->value, USBHUB_PORT_FEAT_POWER); usbhost_putle16(ctrlreq->index, port); usbhost_putle16(ctrlreq->len, 0); ret = DRVR_CTRLOUT(hport->drvr, hport->ep0, ctrlreq, NULL); if (ret < 0) { udbg("ERROR: Failed to power %s port %d: %d\n", on ? "UP" : "DOWN", port, ret); return ret; } } return OK; }
static int usbhost_hport_activate(FAR struct usbhost_hubport_s *hport) { struct usbhost_epdesc_s epdesc; int ret; uvdbg("Activating port %d\n", hport->port); epdesc.hport = hport; epdesc.addr = 0; epdesc.in = false; epdesc.xfrtype = USB_EP_ATTR_XFER_CONTROL; epdesc.interval = 0; epdesc.mxpacketsize = (hport->speed == USB_SPEED_HIGH) ? 64 : 8; ret = DRVR_EPALLOC(hport->drvr, &epdesc, &hport->ep0); if (ret < 0) { udbg("ERROR: Failed to allocate ep0: %d\n", ret); } return ret; }
void usbip_dump_header(struct usbip_header *pdu) { udbg("BASE: cmd %u bus %u dev %u seq %u pipe %04x\n", pdu->base.command, pdu->base.busnum, pdu->base.devnum, pdu->base.seqnum, pdu->base.pipe); usbip_dump_pipe(pdu->base.pipe); switch(pdu->base.command) { case USBIP_CMD_SUBMIT: udbg("CMD_SUBMIT: x_flags %u x_len %u bw %u sf %u #p %u iv %u\n", pdu->u.cmd_submit.transfer_flags, pdu->u.cmd_submit.transfer_buffer_length, pdu->u.cmd_submit.bandwidth, pdu->u.cmd_submit.start_frame, pdu->u.cmd_submit.number_of_packets, pdu->u.cmd_submit.interval); break; case USBIP_CMD_UNLINK: udbg("CMD_UNLINK: seq %u\n", pdu->u.cmd_unlink.seqnum); break; case USBIP_RET_SUBMIT: udbg("RET_SUBMIT: st %d al %u bw %u sf %d ec %d\n", pdu->u.ret_submit.status, pdu->u.ret_submit.actual_length, pdu->u.ret_submit.bandwidth, pdu->u.ret_submit.start_frame, pdu->u.ret_submit.error_count); case USBIP_RET_UNLINK: udbg("RET_UNLINK: status %d\n", pdu->u.ret_unlink.status); break; default: /* NOT REACHED */ udbg("UNKNOWN\n"); } }
static FAR struct usbhost_class_s * usbhost_create(FAR struct usbhost_hubport_s *hport, FAR const struct usbhost_id_s *id) { FAR struct usbhost_hubclass_s *alloc; FAR struct usbhost_class_s *hubclass; FAR struct usbhost_hubpriv_s *priv; size_t maxlen; int port; int ret; /* Allocate a USB host class instance */ alloc = kmm_zalloc(sizeof(struct usbhost_hubclass_s)); if (alloc == NULL) { return NULL; } /* Initialize the public class structure */ hubclass = &alloc->hubclass; hubclass->hport = hport; hubclass->connect = usbhost_connect; hubclass->disconnected = usbhost_disconnected; /* Initialize the private class structure */ priv = &alloc->hubpriv; /* Allocate memory for control requests */ ret = DRVR_ALLOC(hport->drvr, (FAR uint8_t **)&priv->ctrlreq, &maxlen); if (ret < 0) { udbg("ERROR: DRVR_ALLOC failed: %d\n", ret); goto errout_with_hub; } /* Allocate buffer for status change (INT) endpoint. */ ret = DRVR_IOALLOC(hport->drvr, &priv->buffer, INTIN_BUFSIZE); if (ret < 0) { udbg("ERROR: DRVR_IOALLOC failed: %d\n", ret); goto errout_with_ctrlreq; } /* Initialize semaphores (this works okay in the interrupt context) */ sem_init(&priv->exclsem, 0, 1); /* Initialize per-port data */ for (port = 0; port < USBHUB_MAX_PORTS; port++) { FAR struct usbhost_hubport_s *child; /* Initialize the hub port descriptor */ child = &priv->hport[port]; memset(child, 0, sizeof(struct usbhost_hubport_s)); child->drvr = hport->drvr; child->parent = hport; child->port = port; child->speed = USB_SPEED_FULL; } return hubclass; errout_with_ctrlreq: kmm_free(priv->ctrlreq); errout_with_hub: kmm_free(priv); return NULL; }
int stm32_bringup(void) { #ifdef HAVE_RTC_DRIVER FAR struct rtc_lowerhalf_s *lower; #endif int ret = OK; #ifdef CONFIG_ZEROCROSS /* Configure the zero-crossing driver */ stm32_zerocross_initialize(); #endif #ifdef CONFIG_RGBLED /* Configure the RGB LED driver */ stm32_rgbled_setup(); #endif #if defined(CONFIG_PCA9635PW) /* Initialize the PCA9635 chip */ ret = stm32_pca9635_initialize(); if (ret < 0) { sdbg("ERROR: stm32_pca9635_initialize failed: %d\n", ret); } #endif #ifdef HAVE_SDIO /* Initialize the SDIO block driver */ ret = stm32_sdio_initialize(); if (ret != OK) { fdbg("ERROR: Failed to initialize MMC/SD driver: %d\n", ret); return ret; } #endif #ifdef HAVE_USBHOST /* Initialize USB host operation. stm32_usbhost_initialize() starts a thread * will monitor for USB connection and disconnection events. */ ret = stm32_usbhost_initialize(); if (ret != OK) { udbg("ERROR: Failed to initialize USB host: %d\n", ret); return ret; } #endif #ifdef HAVE_USBMONITOR /* Start the USB Monitor */ ret = usbmonitor_start(0, NULL); if (ret != OK) { udbg("ERROR: Failed to start USB monitor: %d\n", ret); return ret; } #endif #ifdef HAVE_RTC_DRIVER /* Instantiate the STM32 lower-half RTC driver */ lower = stm32_rtc_lowerhalf(); if (!lower) { sdbg("ERROR: Failed to instantiate the RTC lower-half driver\n"); return -ENOMEM; } else { /* Bind the lower half driver and register the combined RTC driver * as /dev/rtc0 */ ret = rtc_initialize(0, lower); if (ret < 0) { sdbg("ERROR: Failed to bind/register the RTC driver: %d\n", ret); return ret; } } #endif #ifdef HAVE_ELF /* Initialize the ELF binary loader */ ret = elf_initialize(); if (ret < 0) { sdbg("ERROR: Initialization of the ELF loader failed: %d\n", ret); } #endif #ifdef CONFIG_MAX31855 ret = stm32_max31855initialize("/dev/temp0"); #endif #ifdef CONFIG_MAX6675 ret = stm32_max6675initialize("/dev/temp0"); #endif #ifdef CONFIG_FS_PROCFS /* Mount the procfs file system */ ret = mount(NULL, STM32_PROCFS_MOUNTPOINT, "procfs", 0, NULL); if (ret < 0) { sdbg("ERROR: Failed to mount procfs at %s: %d\n", STM32_PROCFS_MOUNTPOINT, ret); } #endif return ret; }
int usbhost_enumerate(FAR struct usbhost_hubport_s *hport, FAR struct usbhost_class_s **devclass) { FAR struct usb_ctrlreq_s *ctrlreq = NULL; struct usbhost_id_s id; size_t maxlen; unsigned int cfglen; uint8_t maxpacketsize; uint8_t descsize; uint8_t funcaddr = 0; FAR uint8_t *buffer = NULL; int ret; DEBUGASSERT(hport != NULL && hport->drvr != NULL); /* Allocate descriptor buffers for use in this function. We will need two: * One for the request and one for the data buffer. */ ret = DRVR_ALLOC(hport->drvr, (FAR uint8_t **)&ctrlreq, &maxlen); if (ret < 0) { udbg("DRVR_ALLOC failed: %d\n", ret); return ret; } ret = DRVR_ALLOC(hport->drvr, &buffer, &maxlen); if (ret < 0) { udbg("DRVR_ALLOC failed: %d\n", ret); goto errout; } /* Pick an appropriate packet size for this device * * USB 2.0, Paragraph 5.5.3 "Control Transfer Packet Size Constraints" * * "An endpoint for control transfers specifies the maximum data * payload size that the endpoint can accept from or transmit to * the bus. The allowable maximum control transfer data payload * sizes for full-speed devices is 8, 16, 32, or 64 bytes; for * high-speed devices, it is 64 bytes and for low-speed devices, * it is 8 bytes. This maximum applies to the data payloads of the * Data packets following a Setup..." */ if (hport->speed == USB_SPEED_HIGH) { /* For high-speed, we must use 64 bytes */ maxpacketsize = 64; descsize = USB_SIZEOF_DEVDESC; } else { /* Eight will work for both low- and full-speed */ maxpacketsize = 8; descsize = 8; } /* Configure EP0 with the initial maximum packet size */ DRVR_EP0CONFIGURE(hport->drvr, hport->ep0, 0, hport->speed, maxpacketsize); /* Read first bytes of the device descriptor */ ctrlreq->type = USB_REQ_DIR_IN | USB_REQ_RECIPIENT_DEVICE; ctrlreq->req = USB_REQ_GETDESCRIPTOR; usbhost_putle16(ctrlreq->value, (USB_DESC_TYPE_DEVICE << 8)); usbhost_putle16(ctrlreq->index, 0); usbhost_putle16(ctrlreq->len, descsize); ret = DRVR_CTRLIN(hport->drvr, hport->ep0, ctrlreq, buffer); if (ret < 0) { udbg("ERROR: Failed to get device descriptor, length=%d: %d\n", descsize, ret); goto errout; } /* Extract the correct max packetsize from the device descriptor */ maxpacketsize = ((struct usb_devdesc_s *)buffer)->mxpacketsize; uvdbg("maxpacksetsize: %d\n", maxpacketsize); /* And reconfigure EP0 with the correct maximum packet size */ DRVR_EP0CONFIGURE(hport->drvr, hport->ep0, 0, hport->speed, maxpacketsize); /* Now read the full device descriptor (if we have not already done so) */ if (descsize < USB_SIZEOF_DEVDESC) { ctrlreq->type = USB_REQ_DIR_IN | USB_REQ_RECIPIENT_DEVICE; ctrlreq->req = USB_REQ_GETDESCRIPTOR; usbhost_putle16(ctrlreq->value, (USB_DESC_TYPE_DEVICE << 8)); usbhost_putle16(ctrlreq->index, 0); usbhost_putle16(ctrlreq->len, USB_SIZEOF_DEVDESC); ret = DRVR_CTRLIN(hport->drvr, hport->ep0, ctrlreq, buffer); if (ret < 0) { udbg("ERROR: Failed to get device descriptor, length=%d: %d\n", USB_SIZEOF_DEVDESC, ret); goto errout; } } /* Get class identification information from the device descriptor. Most * devices set this to USB_CLASS_PER_INTERFACE (zero) and provide the * identification information in the interface descriptor(s). That allows * a device to support multiple, different classes. */ (void)usbhost_devdesc((struct usb_devdesc_s *)buffer, &id); /* Assign a function address to the device connected to this port */ funcaddr = usbhost_devaddr_create(hport); if (funcaddr < 0) { udbg("ERROR: usbhost_devaddr_create failed: %d\n", ret); goto errout; } /* Set the USB device address */ ctrlreq->type = USB_REQ_DIR_OUT | USB_REQ_RECIPIENT_DEVICE; ctrlreq->req = USB_REQ_SETADDRESS; usbhost_putle16(ctrlreq->value, (uint16_t)funcaddr); usbhost_putle16(ctrlreq->index, 0); usbhost_putle16(ctrlreq->len, 0); ret = DRVR_CTRLOUT(hport->drvr, hport->ep0, ctrlreq, NULL); if (ret < 0) { udbg("ERROR: Failed to set address: %d\n"); goto errout; } usleep(2*1000); /* Assign the function address to the port */ DEBUGASSERT(hport->funcaddr == 0 && funcaddr != 0); hport->funcaddr = funcaddr; /* And reconfigure EP0 with the correct address */ DRVR_EP0CONFIGURE(hport->drvr, hport->ep0, hport->funcaddr, hport->speed, maxpacketsize); /* Get the configuration descriptor (only), index == 0. Should not be * hard-coded! More logic is needed in order to handle devices with * multiple configurations. */ ctrlreq->type = USB_REQ_DIR_IN | USB_REQ_RECIPIENT_DEVICE; ctrlreq->req = USB_REQ_GETDESCRIPTOR; usbhost_putle16(ctrlreq->value, (USB_DESC_TYPE_CONFIG << 8)); usbhost_putle16(ctrlreq->index, 0); usbhost_putle16(ctrlreq->len, USB_SIZEOF_CFGDESC); ret = DRVR_CTRLIN(hport->drvr, hport->ep0, ctrlreq, buffer); if (ret < 0) { udbg("ERROR: Failed to get configuration descriptor, length=%d: %d\n", USB_SIZEOF_CFGDESC, ret); goto errout; } /* Extract the full size of the configuration data */ cfglen = (unsigned int)usbhost_getle16(((struct usb_cfgdesc_s *)buffer)->totallen); uvdbg("sizeof config data: %d\n", cfglen); /* Get all of the configuration descriptor data, index == 0 (Should not be * hard-coded!) */ ctrlreq->type = USB_REQ_DIR_IN | USB_REQ_RECIPIENT_DEVICE; ctrlreq->req = USB_REQ_GETDESCRIPTOR; usbhost_putle16(ctrlreq->value, (USB_DESC_TYPE_CONFIG << 8)); usbhost_putle16(ctrlreq->index, 0); usbhost_putle16(ctrlreq->len, cfglen); ret = DRVR_CTRLIN(hport->drvr, hport->ep0, ctrlreq, buffer); if (ret < 0) { udbg("ERROR: Failed to get configuration descriptor, length=%d: %d\n", cfglen, ret); goto errout; } /* Select device configuration 1 (Should not be hard-coded!) */ ctrlreq->type = USB_REQ_DIR_OUT | USB_REQ_RECIPIENT_DEVICE; ctrlreq->req = USB_REQ_SETCONFIGURATION; usbhost_putle16(ctrlreq->value, 1); usbhost_putle16(ctrlreq->index, 0); usbhost_putle16(ctrlreq->len, 0); ret = DRVR_CTRLOUT(hport->drvr, hport->ep0, ctrlreq, NULL); if (ret < 0) { udbg("ERROR: Failed to set configuration: %d\n", ret); goto errout; } /* Was the class identification information provided in the device * descriptor? Or do we need to find it in the interface descriptor(s)? */ if (id.base == USB_CLASS_PER_INTERFACE) { /* Get the class identification information for this device from the * interface descriptor(s). Hmmm.. More logic is need to handle the * case of multiple interface descriptors. */ ret = usbhost_configdesc(buffer, cfglen, &id); if (ret < 0) { udbg("ERROR: usbhost_configdesc failed: %d\n", ret); goto errout; } } /* Some devices may require some delay before initialization */ usleep(100*1000); /* Parse the configuration descriptor and bind to the class instance for the * device. This needs to be the last thing done because the class driver * will begin configuring the device. */ ret = usbhost_classbind(hport, buffer, cfglen, &id, devclass); if (ret < 0) { udbg("ERROR: usbhost_classbind failed %d\n", ret); } errout: if (ret < 0) { /* Release the device function address on any failure */ usbhost_devaddr_destroy(hport, funcaddr); hport->funcaddr = 0; } /* Release temporary buffers in any event */ if (buffer != NULL) { DRVR_FREE(hport->drvr, buffer); } if (ctrlreq) { DRVR_FREE(hport->drvr, (FAR uint8_t *)ctrlreq); } return ret; }
static void usbhost_hub_event(FAR void *arg) { FAR struct usbhost_class_s *hubclass; FAR struct usbhost_hubport_s *hport; FAR struct usbhost_hubport_s *connport; FAR struct usbhost_hubpriv_s *priv; FAR struct usb_ctrlreq_s *ctrlreq; struct usb_portstatus_s portstatus; irqstate_t flags; uint16_t status; uint16_t change; uint16_t mask; uint16_t feat; uint8_t statuschange; int port; int ret; DEBUGASSERT(arg != NULL); hubclass = (FAR struct usbhost_class_s *)arg; priv = &((FAR struct usbhost_hubclass_s *)hubclass)->hubpriv; /* Has the hub been disconnected? */ if (priv->disconnected) { uvdbg("Disconnected\n"); return; } /* No.. then set up to process the hub event */ DEBUGASSERT(priv->ctrlreq); ctrlreq = priv->ctrlreq; DEBUGASSERT(hubclass->hport); hport = hubclass->hport; statuschange = priv->buffer[0]; uvdbg("StatusChange: %02x\n", statuschange); /* Check for status change on any port */ for (port = 1; port <= priv->nports; port++) { /* Check if port status has changed */ if ((statuschange & (1 << port)) == 0) { continue; } uvdbg("Port %d status change\n", port); /* Port status changed, check what happened */ statuschange &= ~(1 << port); /* Read hub port status */ ctrlreq->type = USB_REQ_DIR_IN | USBHUB_REQ_TYPE_PORT; ctrlreq->req = USBHUB_REQ_GETSTATUS; usbhost_putle16(ctrlreq->value, 0); usbhost_putle16(ctrlreq->index, port); usbhost_putle16(ctrlreq->len, USB_SIZEOF_PORTSTS); ret = DRVR_CTRLIN(hport->drvr, hport->ep0, ctrlreq, (FAR uint8_t *)&portstatus); if (ret < 0) { udbg("ERROR: Failed to read port %d status: %d\n", port, ret); continue; } status = usbhost_getle16(portstatus.status); change = usbhost_getle16(portstatus.change); /* First, clear all change bits */ mask = 1; feat = USBHUB_PORT_FEAT_CCONNECTION; while (change) { if (change & mask) { ctrlreq->type = USBHUB_REQ_TYPE_PORT; ctrlreq->req = USBHUB_REQ_CLEARFEATURE; usbhost_putle16(ctrlreq->value, feat); usbhost_putle16(ctrlreq->index, port); usbhost_putle16(ctrlreq->len, 0); ret = DRVR_CTRLOUT(hport->drvr, hport->ep0, ctrlreq, NULL); if (ret < 0) { udbg("ERROR: Failed to clear port %d change mask %04x: %d\n", port, mask, ret); } change &= (~mask); } mask <<= 1; feat++; } change = usbhost_getle16(portstatus.change); /* Handle connect or disconnect, no power management */ if ((change & USBHUB_PORT_STAT_CCONNECTION) != 0) { uint16_t debouncetime = 0; uint16_t debouncestable = 0; uint16_t connection = 0xffff; uvdbg("Port %d status %04x change %04x\n", port, status, change); /* Debounce */ while (debouncetime < 1500) { ctrlreq->type = USB_REQ_DIR_IN | USBHUB_REQ_TYPE_PORT; ctrlreq->req = USBHUB_REQ_GETSTATUS; usbhost_putle16(ctrlreq->value, 0); usbhost_putle16(ctrlreq->index, port); usbhost_putle16(ctrlreq->len, USB_SIZEOF_PORTSTS); ret = DRVR_CTRLIN(hport->drvr, hport->ep0, ctrlreq, (FAR uint8_t *)&portstatus); if (ret < 0) { udbg("ERROR: Failed to get port %d status: %d\n", port, ret); break; } status = usbhost_getle16(portstatus.status); change = usbhost_getle16(portstatus.change); if ((change & USBHUB_PORT_STAT_CCONNECTION) == 0 && (status & USBHUB_PORT_STAT_CONNECTION) == connection) { debouncestable += 25; if (debouncestable >= 100) { uvdbg("Port %d debouncestable=%d\n", port, debouncestable); break; } } else { debouncestable = 0; connection = status & USBHUB_PORT_STAT_CONNECTION; } if ((change & USBHUB_PORT_STAT_CCONNECTION) != 0) { ctrlreq->type = USBHUB_REQ_TYPE_PORT; ctrlreq->req = USBHUB_REQ_CLEARFEATURE; usbhost_putle16(ctrlreq->value, USBHUB_PORT_FEAT_CCONNECTION); usbhost_putle16(ctrlreq->index, port); usbhost_putle16(ctrlreq->len, 0); (void)DRVR_CTRLOUT(hport->drvr, hport->ep0, ctrlreq, NULL); } debouncetime += 25; usleep(25*1000); } if (ret < 0 || debouncetime >= 1500) { udbg("ERROR: Failed to debounce port %d: %d\n", port, ret); continue; } if ((status & USBHUB_PORT_STAT_CONNECTION) != 0) { /* Device connected to a port on the hub */ uvdbg("Connection on port %d\n", port); ctrlreq->type = USBHUB_REQ_TYPE_PORT; ctrlreq->req = USBHUB_REQ_SETFEATURE; usbhost_putle16(ctrlreq->value, USBHUB_PORT_FEAT_RESET); usbhost_putle16(ctrlreq->index, port); usbhost_putle16(ctrlreq->len, 0); ret = DRVR_CTRLOUT(hport->drvr, hport->ep0, ctrlreq, NULL); if (ret < 0) { udbg("ERROR: Failed to reset port %d: %d\n", port, ret); continue; } usleep(100*1000); ctrlreq->type = USB_REQ_DIR_IN | USBHUB_REQ_TYPE_PORT; ctrlreq->req = USBHUB_REQ_GETSTATUS; usbhost_putle16(ctrlreq->value, 0); usbhost_putle16(ctrlreq->index, port); usbhost_putle16(ctrlreq->len, USB_SIZEOF_PORTSTS); ret = DRVR_CTRLIN(hport->drvr, hport->ep0, ctrlreq, (FAR uint8_t *)&portstatus); if (ret < 0) { udbg("ERROR: Failed to get port %d status: %d\n", port, ret); continue; } status = usbhost_getle16(portstatus.status); change = usbhost_getle16(portstatus.change); uvdbg("port %d status %04x change %04x after reset\n", port, status, change); if ((status & USBHUB_PORT_STAT_RESET) == 0 && (status & USBHUB_PORT_STAT_ENABLE) != 0) { if ((change & USBHUB_PORT_STAT_CRESET) != 0) { ctrlreq->type = USBHUB_REQ_TYPE_PORT; ctrlreq->req = USBHUB_REQ_CLEARFEATURE; usbhost_putle16(ctrlreq->value, USBHUB_PORT_FEAT_CRESET); usbhost_putle16(ctrlreq->index, port); usbhost_putle16(ctrlreq->len, 0); (void)DRVR_CTRLOUT(hport->drvr, hport->ep0, ctrlreq, NULL); } connport = &priv->hport[port]; if ((status & USBHUB_PORT_STAT_HIGH_SPEED) != 0) { connport->speed = USB_SPEED_HIGH; } else if ((status & USBHUB_PORT_STAT_LOW_SPEED) != 0) { connport->speed = USB_SPEED_LOW; } else { connport->speed = USB_SPEED_FULL; } /* Activate the hub port by assigning it a control endpoint. */ ret = usbhost_hport_activate(connport); if (ret < 0) { udbg("ERROR: usbhost_hport_activate failed: %d\n", ret); } else { /* Inform waiters that a new device has been connected */ ret = DRVR_CONNECT(connport->drvr, connport, true); if (ret < 0) { udbg("ERROR: DRVR_CONNECT failed: %d\n", ret); usbhost_hport_deactivate(connport); } } } else { udbg("ERROR: Failed to enable port %d\n", port); continue; } } else { /* Device disconnected from a port on the hub. Release port * resources. */ uvdbg("Disconnection on port %d\n", port); /* Free any devices classes connect on this hub port */ connport = &priv->hport[port]; if (connport->devclass != NULL) { CLASS_DISCONNECTED(connport->devclass); connport->devclass = NULL; } /* Free any resources used by the hub port */ usbhost_hport_deactivate(connport); } } else if (change) { udbg("WARNING: status %04x change %04x not handled\n", status, change); } } /* Check for hub status change */ if ((statuschange & 1) != 0) { /* Hub status changed */ udbg("WARNING: Hub status changed, not handled\n"); } /* The preceding sequence of events may take a significant amount of * time and it is possible that the hub may have been removed while this * logic operated. In any event, we will get here after several failures. * But we do not want to schedule another hub event if the hub has been * removed. */ flags = irqsave(); if (!priv->disconnected) { /* Wait for the next hub event */ ret = DRVR_ASYNCH(hport->drvr, priv->intin, (FAR uint8_t *)priv->buffer, INTIN_BUFSIZE, usbhost_callback, hubclass); if (ret < 0) { udbg("ERROR: Failed to queue interrupt endpoint: %d\n", ret); } } irqrestore(flags); }
static inline int usbhost_hubdesc(FAR struct usbhost_class_s *hubclass) { FAR struct usbhost_hubpriv_s *priv; FAR struct usbhost_hubport_s *hport; FAR struct usb_ctrlreq_s *ctrlreq; struct usb_hubdesc_s hubdesc; uint16_t hubchar; int ret; uvdbg("Read hub descriptor\n"); DEBUGASSERT(hubclass != NULL); priv = &((FAR struct usbhost_hubclass_s *)hubclass)->hubpriv; DEBUGASSERT(hubclass->hport); hport = hubclass->hport; /* Get the hub descriptor */ ctrlreq = priv->ctrlreq; DEBUGASSERT(ctrlreq); ctrlreq->type = USB_REQ_DIR_IN | USBHUB_REQ_TYPE_HUB; ctrlreq->req = USBHUB_REQ_GETDESCRIPTOR; usbhost_putle16(ctrlreq->value, (USB_DESC_TYPE_HUB << 8)); usbhost_putle16(ctrlreq->index, 0); usbhost_putle16(ctrlreq->len, USB_SIZEOF_HUBDESC); ret = DRVR_CTRLIN(hport->drvr, hport->ep0, ctrlreq, (FAR uint8_t *)&hubdesc); if (ret < 0) { udbg("ERROR: Failed to read hub descriptor: %d\n", ret); return ret; } priv->nports = hubdesc.nports; hubchar = usbhost_getle16(hubdesc.characteristics); priv->lpsm = (hubchar & USBHUB_CHAR_LPSM_MASK) >> USBHUB_CHAR_LPSM_SHIFT; priv->compounddev = (hubchar & USBHUB_CHAR_COMPOUND) ? true : false; priv->ocmode = (hubchar & USBHUB_CHAR_OCPM_MASK) >> USBHUB_CHAR_OCPM_SHIFT; priv->indicator = (hubchar & USBHUB_CHAR_PORTIND) ? true : false; priv->pwrondelay = (2 * hubdesc.pwrondelay); priv->ctrlcurrent = hubdesc.ctrlcurrent; uvdbg("Hub Descriptor:\n"); uvdbg(" bDescLength: %d\n", hubdesc.len); uvdbg(" bDescriptorType: 0x%02x\n", hubdesc.type); uvdbg(" bNbrPorts: %d\n", hubdesc.nports); uvdbg(" wHubCharacteristics: 0x%04x\n", usbhost_getle16(hubdesc.characteristics)); uvdbg(" lpsm: %d\n", priv->lpsm); uvdbg(" compounddev: %s\n", priv->compounddev ? "TRUE" : "FALSE"); uvdbg(" ocmode: %d\n", priv->ocmode); uvdbg(" indicator: %s\n", priv->indicator ? "TRUE" : "FALSE"); uvdbg(" bPwrOn2PwrGood: %d\n", hubdesc.pwrondelay); uvdbg(" pwrondelay: %d\n", priv->pwrondelay); uvdbg(" bHubContrCurrent: %d\n", hubdesc.ctrlcurrent); uvdbg(" DeviceRemovable: %d\n", hubdesc.devattached); uvdbg(" PortPwrCtrlMask: %d\n", hubdesc.pwrctrlmask); return OK; }
static inline int usbhost_cfgdesc(FAR struct usbhost_class_s *hubclass, FAR const uint8_t *configdesc, int desclen) { FAR struct usbhost_hubpriv_s *priv; FAR struct usbhost_hubport_s *hport; FAR struct usb_cfgdesc_s *cfgdesc; FAR struct usb_desc_s *desc; FAR struct usbhost_epdesc_s intindesc; int remaining; uint8_t found = 0; int ret; DEBUGASSERT(hubclass != NULL); priv = &((FAR struct usbhost_hubclass_s *)hubclass)->hubpriv; DEBUGASSERT(hubclass->hport); hport = hubclass->hport; DEBUGASSERT(configdesc != NULL && desclen >= sizeof(struct usb_cfgdesc_s)); /* Initialize the interrupt IN endpoint information (only to prevent * compiler complaints) */ intindesc.hport = hport; intindesc.addr = 0; intindesc.in = true; intindesc.xfrtype = USB_EP_ATTR_XFER_INT; intindesc.interval = 0; intindesc.mxpacketsize = 0; /* Verify that we were passed a configuration descriptor */ cfgdesc = (FAR struct usb_cfgdesc_s *)configdesc; if (cfgdesc->type != USB_DESC_TYPE_CONFIG) { return -EINVAL; } /* Get the total length of the configuration descriptor (little endian). * It might be a good check to get the number of interfaces here too. */ remaining = (int)usbhost_getle16(cfgdesc->totallen); /* Skip to the next entry descriptor */ configdesc += cfgdesc->len; remaining -= cfgdesc->len; /* Loop where there are more descriptors to examine */ while (remaining >= sizeof(struct usb_desc_s)) { /* What is the next descriptor? */ desc = (FAR struct usb_desc_s *)configdesc; switch (desc->type) { /* Interface descriptor. We really should get the number of endpoints * from this descriptor too. */ case USB_DESC_TYPE_INTERFACE: { FAR struct usb_ifdesc_s *ifdesc = (FAR struct usb_ifdesc_s *)configdesc; uvdbg("Interface descriptor\n"); DEBUGASSERT(remaining >= USB_SIZEOF_IFDESC); /* Save the interface number and mark ONLY the interface found */ priv->ifno = ifdesc->ifno; found = USBHOST_IFFOUND; } break; /* Endpoint descriptor. Here, we expect one interrupt IN endpoints. */ case USB_DESC_TYPE_ENDPOINT: { FAR struct usb_epdesc_s *epdesc = (FAR struct usb_epdesc_s *)configdesc; uvdbg("Endpoint descriptor\n"); DEBUGASSERT(remaining >= USB_SIZEOF_EPDESC); /* Check for an interrupt endpoint. */ if ((epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) == USB_EP_ATTR_XFER_INT) { /* Yes.. it is a interrupt endpoint. IN or OUT? */ if (USB_ISEPOUT(epdesc->addr)) { /* It is an OUT interrupt endpoint. Ignore */ uvdbg("Interrupt OUT EP addr:%d mxpacketsize:%d\n", (epdesc->addr & USB_EP_ADDR_NUMBER_MASK), usbhost_getle16(epdesc->mxpacketsize)); } else { /* It is an IN interrupt endpoint. */ found |= USBHOST_EPINFOUND; /* Save the interrupt IN endpoint information */ intindesc.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK; intindesc.interval = epdesc->interval; intindesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize); uvdbg("Interrupt IN EP: addr=%d interval=%d mxpacketsize=%d\n", intindesc.addr, intindesc.interval, intindesc.mxpacketsize); } } } break; /* Other descriptors are just ignored for now */ default: break; } /* If we found everything we need with this interface, then break out * of the loop early. */ if (found == USBHOST_ALLFOUND) { break; } /* Increment the address of the next descriptor */ configdesc += desc->len; remaining -= desc->len; } /* Sanity checking... did we find all of things that we need? */ if (found != USBHOST_ALLFOUND) { ulldbg("ERROR: Found IF=%s EPIN=%s\n", (found & USBHOST_IFFOUND) != 0 ? "YES" : "NO", (found & USBHOST_EPINFOUND) != 0 ? "YES" : "NO"); return -EINVAL; } /* We are good... Allocate the interrupt IN endpoint */ ret = DRVR_EPALLOC(hport->drvr, &intindesc, &priv->intin); if (ret < 0) { udbg("ERROR: Failed to allocate Interrupt IN endpoint: %d\n", ret); (void)DRVR_EPFREE(hport->drvr, priv->intin); return ret; } ullvdbg("Endpoint allocated\n"); return OK; }
static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv, FAR const uint8_t *configdesc, int desclen) { FAR struct usbhost_hubport_s *hport; FAR struct usb_cfgdesc_s *cfgdesc; FAR struct usb_desc_s *desc; FAR struct usbhost_epdesc_s bindesc; FAR struct usbhost_epdesc_s boutdesc; int remaining; uint8_t found = 0; int ret; DEBUGASSERT(priv != NULL && priv->usbclass.hport && configdesc != NULL && desclen >= sizeof(struct usb_cfgdesc_s)); hport = priv->usbclass.hport; /* Verify that we were passed a configuration descriptor */ cfgdesc = (FAR struct usb_cfgdesc_s *)configdesc; if (cfgdesc->type != USB_DESC_TYPE_CONFIG) { return -EINVAL; } /* Get the total length of the configuration descriptor (little endian). * It might be a good check to get the number of interfaces here too. */ remaining = (int)usbhost_getle16(cfgdesc->totallen); /* Skip to the next entry descriptor */ configdesc += cfgdesc->len; remaining -= cfgdesc->len; /* Loop where there are more dscriptors to examine */ while (remaining >= sizeof(struct usb_desc_s)) { /* What is the next descriptor? */ desc = (FAR struct usb_desc_s *)configdesc; switch (desc->type) { /* Interface descriptor. We really should get the number of endpoints * from this descriptor too. */ case USB_DESC_TYPE_INTERFACE: { FAR struct usb_ifdesc_s *ifdesc = (FAR struct usb_ifdesc_s *)configdesc; uvdbg("Interface descriptor\n"); DEBUGASSERT(remaining >= USB_SIZEOF_IFDESC); /* Save the interface number and mark ONLY the interface found */ priv->ifno = ifdesc->ifno; found = USBHOST_IFFOUND; } break; /* Endpoint descriptor. Here, we expect two bulk endpoints, an IN * and an OUT. */ case USB_DESC_TYPE_ENDPOINT: { FAR struct usb_epdesc_s *epdesc = (FAR struct usb_epdesc_s *)configdesc; uvdbg("Endpoint descriptor\n"); DEBUGASSERT(remaining >= USB_SIZEOF_EPDESC); /* Check for a bulk endpoint. */ if ((epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) == USB_EP_ATTR_XFER_BULK) { /* Yes.. it is a bulk endpoint. IN or OUT? */ if (USB_ISEPOUT(epdesc->addr)) { /* It is an OUT bulk endpoint. There should be only one * bulk OUT endpoint. */ if ((found & USBHOST_BOUTFOUND) != 0) { /* Oops.. more than one endpoint. We don't know * what to do with this. */ return -EINVAL; } found |= USBHOST_BOUTFOUND; /* Save the bulk OUT endpoint information */ boutdesc.hport = hport; boutdesc.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK; boutdesc.in = false; boutdesc.xfrtype = USB_EP_ATTR_XFER_BULK; boutdesc.interval = epdesc->interval; boutdesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize); uvdbg("Bulk OUT EP addr:%d mxpacketsize:%d\n", boutdesc.addr, boutdesc.mxpacketsize); } else { /* It is an IN bulk endpoint. There should be only one * bulk IN endpoint. */ if ((found & USBHOST_BINFOUND) != 0) { /* Oops.. more than one endpoint. We don't know * what to do with this. */ return -EINVAL; } found |= USBHOST_BINFOUND; /* Save the bulk IN endpoint information */ bindesc.hport = hport; bindesc.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK; bindesc.in = 1; bindesc.xfrtype = USB_EP_ATTR_XFER_BULK; bindesc.interval = epdesc->interval; bindesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize); uvdbg("Bulk IN EP addr:%d mxpacketsize:%d\n", bindesc.addr, bindesc.mxpacketsize); } } } break; /* Other descriptors are just ignored for now */ default: break; } /* If we found everything we need with this interface, then break out * of the loop early. */ if (found == USBHOST_ALLFOUND) { break; } /* Increment the address of the next descriptor */ configdesc += desc->len; remaining -= desc->len; } /* Sanity checking... did we find all of things that we need? */ if (found != USBHOST_ALLFOUND) { ulldbg("ERROR: Found IF:%s BIN:%s BOUT:%s\n", (found & USBHOST_IFFOUND) != 0 ? "YES" : "NO", (found & USBHOST_BINFOUND) != 0 ? "YES" : "NO", (found & USBHOST_BOUTFOUND) != 0 ? "YES" : "NO"); return -EINVAL; } /* We are good... Allocate the endpoints */ ret = DRVR_EPALLOC(hport->drvr, &boutdesc, &priv->epout); if (ret < 0) { udbg("ERROR: Failed to allocate Bulk OUT endpoint\n"); return ret; } ret = DRVR_EPALLOC(hport->drvr, &bindesc, &priv->epin); if (ret < 0) { udbg("ERROR: Failed to allocate Bulk IN endpoint\n"); (void)DRVR_EPFREE(hport->drvr, priv->epout); return ret; } ullvdbg("Endpoints allocated\n"); return OK; }
/* Send/receive messages over TCP/IP. I refer drivers/block/nbd.c */ int usbip_xmit(int send, struct socket *sock, char *buf, int size, int msg_flags) { int result; struct msghdr msg; struct kvec iov; int total = 0; /* for blocks of if (dbg_flag_xmit) */ char *bp = buf; int osize= size; dbg_xmit("enter\n"); if (!sock || !buf || !size) { uerr("usbip_xmit: invalid arg, sock %p buff %p size %d\n", sock, buf, size); return -EINVAL; } if (dbg_flag_xmit) { if (send) { if (!in_interrupt()) printk(KERN_DEBUG "%-10s:", current->comm); else printk(KERN_DEBUG "interupt :"); printk("usbip_xmit: sending... , sock %p, buf %p, size %d, msg_flags %d\n", sock, buf, size, msg_flags); usbip_dump_buffer(buf, size); } } do { sock->sk->sk_allocation = GFP_NOIO; iov.iov_base = buf; iov.iov_len = size; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_namelen = 0; msg.msg_flags = msg_flags | MSG_NOSIGNAL; if (send) result = kernel_sendmsg(sock, &msg, &iov, 1, size); else result = kernel_recvmsg(sock, &msg, &iov, 1, size, MSG_WAITALL); if (result <= 0) { udbg("usbip_xmit: %s sock %p buf %p size %u ret %d total %d\n", send ? "send" : "receive", sock, buf, size, result, total); goto err; } size -= result; buf += result; total += result; } while (size > 0); if (dbg_flag_xmit) { if (!send) { if (!in_interrupt()) printk(KERN_DEBUG "%-10s:", current->comm); else printk(KERN_DEBUG "interupt :"); printk("usbip_xmit: receiving....\n"); usbip_dump_buffer(bp, osize); printk("usbip_xmit: received, osize %d ret %d size %d total %d\n", osize, result, size, total); } if (send) { printk("usbip_xmit: send, total %d\n", total); } } return total; err: return result; }
int board_app_initialize(uintptr_t arg) { #ifdef HAVE_RTC_DRIVER FAR struct rtc_lowerhalf_s *rtclower; #endif #if defined(HAVE_N25QXXX) FAR struct mtd_dev_s *mtd_temp; #endif #if defined(HAVE_N25QXXX_CHARDEV) char blockdev[18]; char chardev[12]; #endif int ret; (void)ret; #ifdef HAVE_PROC /* mount the proc filesystem */ syslog(LOG_INFO, "Mounting procfs to /proc\n"); ret = mount(NULL, CONFIG_NSH_PROC_MOUNTPOINT, "procfs", 0, NULL); if (ret < 0) { syslog(LOG_ERR, "ERROR: Failed to mount the PROC filesystem: %d (%d)\n", ret, errno); return ret; } #endif #ifdef HAVE_RTC_DRIVER /* Instantiate the STM32 lower-half RTC driver */ rtclower = stm32l4_rtc_lowerhalf(); if (!rtclower) { serr("ERROR: Failed to instantiate the RTC lower-half driver\n"); return -ENOMEM; } else { /* Bind the lower half driver and register the combined RTC driver * as /dev/rtc0 */ ret = rtc_initialize(0, rtclower); if (ret < 0) { serr("ERROR: Failed to bind/register the RTC driver: %d\n", ret); return ret; } } #endif #ifdef HAVE_N25QXXX /* Create an instance of the STM32L4 QSPI device driver */ g_qspi = stm32l4_qspi_initialize(0); if (!g_qspi) { _err("ERROR: stm32l4_qspi_initialize failed\n"); return ret; } else { /* Use the QSPI device instance to initialize the * N25QXXX device. */ mtd_temp = n25qxxx_initialize(g_qspi, true); if (!mtd_temp) { _err("ERROR: n25qxxx_initialize failed\n"); return ret; } g_mtd_fs = mtd_temp; #ifdef CONFIG_MTD_PARTITION { FAR struct mtd_geometry_s geo; off_t nblocks; /* Setup a partition of 256KiB for our file system. */ ret = MTD_IOCTL(g_mtd_fs, MTDIOC_GEOMETRY, (unsigned long)(uintptr_t)&geo); if (ret < 0) { _err("ERROR: MTDIOC_GEOMETRY failed\n"); return ret; } nblocks = (256*1024) / geo.blocksize; mtd_temp = mtd_partition(g_mtd_fs, 0, nblocks); if (!mtd_temp) { _err("ERROR: mtd_partition failed\n"); return ret; } g_mtd_fs = mtd_temp; } #endif #ifdef HAVE_N25QXXX_SMARTFS /* Configure the device with no partition support */ ret = smart_initialize(N25QXXX_SMART_MINOR, g_mtd_fs, NULL); if (ret != OK) { _err("ERROR: Failed to initialize SmartFS: %d\n", ret); } #elif defined(HAVE_N25QXXX_NXFFS) /* Initialize to provide NXFFS on the N25QXXX MTD interface */ ret = nxffs_initialize(g_mtd_fs); if (ret < 0) { _err("ERROR: NXFFS initialization failed: %d\n", ret); } /* Mount the file system at /mnt/nxffs */ ret = mount(NULL, "/mnt/nxffs", "nxffs", 0, NULL); if (ret < 0) { _err("ERROR: Failed to mount the NXFFS volume: %d\n", errno); return ret; } #else /* if defined(HAVE_N25QXXX_CHARDEV) */ /* Use the FTL layer to wrap the MTD driver as a block driver */ ret = ftl_initialize(N25QXXX_MTD_MINOR, g_mtd_fs); if (ret < 0) { _err("ERROR: Failed to initialize the FTL layer: %d\n", ret); return ret; } /* Use the minor number to create device paths */ snprintf(blockdev, 18, "/dev/mtdblock%d", N25QXXX_MTD_MINOR); snprintf(chardev, 12, "/dev/mtd%d", N25QXXX_MTD_MINOR); /* Now create a character device on the block device */ /* NOTE: for this to work, you will need to make sure that * CONFIG_FS_WRITABLE is set in the config. It's not a user- * visible setting, but you can make it set by selecting an * arbitrary writable file system (you don't have to actually * use it, just select it so that the block device created via * ftl_initialize() will be writable). */ ret = bchdev_register(blockdev, chardev, false); if (ret < 0) { _err("ERROR: bchdev_register %s failed: %d\n", chardev, ret); return ret; } #endif } #endif #ifdef HAVE_USBHOST /* Initialize USB host operation. stm32l4_usbhost_initialize() starts a thread * will monitor for USB connection and disconnection events. */ ret = stm32l4_usbhost_initialize(); if (ret != OK) { udbg("ERROR: Failed to initialize USB host: %d\n", ret); return ret; } #endif #ifdef HAVE_USBMONITOR /* Start the USB Monitor */ ret = usbmonitor_start(0, NULL); if (ret != OK) { udbg("ERROR: Failed to start USB monitor: %d\n", ret); return ret; } #endif return OK; }