Skip to content

Commit

Permalink
drivers/usbhost/usbhost_composite.c: I'm working on a CDC/NCM driver …
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
aport authored and gregory-nutt committed Jun 21, 2019
1 parent 977893d commit 7d42b19
Showing 1 changed file with 84 additions and 54 deletions.
138 changes: 84 additions & 54 deletions drivers/usbhost/usbhost_composite.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,10 +266,10 @@ static int usbhost_disconnected(struct usbhost_class_s *usbclass)
*
* Description:
* Find an interface descriptor and copy it along with all of its
* following encpoint descriptors.
* following endpoint and cs interface descriptors.
*
* Input Parameters:
* ifno - The interface ID to find.
* ifno - The interface ID to find.
* configdesc - The original configuration descriptor that contains the
* the interface descriptor.
* desclen - the length of configdesc.
Expand All @@ -282,14 +282,15 @@ static int usbhost_disconnected(struct usbhost_class_s *usbclass)
*
* -ENOENT: Did not find interface descriptor
* -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,
int desclen, FAR uint8_t *buffer, int buflen)
{
FAR struct usb_desc_s *desc;
FAR struct usb_ifdesc_s *ifdesc;
FAR struct usb_epdesc_s *epdesc;
int retsize;
int offset;
int neps;
Expand All @@ -305,80 +306,109 @@ static int usbhost_copyinterface(uint8_t ifno, FAR const uint8_t *configdesc,
/* Search for the interface */

for (offset = 0, retsize = 0;
offset < desclen - sizeof(struct usb_ifdesc_s);
offset < desclen - sizeof(struct usb_desc_s);
offset += len)
{
ifdesc = (FAR struct usb_ifdesc_s *)&configdesc[offset];
len = ifdesc->len;
desc = (FAR struct usb_desc_s *)&configdesc[offset];
len = desc->len;

/* Is this an interface descriptor? Is it the one we are looking for? */
/* Is this an interface descriptor? */

if (ifdesc->type == USB_DESC_TYPE_INTERFACE && ifdesc->ifno == ifno)
if (desc->type == USB_DESC_TYPE_INTERFACE)
{
/* Yes.. return the interface descriptor */

memcpy(buffer, ifdesc, len);
buffer += len;
buflen -= len;
retsize += len;
ifdesc = (FAR struct usb_ifdesc_s *)&configdesc[offset];

/* Make sure that the buffer will hold at least the endpoint
* descriptors.
*/
/* Is it the one we are looking for? */

neps = ifdesc->neps;
if (buflen < neps * USB_SIZEOF_EPDESC)
if (ifdesc->ifno == ifno && ifdesc->neps != 0)
{
return -ENOSPC;
}
/* Yes.. return the interface descriptor */

/* The endpoint descriptors should immediately follow the
* interface descriptor.
*/
memcpy(buffer, desc, len);
buffer += len;
buflen -= len;
retsize += len;

for (offset += len;
offset <= desclen - sizeof(struct usb_epdesc_s);
offset += len)
{
epdesc = (FAR struct usb_epdesc_s *)&configdesc[offset];
len = epdesc->len;
/* Make sure that the buffer will hold at least the endpoint
* descriptors.
*/

/* Is this an endpoint descriptor? */
neps = ifdesc->neps;
if (buflen < neps * USB_SIZEOF_EPDESC)
{
return -ENOSPC;
}

/* The CS and endpoint descriptors should immediately
* follow the interface descriptor.
*/

if (epdesc->type == USB_DESC_TYPE_ENDPOINT)
for (offset += len;
offset < desclen - sizeof(struct usb_desc_s);
offset += len)
{
/* Yes.. return the endpoint descriptor */
desc = (FAR struct usb_desc_s *)&configdesc[offset];
len = desc->len;

/* Is this a class-specific interface descriptor? */

if (desc->type == USB_DESC_TYPE_CSINTERFACE)
{
/* Yes... return the descriptor */

memcpy(buffer, epdesc, len);
buffer += len;
buflen -= len;
retsize += len;
if (buflen < len)
{
return -ENOSPC;
}

/* And reduce the number of endpoints we are looking for */
memcpy(buffer, desc, len);
buffer += len;
buflen -= len;
retsize += len;
}

/* Is this an endpoint descriptor? */

if (--neps <= 0)
else if (desc->type == USB_DESC_TYPE_ENDPOINT)
{
/* That is all of them!. Return the total size copied */
/* Yes.. return the endpoint descriptor */

if (buflen < len)
{
return -ENOSPC;
}

memcpy(buffer, desc, len);
buffer += len;
buflen -= len;
retsize += len;

return retsize;
/* And reduce the number of endpoints we are looking for */

if (--neps <= 0)
{
/* That is all of them! Return the total size copied */

return retsize;
}
}
}

/* The endpoint descriptors following the interface descriptor
* should all be contiguous. But we will complain only if another
* interface descriptor is encountered before all of the endpoint
* descriptors have been found.
*/
/* The endpoint descriptors following the interface descriptor
* should all be contiguous. But we will complain only if another
* interface descriptor is encountered before all of the endpoint
* descriptors have been found.
*/

else if (epdesc->type == USB_DESC_TYPE_INTERFACE)
{
break;
else if (desc->type == USB_DESC_TYPE_INTERFACE)
{
break;
}
}
}

/* Did not find all of the interface descriptors */
/* Did not find all of the interface descriptors */

return -EINVAL;
return -EINVAL;
}
}
}

Expand Down Expand Up @@ -446,7 +476,7 @@ static int usbhost_createconfig(FAR struct usbhost_member_s *member,
buffer, buflen);
if (ifsize < 0)
{
uerr("ERROR: Failed to copy inteface: %d\n", ifsize);
uerr("ERROR: Failed to copy interface: %d\n", ifsize);
return ifsize;
}

Expand Down

0 comments on commit 7d42b19

Please sign in to comment.