diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2013-08-26 15:46:16 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2013-08-26 15:46:16 -0600 |
commit | 0b2262e07db923c1211c9c42e0f9b990262f7820 (patch) | |
tree | 6bb07310002fa1c97d4d3005508bdf6f852b40cd | |
parent | 260405d60666ea266e72f56484e56ef37b591851 (diff) | |
download | px4-nuttx-0b2262e07db923c1211c9c42e0f9b990262f7820.tar.gz px4-nuttx-0b2262e07db923c1211c9c42e0f9b990262f7820.tar.bz2 px4-nuttx-0b2262e07db923c1211c9c42e0f9b990262f7820.zip |
Add a new method to the USB host driver interface: getdevinfo. This method will return information about the currently connected device. At present, it only returns the device speed. The speed is needed by the enumeration logic in order to set a credible initial EP0 max packet size
-rw-r--r-- | nuttx/ChangeLog | 8 | ||||
-rw-r--r-- | nuttx/Documentation/NuttxPortingGuide.html | 7 | ||||
-rw-r--r-- | nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c | 46 | ||||
-rwxr-xr-x | nuttx/arch/arm/src/sama5/sam_ehci.c | 61 | ||||
-rw-r--r-- | nuttx/arch/arm/src/sama5/sam_ohci.c | 34 | ||||
-rw-r--r-- | nuttx/arch/arm/src/stm32/stm32_otgfshost.c | 34 | ||||
-rw-r--r-- | nuttx/drivers/usbhost/usbhost_enumerate.c | 44 | ||||
-rw-r--r-- | nuttx/include/nuttx/usb/usbhost.h | 48 |
8 files changed, 265 insertions, 17 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 319c37703..6c2464db4 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -5459,4 +5459,10 @@ by the STM32 SDIO driver. From CCTSAO (2013-6-26) * drivers/net/encx24j600.c and .h: Use the ENC's SRAM for multiple TX packets. From Max Holtzberg (2013-6-26). - + * include/nuttx/usb/usbhost.h, drivers/usbhost/usbhost_enumerate.c, and + all USB host drivers: Added a new driver method: getdevinfo. This + method is intended to get various information about the connected device, + but currently returns only the device speed. The device speed is + necessary by usbhost_enumerate in order to set a credible initial EP0 + max packetsize. High speed needs 64 bytes, low speed needs 8 bytes, + and full speed can handle almost any size (2013-8-26). diff --git a/nuttx/Documentation/NuttxPortingGuide.html b/nuttx/Documentation/NuttxPortingGuide.html index adfc5d36e..444d82659 100644 --- a/nuttx/Documentation/NuttxPortingGuide.html +++ b/nuttx/Documentation/NuttxPortingGuide.html @@ -3434,9 +3434,10 @@ extern void up_ledoff(int led); </p> <p> <b>Examples</b>: - <code>arch/arm/src/lpc17xx/lpc17_usbhost.c</code>. - <code>arch/arm/src/stm32/stm32_otgfshost.c</code>. - <code>arch/arm/src/sama5/sam_ohci.c</code>. + <code>arch/arm/src/lpc17xx/lpc17_usbhost.c</code>, + <code>arch/arm/src/stm32/stm32_otgfshost.c</code>, + <code>arch/arm/src/sama5/sam_ohci.c</code>, and + <code>arch/arm/src/sama5/sam_ehci.c</code>. </p> </li> <li> diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c b/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c index abda1ddf8..08bc9df8b 100644 --- a/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c +++ b/nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c @@ -270,13 +270,13 @@ static void lpc17_setinttab(uint32_t value, unsigned int interval, unsigned int #endif static inline int lpc17_addinted(struct lpc17_usbhost_s *priv, - const FAR struct usbhost_epdesc_s *epdesc, + FAR const struct usbhost_epdesc_s *epdesc, struct lpc17_ed_s *ed); static inline int lpc17_reminted(struct lpc17_usbhost_s *priv, struct lpc17_ed_s *ed); static inline int lpc17_addisoced(struct lpc17_usbhost_s *priv, - const FAR struct usbhost_epdesc_s *epdesc, + FAR const struct usbhost_epdesc_s *epdesc, struct lpc17_ed_s *ed); static inline int lpc17_remisoced(struct lpc17_usbhost_s *priv, struct lpc17_ed_s *ed); @@ -302,8 +302,10 @@ static int lpc17_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx); static int lpc17_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, uint16_t maxpacketsize); +static int lpc17_getdevinfo(FAR struct usbhost_driver_s *drvr, + FAR struct usbhost_devinfo_s *devinfo); static int lpc17_epalloc(FAR struct usbhost_driver_s *drvr, - const FAR struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep); + FAR const struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep); static int lpc17_epfree(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep); static int lpc17_alloc(FAR struct usbhost_driver_s *drvr, FAR uint8_t **buffer, FAR size_t *maxlen); @@ -339,6 +341,7 @@ static struct lpc17_usbhost_s g_usbhost = .drvr = { .ep0configure = lpc17_ep0configure, + .getdevinfo = lpc17_getdevinfo, .epalloc = lpc17_epalloc, .epfree = lpc17_epfree, .alloc = lpc17_alloc, @@ -889,7 +892,7 @@ static void lpc17_setinttab(uint32_t value, unsigned int interval, unsigned int *******************************************************************************/ static inline int lpc17_addinted(struct lpc17_usbhost_s *priv, - const FAR struct usbhost_epdesc_s *epdesc, + FAR const struct usbhost_epdesc_s *epdesc, struct lpc17_ed_s *ed) { #ifndef CONFIG_USBHOST_INT_DISABLE @@ -1125,7 +1128,7 @@ static inline int lpc17_reminted(struct lpc17_usbhost_s *priv, *******************************************************************************/ static inline int lpc17_addisoced(struct lpc17_usbhost_s *priv, - const FAR struct usbhost_epdesc_s *epdesc, + FAR const struct usbhost_epdesc_s *epdesc, struct lpc17_ed_s *ed) { #ifndef CONFIG_USBHOST_ISOC_DISABLE @@ -1695,6 +1698,37 @@ static int lpc17_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcadd } /************************************************************************************ + * Name: lpc17_getdevinfo + * + * Description: + * Get information about the connected device. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * devinfo - A pointer to memory provided by the caller in which to return the + * device information. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +static int lpc17_getdevinfo(FAR struct usbhost_driver_s *drvr, + FAR struct usbhost_devinfo_s *devinfo) +{ + struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr; + + DEBUGASSERT(drvr && devinfo); + devinfo->speed = priv->lowspeed ? DEVINFO_SPEED_LOW : DEVINFO_SPEED_FULL; + return OK; +} + +/************************************************************************************ * Name: lpc17_epalloc * * Description: @@ -1717,7 +1751,7 @@ static int lpc17_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcadd ************************************************************************************/ static int lpc17_epalloc(FAR struct usbhost_driver_s *drvr, - const FAR struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep) + FAR const struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep) { struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr; struct lpc17_ed_s *ed; diff --git a/nuttx/arch/arm/src/sama5/sam_ehci.c b/nuttx/arch/arm/src/sama5/sam_ehci.c index 1889f9783..69c13b4ce 100755 --- a/nuttx/arch/arm/src/sama5/sam_ehci.c +++ b/nuttx/arch/arm/src/sama5/sam_ehci.c @@ -364,6 +364,8 @@ static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx); static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, uint16_t maxpacketsize); +static int sam_getdevinfo(FAR struct usbhost_driver_s *drvr, + FAR struct usbhost_devinfo_s *devinfo); static int sam_epalloc(FAR struct usbhost_driver_s *drvr, const FAR struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep); static int sam_epfree(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep); @@ -2982,6 +2984,64 @@ static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, } /************************************************************************************ + * Name: sam_getdevinfo + * + * Description: + * Get information about the connected device. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * devinfo - A pointer to memory provided by the caller in which to return the + * device information. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +static int sam_getdevinfo(FAR struct usbhost_driver_s *drvr, + FAR struct usbhost_devinfo_s *devinfo) +{ + struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr; + struct sam_epinfo_s *epinfo; + + DEBUGASSERT(drvr && devinfo); + epinfo = &rhport->ep0; + + /* As implemented now, this driver supports only HIGH speed. All + * low or full speed devices are handed off to the OHCI driver. + */ + +#if 0 + switch (epinfo->speed) + { + case EHCI_LOW_SPEED: + devinfo->speed = DEVINFO_SPEED_LOW; + break; + + case EHCI_FULL_SPEED: + devinfo->speed = DEVINFO_SPEED_FULL; + break; + + default: + case EHCI_HIGH_SPEED: + devinfo->speed = DEVINFO_SPEED_HIGH; + break; + } + +#else + devinfo->speed = DEVINFO_SPEED_HIGH; + +#endif + return OK; +} + +/************************************************************************************ * Name: sam_epalloc * * Description: @@ -3670,6 +3730,7 @@ FAR struct usbhost_connection_s *sam_ehci_initialize(int controller) /* Initialize the device operations */ rhport->drvr.ep0configure = sam_ep0configure; + rhport->drvr.getdevinfo = sam_getdevinfo; rhport->drvr.epalloc = sam_epalloc; rhport->drvr.epfree = sam_epfree; rhport->drvr.alloc = sam_alloc; diff --git a/nuttx/arch/arm/src/sama5/sam_ohci.c b/nuttx/arch/arm/src/sama5/sam_ohci.c index ea6f94ddb..c2b6ff26d 100644 --- a/nuttx/arch/arm/src/sama5/sam_ohci.c +++ b/nuttx/arch/arm/src/sama5/sam_ohci.c @@ -383,6 +383,8 @@ static int sam_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx); static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, uint16_t maxpacketsize); +static int sam_getdevinfo(FAR struct usbhost_driver_s *drvr, + FAR struct usbhost_devinfo_s *devinfo); static int sam_epalloc(FAR struct usbhost_driver_s *drvr, const FAR struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep); static int sam_epfree(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep); @@ -2262,6 +2264,37 @@ static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, } /************************************************************************************ + * Name: sam_getdevinfo + * + * Description: + * Get information about the connected device. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * devinfo - A pointer to memory provided by the caller in which to return the + * device information. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +static int sam_getdevinfo(FAR struct usbhost_driver_s *drvr, + FAR struct usbhost_devinfo_s *devinfo) +{ + struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr; + + DEBUGASSERT(drvr && devinfo); + devinfo->speed = rhport->lowspeed ? DEVINFO_SPEED_LOW : DEVINFO_SPEED_FULL; + return OK; +} + +/************************************************************************************ * Name: sam_epalloc * * Description: @@ -3156,6 +3189,7 @@ FAR struct usbhost_connection_s *sam_ohci_initialize(int controller) rhport->rhpndx = i; rhport->drvr.ep0configure = sam_ep0configure; + rhport->drvr.getdevinfo = sam_getdevinfo; rhport->drvr.epalloc = sam_epalloc; rhport->drvr.epfree = sam_epfree; rhport->drvr.alloc = sam_alloc; diff --git a/nuttx/arch/arm/src/stm32/stm32_otgfshost.c b/nuttx/arch/arm/src/stm32/stm32_otgfshost.c index 315782a7e..84903b3f8 100644 --- a/nuttx/arch/arm/src/stm32/stm32_otgfshost.c +++ b/nuttx/arch/arm/src/stm32/stm32_otgfshost.c @@ -364,6 +364,8 @@ static int stm32_enumerate(FAR struct usbhost_connection_s *conn, int rhpndx); static int stm32_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, uint16_t maxpacketsize); +static int stm32_getdevinfo(FAR struct usbhost_driver_s *drvr, + FAR struct usbhost_devinfo_s *devinfo); static int stm32_epalloc(FAR struct usbhost_driver_s *drvr, FAR const FAR struct usbhost_epdesc_s *epdesc, FAR usbhost_ep_t *ep); @@ -409,6 +411,7 @@ static struct stm32_usbhost_s g_usbhost = .drvr = { .ep0configure = stm32_ep0configure, + .getdevinfo = stm32_getdevinfo, .epalloc = stm32_epalloc, .epfree = stm32_epfree, .alloc = stm32_alloc, @@ -3235,6 +3238,37 @@ static int stm32_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcadd } /************************************************************************************ + * Name: stm32_getdevinfo + * + * Description: + * Get information about the connected device. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * devinfo - A pointer to memory provided by the caller in which to return the + * device information. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +static int stm32_getdevinfo(FAR struct usbhost_driver_s *drvr, + FAR struct usbhost_devinfo_s *devinfo) +{ + FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr; + + DEBUGASSERT(drvr && devinfo); + devinfo->speed = priv->lowspeed ? DEVINFO_SPEED_LOW : DEVINFO_SPEED_FULL; + return OK; +} + +/************************************************************************************ * Name: stm32_epalloc * * Description: diff --git a/nuttx/drivers/usbhost/usbhost_enumerate.c b/nuttx/drivers/usbhost/usbhost_enumerate.c index 7bcf1840e..44e1439cd 100644 --- a/nuttx/drivers/usbhost/usbhost_enumerate.c +++ b/nuttx/drivers/usbhost/usbhost_enumerate.c @@ -309,6 +309,7 @@ int usbhost_enumerate(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, FAR struct usbhost_class_s **class) { struct usb_ctrlreq_s *ctrlreq; + struct usbhost_devinfo_s devinfo; struct usbhost_id_s id; size_t maxlen; unsigned int cfglen; @@ -336,17 +337,52 @@ int usbhost_enumerate(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, goto errout; } - /* Set max pkt size = 8 */ + /* Get information about the connected device */ - DRVR_EP0CONFIGURE(drvr, 0, 8); + ret = DRVR_GETDEVINFO(drvr, &devinfo); + if (ret != OK) + { + udbg("DRVR_GETDEVINFO 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 (devinfo.speed == DEVINFO_SPEED_HIGH) + { + /* For high-speed, we must use 64 bytes */ + + maxpacketsize = 64; + } + else + { + /* Eight will work for both low- and full-speed */ + + maxpacketsize = 8; + } + + /* Set the initial maximum packet size */ + + DRVR_EP0CONFIGURE(drvr, 0, maxpacketsize); - /* Read first 8 bytes of the device descriptor */ + /* Read first 'maxpacketsize' 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, 8); + usbhost_putle16(ctrlreq->len, maxpacketsize); ret = DRVR_CTRLIN(drvr, ctrlreq, buffer); if (ret != OK) diff --git a/nuttx/include/nuttx/usb/usbhost.h b/nuttx/include/nuttx/usb/usbhost.h index 1fe4e3dfe..3965edef5 100644 --- a/nuttx/include/nuttx/usb/usbhost.h +++ b/nuttx/include/nuttx/usb/usbhost.h @@ -237,6 +237,35 @@ #define DRVR_EP0CONFIGURE(drvr,funcaddr,mps) ((drvr)->ep0configure(drvr,funcaddr,mps)) /************************************************************************************ + * Name: DRVR_GETDEVINFO + * + * Description: + * Get information about the connected device. + * + * Input Parameters: + * drvr - The USB host driver instance obtained as a parameter from the call to + * the class create() method. + * devinfo - A pointer to memory provided by the caller in which to return the + * device information. + * + * Returned Values: + * On success, zero (OK) is returned. On a failure, a negated errno value is + * returned indicating the nature of the failure + * + * Assumptions: + * This function will *not* be called from an interrupt handler. + * + ************************************************************************************/ + +#define DRVR_GETDEVINFO(drvr,devinfo) ((drvr)->getdevinfo(drvr,devinfo)) + +/* struct usbhost_devinfo_s speed settings */ + +#define DEVINFO_SPEED_LOW 0 +#define DEVINFO_SPEED_FULL 1 +#define DEVINFO_SPEED_HIGH 2 + +/************************************************************************************ * Name: DRVR_EPALLOC * * Description: @@ -578,6 +607,13 @@ struct usbhost_epdesc_s uint16_t mxpacketsize; /* Max packetsize */ }; +/* This structure provides information about the connected device */ + +struct usbhost_devinfo_s +{ + uint8_t speed:2; /* Device speed: 0=low, 1=full, 2=high */ +}; + /* This type represents one endpoint configured by the epalloc() method. * The actual form is know only internally to the USB host controller * (for example, for an OHCI driver, this would probably be a pointer @@ -624,11 +660,17 @@ struct usbhost_driver_s int (*ep0configure)(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, uint16_t maxpacketsize); + /* Get information about the connected device */ + + int (*getdevinfo)(FAR struct usbhost_driver_s *drvr, + FAR struct usbhost_devinfo_s *devinfo); + /* Allocate and configure an endpoint. */ int (*epalloc)(FAR struct usbhost_driver_s *drvr, - const FAR struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep); - int (*epfree)(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep); + FAR const struct usbhost_epdesc_s *epdesc, + FAR usbhost_ep_t *ep); + int (*epfree)(FAR struct usbhost_driver_s *drvr, FAR usbhost_ep_t ep); /* Some hardware supports special memory in which transfer descriptors can * be accessed more efficiently. The following methods provide a mechanism @@ -655,7 +697,7 @@ struct usbhost_driver_s */ int (*ioalloc)(FAR struct usbhost_driver_s *drvr, - FAR uint8_t **buffer, size_t buflen); + FAR uint8_t **buffer, size_t buflen); int (*iofree)(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer); /* Process a IN or OUT request on the control endpoint. These methods |