]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
ALSA: snd-usb: try harder to find USB_DT_CS_ENDPOINT
authorDaniel Mack <zonque@gmail.com>
Wed, 24 Apr 2013 17:38:42 +0000 (19:38 +0200)
committerTakashi Iwai <tiwai@suse.de>
Thu, 25 Apr 2013 05:33:20 +0000 (07:33 +0200)
The USB_DT_CS_ENDPOINT class-specific endpoint descriptor is usually
stuffed directly after the standard USB endpoint descriptor, and this is
where the driver currently expects it to be.

There are, however, devices in the wild that have it the other way
around in their descriptor sets, so the USB_DT_CS_ENDPOINT comes
*before* the standard enpoint. Devices known to implement it that way
are "Sennheiser BTD-500" and Plantronics USB headsets.

When the driver can't find the USB_DT_CS_ENDPOINT, it won't be able to
change sample rates, as the bitmask for the validity of this command is
storen in bmAttributes of that descriptor.

Fix this by searching the entire interface instead of just the extra
bytes of the first endpoint, in case the latter fails.

Signed-off-by: Daniel Mack <zonque@gmail.com>
Reported-and-tested-by: Torstein Hegge <hegge@resisty.net>
Reported-and-tested-by: Yves G <alsa-user@vivigatt.com>
Cc: stable@kernel.org
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/usb/stream.c

index 8951f77a72012e60d10cd14d8a8b7e8dd10393a4..7db2f8958e7942e223f3b48f8df2a922cfde1258 100644 (file)
@@ -393,6 +393,14 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
        if (!csep && altsd->bNumEndpoints >= 2)
                csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
 
+       /*
+        * If we can't locate the USB_DT_CS_ENDPOINT descriptor in the extra
+        * bytes after the first endpoint, go search the entire interface.
+        * Some devices have it directly *before* the standard endpoint.
+        */
+       if (!csep)
+               csep = snd_usb_find_desc(alts->extra, alts->extralen, NULL, USB_DT_CS_ENDPOINT);
+
        if (!csep || csep->bLength < 7 ||
            csep->bDescriptorSubtype != UAC_EP_GENERAL) {
                snd_printk(KERN_WARNING "%d:%u:%d : no or invalid"