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)