by Alan Ster » Wed, 25 Feb 2004 00:00:15
n Mon, 23 Feb 2004, Robert Gadsdon wrote:
The problem is that the prism2's single interface is number 1, but
according to the USB standard interfaces are supposed to be
numbered starting at 0. This is a fairly common error among USB devices.
The patch below will cause the kernel to accept the device; please let us
know how it works out.
Alan Stern
===== drivers/usb/core/config.c 1.28 vs edited =====
--- 1.28/drivers/usb/core/config.c Fri Sep 26 12:37:44 2003
+++ edited/drivers/usb/core/config.c Tue Dec 16 16:41:44 2003
@@ -8,9 +8,7 @@
#define USB_MAXALTSETTING 128 /* Hard limit */
#define USB_MAXENDPOINTS 30 /* Hard limit */
-/* these maximums are arbitrary */
-#define USB_MAXCONFIG 8
-#define USB_MAXINTERFACES 32
+#define USB_MAXCONFIG 8 /* Arbitrary limit */
static int usb_parse_endpoint(struct usb_host_endpoint *endpoint, unsigned char *buffer, int size)
{
@@ -90,7 +88,8 @@
kfree(intf);
}
-static int usb_parse_interface(struct usb_host_config *config, unsigned char *buffer, int size)
+static int usb_parse_interface(struct usb_host_config *config,
+ unsigned char *buffer, int size, u8 inums[])
{
unsigned char *buffer0 = buffer;
struct usb_interface_descriptor *d;
@@ -109,8 +108,15 @@
return -EINVAL;
}
+ interface = NULL;
inum = d->bInterfaceNumber;
- if (inum >= config->desc.bNumInterfaces) {
+ for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+ if (inums[i] == inum) {
+ interface = config->interface[i];
+ break;
+ }
+ }
+ if (!interface) {
/* Skip to the next interface descriptor */
buffer += d->bLength;
@@ -126,7 +132,6 @@
return buffer - buffer0;
}
- interface = config->interface[inum];
asnum = d->bAlternateSetting;
if (asnum >= interface->num_altsetting) {
warn("invalid alternate setting %d for interface %d",
@@ -210,6 +215,8 @@
int numskipped, len;
char *begin;
int retval;
+ int n;
+ u8 inums[USB_MAXINTERFACES], nalts[USB_MAXINTERFACES];
memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
if (config->desc.bDescriptorType != USB_DT_CONFIG ||
@@ -225,25 +232,14 @@
nintf, USB_MAXINTERFACES);
config->desc.bNumInterfaces = nintf = USB_MAXINTERFACES;
}
-
- for (i = 0; i < nintf; ++i) {
- interface = config->interface[i] =
- kmalloc(sizeof(struct usb_interface), GFP_KERNEL);
- dbg("kmalloc IF %p, numif %i", interface, i);
- if (!interface) {
- err("out of memory");
- return -ENOMEM;
- }
- memset(interface, 0, sizeof(struct usb_interface));
- interface->dev.release = usb_release_intf;
- device_initialize(&interface->dev);
- }
+ if (nintf == 0)
+ warn("no interfaces?");
/* Go through the descriptors, checking their length and counting the
* number of altsettings for each interface */
+ n = 0;
buffer2 = buffer;
size2 = size;
- j = 0;
while (size2 >= sizeof(struct usb_descriptor_header)) {
header = (struct usb_descriptor_header *) buffer2;
if ((header->bLength > size2) || (header->bLength < 2)) {
@@ -253,42 +249,67 @@
if (header->bDescriptorType == USB_DT_INTERFACE) {
struct usb_interface_descriptor *d;
+ int inum;
if (header->bLength < USB_DT_INTERFACE_SIZE) {
warn("invalid interface descriptor");
return -EINVAL;
}
d = (struct usb_interface_descriptor *) header;
- i = d->bInterfaceNumber;