Messages in this thread Patch in this message | | | Date | Tue, 24 Feb 2004 00:15:59 +0000 | From | Robert Gadsdon <> | Subject | Re: [linux-usb-devel] 2.6.x support for prism2 USB wireless adapter? |
| |
I applied the patch to vanilla 2.6.3, and now get the following output:
usb 1-1: new full speed USB device using address 4
# lsusb Bus 001 Device 004: ID 066b:2212 Linksys, Inc. WUSB11v2.5 802.11b Adapter Bus 001 Device 001: ID 0000:0000
I unplugged/plugged-in the adapter several times with no problems..
Prism2_usb module loads (apparently) OK (and I agree that any problems with _this_ are not for the kernel.org lists..)
Thanks..
Robert Gadsdon
Alan Stern wrote: > On Mon, 23 Feb 2004, Robert Gadsdon wrote: > > >>I had my Linksys prism2 USB wireless adapter (WUSB11 v2.5) working >>reasonably well with kernel 2.4.23, but with kernel 2.6.3 (and udev 018) >>I get: >> >>usb 1-1: new full speed USB device using address 5 >>drivers/usb/core/config.c: invalid interface number (1/1) >>usb 1-1: can't read configurations, error -22 snip > > 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; > - if (i >= nintf_orig) { > + inum = d->bInterfaceNumber; > + if (inum > nintf_orig) { > warn("invalid interface number (%d/%d)", > - i, nintf_orig); > + inum, nintf_orig); > + return -EINVAL; > + } > + > + /* Have we already encountered this interface? */ > + for (i = n - 1; i >= 0; --i) { > + if (inums[i] == inum) > + break; > + } > + if (i >= 0) > + ++nalts[i]; > + else if (n >= nintf_orig) { > + warn("too many interfaces (> %d)", nintf_orig); > return -EINVAL; > + } else if (n < nintf) { > + inums[n] = inum; > + nalts[n] = 1; > + ++n; > } > - if (i < nintf) > - ++config->interface[i]->num_altsetting; > > } else if ((header->bDescriptorType == USB_DT_DEVICE || > - header->bDescriptorType == USB_DT_CONFIG) && j) { > + header->bDescriptorType == USB_DT_CONFIG) && buffer2 > buffer) { > warn("unexpected descriptor type 0x%X", header->bDescriptorType); > return -EINVAL; > } > > - j = 1; > buffer2 += header->bLength; > size2 -= header->bLength; > } > + if (n < nintf) { > + warn("not enough interfaces (%d/%d)", n, nintf); > + return -EINVAL; > + } > > - /* Allocate the altsetting arrays */ > - for (i = 0; i < config->desc.bNumInterfaces; ++i) { > - interface = config->interface[i]; > + /* Allocate the interfaces and altsetting arrays */ > + 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); > + > + interface->num_altsetting = nalts[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); > - return -EINVAL; > - } > - if (interface->num_altsetting == 0) { > - warn("no alternate settings for interface %d", i); > + inums[i], interface->num_altsetting, USB_MAXALTSETTING); > return -EINVAL; > } > > @@ -329,7 +350,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; > > ===== include/linux/usb.h 1.165 vs edited ===== > --- 1.165/include/linux/usb.h Mon Dec 8 12:39:26 2003 > +++ edited/include/linux/usb.h Tue Dec 16 16:49:47 2003 > @@ -74,8 +74,8 @@ > * struct usb_interface - what usb device drivers talk to > * @altsetting: array of interface descriptors, one for each alternate > * setting that may be selected. Each one includes a set of > - * endpoint configurations and will be in numberic order, > - * 0..num_altsetting. > + * endpoint configurations, and they will be in numeric order: > + * 0..num_altsetting-1. > * @num_altsetting: number of altsettings defined. > * @act_altsetting: index of current altsetting. this number is always > * less than num_altsetting. after the device is configured, each > @@ -110,10 +110,8 @@ > * will use them in non-default settings. > */ > struct usb_interface { > - /* array of alternate settings for this interface. > - * these will be in numeric order, 0..num_altsettting > - */ > - struct usb_host_interface *altsetting; > + struct usb_host_interface *altsetting; /* array of alternate */ > + /* setting structures for this interface */ > > unsigned act_altsetting; /* active alternate setting */ > unsigned num_altsetting; /* number of alternate settings */ > @@ -150,8 +148,12 @@ > struct usb_host_config { > struct usb_config_descriptor desc; > > - /* the interfaces associated with this configuration > - * these will be in numeric order, 0..desc.bNumInterfaces > + /* The interfaces associated with this configuration. > + * There are desc.bNumInterfaces of them, and they are > + * *not* guaranteed to be in numeric order. Even worse, > + * some non-compliant devices number the interfaces > + * starting with 1, not 0. To be safe don't index this > + * array directly; instead use usb_ifnum_to_if(). > */ > struct usb_interface *interface[USB_MAXINTERFACES]; > > > >
-- .................................. Robert Gadsdon 01442 872 633 rgadsdon2@netscape.net .................................. - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |