diff -Nru linux-2.5.68/drivers/usb/core/usb.c linux-2.5.68/drivers/usb_patch/core/usb.c
Here's an updated version, against 2.6.0-test4. It updates the doc and also adds a bit of paranoia in case the altsettings are out of order.
This has gotten some discussion from time to time, I saw agreement that inactive altsettings must be ignored. Potentially affects user-mode drivers, ones relying on usbfs misbehavior.
- Dave
--- 1.138/drivers/usb/core/usb.c Wed Aug 27 10:04:01 2003 +++ edited/drivers/usb/core/usb.c Tue Sep 2 12:33:30 2003 @@ -217,33 +217,48 @@ /** * usb_epnum_to_ep_desc - get the endpoint object with a given endpoint number - * @dev: the device whose current configuration is considered - * @epnum: the desired endpoint + * @dev: the device whose current configuration+altsettings is considered + * @epnum: the desired endpoint, masked with USB_DIR_IN as appropriate. * * This walks the device descriptor for the currently active configuration, * and returns a pointer to the endpoint with that particular endpoint * number, or null. * - * Note that interface descriptors are not required to assign endpont - * numbers sequentially, so that it would be incorrect to assume that - * the first endpoint in that descriptor corresponds to interface zero. + * Note that interface descriptors are not required to list endpoint + * numbers in any standardized order, so that it would be wrong to + * assume that ep2in precedes either ep5in, ep2out, or even ep1out. * This routine helps device drivers avoid such mistakes. */ struct usb_endpoint_descriptor * usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum) { - int i, j, k; + int i, k; - for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) - for (j = 0; j < dev->actconfig->interface[i]->num_altsetting; j++) - for (k = 0; k < dev->actconfig->interface[i]-> - altsetting[j].desc.bNumEndpoints; k++) - if (epnum == dev->actconfig->interface[i]-> - altsetting[j].endpoint[k] - .desc.bEndpointAddress) - return &dev->actconfig->interface[i]-> - altsetting[j].endpoint[k] - .desc; + for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { + struct usb_interface *intf; + struct usb_host_interface *alt = 0; + + /* paranoia, in case altsettings aren't sequential */ + intf = dev->actconfig->interface[i]; + for (k = 0; k < intf->num_altsetting; k++) { + if (intf->altsetting [k].desc.bAlternateSetting + == intf->act_altsetting) { + alt = intf->altsetting + k; + break; + } + } + if (!alt) { + dev_dbg(&dev->dev, + "interface %d has no altsetting %d!\n", + i, intf->act_altsetting); + continue; + } + + /* only endpoints in current altseting are active */ + for (k = 0; k < alt->desc.bNumEndpoints; k++) + if (epnum == alt->endpoint[k].desc.bEndpointAddress) + return &alt->endpoint[k].desc; + } return NULL; }