On Thu, Jan 28, 2021 at 09:56:14AM +0000, Edd Barrett wrote:
>

Here's a revised diff that always searches the array, instead of first
trying the expected index. Everyone agreed that this makes for simpler
code, and that since this function isn't called much, there's no real
performance concern.

Cursory testing seems good. All USB devices working so far, including
the non-compliant uaudio device.

Please give this a spin to check for breakage.

Index: usbdi.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/usbdi.c,v
retrieving revision 1.107
diff -u -p -r1.107 usbdi.c
--- usbdi.c     27 Jan 2021 17:28:19 -0000      1.107
+++ usbdi.c     28 Jan 2021 14:19:28 -0000
@@ -638,12 +638,23 @@ usbd_status
 usbd_device2interface_handle(struct usbd_device *dev, u_int8_t ifaceno,
     struct usbd_interface **iface)
 {
+       u_int8_t idx;
+
        if (dev->cdesc == NULL)
                return (USBD_NOT_CONFIGURED);
-       if (ifaceno >= dev->cdesc->bNumInterfaces)
-               return (USBD_INVAL);
-       *iface = &dev->ifaces[ifaceno];
-       return (USBD_NORMAL_COMPLETION);
+       /*
+        * The correct interface should be at dev->ifaces[ifaceno], but we've
+        * seen non-compliant devices in the wild which present non-contiguous
+        * interface numbers and this skews the indices. For this reason we
+        * linearly search the interface array.
+        */
+       for (idx = 0; idx < dev->cdesc->bNumInterfaces; idx++) {
+               if (dev->ifaces[idx].idesc->bInterfaceNumber == ifaceno) {
+                       *iface = &dev->ifaces[idx];
+                       return (USBD_NORMAL_COMPLETION);
+               }
+       }
+       return (USBD_INVAL);
 }
 
 /* XXXX use altno */

-- 
Best Regards
Edd Barrett

http://www.theunixzoo.co.uk

Reply via email to