[PATCH] USB (invalid interface number error) kernel 2.6.5

From: Papik Meli
Date: Sun May 09 2004 - 18:02:47 EST


Hi, this is the first time I post to this list, so please excuse any
mistake...

Until kernel 2.6.3 there was a patch that permitted to use some USB
whose first interface number is 1 instead of 0. But with kernel 2.6.5
the patch didn't work anymore. So I "ported" the patch in the new kernel.

Disclaimer:
I never coded anything in the kernel and I've never seen any USB
specification, but now my usb mouse works ;), I hope someone
could say if I did the right things...

I'm not subscribed to the list so please CC me: papik (at) ticino (dot) com

-Papik


Here is the patch:
--- linux-2.6.5/drivers/usb/core/config.c 2004-04-16 15:29:58.000000000 +0200
+++ edited/drivers/usb/core/config.c 2004-05-10 00:37:50.205602696 +0200
@@ -87,11 +87,11 @@
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, int inums[])
{
unsigned char *buffer0 = buffer;
struct usb_interface_descriptor *d;
- int inum, asnum;
+ int inum, intfindx, asnum;
struct usb_interface *interface;
struct usb_host_interface *ifp;
int len, numskipped;
@@ -107,7 +107,14 @@
}

inum = d->bInterfaceNumber;
- if (inum >= config->desc.bNumInterfaces) {
+
+ /* find in inums the index of inum */
+ for (intfindx=0; intfindx < config->desc.bNumInterfaces; ++intfindx)
+ {
+ if (inums[intfindx] == inum)
+ break;
+ }
+ if (intfindx >= config->desc.bNumInterfaces) {

/* Skip to the next interface descriptor */
buffer += d->bLength;
@@ -123,7 +130,7 @@
return buffer - buffer0;
}

- interface = config->interface[inum];
+ interface = config->interface[intfindx];
asnum = d->bAlternateSetting;
if (asnum >= interface->num_altsetting) {
warn("invalid alternate setting %d for interface %d",
@@ -199,7 +206,8 @@
int usb_parse_configuration(struct usb_host_config *config, char *buffer, int size)
{
int nintf, nintf_orig;
- int i, j;
+ int i, j, n;
+ int inum, inums[USB_MAXINTERFACES];
struct usb_interface *interface;
char *buffer2;
int size2;
@@ -223,6 +231,7 @@
config->desc.bNumInterfaces = nintf = USB_MAXINTERFACES;
}

+ /* Alloc and clear memory for interfaces */
for (i = 0; i < nintf; ++i) {
interface = config->interface[i] =
kmalloc(sizeof(struct usb_interface), GFP_KERNEL);
@@ -238,6 +247,7 @@
* number of altsettings for each interface */
buffer2 = buffer;
size2 = size;
+ i = 0; /* Interface number counter */
j = 0;
while (size2 >= sizeof(struct usb_descriptor_header)) {
header = (struct usb_descriptor_header *) buffer2;
@@ -254,14 +264,26 @@
return -EINVAL;
}
d = (struct usb_interface_descriptor *) header;
- i = d->bInterfaceNumber;
- if (i >= nintf_orig) {
- warn("invalid interface number (%d/%d)",
- i, nintf_orig);
+ inum = d->bInterfaceNumber;
+ /* Interface already encountered ? */
+ for (n = i-1; n >=0; --n)
+ if (inums[n] == inum)
+ break;
+ if (n < 0)
+ {
+ n = i;
+ inums[n]=inum;
+ ++i;
+ }
+ if (n >= nintf_orig) {
+ warn("too many interfaces(%d/%d)",
+ n, nintf_orig);
return -EINVAL;
}
- if (i < nintf)
- ++config->interface[i]->num_altsetting;
+ if (n < nintf)
+ {
+ ++config->interface[n]->num_altsetting;
+ }

} else if ((header->bDescriptorType == USB_DT_DEVICE ||
header->bDescriptorType == USB_DT_CONFIG) && j) {
@@ -279,11 +301,11 @@
interface = config->interface[i];
if (interface->num_altsetting > USB_MAXALTSETTING) {
warn("too many alternate settings for interface %d (%d max %d)\n",
- i, interface->num_altsetting, USB_MAXALTSETTING);
+ inums[i], interface->num_altsetting, USB_MAXALTSETTING);
return -EINVAL;
}
if (interface->num_altsetting == 0) {
- warn("no alternate settings for interface %d", i);
+ warn("no alternate settings for interface %d", inums[i]);
return -EINVAL;
}

@@ -324,7 +346,7 @@

/* Parse all the interface/altsetting descriptors */
while (size >= sizeof(struct usb_descriptor_header)) {
- retval = usb_parse_interface(config, buffer, size);
+ retval = usb_parse_interface(config, buffer, size, inums);
if (retval < 0)
return retval;

@@ -337,7 +359,7 @@
interface = config->interface[i];
for (j = 0; j < interface->num_altsetting; ++j) {
if (!interface->altsetting[j].desc.bLength) {
- warn("missing altsetting %d for interface %d", j, i);
+ warn("missing altsetting %d for interface %d", j, inums[i]);
return -EINVAL;
}
}
-------------------- End of patch -----------------
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/