On Sat, Jun 23, 2001, Brad Hards <[EMAIL PROTECTED]> wrote:
> Could someone please explain the functionality for device descriptor parsing
> in usb.c?
> I am specifically interested in usb_parse_endpoint(), usb_parse_interface()
> and usb_parse_configuration(), and this code fragment:
> /* If we find another descriptor which is at or below */
> /* us in the descriptor heirarchy then return */
> if ((header->bDescriptorType == USB_DT_INTERFACE) ||
> (header->bDescriptorType == USB_DT_ENDPOINT) ||
> (header->bDescriptorType == USB_DT_CONFIG) ||
> (header->bDescriptorType == USB_DT_DEVICE))
> break;
>
> Issue 1:
> What does the "descriptor hierachy" mean, (or how can "us" be at or below in
> each case)?
device descriptor (one)
config descriptor (one or more)
interface/alternate setting descriptor (one or more)
endpoint descriptor (one or more)
The reason we do it this way is because we don't know how many alternate
settings there will be for one. Also, we don't know if class or vendor
descriptors exist.
> Issue 2:
> It looks like usb_parse_configuration() is br0ken. In this loop, if the extra
> descriptor information isn't only in the last descriptor, then the previous
> ones leak memory, and the extra information gets lost:
> for (i = 0; i < config->bNumInterfaces; i++) {
> int numskipped, len;
> char *begin;
>
> /* Skip over the rest of the Class Specific or Vendor */
> /* Specific descriptors */
> begin = buffer;
> numskipped = 0;
> while (size >= sizeof(struct usb_descriptor_header)) {
> header = (struct usb_descriptor_header *)buffer;
>
> if ((header->bLength > size) || (header->bLength < 2)) {
> err("invalid descriptor length of %d",
>header->bLength);
> return -1;
> }
>
> /* If we find another descriptor which is at or below */
> /* us in the descriptor heirarchy then we're done */
> if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
> (header->bDescriptorType == USB_DT_INTERFACE) ||
> (header->bDescriptorType == USB_DT_CONFIG) ||
> (header->bDescriptorType == USB_DT_DEVICE))
> break;
>
> dbg("skipping descriptor 0x%X", header->bDescriptorType);
> numskipped++;
>
> buffer += header->bLength;
> size -= header->bLength;
> }
> if (numskipped)
> dbg("skipped %d class/vendor specific endpoint descriptors",
>numskipped);
>
> /* Copy any unknown descriptors into a storage area for */
> /* drivers to later parse */
> len = (int)(buffer - begin);
> if (!len) {
> config->extra = NULL;
> config->extralen = 0;
> } else {
> config->extra = kmalloc(len, GFP_KERNEL);
> if (!config->extra) {
> err("couldn't allocate memory for config extra
>descriptors");
> config->extralen = 0;
> return -1;
> }
>
> memcpy(config->extra, begin, len);
> config->extralen = len;
> }
>
> retval = usb_parse_interface(dev, config->interface + i, buffer, size);
> if (retval < 0)
> return retval;
>
> buffer += retval;
> size -= retval;
> }
>
> Anyone enlighten me?
That is only for class or vendor descriptors that apply to the
configuration. You can have class or vendor descriptors that apply to
interfaces, or endpoints IIRC.
JE
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
http://lists.sourceforge.net/lists/listinfo/linux-usb-devel