On Thu, Jan 28, 2021 at 02:38:04PM +0000, Edd Barrett wrote:
> 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.
The code looks good to me (cleaner than before), and I also quickly
tested the diff with some devices.
ok mglocker@
> 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 */