Alan, With this patch prism2_usb works. Great fix, thanks!!!
//lauri On Monday 27 October 2003 18:10, Alan Stern wrote: > This patch makes config.c more liberal about the sorts of interface > numbering it will accept when reading interface descriptors. The current > code only allows interfaces numbered 0..(bNumInterfaces-1), but a number > of devices erroneously number their interfaces starting at 1. > > With this patch, the code will accept a total of bNumInterfaces with > numbers in the interval 0..bNumInterfaces. That will accomodate origin-1 > indexing (and a few other things beside). Also included is a comment in > include/linux/usb.h warning people that the interface numbers might not > correspond to the locations in the usb_host_config->interface[] array and > telling them they should use usb_ifnum_to_if(). > > Lauri, can you try this out and see if it helps with your prism2_usb? > > 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 Mon Oct 27 09:52:20 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,72 @@ > > 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; > + } > + > + /* Insertion sort is slow but it works */ > + for (i = n - 1; i >= 0; --i) { > + if (inums[i] < inum) > + break; > + } > + if (++i < n && inums[i] == inum) > + ++nalts[i]; > + else if (n >= nintf_orig) { > + warn("too many interfaces (> %d)", nintf_orig); > return -EINVAL; > + } else if (i < nintf) { > + if (n < nintf) > + ++n; > + for (j = n-1; j > i; --j) { > + inums[j] = inums[j-1]; > + nalts[j] = nalts[j-1]; > + } > + inums[i] = inum; > + nalts[i] = 1; > } > - 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 +355,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.164 vs edited ===== > --- 1.164/include/linux/usb.h Mon Oct 6 13:46:13 2003 > +++ edited/include/linux/usb.h Mon Oct 27 10:02:27 2003 > @@ -75,7 +75,7 @@ > * @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. > + * 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 > @@ -111,7 +111,7 @@ > */ > struct usb_interface { > /* array of alternate settings for this interface. > - * these will be in numeric order, 0..num_altsettting > + * these will be in numeric order, 0..num_altsetting-1 > */ > struct usb_host_interface *altsetting; > > @@ -150,8 +150,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 > + * in numeric order. But 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]; ------------------------------------------------------- This SF.net email is sponsored by: The SF.net Donation Program. Do you like what SourceForge.net is doing for the Open Source Community? Make a contribution, and help us add new features and functionality. Click here: http://sourceforge.net/donate/ _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel