summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-08-26 15:46:16 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-08-26 15:46:16 -0600
commit0b2262e07db923c1211c9c42e0f9b990262f7820 (patch)
tree6bb07310002fa1c97d4d3005508bdf6f852b40cd
parent260405d60666ea266e72f56484e56ef37b591851 (diff)
downloadnuttx-0b2262e07db923c1211c9c42e0f9b990262f7820.tar.gz
nuttx-0b2262e07db923c1211c9c42e0f9b990262f7820.tar.bz2
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/ChangeLog8
-rw-r--r--nuttx/Documentation/NuttxPortingGuide.html7
-rw-r--r--nuttx/arch/arm/src/lpc17xx/lpc17_usbhost.c46
-rwxr-xr-xnuttx/arch/arm/src/sama5/sam_ehci.c61
-rw-r--r--nuttx/arch/arm/src/sama5/sam_ohci.c34
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_otgfshost.c34
-rw-r--r--nuttx/drivers/usbhost/usbhost_enumerate.c44
-rw-r--r--nuttx/include/nuttx/usb/usbhost.h48
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