Core: Cache device descriptors in the core
authorNathan Hjelm <hjelmn@me.com>
Thu, 29 Nov 2012 20:53:41 +0000 (13:53 -0700)
committerHans de Goede <hdegoede@redhat.com>
Wed, 15 May 2013 11:05:07 +0000 (13:05 +0200)
Discussion: It is necessary to cache the device descriptor in the core to
support reading the descriptors after a device is disconnected. We could
either 1) allow each backend to handle this caching (which would most
certainly duplicate code), or 2) cache the descritors when a device
is added. This patch does the later.

Further discussion: It might be beneficial to cache more than just the
device descriptors in the core. It might also be worthwhile caching the
configuration and BOS descriptors as well.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
libusb/core.c
libusb/descriptor.c
libusb/libusbi.h
libusb/os/windows_usb.c
libusb/version_nano.h

index 3fb3999..9a2d1b7 100644 (file)
@@ -537,15 +537,13 @@ struct libusb_device *usbi_alloc_device(struct libusb_context *ctx,
 int usbi_sanitize_device(struct libusb_device *dev)
 {
        int r;
-       unsigned char raw_desc[DEVICE_DESC_LENGTH];
        uint8_t num_configurations;
-       int host_endian;
 
-       r = usbi_backend->get_device_descriptor(dev, raw_desc, &host_endian);
+       r = usbi_device_cache_descriptor(dev);
        if (r < 0)
                return r;
 
-       num_configurations = raw_desc[DEVICE_DESC_LENGTH - 1];
+       num_configurations = dev->device_descriptor.bNumConfigurations;
        if (num_configurations > USB_MAXCONFIG) {
                usbi_err(DEVICE_CTX(dev), "too many configurations");
                return LIBUSB_ERROR_IO;
index 7e47aae..505fc28 100644 (file)
@@ -437,6 +437,25 @@ err:
        return r;
 }
 
+int usbi_device_cache_descriptor(libusb_device *dev)
+{
+       int r, host_endian;
+
+       r = usbi_backend->get_device_descriptor(dev, (unsigned char *) &dev->device_descriptor,
+                                               &host_endian);
+       if (r < 0)
+               return r;
+
+       if (!host_endian) {
+               dev->device_descriptor.bcdUSB = libusb_le16_to_cpu(dev->device_descriptor.bcdUSB);
+               dev->device_descriptor.idVendor = libusb_le16_to_cpu(dev->device_descriptor.idVendor);
+               dev->device_descriptor.idProduct = libusb_le16_to_cpu(dev->device_descriptor.idProduct);
+               dev->device_descriptor.bcdDevice = libusb_le16_to_cpu(dev->device_descriptor.bcdDevice);
+       }
+
+       return LIBUSB_SUCCESS;
+}
+
 /** \ingroup desc
  * Get the USB device descriptor for a given device.
  *
@@ -449,22 +468,9 @@ err:
 int API_EXPORTED libusb_get_device_descriptor(libusb_device *dev,
        struct libusb_device_descriptor *desc)
 {
-       unsigned char raw_desc[DEVICE_DESC_LENGTH];
-       int host_endian = 0;
-       int r;
-
        usbi_dbg("");
-       r = usbi_backend->get_device_descriptor(dev, raw_desc, &host_endian);
-       if (r < 0)
-               return r;
-
-       memcpy((unsigned char *) desc, raw_desc, sizeof(raw_desc));
-       if (!host_endian) {
-               desc->bcdUSB = libusb_le16_to_cpu(desc->bcdUSB);
-               desc->idVendor = libusb_le16_to_cpu(desc->idVendor);
-               desc->idProduct = libusb_le16_to_cpu(desc->idProduct);
-               desc->bcdDevice = libusb_le16_to_cpu(desc->bcdDevice);
-       }
+       memcpy((unsigned char *) desc, (unsigned char *) &dev->device_descriptor,
+              sizeof (dev->device_descriptor));
        return 0;
 }
 
index 1957053..b0cc53e 100644 (file)
@@ -288,6 +288,9 @@ struct libusb_device {
 
        struct list_head list;
        unsigned long session_data;
+
+       struct libusb_device_descriptor device_descriptor;
+
        unsigned char os_priv[0];
 };
 
@@ -394,6 +397,7 @@ int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer);
 
 int usbi_parse_descriptor(unsigned char *source, const char *descriptor,
        void *dest, int host_endian);
+int usbi_device_cache_descriptor(libusb_device *dev);
 int usbi_get_config_index_by_value(struct libusb_device *dev,
        uint8_t bConfigurationValue, int *idx);
 
index e0d2a1c..9c0888a 100644 (file)
@@ -1170,6 +1170,8 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d
                force_hcd_device_descriptor(dev);
        }
 
+       usbi_sanitize_device(dev);
+
        usbi_dbg("(bus: %d, addr: %d, depth: %d, port: %d): '%s'",
                dev->bus_number, dev->device_address, priv->depth, priv->port, device_id);
 
index 95fb90e..a4e4971 100644 (file)
@@ -1 +1 @@
-#define LIBUSB_NANO 10649
+#define LIBUSB_NANO 10650