public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* 2.6.x support for prism2 USB wireless adapter?
@ 2004-02-23  1:11 Robert Gadsdon
  2004-02-23  2:02 ` Greg KH
  2004-02-23 14:54 ` [linux-usb-devel] " Alan Stern
  0 siblings, 2 replies; 8+ messages in thread
From: Robert Gadsdon @ 2004-02-23  1:11 UTC (permalink / raw)
  To: linux kernel, Linux-USB

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

#modprobe prism2_usb     gives:
prism2usb_init: prism2_usb.o: 0.2.1-pre20 Loaded
prism2usb_init: dev_info is: prism2_usb
drivers/usb/core/usb.c: registered new driver prism2_usb

#lsusb     does not show the device at all...

Is this still 'work in progress'?


Robert Gadsdon


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: 2.6.x support for prism2 USB wireless adapter?
  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 14:54 ` [linux-usb-devel] " Alan Stern
  1 sibling, 1 reply; 8+ messages in thread
From: Greg KH @ 2004-02-23  2:02 UTC (permalink / raw)
  To: Robert Gadsdon; +Cc: linux kernel, Linux-USB

On Mon, Feb 23, 2004 at 01:11:34AM +0000, 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
> 
> #modprobe prism2_usb     gives:
> prism2usb_init: prism2_usb.o: 0.2.1-pre20 Loaded
> prism2usb_init: dev_info is: prism2_usb
> drivers/usb/core/usb.c: registered new driver prism2_usb
> 
> #lsusb     does not show the device at all...
> 
> Is this still 'work in progress'?

I don't see this driver in the kernel tree.  Where did you find it?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: 2.6.x support for prism2 USB wireless adapter?
  2004-02-23  2:02 ` Greg KH
@ 2004-02-23  9:31   ` Robert Gadsdon
  2004-02-23 17:37     ` Greg KH
  0 siblings, 1 reply; 8+ messages in thread
From: Robert Gadsdon @ 2004-02-23  9:31 UTC (permalink / raw)
  To: Greg KH; +Cc: linux kernel, Linux-USB

The prism2_usb driver is from the linux-wlan-ng project at
http://www.linux-wlan.com/linux-wlan/index.html#Download

This driver driver compiles OK under 2.6.3 and loads, but the problem is 
that the device is not recognised by the USB kernel subsystem before that..

Under 2.4.23 (and without loading the prism2_usb driver) I get the 
following output from #lsusb:
Bus 001 Device 001: ID 0000:0000
Bus 001 Device 002: ID 066b:2212 Linksys, Inc. WUSB11v2.5 802.11b Adapter

Under 2.6.3 I get:
Bus 001 Device 001: ID 0000:0000

Robert Gadsdon

Greg KH wrote:
> On Mon, Feb 23, 2004 at 01:11:34AM +0000, 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
>>
>>#modprobe prism2_usb     gives:
>>prism2usb_init: prism2_usb.o: 0.2.1-pre20 Loaded
>>prism2usb_init: dev_info is: prism2_usb
>>drivers/usb/core/usb.c: registered new driver prism2_usb
>>
>>#lsusb     does not show the device at all...
>>
>>Is this still 'work in progress'?
> 
> 
> I don't see this driver in the kernel tree.  Where did you find it?
> 
> thanks,
> 
> greg k-h
> 
> 

-- 
..................................
Robert Gadsdon
01442 872 633
rgadsdon2@netscape.net
..................................

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [linux-usb-devel] 2.6.x support for prism2 USB wireless adapter?
  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 14:54 ` Alan Stern
  2004-02-24  0:15   ` Robert Gadsdon
  2004-04-17 21:15   ` Guido Classen
  1 sibling, 2 replies; 8+ messages in thread
From: Alan Stern @ 2004-02-23 14:54 UTC (permalink / raw)
  To: Robert Gadsdon; +Cc: linux kernel, Linux-USB

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
> 
> #modprobe prism2_usb     gives:
> prism2usb_init: prism2_usb.o: 0.2.1-pre20 Loaded
> prism2usb_init: dev_info is: prism2_usb
> drivers/usb/core/usb.c: registered new driver prism2_usb
> 
> #lsusb     does not show the device at all...
> 
> Is this still 'work in progress'?

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];
 


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: 2.6.x support for prism2 USB wireless adapter?
  2004-02-23  9:31   ` Robert Gadsdon
