From: Robert Gadsdon <robert@gadsdon.giointernet.co.uk>
To: Alan Stern <stern@rowland.harvard.edu>
Cc: linux kernel <linux-kernel@vger.kernel.org>,
Linux-USB <linux-usb-devel@lists.sourceforge.net>,
greg@kroah.com
Subject: Re: [linux-usb-devel] 2.6.x support for prism2 USB wireless adapter?
Date: Tue, 24 Feb 2004 00:15:59 +0000 [thread overview]
Message-ID: <403A97BF.7070706@gadsdon.giointernet.co.uk> (raw)
In-Reply-To: <Pine.LNX.4.44L0.0402230953141.1175-100000@ida.rowland.org>
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
..................................
next prev parent reply other threads:[~2004-02-24 0:11 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-02-23 1:11 2.6.x support for prism2 USB wireless adapter? Robert Gadsdon
2004-02-23 2:02 ` Greg KH
2004-02-23 9:31 ` Robert Gadsdon
2004-02-23 17:37 ` Greg KH
2004-02-23 14:54 ` [linux-usb-devel] " Alan Stern
2004-02-24 0:15 ` Robert Gadsdon [this message]
2004-04-17 21:15 ` Guido Classen
-- strict thread matches above, loose matches on Subject: below --
2004-05-04 16:09 rm
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=403A97BF.7070706@gadsdon.giointernet.co.uk \
--to=robert@gadsdon.giointernet.co.uk \
--cc=greg@kroah.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb-devel@lists.sourceforge.net \
--cc=stern@rowland.harvard.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox