all: Allow backend to provide a better get_config_descriptor_by_value
authorHans de Goede <hdegoede@redhat.com>
Thu, 23 May 2013 17:51:07 +0000 (19:51 +0200)
committerHans de Goede <hdegoede@redhat.com>
Fri, 24 May 2013 14:30:38 +0000 (16:30 +0200)
Our core get_config_descriptor_by_value is not exactly pretty nor efficient,
allow the backends to provide something better.

Note that the callback signature differs from get_config_descriptor in that
backend owned memory gets returned. This saves a needless malloc + memcpy +
free. If this turns out to be a problem for some backends we can always
change things to work like get_config_descriptor.

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

index 5fb96ea..44d93ee 100644 (file)
@@ -678,8 +678,18 @@ int usbi_get_config_index_by_value(struct libusb_device *dev,
 int API_EXPORTED libusb_get_config_descriptor_by_value(libusb_device *dev,
        uint8_t bConfigurationValue, struct libusb_config_descriptor **config)
 {
-       int idx;
-       int r = usbi_get_config_index_by_value(dev, bConfigurationValue, &idx);
+       int r, idx, host_endian;
+       unsigned char *buf = NULL;
+
+       if (usbi_backend->get_config_descriptor_by_value) {
+               r = usbi_backend->get_config_descriptor_by_value(dev,
+                       bConfigurationValue, &buf, &host_endian);
+               if (r < 0)
+                       return r;
+               return raw_desc_to_config(dev->ctx, buf, r, host_endian, config);
+       }
+
+       r = usbi_get_config_index_by_value(dev, bConfigurationValue, &idx);
        if (r < 0)
                return r;
        else if (idx == -1)
index bf240e8..090ac5b 100644 (file)
@@ -665,6 +665,22 @@ struct usbi_os_backend {
                uint8_t config_index, unsigned char *buffer, size_t len,
                int *host_endian);
 
+       /* Like get_config_descriptor but then by bConfigurationValue instead
+        * of by index.
+        *
+        * Optional, if not present the core will call get_config_descriptor
+        * for all configs until it finds the desired bConfigurationValue.
+        *
+        * Returns a pointer to the raw-descriptor in *buffer, this memory
+        * is valid as long as device is valid.
+        *
+        * Returns the length of the returned raw-descriptor on success,
+        * or a LIBUSB_ERROR code on failure.
+        */
+       int (*get_config_descriptor_by_value)(struct libusb_device *device,
+               uint8_t bConfigurationValue, unsigned char **buffer,
+               int *host_endian);
+
        /* Get the bConfigurationValue for the active configuration for a device.
         * Optional. This should only be implemented if you can retrieve it from
         * cache (don't generate I/O).
index 280e312..57ab80c 100644 (file)
@@ -701,8 +701,8 @@ static int seek_to_next_config(struct libusb_context *ctx,
        }
 }
 
-static int get_config_descriptor_by_value(struct libusb_device *dev,
-       unsigned char **buffer, uint8_t value)
+static int op_get_config_descriptor_by_value(struct libusb_device *dev,
+       uint8_t value, unsigned char **buffer, int *host_endian)
 {
        struct libusb_context *ctx = DEVICE_CTX(dev);
        struct linux_device_priv *priv = _device_priv(dev);
@@ -711,6 +711,8 @@ static int get_config_descriptor_by_value(struct libusb_device *dev,
        struct libusb_config_descriptor *config;
 
        *buffer = NULL;
+       /* Unlike the device desc. config descs. are always in raw format */
+       *host_endian = 0;
 
        /* Skip device header */
        descriptors += DEVICE_DESC_LENGTH;
@@ -737,9 +739,6 @@ static int op_get_active_config_descriptor(struct libusb_device *dev,
        int r, config;
        unsigned char *config_desc;
 
-       /* Unlike the device desc. config descs. are always in raw format */
-       *host_endian = 0;
-
        if (sysfs_can_relate_devices) {
                r = sysfs_get_active_config(dev, &config);
                if (r < 0)
@@ -752,7 +751,8 @@ static int op_get_active_config_descriptor(struct libusb_device *dev,
        if (config == -1)
                return LIBUSB_ERROR_NOT_FOUND;
 
-       r = get_config_descriptor_by_value(dev, &config_desc, config);
+       r = op_get_config_descriptor_by_value(dev, config, &config_desc,
+                                             host_endian);
        if (r < 0)
                return r;
 
@@ -2458,6 +2458,7 @@ const struct usbi_os_backend linux_usbfs_backend = {
        .get_device_descriptor = op_get_device_descriptor,
        .get_active_config_descriptor = op_get_active_config_descriptor,
        .get_config_descriptor = op_get_config_descriptor,
+       .get_config_descriptor_by_value = op_get_config_descriptor_by_value,
 
        .open = op_open,
        .close = op_close,
index 06aaff4..e1c91f4 100644 (file)
@@ -99,6 +99,7 @@ const struct usbi_os_backend openbsd_backend = {
        obsd_get_device_descriptor,
        obsd_get_active_config_descriptor,
        obsd_get_config_descriptor,
+       NULL,                           /* get_config_descriptor_by_value() */
 
        obsd_get_configuration,
        obsd_set_configuration,
index 2e6eedd..f1f64ac 100644 (file)
@@ -984,6 +984,7 @@ const struct usbi_os_backend wince_backend = {
         wince_get_device_descriptor,
         wince_get_active_config_descriptor,
         wince_get_config_descriptor,
+       NULL,                           /* get_config_descriptor_by_value() */
 
         wince_get_configuration,
         wince_set_configuration,
index 061a0f8..3eb5585 100644 (file)
@@ -2275,6 +2275,7 @@ const struct usbi_os_backend windows_backend = {
        windows_get_device_descriptor,
        windows_get_active_config_descriptor,
        windows_get_config_descriptor,
+       NULL,                           /* get_config_descriptor_by_value() */
 
        windows_get_configuration,
        windows_set_configuration,
index 0d49847..c29c8ff 100644 (file)
@@ -1 +1 @@
-#define LIBUSB_NANO 10713
+#define LIBUSB_NANO 10714