Fetch configurations by index (not value)
authorDaniel Drake <dsd@gentoo.org>
Sat, 10 May 2008 13:42:43 +0000 (14:42 +0100)
committerDaniel Drake <dsd@gentoo.org>
Sat, 10 May 2008 14:36:29 +0000 (15:36 +0100)
Otherwise there is no way to know which values to look for.

libusb/core.c
libusb/descriptor.c
libusb/libusb.h
libusb/libusbi.h
libusb/os/linux_usbfs.c

index 43491ad..d94d7b8 100644 (file)
@@ -325,6 +325,7 @@ int usbi_sanitize_device(struct libusb_device *dev)
                return LIBUSB_ERROR_IO;
        }
 
+       dev->num_configurations = num_configurations;
        return 0;
 }
 
index e07711a..8814ced 100644 (file)
@@ -432,6 +432,7 @@ API_EXPORTED int libusb_get_device_descriptor(libusb_device *dev,
        unsigned char raw_desc[DEVICE_DESC_LENGTH];
        int r;
 
+       usbi_dbg("");
        r = usbi_backend->get_device_descriptor(dev, raw_desc);
        if (r < 0)
                return r;
@@ -460,6 +461,7 @@ struct libusb_config_descriptor *libusb_get_active_config_descriptor(
        unsigned char *buf = NULL;
        int r;
 
+       usbi_dbg("");
        if (!config)
                return NULL;
 
@@ -467,7 +469,7 @@ struct libusb_config_descriptor *libusb_get_active_config_descriptor(
        if (r < 0)
                goto err;
 
-       usbi_parse_descriptor(tmp, "bbw", &config);
+       usbi_parse_descriptor(tmp, "bbw", config);
        buf = malloc(config->wTotalLength);
        if (!buf)
                goto err;
@@ -495,40 +497,45 @@ err:
 }
 
 /** \ingroup desc
- * Get the USB configuration descriptor for the currently active configuration.
+ * Get a USB configuration descriptor based on its index.
  * This is a non-blocking function which does not involve any requests being
  * sent to the device.
  *
  * \param dev a device
- * \param bConfigurationValue the bConfigurationValue of the configuration
- * you wish to retreive
+ * \param config_index the index of the configuration you wish to retrieve
  * \returns the USB configuration descriptor which must be freed with
  * libusb_free_config_descriptor() when done
  * \returns NULL on error
  * \see libusb_get_active_config_descriptor()
+ * \see libusb_get_config_descriptor_by_value()
  */
 API_EXPORTED struct libusb_config_descriptor *libusb_get_config_descriptor(
-       libusb_device *dev, uint8_t bConfigurationValue)
+       libusb_device *dev, uint8_t config_index)
 {
-       struct libusb_config_descriptor *config = malloc(sizeof(*config));
+       struct libusb_config_descriptor *config;
        unsigned char tmp[8];
        unsigned char *buf = NULL;
        int r;
 
+       usbi_dbg("index %d", config_index);
+       if (config_index >= dev->num_configurations)
+               return NULL;
+
+       config = malloc(sizeof(*config));
        if (!config)
                return NULL;
 
-       r = usbi_backend->get_config_descriptor(dev, bConfigurationValue, tmp,
+       r = usbi_backend->get_config_descriptor(dev, config_index, tmp,
                sizeof(tmp));
        if (r < 0)
                goto err;
 
-       usbi_parse_descriptor(tmp, "bbw", &config);
+       usbi_parse_descriptor(tmp, "bbw", config);
        buf = malloc(config->wTotalLength);
        if (!buf)
                goto err;
 
-       r = usbi_backend->get_config_descriptor(dev, bConfigurationValue, buf,
+       r = usbi_backend->get_config_descriptor(dev, config_index, buf,
                config->wTotalLength);
        if (r < 0)
                goto err;
@@ -551,6 +558,46 @@ err:
 }
 
 /** \ingroup desc
+ * Get a USB configuration descriptor with a specific bConfigurationValue.
+ * This is a non-blocking function which does not involve any requests being
+ * sent to the device.
+ *
+ * \param dev a device
+ * \param bConfigurationValue the bConfigurationValue of the configuration you
+ * wish to retrieve
+ * \returns the USB configuration descriptor which must be freed with
+ * libusb_free_config_descriptor() when done
+ * \returns NULL on error
+ * \see libusb_get_active_config_descriptor()
+ * \see libusb_get_config_descriptor()
+ */
+API_EXPORTED
+struct libusb_config_descriptor *libusb_get_config_descriptor_by_value(
+       libusb_device *dev, uint8_t bConfigurationValue)
+{
+       int i;
+       int r;
+       int found = -1;
+
+       usbi_dbg("value %d", bConfigurationValue);
+       for (i = 0; i < dev->num_configurations; i++) {
+               unsigned char tmp[6];
+               r = usbi_backend->get_config_descriptor(dev, i, tmp, sizeof(tmp));
+               if (r < 0)
+                       return NULL;
+               if (tmp[5] == bConfigurationValue) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (!found)
+               return NULL;
+       else
+               return libusb_get_config_descriptor(dev, i);
+}
+
+/** \ingroup desc
  * Free a configuration descriptor obtained from
  * libusb_get_active_config_descriptor() or libusb_get_config_descriptor().
  * It is safe to call this function with a NULL config parameter, in which
index 62ed0ea..f946a27 100644 (file)
@@ -670,7 +670,9 @@ int libusb_get_device_descriptor(libusb_device *dev,
 struct libusb_config_descriptor *libusb_get_active_config_descriptor(
        libusb_device *dev);
 struct libusb_config_descriptor *libusb_get_config_descriptor(
-       libusb_device *dev, uint8_t config);
+       libusb_device *dev, uint8_t config_index);
+struct libusb_config_descriptor *libusb_get_config_descriptor_by_value(
+       libusb_device *dev, uint8_t bConfigurationValue);
 void libusb_free_config_descriptor(struct libusb_config_descriptor *config);
 uint8_t libusb_get_bus_number(libusb_device *dev);
 uint8_t libusb_get_device_address(libusb_device *dev);
index e596b86..c807903 100644 (file)
@@ -150,6 +150,7 @@ struct libusb_device {
 
        uint8_t bus_number;
        uint8_t device_address;
+       uint8_t num_configurations;
 
        struct list_head list;
        unsigned long session_data;
@@ -273,8 +274,8 @@ struct usbi_os_backend {
                unsigned char *buffer);
        int (*get_active_config_descriptor)(struct libusb_device *device,
                unsigned char *buffer, size_t len);
-       int (*get_config_descriptor)(struct libusb_device *device, uint8_t config,
-               unsigned char *buffer, size_t len);
+       int (*get_config_descriptor)(struct libusb_device *device,
+               uint8_t config_index, unsigned char *buffer, size_t len);
 
        int (*set_configuration)(struct libusb_device_handle *handle, int config);
 
index 6bebc06..957900a 100644 (file)
@@ -301,49 +301,22 @@ static int op_get_active_config_descriptor(struct libusb_device *dev,
 /* takes a usbfs fd, attempts to find the requested config and copy a certain
  * amount of it into an output buffer. a bConfigurationValue of -1 indicates
  * that the first config should be retreived. */
-static int get_config_descriptor(int fd, int bConfigurationValue,
+static int get_config_descriptor(int fd, uint8_t config_index,
        unsigned char *buffer, size_t len)
 {
        unsigned char tmp[8];
-       uint8_t num_configurations;
        off_t off;
        ssize_t r;
 
-       if (bConfigurationValue == -1) {
-               /* read first configuration */
-               off = lseek(fd, DEVICE_DESC_LENGTH, SEEK_SET);
-               if (off < 0) {
-                       usbi_err("seek failed, ret=%d errno=%d", off, errno);
-                       return LIBUSB_ERROR_IO;
-               }
-               r = read(fd, buffer, len);
-               if (r < 0) {
-                       usbi_err("read failed ret=%d errno=%d", r, errno);
-                       return LIBUSB_ERROR_IO;
-               } else if (r < len) {
-                       usbi_err("short output read %d/%d", r, len);
-                       return LIBUSB_ERROR_IO;
-               }
-               return 0;
-       }
-
-       /* seek to last byte of device descriptor to determine number of
-        * configurations */
-       off = lseek(fd, DEVICE_DESC_LENGTH - 1, SEEK_SET);
+       off = lseek(fd, DEVICE_DESC_LENGTH, SEEK_SET);
        if (off < 0) {
-               usbi_err("seek failed, ret=%d errno=%d", off, errno);
-               return LIBUSB_ERROR_IO;
-       }
-
-       r = read(fd, &num_configurations, 1);
-       if (r < 0) {
-               usbi_err("read num_configurations failed, ret=%d errno=%d", off, errno);
+               usbi_err("seek failed ret=%d errno=%d", off, errno);
                return LIBUSB_ERROR_IO;
        }
 
        /* might need to skip some configuration descriptors to reach the
         * requested configuration */
-       while (num_configurations) {
+       while (config_index) {
                struct libusb_config_descriptor config;
 
                /* read first 8 bytes of descriptor */
@@ -357,8 +330,6 @@ static int get_config_descriptor(int fd, int bConfigurationValue,
                }
 
                usbi_parse_descriptor(tmp, "bbwbb", &config);
-               if (config.bConfigurationValue == bConfigurationValue)
-                       break;
 
                /* seek forward to end of config */
                off = lseek(fd, config.wTotalLength - sizeof(tmp), SEEK_CUR);
@@ -367,21 +338,15 @@ static int get_config_descriptor(int fd, int bConfigurationValue,
                        return LIBUSB_ERROR_IO;
                }
 
-               num_configurations--;
+               config_index--;
        }
 
-       if (num_configurations == 0)
-               return LIBUSB_ERROR_NOT_FOUND;
-
-       /* copy config-so-far */
-       memcpy(buffer, tmp, sizeof(tmp));
-
        /* read the rest of the descriptor */
-       r = read(fd, buffer + sizeof(tmp), len - sizeof(tmp));
+       r = read(fd, buffer, len);
        if (r < 0) {
                usbi_err("read failed ret=%d errno=%d", r, errno);
                return LIBUSB_ERROR_IO;
-       } else if (r < (len - sizeof(tmp))) {
+       } else if (r < len) {
                usbi_err("short output read %d/%d", r, len);
                return LIBUSB_ERROR_IO;
        }
@@ -389,8 +354,8 @@ static int get_config_descriptor(int fd, int bConfigurationValue,
        return 0;
 }
 
-static int op_get_config_descriptor(struct libusb_device *dev, uint8_t config,
-       unsigned char *buffer, size_t len)
+static int op_get_config_descriptor(struct libusb_device *dev,
+       uint8_t config_index, unsigned char *buffer, size_t len)
 {
        char filename[PATH_MAX + 1];
        int fd;
@@ -406,7 +371,7 @@ static int op_get_config_descriptor(struct libusb_device *dev, uint8_t config,
                return LIBUSB_ERROR_IO;
        }
 
-       r = get_config_descriptor(fd, config, buffer, len);
+       r = get_config_descriptor(fd, config_index, buffer, len);
        close(fd);
        return r;
 }
@@ -420,6 +385,7 @@ static int cache_active_config(struct libusb_device *dev, int fd,
        unsigned char *buf;
        int r;
 
+       /* FIXME */
        r = get_config_descriptor(fd, active_config, tmp, sizeof(tmp));
        if (r < 0) {
                usbi_err("first read error %d", r);