fix USB devices with multiple configurations
authorHarald Welte <laforge@gnumonks.org>
Sun, 6 Jul 2008 16:58:05 +0000 (00:58 +0800)
committerJohn Rigby <jrigby@freescale.com>
Thu, 10 Jul 2008 16:53:04 +0000 (10:53 -0600)
This patch fixes bugs in usbdcore*.c related to the use of devices
with multiple configurations.

The original code made mistakes about the meaning of configuration value and
configuration index, and the resulting off-by-one errors resulted in:

* SET_CONFIGURATION always selected the first configuration, no matter what
  wValue is being passed.
* GET_DESCRIPTOR/CONFIGURATION always returned the descriptor for the first
  configuration (index 0).

Signed-off-by: Harald Welte <laforge@openmoko.org>
Acked-by: Markus Klotzbuecher <mk@denx.de>
drivers/usb/usbdcore.c
drivers/usb/usbdcore_ep0.c

index 308c7ceccc648d4874016ef510a50c7099c1bbe3..a621ce7a399128e4451c2d6aa5c24de8a89f0eb1 100644 (file)
@@ -146,12 +146,9 @@ struct usb_string_descriptor *usbd_get_string (__u8 index)
 static struct usb_configuration_instance *usbd_device_configuration_instance (struct usb_device_instance *device,
                unsigned int port, unsigned int configuration)
 {
-       /* XXX */
-       configuration = configuration ? configuration - 1 : 0;
-
-       if (configuration >= device->configurations) {
+       if (configuration >= device->configurations)
                return NULL;
-       }
+
        return device->configuration_instance_array + configuration;
 }
 
index 1e44f322a7977513630df0011ec852e6f0351750..cf3f3826cbfc08de3097fd9d1a4b061b25604a11 100644 (file)
@@ -235,8 +235,8 @@ static int ep0_get_descriptor (struct usb_device_instance *device,
                                return -1;
                        }
                        /*dbg_ep0(2, "%d %d", index, device_descriptor->bNumConfigurations); */
-                       if (index > device_descriptor->bNumConfigurations) {
-                               dbg_ep0 (0, "index too large: %d > %d", index,
+                       if (index >= device_descriptor->bNumConfigurations) {
+                               dbg_ep0 (0, "index too large: %d >= %d", index,
                                         device_descriptor->
                                         bNumConfigurations);
                                return -1;
@@ -571,14 +571,8 @@ int ep0_recv_setup (struct urb *urb)
 
                case USB_REQ_SET_CONFIGURATION:
                        /* c.f. 9.4.7 - the top half of wValue is reserved */
-                       /* */
-                       if ((device->configuration =
-                               le16_to_cpu (request->wValue) & 0xFF80) != 0) {
-                               /* c.f. 9.4.7 - zero is the default or addressed state, in our case this */
-                               /* is the same is configuration zero */
-                               serial_printf("error setting dev->config to zero!\n");
-                               device->configuration = 0;      /* TBR - ?????? */
-                       }
+                       device->configuration = le16_to_cpu(request->wValue) & 0xff;
+
                        /* reset interface and alternate settings */
                        device->interface = device->alternate = 0;