@ 2004-02-23 17:37     ` Greg KH
  0 siblings, 0 replies; 8+ messages in thread
From: Greg KH @ 2004-02-23 17:37 UTC (permalink / raw)
  To: Robert Gadsdon; +Cc: linux kernel, Linux-USB

On Mon, Feb 23, 2004 at 09:31:20AM +0000, Robert Gadsdon wrote:
> The prism2_usb driver is from the linux-wlan-ng project at
> http://www.linux-wlan.com/linux-wlan/index.html#Download

Um, then why not ask the developers of that project, as it is not
included in the main kernel.org tree at all...

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [linux-usb-devel] 2.6.x support for prism2 USB wireless adapter?
  2004-02-23 14:54 ` [linux-usb-devel] " Alan Stern
@ 2004-02-24  0:15   ` Robert Gadsdon
  2004-04-17 21:15   ` Guido Classen
  1 sibling, 0 replies; 8+ messages in thread
From: Robert Gadsdon @ 2004-02-24  0:15 UTC (permalink / raw)
  To: Alan Stern; +Cc: linux kernel, Linux-USB, greg

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
..................................

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [linux-usb-devel] 2.6.x support for prism2 USB wireless adapter?
  2004-02-23 14:54 ` [linux-usb-devel] " Alan Stern
  2004-02-24  0:15   ` Robert Gadsdon
@ 2004-04-17 21:15   ` Guido Classen
  1 sibling, 0 replies; 8+ messages in thread
From: Guido Classen @ 2004-04-17 21:15 UTC (permalink / raw)
  To: Alan Stern; +Cc: linux kernel, Linux-USB

> 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.
Is anyone working on this issue? The patch works great for me with
kernel 2.6.3 but it dosn't apply to 2.6.5. Im using a Sitecom WL12
Prims2 USB WLAN apdaper

any suggestions?

kindly regards
   Guido Classen

> [PATCH]



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [linux-usb-devel] 2.6.x support for prism2 USB wireless adapter?
@ 2004-05-04 16:09 rm
  0 siblings, 0 replies; 8+ messages in thread
From: rm @ 2004-05-04 16:09 UTC (permalink / raw)
  To: linux-kernel

hi, 
	i modified Alan Stern's original patch that allows usb
interfaces numbered from 1 to work (which was against 2.6.3) to apply
against 2.6.5.
	it seems to work, but i'm suspicious of having to do this:

+		/*interface->dev.release = usb_release_intf;*/
+		/*device_initialize(&interface->dev);*/

	Alan, can you provide an update of the patch for 2.6.5?

	rob

--- drivers/usb/core/config.c.orig	2004-04-03 22:36:14.000000000 -0500
+++ drivers/usb/core/config.c	2004-05-04 10:23:14.000000000 -0400
@@ -87,7 +87,7 @@
 	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;
@@ -106,8 +106,16 @@
 		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;
@@ -123,7 +131,7 @@
 		return buffer - buffer0;
 	}
 
-	interface = config->interface[inum];
+
 	asnum = d->bAlternateSetting;
 	if (asnum >= interface->num_altsetting) {
 		warn("invalid alternate setting %d for interface %d",
@@ -207,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 ||
@@ -223,22 +233,15 @@
 		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));
-	}
+	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)) {
@@ -248,42 +251,73 @@
 
 		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;
 	}
 
-	/* Allocate the altsetting arrays */
-	for (i = 0; i < config->desc.bNumInterfaces; ++i) {
-		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);
-			return -EINVAL;
+	if (n < nintf) {
+		warn("not enough interfaces (%d/%d)", n, nintf);
+		return -EINVAL;
+	}
+
+	/* 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;
 		}
-		if (interface->num_altsetting == 0) {
-			warn("no alternate settings for interface %d", i);
+		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",
+		       inums[i], interface->num_altsetting, USB_MAXALTSETTING);
 			return -EINVAL;
 		}
 
@@ -324,7 +358,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;
 





----
Robert Melby
Georgia Institute of Technology, Atlanta Georgia, 30332
uucp:     ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!gt4255a
Internet: async!cc!gatech!edu!...

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2004-05-04 16:10 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
2004-04-17 21:15   ` Guido Classen
  -- strict thread matches above, loose matches on Subject: below --
2004-05-04 16:09 rm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox