summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2009-07-13 13:21:58 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2009-07-30 16:06:00 -0700
commit2a1495a3933cb333301693b32311f0798e6d2607 (patch)
treef0755c83fd96059ca1ca19779fc93bd2b3baaaa5
parentd9120d6d357e869bd8d064b38ac33a6b48ba36c9 (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.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index c10e476226cd..915a1316724c 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)