usbhost: Can now handle multiple interface descriptors.

See #3644. Code from:
https://github.com/apache/nuttx/compare/master...btashton:libusb
This commit is contained in:
Lwazi Dube
2023-05-19 00:11:34 -04:00
committed by Alan Carvalho de Assis
parent 1de1b8adb7
commit ae1fd83a46
+61 -37
View File
@@ -51,7 +51,9 @@ static void usbhost_putle16(uint8_t *dest, uint16_t val);
static inline int usbhost_devdesc(const struct usb_devdesc_s *devdesc, static inline int usbhost_devdesc(const struct usb_devdesc_s *devdesc,
FAR struct usbhost_id_s *id); FAR struct usbhost_id_s *id);
static inline int usbhost_configdesc(const uint8_t *configdesc, int desclen, static inline int usbhost_configdesc(const uint8_t *configdesc, int desclen,
FAR struct usbhost_id_s *id); uint8_t start_ifnum,
uint8_t *ret_ifnum,
struct usbhost_id_s *id);
static inline int usbhost_classbind(FAR struct usbhost_hubport_s *hport, static inline int usbhost_classbind(FAR struct usbhost_hubport_s *hport,
FAR const uint8_t *configdesc, int desclen, FAR const uint8_t *configdesc, int desclen,
FAR struct usbhost_id_s *id, FAR struct usbhost_id_s *id,
@@ -130,6 +132,8 @@ static inline int usbhost_devdesc(FAR const struct usb_devdesc_s *devdesc,
****************************************************************************/ ****************************************************************************/
static inline int usbhost_configdesc(const uint8_t *configdesc, int cfglen, static inline int usbhost_configdesc(const uint8_t *configdesc, int cfglen,
uint8_t start_ifnum,
uint8_t *ret_ifnum,
struct usbhost_id_s *id) struct usbhost_id_s *id)
{ {
FAR struct usb_cfgdesc_s *cfgdesc; FAR struct usb_cfgdesc_s *cfgdesc;
@@ -161,7 +165,8 @@ static inline int usbhost_configdesc(const uint8_t *configdesc, int cfglen,
/* What is the next descriptor? Is it an interface descriptor? */ /* What is the next descriptor? Is it an interface descriptor? */
ifdesc = (struct usb_ifdesc_s *)configdesc; ifdesc = (struct usb_ifdesc_s *)configdesc;
if (ifdesc->type == USB_DESC_TYPE_INTERFACE) if (ifdesc->type == USB_DESC_TYPE_INTERFACE &&
ifdesc->ifno >= start_ifnum)
{ {
/* Yes, extract the class information from the interface /* Yes, extract the class information from the interface
* descriptor. * descriptor.
@@ -175,6 +180,7 @@ static inline int usbhost_configdesc(const uint8_t *configdesc, int cfglen,
id->proto = ifdesc->protocol; id->proto = ifdesc->protocol;
uinfo("class:%d subclass:%d protocol:%d\n", uinfo("class:%d subclass:%d protocol:%d\n",
id->base, id->subclass, id->proto); id->base, id->subclass, id->proto);
*ret_ifnum = ifdesc->ifno;
return OK; return OK;
} }
@@ -499,6 +505,10 @@ int usbhost_enumerate(FAR struct usbhost_hubport_s *hport,
goto errout; goto errout;
} }
/* Some devices may require some delay before initialization */
nxsig_usleep(100 * 1000);
/* Was the class identification information provided in the device /* Was the class identification information provided in the device
* descriptor? Or do we need to find it in the interface descriptor(s)? * descriptor? Or do we need to find it in the interface descriptor(s)?
*/ */
@@ -510,49 +520,63 @@ int usbhost_enumerate(FAR struct usbhost_hubport_s *hport,
* case of multiple interface descriptors. * case of multiple interface descriptors.
*/ */
ret = usbhost_configdesc(buffer, cfglen, &id); uint8_t ninterfaces = ((struct usb_cfgdesc_s *)buffer)->ninterfaces;
if (ret < 0) uint8_t ifnum = 0;
for (ifnum = 0; ifnum < ninterfaces; ifnum++)
{ {
uerr("ERROR: usbhost_configdesc failed: %d\n", ret); uinfo("Parsing interface: %d\n", ifnum);
goto errout; ret = usbhost_configdesc(buffer, cfglen, ifnum, &ifnum, &id);
if (ret < 0)
{
uerr("ERROR: usbhost_configdesc failed: %d\n", ret);
goto errout;
}
ret = usbhost_classbind(hport, buffer, cfglen, &id, devclass);
if (ret < 0)
{
uerr("ERROR: usbhost_classbind failed %d\n", ret);
}
ret = OK;
} }
} }
/* Some devices may require some delay before initialization */
nxsig_usleep(100 * 1000);
#ifdef CONFIG_USBHOST_COMPOSITE
/* Check if the device attached to the downstream port if a USB composite
* device and, if so, create the composite device wrapper and bind it to
* the HCD.
*
* usbhost_composite() will return a negated errno value is on any
* failure. The value -ENOENT, in particular means that the attached
* device is not a composite device. Other values would indicate other
* various, unexpected failures. We make no real distinction here.
*/
ret = usbhost_composite(hport, buffer, cfglen, &id, devclass);
if (ret >= 0)
{
uinfo("usbhost_composite has bound the composite device\n");
}
/* Apparently this is not a composite device */
else else
#endif
{ {
/* Parse the configuration descriptor and bind to the class instance #ifdef CONFIG_USBHOST_COMPOSITE
* for the device. This needs to be the last thing done because the /* Check if the device attached to the downstream port if a USB
* class driver will begin configuring the device. * composite device and, if so, create the composite device wrapper
* and bind it to the HCD.
*
* usbhost_composite() will return a negated errno value is on any
* failure. The value -ENOENT, in particular means that the attached
* device is not a composite device. Other values would indicate other
* various, unexpected failures. We make no real distinction here.
*/ */
ret = usbhost_classbind(hport, buffer, cfglen, &id, devclass); ret = usbhost_composite(hport, buffer, cfglen, &id, devclass);
if (ret < 0) if (ret >= 0)
{ {
uerr("ERROR: usbhost_classbind failed %d\n", ret); uinfo("usbhost_composite has bound the composite device\n");
}
/* Apparently this is not a composite device */
else
#endif
{
/* 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)
{
uerr("ERROR: usbhost_classbind failed %d\n", ret);
}
} }
} }