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:
parent
977893d5a7
commit
7d42b19a8d
@ -266,10 +266,10 @@ 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.
|
||||||
* configdesc - The original configuration descriptor that contains the
|
* configdesc - The original configuration descriptor that contains the
|
||||||
* the interface descriptor.
|
* the interface descriptor.
|
||||||
* desclen - the length of configdesc.
|
* desclen - the length of configdesc.
|
||||||
@ -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,80 +306,109 @@ 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)
|
||||||
{
|
{
|
||||||
ifdesc = (FAR struct usb_ifdesc_s *)&configdesc[offset];
|
desc = (FAR struct usb_desc_s *)&configdesc[offset];
|
||||||
len = ifdesc->len;
|
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 */
|
ifdesc = (FAR struct usb_ifdesc_s *)&configdesc[offset];
|
||||||
|
|
||||||
memcpy(buffer, ifdesc, len);
|
/* Is it the one we are looking for? */
|
||||||
buffer += len;
|
|
||||||
buflen -= len;
|
|
||||||
retsize += len;
|
|
||||||
|
|
||||||
/* Make sure that the buffer will hold at least the endpoint
|
if (ifdesc->ifno == ifno && ifdesc->neps != 0)
|
||||||
* descriptors.
|
|
||||||
*/
|
|
||||||
|
|
||||||
neps = ifdesc->neps;
|
|
||||||
if (buflen < neps * USB_SIZEOF_EPDESC)
|
|
||||||
{
|
{
|
||||||
return -ENOSPC;
|
/* Yes.. return the interface descriptor */
|
||||||
}
|
|
||||||
|
|
||||||
/* The endpoint descriptors should immediately follow the
|
memcpy(buffer, desc, len);
|
||||||
* interface descriptor.
|
buffer += len;
|
||||||
*/
|
buflen -= len;
|
||||||
|
retsize += len;
|
||||||
|
|
||||||
for (offset += len;
|
/* Make sure that the buffer will hold at least the endpoint
|
||||||
offset <= desclen - sizeof(struct usb_epdesc_s);
|
* descriptors.
|
||||||
offset += len)
|
*/
|
||||||
{
|
|
||||||
epdesc = (FAR struct usb_epdesc_s *)&configdesc[offset];
|
|
||||||
len = epdesc->len;
|
|
||||||
|
|
||||||
/* Is this an endpoint descriptor? */
|
neps = ifdesc->neps;
|
||||||
|
if (buflen < neps * USB_SIZEOF_EPDESC)
|
||||||
if (epdesc->type == USB_DESC_TYPE_ENDPOINT)
|
|
||||||
{
|
{
|
||||||
/* Yes.. return the endpoint descriptor */
|
return -ENOSPC;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(buffer, epdesc, len);
|
/* The CS and endpoint descriptors should immediately
|
||||||
buffer += len;
|
* follow the interface descriptor.
|
||||||
buflen -= len;
|
*/
|
||||||
retsize += len;
|
|
||||||
|
|
||||||
/* And reduce the number of endpoints we are looking for */
|
for (offset += len;
|
||||||
|
offset < desclen - sizeof(struct usb_desc_s);
|
||||||
|
offset += len)
|
||||||
|
{
|
||||||
|
desc = (FAR struct usb_desc_s *)&configdesc[offset];
|
||||||
|
len = desc->len;
|
||||||
|
|
||||||
if (--neps <= 0)
|
/* Is this a class-specific interface descriptor? */
|
||||||
|
|
||||||
|
if (desc->type == USB_DESC_TYPE_CSINTERFACE)
|
||||||
{
|
{
|
||||||
/* That is all of them!. Return the total size copied */
|
/* Yes... return the descriptor */
|
||||||
|
|
||||||
return retsize;
|
if (buflen < len)
|
||||||
|
{
|
||||||
|
return -ENOSPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer, desc, len);
|
||||||
|
buffer += len;
|
||||||
|
buflen -= len;
|
||||||
|
retsize += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is this an endpoint descriptor? */
|
||||||
|
|
||||||
|
else if (desc->type == USB_DESC_TYPE_ENDPOINT)
|
||||||
|
{
|
||||||
|
/* Yes.. return the endpoint descriptor */
|
||||||
|
|
||||||
|
if (buflen < len)
|
||||||
|
{
|
||||||
|
return -ENOSPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer, desc, len);
|
||||||
|
buffer += len;
|
||||||
|
buflen -= len;
|
||||||
|
retsize += len;
|
||||||
|
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
else if (desc->type == USB_DESC_TYPE_INTERFACE)
|
||||||
|
{
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The endpoint descriptors following the interface descriptor
|
/* Did not find all of the interface descriptors */
|
||||||
* 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)
|
return -EINVAL;
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Did not find all of the interface descriptors */
|
|
||||||
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user