From 6b41074352bec3e8fe132fc74768da8e930a2ab5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 23 May 2013 19:51:07 +0200 Subject: [PATCH] all: Allow backend to provide a better get_config_descriptor_by_value 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 --- libusb/descriptor.c | 14 ++++++++++++-- libusb/libusbi.h | 16 ++++++++++++++++ libusb/os/linux_usbfs.c | 13 +++++++------ libusb/os/openbsd_usb.c | 1 + libusb/os/wince_usb.c | 1 + libusb/os/windows_usb.c | 1 + libusb/version_nano.h | 2 +- 7 files changed, 39 insertions(+), 9 deletions(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 5fb96ea..44d93ee 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -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) diff --git a/libusb/libusbi.h b/libusb/libusbi.h index bf240e8..090ac5b 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -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). diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 280e312..57ab80c 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -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, diff --git a/libusb/os/openbsd_usb.c b/libusb/os/openbsd_usb.c index 06aaff4..e1c91f4 100644 --- a/libusb/os/openbsd_usb.c +++ b/libusb/os/openbsd_usb.c @@ -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, diff --git a/libusb/os/wince_usb.c b/libusb/os/wince_usb.c index 2e6eedd..f1f64ac 100644 --- a/libusb/os/wince_usb.c +++ b/libusb/os/wince_usb.c @@ -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, diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c index 061a0f8..3eb5585 100644 --- a/libusb/os/windows_usb.c +++ b/libusb/os/windows_usb.c @@ -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, diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 0d49847..c29c8ff 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 10713 +#define LIBUSB_NANO 10714 -- 2.11.4.GIT