drivers/usbhost/usbhost_composite.c: I'm working on a CDC/NCM driver and in my driver's usbhost_cfgdesc() function I need access to the class-specific descriptors. Currently these are not available if the interface is part of a composite device, since only interface and endpoint descriptors are copied by usbhost_copyinterface(). This comit will also copy any class-specific interface descriptors for use in downstream class drivers.

NOTE: There's one change that might be incorrect, where I skip interfaces with zero endpoints. I did this because my device has two consecutive interface descriptors with the same interface number, one for altsetting 0 with no endpoints, and another for altsetting 1 with 1 endpoint.  The loop was aborting due to finding two interface descriptors back-to-back.
This commit is contained in:
Adam Porter 2019-06-21 06:57:17 -06:00 committed by Gregory Nutt
parent 977893d5a7
commit 7d42b19a8d

View File

@ -266,7 +266,7 @@ static int usbhost_disconnected(struct usbhost_class_s *usbclass)
* *
* Description: * Description:
* Find an interface descriptor and copy it along with all of its * Find an interface descriptor and copy it along with all of its
* following encpoint descriptors. * following endpoint and cs interface descriptors.
* *
* Input Parameters: * Input Parameters:
* ifno - The interface ID to find. * ifno - The interface ID to find.
@ -282,14 +282,15 @@ static int usbhost_disconnected(struct usbhost_class_s *usbclass)
* *
* -ENOENT: Did not find interface descriptor * -ENOENT: Did not find interface descriptor
* -EINVAL: Did not find all endpoint descriptors * -EINVAL: Did not find all endpoint descriptors
* -ENOSPC: Provided buffer too small to hold all found descriptors
* *
****************************************************************************/ ****************************************************************************/
static int usbhost_copyinterface(uint8_t ifno, FAR const uint8_t *configdesc, static int usbhost_copyinterface(uint8_t ifno, FAR const uint8_t *configdesc,
int desclen, FAR uint8_t *buffer, int buflen) int desclen, FAR uint8_t *buffer, int buflen)
{ {
FAR struct usb_desc_s *desc;
FAR struct usb_ifdesc_s *ifdesc; FAR struct usb_ifdesc_s *ifdesc;
FAR struct usb_epdesc_s *epdesc;
int retsize; int retsize;
int offset; int offset;
int neps; int neps;
@ -305,19 +306,25 @@ static int usbhost_copyinterface(uint8_t ifno, FAR const uint8_t *configdesc,
/* Search for the interface */ /* Search for the interface */
for (offset = 0, retsize = 0; for (offset = 0, retsize = 0;
offset < desclen - sizeof(struct usb_ifdesc_s); offset < desclen - sizeof(struct usb_desc_s);
offset += len) offset += len)
{
desc = (FAR struct usb_desc_s *)&configdesc[offset];
len = desc->len;
/* Is this an interface descriptor? */
if (desc->type == USB_DESC_TYPE_INTERFACE)
{ {
ifdesc = (FAR struct usb_ifdesc_s *)&configdesc[offset]; ifdesc = (FAR struct usb_ifdesc_s *)&configdesc[offset];
len = ifdesc->len;
/* Is this an interface descriptor? Is it the one we are looking for? */ /* Is it the one we are looking for? */
if (ifdesc->type == USB_DESC_TYPE_INTERFACE && ifdesc->ifno == ifno) if (ifdesc->ifno == ifno && ifdesc->neps != 0)
{ {
/* Yes.. return the interface descriptor */ /* Yes.. return the interface descriptor */
memcpy(buffer, ifdesc, len); memcpy(buffer, desc, len);
buffer += len; buffer += len;
buflen -= len; buflen -= len;
retsize += len; retsize += len;
@ -332,24 +339,46 @@ static int usbhost_copyinterface(uint8_t ifno, FAR const uint8_t *configdesc,
return -ENOSPC; return -ENOSPC;
} }
/* The endpoint descriptors should immediately follow the /* The CS and endpoint descriptors should immediately
* interface descriptor. * follow the interface descriptor.
*/ */
for (offset += len; for (offset += len;
offset <= desclen - sizeof(struct usb_epdesc_s); offset < desclen - sizeof(struct usb_desc_s);
offset += len) offset += len)
{ {
epdesc = (FAR struct usb_epdesc_s *)&configdesc[offset]; desc = (FAR struct usb_desc_s *)&configdesc[offset];
len = epdesc->len; len = desc->len;
/* Is this a class-specific interface descriptor? */
if (desc->type == USB_DESC_TYPE_CSINTERFACE)
{
/* Yes... return the descriptor */
if (buflen < len)
{
return -ENOSPC;
}
memcpy(buffer, desc, len);
buffer += len;
buflen -= len;
retsize += len;
}
/* Is this an endpoint descriptor? */ /* Is this an endpoint descriptor? */
if (epdesc->type == USB_DESC_TYPE_ENDPOINT) else if (desc->type == USB_DESC_TYPE_ENDPOINT)
{ {
/* Yes.. return the endpoint descriptor */ /* Yes.. return the endpoint descriptor */
memcpy(buffer, epdesc, len); if (buflen < len)
{
return -ENOSPC;
}
memcpy(buffer, desc, len);
buffer += len; buffer += len;
buflen -= len; buflen -= len;
retsize += len; retsize += len;
@ -358,7 +387,7 @@ static int usbhost_copyinterface(uint8_t ifno, FAR const uint8_t *configdesc,
if (--neps <= 0) if (--neps <= 0)
{ {
/* That is all of them!. Return the total size copied */ /* That is all of them! Return the total size copied */
return retsize; return retsize;
} }
@ -370,7 +399,7 @@ static int usbhost_copyinterface(uint8_t ifno, FAR const uint8_t *configdesc,
* descriptors have been found. * descriptors have been found.
*/ */
else if (epdesc->type == USB_DESC_TYPE_INTERFACE) else if (desc->type == USB_DESC_TYPE_INTERFACE)
{ {
break; break;
} }
@ -381,6 +410,7 @@ static int usbhost_copyinterface(uint8_t ifno, FAR const uint8_t *configdesc,
return -EINVAL; return -EINVAL;
} }
} }
}
/* Could not find the interface descriptor */ /* Could not find the interface descriptor */
@ -446,7 +476,7 @@ static int usbhost_createconfig(FAR struct usbhost_member_s *member,
buffer, buflen); buffer, buflen);
if (ifsize < 0) if (ifsize < 0)
{ {
uerr("ERROR: Failed to copy inteface: %d\n", ifsize); uerr("ERROR: Failed to copy interface: %d\n", ifsize);
return ifsize; return ifsize;
} }