diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2009-07-13 13:21:58 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-07-30 16:06:00 -0700 |
commit | 2a1495a3933cb333301693b32311f0798e6d2607 (patch) | |
tree | f0755c83fd96059ca1ca19779fc93bd2b3baaaa5 | |
parent | d9120d6d357e869bd8d064b38ac33a6b48ba36c9 (diff) |
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 <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | sound/usb/usbaudio.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index c10e476226c..915a1316724 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -2674,7 +2674,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; @@ -2747,6 +2747,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) |