void usb_fetch_and_parse_descriptors(usb_dev_handle * udev) { struct usb_device *dev; struct libusb20_device *pdev; uint8_t *ptr; int error; uint32_t size; uint16_t len; uint8_t x; if (udev == NULL) { /* be NULL safe */ return; } dev = usb_device(udev); pdev = (void *)udev; if (dev->descriptor.bNumConfigurations == 0) { /* invalid device */ return; } size = dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor); dev->config = malloc(size); if (dev->config == NULL) { /* out of memory */ return; } memset(dev->config, 0, size); for (x = 0; x != dev->descriptor.bNumConfigurations; x++) { error = (pdev->methods->get_config_desc_full) ( pdev, &ptr, &len, x); if (error) { usb_destroy_configuration(dev); return; } usb_parse_configuration(dev->config + x, ptr); /* free config buffer */ free(ptr); } return; }
/* * Get the USB config descriptors, cache and parse'em * * hub-only!! ... and only in reset path, or usb_new_device() * (used by real hubs and virtual root hubs) * * NOTE: if this is a WUSB device and is not authorized, we skip the * whole thing. A non-authorized USB device has no * configurations. */ int usb_get_configuration(struct usb_device *dev) { struct device *ddev = &dev->dev; int ncfg = dev->descriptor.bNumConfigurations; int result = 0; unsigned int cfgno, length; unsigned char *buffer; unsigned char *bigbuffer; struct usb_config_descriptor *desc; cfgno = 0; if (dev->authorized == 0) /* Not really an error */ goto out_not_authorized; result = -ENOMEM; if (ncfg > USB_MAXCONFIG) { dev_warn(ddev, "too many configurations: %d, " "using maximum allowed: %d\n", ncfg, USB_MAXCONFIG); dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG; } if (ncfg < 1) { dev_err(ddev, "no configurations\n"); return -EINVAL; } length = ncfg * sizeof(struct usb_host_config); dev->config = kzalloc(length, GFP_KERNEL); if (!dev->config) goto err2; length = ncfg * sizeof(char *); dev->rawdescriptors = kzalloc(length, GFP_KERNEL); if (!dev->rawdescriptors) goto err2; buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL); if (!buffer) goto err2; desc = (struct usb_config_descriptor *)buffer; result = 0; for (; cfgno < ncfg; cfgno++) { /* We grab just the first descriptor so we know how long * the whole configuration is */ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, USB_DT_CONFIG_SIZE); if (result < 0) { dev_err(ddev, "unable to read config index %d " "descriptor/%s: %d\n", cfgno, "start", result); dev_err(ddev, "chopping to %d config(s)\n", cfgno); dev->descriptor.bNumConfigurations = cfgno; break; } else if (result < 4) { dev_err(ddev, "config index %d descriptor too short " "(expected %i, got %i)\n", cfgno, USB_DT_CONFIG_SIZE, result); result = -EINVAL; goto err; } length = max((int) le16_to_cpu(desc->wTotalLength), USB_DT_CONFIG_SIZE); /* Now that we know the length, get the whole thing */ bigbuffer = kmalloc(length, GFP_KERNEL); if (!bigbuffer) { result = -ENOMEM; goto err; } result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length); if (result < 0) { dev_err(ddev, "unable to read config index %d " "descriptor/%s\n", cfgno, "all"); kfree(bigbuffer); goto err; } if (result < length) { dev_warn(ddev, "config index %d descriptor too short " "(expected %i, got %i)\n", cfgno, length, result); length = result; } #if defined(__VMKLNX__) dev->rawdescriptors[cfgno] = (char *)bigbuffer; #else dev->rawdescriptors[cfgno] = bigbuffer; #endif result = usb_parse_configuration(&dev->dev, cfgno, &dev->config[cfgno], bigbuffer, length); if (result < 0) { ++cfgno; goto err; } } result = 0; err: kfree(buffer); out_not_authorized: dev->descriptor.bNumConfigurations = cfgno; err2: if (result == -ENOMEM) dev_err(ddev, "out of memory\n"); return result; }
int usb_os_find_devices(struct usb_bus *bus, struct usb_device **devices) { struct usb_device *fdev = NULL; DIR *dir; struct dirent *entry; char dirpath[PATH_MAX + 1]; snprintf(dirpath, PATH_MAX, "%s/%s", usb_path, bus->dirname); dir = opendir(dirpath); if (!dir) USB_ERROR_STR(-errno, "couldn't opendir(%s): %s", dirpath, strerror(errno)); while ((entry = readdir(dir)) != NULL) { unsigned char device_desc[DEVICE_DESC_LENGTH]; char filename[PATH_MAX + 1]; struct usb_device *dev; struct usb_connectinfo connectinfo; int i, fd, ret; /* Skip anything starting with a . */ if (entry->d_name[0] == '.') continue; dev = malloc(sizeof(*dev)); if (!dev) USB_ERROR(-ENOMEM); memset((void *)dev, 0, sizeof(*dev)); dev->bus = bus; strncpy(dev->filename, entry->d_name, sizeof(dev->filename) - 1); dev->filename[sizeof(dev->filename) - 1] = 0; snprintf(filename, sizeof(filename) - 1, "%s/%s", dirpath, entry->d_name); fd = open(filename, O_RDWR); if (fd < 0) { fd = open(filename, O_RDONLY); if (fd < 0) { if (usb_debug >= 2) fprintf(stderr, "usb_os_find_devices: Couldn't open %s\n", filename); free(dev); continue; } } /* Get the device number */ ret = ioctl(fd, IOCTL_USB_CONNECTINFO, &connectinfo); if (ret < 0) { if (usb_debug) fprintf(stderr, "usb_os_find_devices: couldn't get connect info\n"); } else dev->devnum = connectinfo.devnum; ret = read(fd, (void *)device_desc, DEVICE_DESC_LENGTH); if (ret < 0) { if (usb_debug) fprintf(stderr, "usb_os_find_devices: Couldn't read descriptor\n"); free(dev); goto err; } /* * Linux kernel converts the words in this descriptor to CPU endian, so * we use the undocumented W character for usb_parse_descriptor() that * doesn't convert endianess when parsing the descriptor */ usb_parse_descriptor(device_desc, "bbWbbbbWWWbbbb", &dev->descriptor); LIST_ADD(fdev, dev); if (usb_debug >= 2) fprintf(stderr, "usb_os_find_devices: Found %s on %s\n", dev->filename, bus->dirname); /* Now try to fetch the rest of the descriptors */ if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) /* Silent since we'll try again later */ goto err; if (dev->descriptor.bNumConfigurations < 1) /* Silent since we'll try again later */ goto err; dev->config = (struct usb_config_descriptor *)malloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor)); if (!dev->config) /* Silent since we'll try again later */ goto err; 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; /* Get the first 8 bytes so we can figure out what the total length is */ ret = read(fd, (void *)buffer, 8); if (ret < 8) { if (usb_debug >= 1) { if (ret < 0) fprintf(stderr, "Unable to get descriptor (%d)\n", ret); else fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", 8, ret); } 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; } /* Read the rest of the config descriptor */ memcpy(bigbuffer, buffer, 8); ret = read(fd, (void *)(bigbuffer + 8), config.wTotalLength - 8); if (ret < config.wTotalLength - 8) { if (usb_debug >= 1) { if (ret < 0) fprintf(stderr, "Unable to get descriptor (%d)\n", ret); else fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", config.wTotalLength, ret); } free(bigbuffer); goto err; } ret = usb_parse_configuration(&dev->config[i], bigbuffer); if (usb_debug >= 2) { if (ret > 0) fprintf(stderr, "Descriptor data still left\n"); else if (ret < 0) fprintf(stderr, "Unable to parse descriptors\n"); } free(bigbuffer); } err: close(fd); } closedir(dir); *devices = fdev; return 0; }
int usb_os_find_devices( struct usb_bus *bus, struct usb_device **devices) { int rtn = 0; APIRET rc; ULONG cntDev; ULONG ctr; ULONG i; ULONG len; struct usb_device * fdev = NULL; struct usb_device * dev; char report[4096]; rc = UsbQueryNumberDevices( &cntDev); if (rc) { USB_ERROR_MSG( "unable to query number of USB devices - rc= %x", (int)rc); return -1; } for (ctr = 1; ctr <= cntDev; ctr++) { len = sizeof(report); rc = UsbQueryDeviceReport( ctr, &len, report); if (rc) { USB_ERROR_MSG( "unable to query device report - device= %d rc= %x", (int)ctr, (int)rc); return -1; } dev = calloc( 1, sizeof(struct usb_device)); if (!dev) { USB_ERROR_MSG( "unable to allocate memory in usb_os_find_devices"); return -1; } dev->bus = bus; dev->devnum = ctr; itoa( ctr, dev->filename, 10); memcpy( &dev->descriptor, report, sizeof(dev->descriptor)); LIST_ADD( fdev, dev); USB_DEBUG_MSG( "Found device %s on bus %s", dev->filename, bus->dirname); if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG || dev->descriptor.bNumConfigurations < 1) { USB_DEBUG_MSG( "invalid number of device configurations - nbr= %d continuing...", dev->descriptor.bNumConfigurations); continue; } i = sizeof(struct usb_device_descriptor) + (dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor)); if (len < i) { USB_DEBUG_MSG( "device report too short - expected= %d actual= %d continuing...", (int)i, (int)len); continue; } dev->config = (struct usb_config_descriptor *)calloc( dev->descriptor.bNumConfigurations, sizeof(struct usb_config_descriptor)); if (!dev->config) { USB_ERROR_MSG( "unable to allocate memory in usb_os_find_devices"); return -1; } for (i = 0, len = sizeof(struct usb_device_descriptor); i < dev->descriptor.bNumConfigurations; i++) { char * ptr; ptr = &report[len]; len += ((struct usb_config_descriptor *)ptr)->wTotalLength; rtn = usb_parse_configuration( &dev->config[i], ptr); if (rtn > 0) USB_DEBUG_MSG( "Descriptor data still left - bytes= %d", rtn); else if (rtn < 0) USB_DEBUG_MSG( "Unable to parse descriptors"); } // configs } // devices *devices = fdev; return 0; }
// hub-only!! ... and only in reset path, or usb_new_device() // (used by real hubs and virtual root hubs) int usb_get_configuration(struct usb_device *dev) { int result; unsigned int cfgno, length; unsigned char *buffer; unsigned char *bigbuffer; struct usb_config_descriptor *desc; if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) { warn("too many configurations"); return -EINVAL; } if (dev->descriptor.bNumConfigurations < 1) { warn("not enough configurations"); return -EINVAL; } dev->config = (struct usb_host_config *) kmalloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_host_config), GFP_KERNEL); if (!dev->config) { err("out of memory"); return -ENOMEM; } memset(dev->config, 0, dev->descriptor.bNumConfigurations * sizeof(struct usb_host_config)); dev->rawdescriptors = (char **)kmalloc(sizeof(char *) * dev->descriptor.bNumConfigurations, GFP_KERNEL); if (!dev->rawdescriptors) { err("out of memory"); return -ENOMEM; } buffer = kmalloc(8, GFP_KERNEL); if (!buffer) { err("unable to allocate memory for configuration descriptors"); return -ENOMEM; } desc = (struct usb_config_descriptor *)buffer; for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) { /* We grab the first 8 bytes so we know how long the whole */ /* configuration is */ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8); if (result < 8) { if (result < 0) err("unable to get descriptor"); else { err("config descriptor too short (expected %i, got %i)", 8, result); result = -EINVAL; } goto err; } /* Get the full buffer */ length = le16_to_cpu(desc->wTotalLength); bigbuffer = kmalloc(length, GFP_KERNEL); if (!bigbuffer) { err("unable to allocate memory for configuration descriptors"); result = -ENOMEM; goto err; } /* Now that we know the length, get the whole thing */ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length); if (result < 0) { err("couldn't get all of config descriptors"); kfree(bigbuffer); goto err; } if (result < length) { err("config descriptor too short (expected %i, got %i)", length, result); result = -EINVAL; kfree(bigbuffer); goto err; } dev->rawdescriptors[cfgno] = bigbuffer; result = usb_parse_configuration(&dev->config[cfgno], bigbuffer); if (result > 0) dbg("descriptor data left"); else if (result < 0) { result = -EINVAL; goto err; } } kfree(buffer); return 0; err: kfree(buffer); dev->descriptor.bNumConfigurations = cfgno; return result; }
// hub-only!! ... and only in reset path, or usb_new_device() // (used by real hubs and virtual root hubs) int usb_get_configuration(struct usb_device *dev) { struct device *ddev = &dev->dev; int ncfg = dev->descriptor.bNumConfigurations; int result = -ENOMEM; unsigned int cfgno, length; unsigned char *buffer; unsigned char *bigbuffer; struct usb_config_descriptor *desc; if (ncfg > USB_MAXCONFIG) { dev_warn(ddev, "too many configurations: %d, " "using maximum allowed: %d\n", ncfg, USB_MAXCONFIG); dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG; } if (ncfg < 1) { #if 0 dev_err(ddev, "no configurations\n"); return -EINVAL; #else dev_err(ddev, "no configurations, try to get configurations [cfyeh]\n"); ncfg = 1; #endif } length = ncfg * sizeof(struct usb_host_config); dev->config = kmalloc(length, GFP_KERNEL); if (!dev->config) goto err2; memset(dev->config, 0, length); length = ncfg * sizeof(char *); dev->rawdescriptors = kmalloc(length, GFP_KERNEL); if (!dev->rawdescriptors) goto err2; memset(dev->rawdescriptors, 0, length); #ifdef USB_512B_ALIGNMENT buffer = kmalloc(USB_512B_ALIGNMENT_SIZE, GFP_KERNEL); #else buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL); #endif /* USB_512B_ALIGNMENT */ if (!buffer) goto err2; desc = (struct usb_config_descriptor *)buffer; for (cfgno = 0; cfgno < ncfg; cfgno++) { /* We grab just the first descriptor so we know how long * the whole configuration is */ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, USB_DT_CONFIG_SIZE); if (result < 0) { dev_err(ddev, "unable to read config index %d " "descriptor/%s\n", cfgno, "start"); goto err; } else if (result < 4) { dev_err(ddev, "config index %d descriptor too short " "(expected %i, got %i)\n", cfgno, USB_DT_CONFIG_SIZE, result); result = -EINVAL; goto err; } length = max((int) le16_to_cpu(desc->wTotalLength), USB_DT_CONFIG_SIZE); /* Now that we know the length, get the whole thing */ #ifdef USB_512B_ALIGNMENT if(length > USB_512B_ALIGNMENT_SIZE) bigbuffer = kmalloc(length, GFP_KERNEL); else bigbuffer = kmalloc(USB_512B_ALIGNMENT_SIZE, GFP_KERNEL); #else bigbuffer = kmalloc(length, GFP_KERNEL); #endif /* USB_512B_ALIGNMENT */ if (!bigbuffer) { result = -ENOMEM; goto err; } result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length); if (result < 0) { dev_err(ddev, "unable to read config index %d " "descriptor/%s\n", cfgno, "all"); kfree(bigbuffer); goto err; } if (result < length) { dev_warn(ddev, "config index %d descriptor too short " "(expected %i, got %i)\n", cfgno, length, result); length = result; } dev->rawdescriptors[cfgno] = bigbuffer; result = usb_parse_configuration(&dev->dev, cfgno, &dev->config[cfgno], bigbuffer, length); if (result < 0) { ++cfgno; goto err; } } result = 0; err: kfree(buffer); dev->descriptor.bNumConfigurations = cfgno; err2: if (result == -ENOMEM) dev_err(ddev, "out of memory\n"); return result; }
int usb_find_devices( usb_device **devices) { int rtn = 0; int rc; ULONG cntDev; int ctr; int i; ULONG len; usb_device * devList = 0; usb_device * dev; char report[4096]; rc = UsbQueryNumberDevices( &cntDev); if (rc) { printf( "UsbQueryNumberDevices - rc= 0x%x\n", (int)rc); return (rc); } for (ctr = 1; ctr <= cntDev; ctr++) { len = sizeof(report); rc = UsbQueryDeviceReport( ctr, &len, report); if (rc) { printf( "UsbQueryDeviceReport - device= %d rc= 0x%x\n", (int)ctr, (int)rc); return (rc); } dev = calloc( 1, sizeof(usb_device)); if (!dev) { printf( "malloc\n"); return (-1); } dev->next = devList; devList = dev; dev->devnum = ctr; memcpy( &dev->descriptor, report, sizeof(dev->descriptor)); printf( "Found device %d\n", dev->devnum); if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG || dev->descriptor.bNumConfigurations < 1) { printf( "invalid number of device configurations - nbr= %d continuing...\n", dev->descriptor.bNumConfigurations); continue; } i = sizeof(usb_device_descriptor) + (dev->descriptor.bNumConfigurations * sizeof(usb_config_descriptor)); if (len < i) { printf( "device report too short - expected= %d actual= %d continuing...\n", (int)i, (int)len); continue; } dev->config = (usb_config_descriptor *)calloc( dev->descriptor.bNumConfigurations, sizeof(usb_config_descriptor)); if (!dev->config) { printf( "malloc\n"); return (-1); } for (i = 0, len = sizeof(usb_device_descriptor); i < dev->descriptor.bNumConfigurations; i++) { char * ptr; ptr = &report[len]; len += ((usb_config_descriptor *)ptr)->wTotalLength; rtn = usb_parse_configuration( &dev->config[i], ptr); if (rtn > 0) printf( "Descriptor data still left - bytes= %d\n", rtn); else if (rtn < 0) printf( "Unable to parse descriptors\n"); } // configs } // devices *devices = devList; return (0); }
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, (unsigned char)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, (unsigned char)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; }