Beispiel #1
0
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;
}
Beispiel #2
0
/*
 * 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;
}
Beispiel #3
0
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;
}
Beispiel #4
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;
}
Beispiel #5
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;
}
Beispiel #6
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)
{
	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;
}