public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
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
..................................

  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