aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2013-04-24 19:38:42 +0200
committerLuis Henriques <luis.henriques@canonical.com>2013-05-14 11:24:25 +0100
commit0ba1a892798e18a42a8704cc6c78e167ae39f409 (patch)
tree84279b1de9adc868d855c3629e57f9ad747e1b2d
parent3055f9e34a2dd3630c5dbe786cf29f661b73ec12 (diff)
ALSA: snd-usb: try harder to find USB_DT_CS_ENDPOINT
commit ebfc594c02148b6a85c2f178cf167a44a3c3ce10 upstream. 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> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
-rw-r--r--sound/usb/stream.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 20252057c53a..1891e49b5ca2 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -194,6 +194,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"