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