diff --git a/arch/arm/src/lpc17xx/lpc17_ohciram.h b/arch/arm/src/lpc17xx/lpc17_ohciram.h index 477a57a2b4..d2fc11248d 100755 --- a/arch/arm/src/lpc17xx/lpc17_ohciram.h +++ b/arch/arm/src/lpc17xx/lpc17_ohciram.h @@ -171,9 +171,8 @@ * * Configuration: * CONFIG_USBHOST_OHCIRAM_SIZE 1280 - * CONFIG_USBHOST_NTDS 2 * CONFIG_USBHOST_NEDS 2 - * CONFIG_USBHOST_TDBUFFERS 1 + * CONFIG_USBHOST_TDBUFFERS 2 * CONFIG_USBHOST_TDBUFSIZE 128 * CONFIG_USBHOST_IOBUFSIZE 512 * diff --git a/arch/arm/src/lpc17xx/lpc17_usbhost.c b/arch/arm/src/lpc17xx/lpc17_usbhost.c index d1d64ea126..8109523429 100755 --- a/arch/arm/src/lpc17xx/lpc17_usbhost.c +++ b/arch/arm/src/lpc17xx/lpc17_usbhost.c @@ -552,8 +552,16 @@ static uint8_t *lpc17_tdalloc(struct lpc17_usbhost_s *priv) static void lpc17_tdfree(struct lpc17_usbhost_s *priv, uint8_t *buffer) { struct lpc17_buflist_s *tdfree = (struct lpc17_buflist_s *)buffer; - tdfree->flink = g_tdfree; - g_tdfree = tdfree; + + /* This may get called with a NULL buffer pointer on certain error handling + * paths. + */ + + if (tdfree) + { + tdfree->flink = g_tdfree; + g_tdfree = tdfree; + } } /******************************************************************************* @@ -581,7 +589,7 @@ static uint8_t *lpc17_ioalloc(struct lpc17_usbhost_s *priv) #endif /******************************************************************************* - * Name: lpc17_tdfree + * Name: lpc17_iofree * * Description: * Return an TD buffer to the free list @@ -1045,7 +1053,7 @@ static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr) if (!buffer) { ret = -ENOMEM; - goto errout_nobuffer; + goto errout; } /* USB 2.0 spec says at least 50ms delay before port reset */ @@ -1088,6 +1096,14 @@ static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr) EDCTRL->ctrl = (uint32_t)(((struct usb_devdesc_s *)buffer)->mxpacketsize) << ED_CONTROL_MPS_SHIFT; + /* NOTE: Additional logic is needed here. The device descriptor contains + * the class, subclass, protocol, and VID/PID. However, here we have assumed + * for the time being that class == USB_CLASS_PER_INTERFACE. This is not + * generally a good assumption and will need to get fixed someday. + */ + + DEBUGASSERT(((struct usb_devdesc_s *)buffer)->class == USB_CLASS_PER_INTERFACE); + /* Set the device address to 1 */ ctrlreq->type = USB_REQ_DIR_OUT|USB_REQ_RECIPIENT_DEVICE; @@ -1157,6 +1173,14 @@ static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr) goto errout; } + /* Free the TD that we were using for the request buffer. It is not needed + * further here but it may be needed by the class driver during its connection + * operations. NOTE: lpc17_tdfree() can be called with a NULL pointer later. + */ + + lpc17_tdfree(priv, (uint8_t*)ctrlreq); + ctrlreq = NULL; + /* Some devices may require this delay before initialization */ up_mdelay(100); @@ -1174,7 +1198,6 @@ static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr) errout: lpc17_tdfree(priv, buffer); -errout_nobuffer: lpc17_tdfree(priv, (uint8_t*)ctrlreq); return ret; } @@ -1268,13 +1291,15 @@ static int lpc17_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer) * Input Parameters: * drvr - The USB host driver instance obtained as a parameter from the call to * the class create() method. - * req - Describes the request to be sent. This data will be copied from the - * user provided memory. Therefore, the req buffer may be declared on the - * stack. + * req - Describes the request to be sent. This request must lie in memory + * created by DRVR_ALLOC. * buffer - A buffer used for sending the request and for returning any * responses. This buffer must be large enough to hold the length value * in the request description. buffer must have been allocated using DRVR_ALLOC * + * NOTE: On an IN transaction, req and buffer may refer to the same allocated + * memory. + * * Returned Values: * On success, zero (OK) is returned. On a failure, a negated errno value is * returned indicating the nature of the failure diff --git a/configs/olimex-lpc1766stk/nsh/defconfig b/configs/olimex-lpc1766stk/nsh/defconfig index 272555f1ca..12a751cec9 100755 --- a/configs/olimex-lpc1766stk/nsh/defconfig +++ b/configs/olimex-lpc1766stk/nsh/defconfig @@ -593,7 +593,18 @@ CONFIG_USBDEV_TRACE=n CONFIG_USBDEV_TRACE_NRECORDS=128 # -# LPC17xx USB Configuration +# USB Host Configuration +# +# CONFIG_USBHOST +# Enables USB host support +# CONFIG_USBHOST_NPREALLOC +# Number of pre-allocated class instances +# +CONFIG_USBHOST=n +CONFIG_USBHOST_NPREALLOC=0 + +# +# LPC17xx USB Device Configuration # # CONFIG_LPC17_USBDEV_FRAME_INTERRUPT # Handle USB Start-Of-Frame events. @@ -614,6 +625,27 @@ CONFIG_LPC17_USBDEV_DMA=n CONFIG_LPC17_USBDEV_NDMADESCRIPTORS=0 CONFIG_LPC17_USBDEV_DMAINTMASK=0 +# +# LPC17xx USB Host Configuration +# +# OHCI RAM layout: +# CONFIG_USBHOST_OHCIRAM_SIZE +# Total size of OHCI RAM (in AHB SRAM Bank 1) +# CONFIG_USBHOST_NEDS +# Number of endpoint descriptors +# CONFIG_USBHOST_TDBUFFERS +# Number of transfer descriptor buffers +# CONFIG_USBHOST_TDBUFSIZE +# Size of one transfer descriptor buffer +# CONFIG_USBHOST_IOBUFSIZE +# Size of one end-user I/O buffer +# +CONFIG_USBHOST_OHCIRAM_SIZE=1280 +CONFIG_USBHOST_NEDS=2 +CONFIG_USBHOST_TDBUFFERS=3 +CONFIG_USBHOST_TDBUFSIZE=128 +CONFIG_USBHOST_IOBUFSIZE=512 + # # USB Serial Device Configuration # diff --git a/drivers/net/dm90x0.c b/drivers/net/dm90x0.c index 361a0dea8f..32dc93069e 100644 --- a/drivers/net/dm90x0.c +++ b/drivers/net/dm90x0.c @@ -1763,7 +1763,7 @@ int dm9x_initialize(void) if (vid != DM9X_DAVICOMVID || (pid != DM9X_DM9000PID && pid != DM9X_DM9010PID)) { - nlldbg("DM90x0 vender/product ID not found at this base address\n"); + nlldbg("DM90x0 vendor/product ID not found at this base address\n"); return -ENODEV; } diff --git a/drivers/usbhost/usbhost_storage.c b/drivers/usbhost/usbhost_storage.c index efc087dcce..cfe6af668b 100644 --- a/drivers/usbhost/usbhost_storage.c +++ b/drivers/usbhost/usbhost_storage.c @@ -190,8 +190,8 @@ static void usbhost_putbe32(uint8_t *dest, uint32_t val); /* Transfer descriptor memory management */ -static int usbhost_tdalloc(FAR struct usbhost_state_s *priv); -static int usbhost_tdfree(FAR struct usbhost_state_s *priv); +static inline int usbhost_tdalloc(FAR struct usbhost_state_s *priv); +static inline int usbhost_tdfree(FAR struct usbhost_state_s *priv); static FAR struct usbstrg_cbw_s *usbhost_cbwalloc(FAR struct usbhost_state_s *priv); /* struct usbhost_registry_s methods */ @@ -578,25 +578,20 @@ usbhost_writecbw(size_t startsector, uint16_t blocksize, static inline int usbhost_maxlunreq(FAR struct usbhost_state_s *priv) { - struct usb_ctrlreq_s req; - int result; - - /* Make sure that we have a buffer allocated */ + FAR struct usb_ctrlreq_s *req = (FAR struct usb_ctrlreq_s *)priv->tdbuffer; + DEBUGASSERT(priv && priv->tdbuffer); - result = usbhost_tdalloc(priv); - if (result == OK) - { - /* Request maximum logical unit number */ + /* Request maximum logical unit number. NOTE: On an IN transaction, The + * req and buffer pointers passed to DRVR_CTRLIN may refer to the same + * allocated memory. + */ - uvdbg("Request maximum logical unit number\n"); - memset(&req, 0, sizeof(struct usb_ctrlreq_s)); - req.type = USB_DIR_IN|USB_REQ_TYPE_CLASS|USB_REQ_RECIPIENT_INTERFACE; - req.req = USBSTRG_REQ_GETMAXLUN; - usbhost_putle16(req.len, 1); - - result = DRVR_CTRLIN(priv->drvr, &req, priv->tdbuffer); - } - return result; + uvdbg("Request maximum logical unit number\n"); + memset(req, 0, sizeof(struct usb_ctrlreq_s)); + req->type = USB_DIR_IN|USB_REQ_TYPE_CLASS|USB_REQ_RECIPIENT_INTERFACE; + req->req = USBSTRG_REQ_GETMAXLUN; + usbhost_putle16(req->len, 1); + return DRVR_CTRLIN(priv->drvr, req, priv->tdbuffer); } static inline int usbhost_testunitready(FAR struct usbhost_state_s *priv) @@ -604,7 +599,7 @@ static inline int usbhost_testunitready(FAR struct usbhost_state_s *priv) FAR struct usbstrg_cbw_s *cbw; int result = -ENOMEM; - /* Initialize a CBW (allocating it if necessary) */ + /* Initialize a CBW (re-using the allocated transfer buffer) */ cbw = usbhost_cbwalloc(priv); if (cbw) @@ -630,7 +625,7 @@ static inline int usbhost_requestsense(FAR struct usbhost_state_s *priv) FAR struct usbstrg_cbw_s *cbw; int result = -ENOMEM; - /* Initialize a CBW (allocating it if necessary) */ + /* Initialize a CBW (re-using the allocated transfer buffer) */ cbw = usbhost_cbwalloc(priv); if (cbw) @@ -664,7 +659,7 @@ static inline int usbhost_readcapacity(FAR struct usbhost_state_s *priv) FAR struct scsiresp_readcapacity10_s *resp; int result = -ENOMEM; - /* Initialize a CBW (allocating it if necessary) */ + /* Initialize a CBW (re-using the allocated transfer buffer) */ cbw = usbhost_cbwalloc(priv); if (cbw) @@ -704,7 +699,7 @@ static inline int usbhost_inquiry(FAR struct usbhost_state_s *priv) FAR struct scsiresp_inquiry_s *resp; int result = -ENOMEM; - /* Initialize a CBW (allocating it if necessary) */ + /* Initialize a CBW (re-using the allocated transfer buffer) */ cbw = usbhost_cbwalloc(priv); if (cbw) @@ -812,6 +807,15 @@ static void usbhost_initvolume(FAR void *arg) DEBUGASSERT(priv != NULL); + /* Set aside a transfer buffer for exclusive use by the mass storage driver */ + + result = usbhost_tdalloc(priv); + if (result != OK) + { + udbg("Failed to allocate transfer buffer\n"); + return; + } + /* Request the maximum logical unit number */ uvdbg("Get max LUN\n"); @@ -1120,17 +1124,10 @@ static void usbhost_putbe32(uint8_t *dest, uint32_t val) * ****************************************************************************/ -static int usbhost_tdalloc(FAR struct usbhost_state_s *priv) +static inline int usbhost_tdalloc(FAR struct usbhost_state_s *priv) { - int result = OK; - - /* Is a descriptor already allocated? */ - - if (!priv->tdbuffer) - { - result = DRVR_ALLOC(priv->drvr, &priv->tdbuffer, &priv->tdbuflen); - } - return result; + DEBUGASSERT(priv && priv->tdbuffer == NULL); + return DRVR_ALLOC(priv->drvr, &priv->tdbuffer, &priv->tdbuflen); } /**************************************************************************** @@ -1148,18 +1145,14 @@ static int usbhost_tdalloc(FAR struct usbhost_state_s *priv) * ****************************************************************************/ -static int usbhost_tdfree(FAR struct usbhost_state_s *priv) +static inline int usbhost_tdfree(FAR struct usbhost_state_s *priv) { - int result = OK; + int result; + DEBUGASSERT(priv && priv->tdbuffer != NULL); - /* Is a descriptor already allocated? */ - - if (!priv->tdbuffer) - { - result = DRVR_FREE(priv->drvr, priv->tdbuffer); - priv->tdbuffer = NULL; - priv->tdbuflen = 0; - } + result = DRVR_FREE(priv->drvr, priv->tdbuffer); + priv->tdbuffer = NULL; + priv->tdbuflen = 0; return result; } @@ -1167,8 +1160,8 @@ static int usbhost_tdfree(FAR struct usbhost_state_s *priv) * Name: usbhost_cbwalloc * * Description: - * Allocate and initialize a CBW. Upon successful return, the CBW is cleared - * and has the CBW signature in place. + * Initialize a CBW (re-using the allocated transfer buffer). Upon + * successful return, the CBW is cleared and has the CBW signature in place. * * Input Parameters: * priv - A reference to the class instance. @@ -1181,19 +1174,14 @@ static int usbhost_tdfree(FAR struct usbhost_state_s *priv) static FAR struct usbstrg_cbw_s *usbhost_cbwalloc(FAR struct usbhost_state_s *priv) { FAR struct usbstrg_cbw_s *cbw = NULL; - int result; - /* Allocate any special memory that the the driver may have for us */ + DEBUGASSERT(priv->tdbuffer && priv->tdbuflen >= sizeof(struct usbstrg_cbw_s)) - result = usbhost_tdalloc(priv); - if (result == OK && priv->tdbuflen >= sizeof(struct usbstrg_cbw_s)) - { - /* Intialize the CBW sructure */ + /* Intialize the CBW sructure */ - cbw = (FAR struct usbstrg_cbw_s *)priv->tdbuffer; - memset(cbw, 0, sizeof(struct usbstrg_cbw_s)); - usbhost_putle32(cbw->signature, USBSTRG_CBW_SIGNATURE); - } + cbw = (FAR struct usbstrg_cbw_s *)priv->tdbuffer; + memset(cbw, 0, sizeof(struct usbstrg_cbw_s)); + usbhost_putle32(cbw->signature, USBSTRG_CBW_SIGNATURE); return cbw; } @@ -1635,7 +1623,7 @@ static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer, ret = -ENOMEM; - /* Initialize a CBW (allocating it if necessary) */ + /* Initialize a CBW (re-using the allocated transfer buffer) */ cbw = usbhost_cbwalloc(priv); if (cbw) @@ -1727,7 +1715,7 @@ static ssize_t usbhost_write(FAR struct inode *inode, const unsigned char *buffe ret = -ENOMEM; - /* Initialize a CBW (allocating it if necessary) */ + /* Initialize a CBW (re-using the allocated transfer buffer) */ cbw = usbhost_cbwalloc(priv); if (cbw) diff --git a/include/nuttx/usb/usb.h b/include/nuttx/usb/usb.h index 69b9a1c1f7..6e45334e65 100644 --- a/include/nuttx/usb/usb.h +++ b/include/nuttx/usb/usb.h @@ -230,7 +230,7 @@ struct usb_devdesc_s uint8_t subclass; /* Device sub-class */ uint8_t protocol; /* Device protocol */ uint8_t mxpacketsize; /* Max packet size (ep0) */ - uint8_t vender[2]; /* Vendor ID */ + uint8_t vendor[2]; /* Vendor ID */ uint8_t product[2]; /* Product ID */ uint8_t device[2]; /* Device ID */ uint8_t imfgr; /* Manufacturer */ diff --git a/include/nuttx/usb/usbhost.h b/include/nuttx/usb/usbhost.h index 8a7457bbdc..fc4d6ad552 100644 --- a/include/nuttx/usb/usbhost.h +++ b/include/nuttx/usb/usbhost.h @@ -263,12 +263,14 @@ * Input Parameters: * drvr - The USB host driver instance obtained as a parameter from the call to * the class create() method. - * req - Describes the request to be sent. This data will be copied from the - * user provided memory. Therefore, the req buffer may be declared on the - * stack. + * req - Describes the request to be sent. This request must lie in memory + * created by DRVR_ALLOC. * buffer - A buffer used for sending the request and for returning any * responses. This buffer must be large enough to hold the length value - * in the request description. buffer must have been allocated using DRVR_ALLOC + * in the request description. buffer must have been allocated using DRVR_ALLOC. + * + * NOTE: On an IN transaction, req and buffer may refer to the same allocated + * memory. * * Returned Values: * On success, zero (OK) is returned. On a failure, a negated errno value is