mirror of
https://github.com/apache/nuttx.git
synced 2026-05-30 21:36:28 +08:00
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:
committed by
Alan Carvalho de Assis
parent
1de1b8adb7
commit
ae1fd83a46
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user