On Tue, Jan 26, 2021 at 08:56:29PM +0000, Edd Barrett wrote:

> Hi,
> 
> I've recently come across a uaudio device which doesn't work in OpenBSD:
> 
> uaudio2 at uhub0 port 1 configuration 1 interface 3 "E+ Corp. DAC Audio" rev 
> 1.10/0.01 addr 2
> uaudio2: class v1, full-speed, async, channels: 2 play, 0 rec, 3 ctls
> audio3 at uaudio2
> 
> When opening the audio device, the kernel reports `uaudio0: can't get iface
> handle` in the dmesg buffer.
> 
> I posted information about the device and sthen@ and kettenis@ spotted
> the problem: the device exposes non-consecutive interface numbers, and
> is thus not compliant with the USB standard.
> 
> It has interfaces 0, 1 and 3, in that order. The audio stream is on
> interface 3, which the kernel expects to find at index 3 in the ifaces
> array, but actually it's at index 2!
> 
> I've pasted a load of info about the device (lsusb and debug kernel
> output) here:
> https://gist.github.com/vext01/958756d0fd515cc321f99a3ee1e3351a
> 
> The following diff makes this device work. It searches the ifaces array
> in the event that the correct entry is not found at the expect index.
> This should be a "no functional change" for all existing compliant
> devices.
> 
> I've tested this for the past two days and all seems well, but I'd like
> some USB stack hackers to verify it.

I'm OK with this approach.  Also I can't currently see how that would
break other devices.  I gave it a quick spin here and couldn't find any
issues.

If you could wrap the comment to 80 chars would be nice.  Otherwise
ok mglocker@

BTW:
The first thing which jumped in my face when reading your diff is that
the configuration descriptor member 'bNumInterface' should be called
'bNumInterfaces' instead, but I'll send out a separate diff for that
later :-)
 
> Cheers
> 
> 
> Index: usbdi.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/usb/usbdi.c,v
> retrieving revision 1.106
> diff -u -p -r1.106 usbdi.c
> --- usbdi.c   3 Apr 2020 20:11:47 -0000       1.106
> +++ usbdi.c   24 Jan 2021 20:44: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->bNumInterface)
> -             return (USBD_INVAL);
> -     *iface = &dev->ifaces[ifaceno];
> -     return (USBD_NORMAL_COMPLETION);
> +     if (ifaceno < dev->cdesc->bNumInterface &&
> +         dev->ifaces[ifaceno].idesc->bInterfaceNumber == ifaceno) {
> +             *iface = &dev->ifaces[ifaceno];
> +             return (USBD_NORMAL_COMPLETION);
> +     }
> +     /* With some non-compliant devices, the interface may be at the wrong 
> index */
> +     for (idx = 0; idx < dev->cdesc->bNumInterface; idx++) {
> +             if (dev->ifaces[idx].idesc->bInterfaceNumber == ifaceno) {
> +                     *iface = &dev->ifaces[idx];
> +                     return (USBD_NORMAL_COMPLETION);
> +             }
> +     }
> +     return (USBD_INVAL);
>  }
>  
>  /* XXXX use altno */

Reply via email to