From: Clemens Ladisch Date: Mon, 13 Jul 2009 11:21:58 +0000 (+0200) Subject: sound: usb-audio: add workaround for Blue Microphones devices X-Git-Tag: v2.6.30.4~66 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=843f9d9fa71d3889169172b20ee07ae6e51c0be4;p=thirdparty%2Fkernel%2Fstable.git sound: usb-audio: add workaround for Blue Microphones devices commit 8886f33f25083a47d5fa24ad7b57bb708c5c5403 upstream. Blue Microphones USB devices have an alternate setting that sends two channels of data to the computer. Unfortunately, the descriptors of that altsetting have a wrong channel setting, which means that any recorded data from such a device has twice the sample rate from what would be expected. This patch adds a workaround to ignore that altsetting. Since these devices have only one actual channel, no data is lost. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index a6b88482637be..6ea6868023b9f 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -2649,7 +2649,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) struct usb_interface_descriptor *altsd; int i, altno, err, stream; int format; - struct audioformat *fp; + struct audioformat *fp = NULL; unsigned char *fmt, *csep; int num; @@ -2722,6 +2722,18 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) continue; } + /* + * Blue Microphones workaround: The last altsetting is identical + * with the previous one, except for a larger packet size, but + * is actually a mislabeled two-channel setting; ignore it. + */ + if (fmt[4] == 1 && fmt[5] == 2 && altno == 2 && num == 3 && + fp && fp->altsetting == 1 && fp->channels == 1 && + fp->format == SNDRV_PCM_FORMAT_S16_LE && + le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == + fp->maxpacksize * 2) + continue; + csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT); /* Creamware Noah has this descriptor after the 2nd endpoint */ if (!csep && altsd->bNumEndpoints >= 2)