static void usb_parse_iface_sub(struct usb_parse_state *ps) { struct libusb20_interface *aifc; struct usb_interface_descriptor *bifc; uint8_t x; aifc = ps->a.currifc; bifc = ps->b.currifc++; if (ps->preparse == 0) { /* copy descriptor fields */ bifc->bLength = aifc->desc.bLength; bifc->bDescriptorType = aifc->desc.bDescriptorType; bifc->bInterfaceNumber = aifc->desc.bInterfaceNumber; bifc->bAlternateSetting = aifc->desc.bAlternateSetting; bifc->bNumEndpoints = aifc->num_endpoints; bifc->bInterfaceClass = aifc->desc.bInterfaceClass; bifc->bInterfaceSubClass = aifc->desc.bInterfaceSubClass; bifc->bInterfaceProtocol = aifc->desc.bInterfaceProtocol; bifc->iInterface = aifc->desc.iInterface; bifc->endpoint = ps->b.currep; } for (x = 0; x != aifc->num_endpoints; x++) { ps->a.currep = aifc->endpoints + x; usb_parse_endpoint(ps); } ps->a.currextra = &aifc->extra; usb_parse_extra(ps, &bifc->extra, &bifc->extralen); return; }
static int usb_parse_interface(struct device *ddev, int cfgno, struct usb_host_config *config, unsigned char *buffer, int size, u8 inums[], u8 nalts[]) { unsigned char *buffer0 = buffer; struct usb_interface_descriptor *d; int inum, asnum; struct usb_interface_cache *intfc; struct usb_host_interface *alt; int i, n; int len, retval; int num_ep, num_ep_orig; d = (struct usb_interface_descriptor *) buffer; buffer += d->bLength; size -= d->bLength; if (d->bLength < USB_DT_INTERFACE_SIZE) goto skip_to_next_interface_descriptor; /* Which interface entry is this? */ intfc = NULL; inum = d->bInterfaceNumber; for (i = 0; i < config->desc.bNumInterfaces; ++i) { if (inums[i] == inum) { intfc = config->intf_cache[i]; break; } } if (!intfc || intfc->num_altsetting >= nalts[i]) goto skip_to_next_interface_descriptor; /* Check for duplicate altsetting entries */ asnum = d->bAlternateSetting; for ((i = 0, alt = &intfc->altsetting[0]); i < intfc->num_altsetting; (++i, ++alt)) { if (alt->desc.bAlternateSetting == asnum) { dev_warn(ddev, "Duplicate descriptor for config %d " "interface %d altsetting %d, skipping\n", cfgno, inum, asnum); goto skip_to_next_interface_descriptor; } } ++intfc->num_altsetting; memcpy(&alt->desc, d, USB_DT_INTERFACE_SIZE); /* Skip over any Class Specific or Vendor Specific descriptors; * find the first endpoint or interface descriptor */ alt->extra = buffer; i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT, USB_DT_INTERFACE, &n); alt->extralen = i; if (n > 0) dev_dbg(ddev, "skipped %d descriptor%s after %s\n", n, plural(n), "interface"); buffer += i; size -= i; /* Allocate space for the right(?) number of endpoints */ num_ep = num_ep_orig = alt->desc.bNumEndpoints; alt->desc.bNumEndpoints = 0; // Use as a counter if (num_ep > USB_MAXENDPOINTS) { dev_warn(ddev, "too many endpoints for config %d interface %d " "altsetting %d: %d, using maximum allowed: %d\n", cfgno, inum, asnum, num_ep, USB_MAXENDPOINTS); num_ep = USB_MAXENDPOINTS; } if (num_ep > 0) { /* Can't allocate 0 bytes */ len = sizeof(struct usb_host_endpoint) * num_ep; alt->endpoint = kzalloc(len, GFP_KERNEL); if (!alt->endpoint) return -ENOMEM; } /* Parse all the endpoint descriptors */ n = 0; while (size > 0) { if (((struct usb_descriptor_header *) buffer)->bDescriptorType == USB_DT_INTERFACE) break; retval = usb_parse_endpoint(ddev, cfgno, inum, asnum, alt, num_ep, buffer, size); if (retval < 0) return retval; ++n; buffer += retval; size -= retval; } if (n != num_ep_orig) dev_warn(ddev, "config %d interface %d altsetting %d has %d " "endpoint descriptor%s, different from the interface " "descriptor's value: %d\n", cfgno, inum, asnum, n, plural(n), num_ep_orig); return buffer - buffer0; skip_to_next_interface_descriptor: i = find_next_descriptor(buffer, size, USB_DT_INTERFACE, USB_DT_INTERFACE, NULL); return buffer - buffer0 + i; }
int usb_parse_interface( usb_interface *interface, unsigned char *buffer, int size) { int i; int retval; int parsed = 0; usb_descriptor_header *header; usb_interface_descriptor *ifp; unsigned char *begin; interface->num_altsetting = 0; while (size > 0) { interface->altsetting = realloc(interface->altsetting, sizeof(usb_interface_descriptor) * (interface->num_altsetting + 1)); if (!interface->altsetting) { printf( "malloc\n"); return -1; } ifp = interface->altsetting + interface->num_altsetting; interface->num_altsetting++; memcpy( ifp, buffer, USB_DT_INTERFACE_SIZE); /* Skip over the interface */ buffer += ifp->bLength; parsed += ifp->bLength; size -= ifp->bLength; begin = buffer; /* Skip over any interface, class or vendor descriptors */ while (size >= sizeof(usb_descriptor_header)) { header = (usb_descriptor_header *)buffer; if (header->bLength < 2) { printf( "invalid descriptor length of %d\n", header->bLength); return -1; } /* If we find another "proper" descriptor then we're done */ if ((header->bDescriptorType == USB_DT_INTERFACE) || (header->bDescriptorType == USB_DT_ENDPOINT) || (header->bDescriptorType == USB_DT_CONFIG) || (header->bDescriptorType == USB_DT_DEVICE)) break; buffer += header->bLength; parsed += header->bLength; size -= header->bLength; } // Did we hit an unexpected descriptor? header = (usb_descriptor_header *)buffer; if ((size >= sizeof(usb_descriptor_header)) && ((header->bDescriptorType == USB_DT_CONFIG) || (header->bDescriptorType == USB_DT_DEVICE))) return parsed; if (ifp->bNumEndpoints > USB_MAXENDPOINTS) { printf( "too many endpoints\n"); return -1; } ifp->endpoint = (usb_endpoint_descriptor *) malloc( ifp->bNumEndpoints * sizeof(usb_endpoint_descriptor)); if (!ifp->endpoint) { printf( "malloc\n"); return -1; } memset( ifp->endpoint, 0, ifp->bNumEndpoints * sizeof(usb_endpoint_descriptor)); for (i = 0; i < ifp->bNumEndpoints; i++) { header = (usb_descriptor_header *)buffer; if (header->bLength > size) { printf( "ran out of descriptors parsing\n"); return -1; } retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size); if (retval < 0) return retval; buffer += retval; parsed += retval; size -= retval; } // We check to see if it's an alternate to this one ifp = (usb_interface_descriptor *)buffer; if (size < USB_DT_INTERFACE_SIZE || ifp->bDescriptorType != USB_DT_INTERFACE || !ifp->bAlternateSetting) return parsed; } return parsed; }
static int usb_parse_interface(struct usb_interface *interface, unsigned char *buffer, int size) { int i, len, numskipped, retval, parsed = 0; struct usb_descriptor_header *header; struct usb_host_interface *ifp; unsigned char *begin; interface->act_altsetting = 0; interface->num_altsetting = 0; interface->max_altsetting = USB_ALTSETTINGALLOC; device_initialize(&interface->dev); interface->altsetting = kmalloc(sizeof(*interface->altsetting) * interface->max_altsetting, GFP_KERNEL); if (!interface->altsetting) { err("couldn't kmalloc interface->altsetting"); return -1; } while (size > 0) { struct usb_interface_descriptor *d; if (interface->num_altsetting >= interface->max_altsetting) { struct usb_host_interface *ptr; int oldmas; oldmas = interface->max_altsetting; interface->max_altsetting += USB_ALTSETTINGALLOC; if (interface->max_altsetting > USB_MAXALTSETTING) { warn("too many alternate settings (incr %d max %d)\n", USB_ALTSETTINGALLOC, USB_MAXALTSETTING); return -1; } ptr = kmalloc(sizeof(*ptr) * interface->max_altsetting, GFP_KERNEL); if (ptr == NULL) { err("couldn't kmalloc interface->altsetting"); return -1; } memcpy(ptr, interface->altsetting, sizeof(*interface->altsetting) * oldmas); kfree(interface->altsetting); interface->altsetting = ptr; } ifp = interface->altsetting + interface->num_altsetting; ifp->endpoint = NULL; ifp->extra = NULL; ifp->extralen = 0; interface->num_altsetting++; memcpy(ifp, buffer, USB_DT_INTERFACE_SIZE); /* Skip over the interface */ buffer += ifp->desc.bLength; parsed += ifp->desc.bLength; size -= ifp->desc.bLength; begin = buffer; numskipped = 0; /* Skip over any interface, class or vendor descriptors */ while (size >= sizeof(struct usb_descriptor_header)) { header = (struct usb_descriptor_header *)buffer; if (header->bLength < 2) { err("invalid descriptor length of %d", header->bLength); return -1; } /* If we find another "proper" descriptor then we're done */ if ((header->bDescriptorType == USB_DT_INTERFACE) || (header->bDescriptorType == USB_DT_ENDPOINT) || (header->bDescriptorType == USB_DT_CONFIG) || (header->bDescriptorType == USB_DT_DEVICE)) break; numskipped++; buffer += header->bLength; parsed += header->bLength; size -= header->bLength; } if (numskipped) dbg("skipped %d class/vendor specific interface descriptors", numskipped); /* Copy any unknown descriptors into a storage area for */ /* drivers to later parse */ len = (int)(buffer - begin); if (len) { ifp->extra = kmalloc(len, GFP_KERNEL); if (!ifp->extra) { err("couldn't allocate memory for interface extra descriptors"); ifp->extralen = 0; return -1; } memcpy(ifp->extra, begin, len); ifp->extralen = len; } /* Did we hit an unexpected descriptor? */ header = (struct usb_descriptor_header *)buffer; if ((size >= sizeof(struct usb_descriptor_header)) && ((header->bDescriptorType == USB_DT_CONFIG) || (header->bDescriptorType == USB_DT_DEVICE))) return parsed; if (ifp->desc.bNumEndpoints > USB_MAXENDPOINTS) { warn("too many endpoints"); return -1; } ifp->endpoint = (struct usb_host_endpoint *) kmalloc(ifp->desc.bNumEndpoints * sizeof(struct usb_host_endpoint), GFP_KERNEL); if (!ifp->endpoint) { err("out of memory"); return -1; } memset(ifp->endpoint, 0, ifp->desc.bNumEndpoints * sizeof(struct usb_host_endpoint)); for (i = 0; i < ifp->desc.bNumEndpoints; i++) { header = (struct usb_descriptor_header *)buffer; if (header->bLength > size) { err("ran out of descriptors parsing"); return -1; } retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size); if (retval < 0) return retval; buffer += retval; parsed += retval; size -= retval; } /* We check to see if it's an alternate to this one */ d = (struct usb_interface_descriptor *)buffer; if (size < USB_DT_INTERFACE_SIZE || d->bDescriptorType != USB_DT_INTERFACE || !d->bAlternateSetting) return parsed; } return parsed; }
static int usb_parse_interface(struct usb_interface *interface, unsigned char *buffer, int size) { int i, len, numskipped, retval, parsed = 0; struct usb_descriptor_header header; struct usb_interface_descriptor *ifp; unsigned char *begin; interface->num_altsetting = 0; while (size >= INTERFACE_DESC_LENGTH) { interface->altsetting = realloc(interface->altsetting, sizeof(struct usb_interface_descriptor) * (interface->num_altsetting + 1)); if (!interface->altsetting) { if (usb_debug >= 1) fprintf(stderr, "couldn't malloc interface->altsetting\n"); return -1; } ifp = interface->altsetting + interface->num_altsetting; interface->num_altsetting++; usb_parse_descriptor(buffer, "bbbbbbbbb", ifp); /* Skip over the interface */ buffer += ifp->bLength; parsed += ifp->bLength; size -= ifp->bLength; begin = buffer; numskipped = 0; /* Skip over any interface, class or vendor descriptors */ while (size >= DESC_HEADER_LENGTH) { usb_parse_descriptor(buffer, "bb", &header); if (header.bLength < 2) { if (usb_debug >= 1) fprintf(stderr, "invalid descriptor length of %d\n", header.bLength); return -1; } /* If we find another "proper" descriptor then we're done */ if ((header.bDescriptorType == USB_DT_INTERFACE) || (header.bDescriptorType == USB_DT_ENDPOINT) || (header.bDescriptorType == USB_DT_CONFIG) || (header.bDescriptorType == USB_DT_DEVICE)) break; numskipped++; buffer += header.bLength; parsed += header.bLength; size -= header.bLength; } if (numskipped && usb_debug >= 2) fprintf(stderr, "skipped %d class/vendor specific interface descriptors\n", numskipped); /* Copy any unknown descriptors into a storage area for */ /* drivers to later parse */ len = (int)(buffer - begin); if (!len) { ifp->extra = NULL; ifp->extralen = 0; } else { ifp->extra = malloc(len); if (!ifp->extra) { if (usb_debug >= 1) fprintf(stderr, "couldn't allocate memory for interface extra descriptors\n"); ifp->extralen = 0; return -1; } memcpy(ifp->extra, begin, len); ifp->extralen = len; } /* Did we hit an unexpected descriptor? */ usb_parse_descriptor(buffer, "bb", &header); if ((size >= DESC_HEADER_LENGTH) && ((header.bDescriptorType == USB_DT_CONFIG) || (header.bDescriptorType == USB_DT_DEVICE))) return parsed; if (ifp->bNumEndpoints > USB_MAXENDPOINTS) { if (usb_debug >= 1) fprintf(stderr, "too many endpoints\n"); return -1; } if (ifp->bNumEndpoints > 0) { ifp->endpoint = (struct usb_endpoint_descriptor *) malloc(ifp->bNumEndpoints * sizeof(struct usb_endpoint_descriptor)); if (!ifp->endpoint) { if (usb_debug >= 1) fprintf(stderr, "couldn't allocate memory for ifp->endpoint\n"); return -1; } memset(ifp->endpoint, 0, ifp->bNumEndpoints * sizeof(struct usb_endpoint_descriptor)); for (i = 0; i < ifp->bNumEndpoints; i++) { usb_parse_descriptor(buffer, "bb", &header); if (header.bLength > size) { if (usb_debug >= 1) fprintf(stderr, "ran out of descriptors parsing\n"); return -1; } retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size); if (retval < 0) return retval; buffer += retval; parsed += retval; size -= retval; } } else ifp->endpoint = NULL; /* We check to see if it's an alternate to this one */ ifp = (struct usb_interface_descriptor *)buffer; if (size < USB_DT_INTERFACE_SIZE || ifp->bDescriptorType != USB_DT_INTERFACE || !ifp->bAlternateSetting) return parsed; } return parsed; }