diff options
Diffstat (limited to 'libusb/descriptors.c')
-rw-r--r-- | libusb/descriptors.c | 520 |
1 files changed, 0 insertions, 520 deletions
diff --git a/libusb/descriptors.c b/libusb/descriptors.c deleted file mode 100644 index 0146a82..0000000 --- a/libusb/descriptors.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - * Parses descriptors - * - * Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com> - * - * This library is covered by the LGPL, read LICENSE for details. - */ - -#include <stdio.h> -#include <string.h> -#include <stdint.h> -#include "usbi.h" - -int usb_get_descriptor_by_endpoint(usb_dev_handle *udev, int ep, - unsigned char type, unsigned char index, void *buf, int size) -{ - memset(buf, 0, size); - - return usb_control_msg(udev, ep | USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, - (type << 8) + index, 0, buf, size, 1000); -} - -int usb_get_descriptor(usb_dev_handle *udev, unsigned char type, - unsigned char index, void *buf, int size) -{ - memset(buf, 0, size); - - return usb_control_msg(udev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, - (type << 8) + index, 0, buf, size, 1000); -} - -int usb_parse_descriptor(unsigned char *source, char *description, void *dest) -{ - unsigned char *sp = source, *dp = dest; - uint16_t w; - uint32_t d; - char *cp; - - for (cp = description; *cp; cp++) { - switch (*cp) { - case 'b': /* 8-bit byte */ - *dp++ = *sp++; - break; - case 'w': /* 16-bit word, convert from little endian to CPU */ - w = (sp[1] << 8) | sp[0]; sp += 2; - dp += ((unsigned long)dp & 1); /* Align to word boundary */ - *((uint16_t *)dp) = w; dp += 2; - break; - case 'd': /* 32-bit dword, convert from little endian to CPU */ - d = (sp[3] << 24) | (sp[2] << 16) | (sp[1] << 8) | sp[0]; sp += 4; - dp += ((unsigned long)dp & 2); /* Align to dword boundary */ - *((uint32_t *)dp) = d; dp += 4; - break; - /* These two characters are undocumented and just a hack for Linux */ - case 'W': /* 16-bit word, keep CPU endianess */ - dp += ((unsigned long)dp & 1); /* Align to word boundary */ - memcpy(dp, sp, 2); sp += 2; dp += 2; - break; - case 'D': /* 32-bit dword, keep CPU endianess */ - dp += ((unsigned long)dp & 2); /* Align to dword boundary */ - memcpy(dp, sp, 4); sp += 4; dp += 4; - break; - } - } - - return sp - source; -} - -/* - * This code looks surprisingly similar to the code I wrote for the Linux - * kernel. It's not a coincidence :) - */ - -static int usb_parse_endpoint(struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size) -{ - struct usb_descriptor_header header; - unsigned char *begin; - int parsed = 0, len, numskipped; - - usb_parse_descriptor(buffer, "bb", &header); - - /* Everything should be fine being passed into here, but we sanity */ - /* check JIC */ - if (header.bLength > size) { - if (usb_debug >= 1) - fprintf(stderr, "ran out of descriptors parsing\n"); - return -1; - } - - if (header.bDescriptorType != USB_DT_ENDPOINT) { - if (usb_debug >= 2) - fprintf(stderr, "unexpected descriptor 0x%X, expecting endpoint descriptor, type 0x%X\n", - header.bDescriptorType, USB_DT_ENDPOINT); - return parsed; - } - - if (header.bLength >= ENDPOINT_AUDIO_DESC_LENGTH) - usb_parse_descriptor(buffer, "bbbbwbbb", endpoint); - else if (header.bLength >= ENDPOINT_DESC_LENGTH) - usb_parse_descriptor(buffer, "bbbbwb", endpoint); - - buffer += header.bLength; - size -= header.bLength; - parsed += header.bLength; - - /* Skip over the rest of the Class Specific or Vendor Specific */ - /* descriptors */ - begin = buffer; - numskipped = 0; - 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_ENDPOINT) || - (header.bDescriptorType == USB_DT_INTERFACE) || - (header.bDescriptorType == USB_DT_CONFIG) || - (header.bDescriptorType == USB_DT_DEVICE)) - break; - - if (usb_debug >= 1) - fprintf(stderr, "skipping descriptor 0x%X\n", header.bDescriptorType); - numskipped++; - - buffer += header.bLength; - size -= header.bLength; - parsed += header.bLength; - } - - if (numskipped && usb_debug >= 2) - fprintf(stderr, "skipped %d class/vendor specific endpoint descriptors\n", numskipped); - - /* Copy any unknown descriptors into a storage area for drivers */ - /* to later parse */ - len = (int)(buffer - begin); - if (!len) { - endpoint->extra = NULL; - endpoint->extralen = 0; - return parsed; - } - - endpoint->extra = malloc(len); - if (!endpoint->extra) { - if (usb_debug >= 1) - fprintf(stderr, "couldn't allocate memory for endpoint extra descriptors\n"); - endpoint->extralen = 0; - return parsed; - } - - memcpy(endpoint->extra, begin, len); - endpoint->extralen = len; - - 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; -} - -int usb_parse_configuration(struct usb_config_descriptor *config, - unsigned char *buffer) -{ - int i, retval, size; - struct usb_descriptor_header header; - - usb_parse_descriptor(buffer, "bbwbbbbb", config); - size = config->wTotalLength; - - if (config->bNumInterfaces > USB_MAXINTERFACES) { - if (usb_debug >= 1) - fprintf(stderr, "too many interfaces\n"); - return -1; - } - - config->interface = (struct usb_interface *) - malloc(config->bNumInterfaces * - sizeof(struct usb_interface)); - if (!config->interface) { - if (usb_debug >= 1) - fprintf(stderr, "out of memory\n"); - return -1; - } - - memset(config->interface, 0, config->bNumInterfaces * sizeof(struct usb_interface)); - - buffer += config->bLength; - size -= config->bLength; - - config->extra = NULL; - config->extralen = 0; - - for (i = 0; i < config->bNumInterfaces; i++) { - int numskipped, len; - unsigned char *begin; - - /* Skip over the rest of the Class Specific or Vendor */ - /* Specific descriptors */ - begin = buffer; - numskipped = 0; - while (size >= DESC_HEADER_LENGTH) { - usb_parse_descriptor(buffer, "bb", &header); - - if ((header.bLength > size) || (header.bLength < DESC_HEADER_LENGTH)) { - 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_ENDPOINT) || - (header.bDescriptorType == USB_DT_INTERFACE) || - (header.bDescriptorType == USB_DT_CONFIG) || - (header.bDescriptorType == USB_DT_DEVICE)) - break; - - if (usb_debug >= 2) - fprintf(stderr, "skipping descriptor 0x%X\n", header.bDescriptorType); - numskipped++; - - buffer += header.bLength; - size -= header.bLength; - } - - if (numskipped && usb_debug >= 2) - fprintf(stderr, "skipped %d class/vendor specific endpoint descriptors\n", numskipped); - - /* Copy any unknown descriptors into a storage area for */ - /* drivers to later parse */ - len = (int)(buffer - begin); - if (len) { - /* FIXME: We should realloc and append here */ - if (!config->extralen) { - config->extra = malloc(len); - if (!config->extra) { - if (usb_debug >= 1) - fprintf(stderr, "couldn't allocate memory for config extra descriptors\n"); - config->extralen = 0; - return -1; - } - - memcpy(config->extra, begin, len); - config->extralen = len; - } - } - - retval = usb_parse_interface(config->interface + i, buffer, size); - if (retval < 0) - return retval; - - buffer += retval; - size -= retval; - } - - return size; -} - -void usb_destroy_configuration(struct usb_device *dev) -{ - int c, i, j, k; - - if (!dev->config) - return; - - for (c = 0; c < dev->descriptor.bNumConfigurations; c++) { - struct usb_config_descriptor *cf = &dev->config[c]; - - if (!cf->interface) - continue; - - for (i = 0; i < cf->bNumInterfaces; i++) { - struct usb_interface *ifp = &cf->interface[i]; - - if (!ifp->altsetting) - continue; - - for (j = 0; j < ifp->num_altsetting; j++) { - struct usb_interface_descriptor *as = &ifp->altsetting[j]; - - if (as->extra) - free(as->extra); - - if (!as->endpoint) - continue; - - for (k = 0; k < as->bNumEndpoints; k++) { - if (as->endpoint[k].extra) - free(as->endpoint[k].extra); - } - free(as->endpoint); - } - - free(ifp->altsetting); - } - - free(cf->interface); - } - - free(dev->config); -} - -void usb_fetch_and_parse_descriptors(usb_dev_handle *udev) -{ - struct usb_device *dev = udev->device; - int i; - - if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) { - if (usb_debug >= 1) - fprintf(stderr, "Too many configurations (%d > %d)\n", dev->descriptor.bNumConfigurations, USB_MAXCONFIG); - return; - } - - if (dev->descriptor.bNumConfigurations < 1) { - if (usb_debug >= 1) - fprintf(stderr, "Not enough configurations (%d < %d)\n", dev->descriptor.bNumConfigurations, 1); - return; - } - - dev->config = (struct usb_config_descriptor *)malloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor)); - if (!dev->config) { - if (usb_debug >= 1) - fprintf(stderr, "Unable to allocate memory for config descriptor\n"); - return; - } - - memset(dev->config, 0, dev->descriptor.bNumConfigurations * - sizeof(struct usb_config_descriptor)); - - for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { - unsigned char buffer[8], *bigbuffer; - struct usb_config_descriptor config; - int res; - - /* Get the first 8 bytes so we can figure out what the total length is */ - res = usb_get_descriptor(udev, USB_DT_CONFIG, i, buffer, 8); - if (res < 8) { - if (usb_debug >= 1) { - if (res < 0) - fprintf(stderr, "Unable to get descriptor (%d)\n", res); - else - fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", 8, res); - } - - goto err; - } - - usb_parse_descriptor(buffer, "bbw", &config); - - bigbuffer = malloc(config.wTotalLength); - if (!bigbuffer) { - if (usb_debug >= 1) - fprintf(stderr, "Unable to allocate memory for descriptors\n"); - goto err; - } - - res = usb_get_descriptor(udev, USB_DT_CONFIG, i, bigbuffer, config.wTotalLength); - if (res < config.wTotalLength) { - if (usb_debug >= 1) { - if (res < 0) - fprintf(stderr, "Unable to get descriptor (%d)\n", res); - else - fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", config.wTotalLength, res); - } - - free(bigbuffer); - goto err; - } - - res = usb_parse_configuration(&dev->config[i], bigbuffer); - if (usb_debug >= 2) { - if (res > 0) - fprintf(stderr, "Descriptor data still left\n"); - else if (res < 0) - fprintf(stderr, "Unable to parse descriptors\n"); - } - - free(bigbuffer); - } - - return; - -err: - free(dev->config); - - dev->config = NULL; -} - |