Hi,

the logitech c310 is supported by uvideo, but its uaudio fails to
attach properly and fallbacks to ugen.

uaudio0 at uhub0 port 1 configuration 1 interface 2 "Logitech Webcam C310" rev 
2.00/0.12 addr 2
uaudio_identify_ac: AC interface is 2
uaudio_identify_ac: found AC header, vers=100, len=38
uaudio0: audio descriptors make no sense, error=4
ugen0 at uhub0 port 1 configuration 1 "Logitech Webcam C310" rev 2.00/0.12 addr 
2

after a bit of poking, and looking at lsusb -v output i figured out that
the audio descriptor was lying on its size, saying it was 38:

      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength           38

but the sum of the sub-descriptor lengths is in fact 9+12+9+9=39..

      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorSubtype      1 (HEADER)
      AudioControl Interface Descriptor:
        bLength                12
        bDescriptorSubtype      2 (INPUT_TERMINAL)
        wTerminalType      0x0201 Microphone
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorSubtype      3 (OUTPUT_TERMINAL)
        wTerminalType      0x0101 USB Streaming
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorSubtype      6 (FEATURE_UNIT)

if i 'fix' aclen to be 39 in sys/dev/usb/uaudio.c, line 1806 then the
device attaches and works fine:
uaudio0 at uhub1 port 2 configuration 1 interface 2 "Logitech Webcam C310" rev 
2.00/0.12 addr 5

from that point, i dunno if my analysis is wrong or right, nor how to
properly handle it, so here's my take:
- add a UAUDIO_FLAG_BAD_ADC_LEN quirk
- set it for the c310 vendor/product
- if the device matches this quirk, aclen++

feedback or better ideas welcome :)

Landry
Index: uaudio.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/uaudio.c,v
retrieving revision 1.128
diff -u -r1.128 uaudio.c
--- uaudio.c    30 Dec 2017 23:08:29 -0000      1.128
+++ uaudio.c    24 Jun 2018 11:10:53 -0000
@@ -62,10 +62,11 @@
 #include <dev/usb/uaudioreg.h>
 
 /* #define UAUDIO_DEBUG */
+#define UAUDIO_DEBUG
 #ifdef UAUDIO_DEBUG
 #define DPRINTF(x)     do { if (uaudiodebug) printf x; } while (0)
 #define DPRINTFN(n,x)  do { if (uaudiodebug>(n)) printf x; } while (0)
-int    uaudiodebug = 0;
+int    uaudiodebug = 5;
 #else
 #define DPRINTF(x)
 #define DPRINTFN(n,x)
@@ -172,6 +173,7 @@
 #define UAUDIO_FLAG_VENDOR_CLASS 0x0010        /* claims vendor class but 
works */
 #define UAUDIO_FLAG_DEPENDENT   0x0020 /* play and record params must equal */
 #define UAUDIO_FLAG_EMU0202     0x0040
+#define UAUDIO_FLAG_BAD_ADC_LEN         0x0080 /* bad audio control descriptor 
size */
 
 struct uaudio_devs {
        struct usb_devno         uv_dev;
@@ -222,6 +224,8 @@
                UAUDIO_FLAG_BAD_AUDIO },
        { { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMZOOM },
                UAUDIO_FLAG_BAD_AUDIO },
+       { { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_WEBCAMC310 },
+               UAUDIO_FLAG_BAD_ADC_LEN },
        { { USB_VENDOR_TELEX, USB_PRODUCT_TELEX_MIC1 },
                UAUDIO_FLAG_NO_FRAC }
 };
@@ -1806,6 +1810,9 @@
        aclen = UGETW(acdp->wTotalLength);
        if (offs + aclen > size)
                return (USBD_INVAL);
+
+       if (sc->sc_quirks & UAUDIO_FLAG_BAD_ADC_LEN)
+               aclen++;
 
        if (!(sc->sc_quirks & UAUDIO_FLAG_BAD_ADC) &&
             UGETW(acdp->bcdADC) != UAUDIO_VERSION)

Reply via email to