From a2acad8298a42b7be684a32fafaf83332bba9c2b Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Fri, 3 Sep 2010 10:53:11 +0200 Subject: ALSA: usb-audio: fix detection of vendor-specific device protocol settings The Audio Class v2 support code in 2.6.35 added checks for the bInterfaceProtocol field. However, there are devices (usually those detected by vendor-specific quirks) that do not have one of the predefined values in this field, which made the driver reject them. To fix this regression, restore the old behaviour, i.e., assume that a device with an unknown bInterfaceProtocol field (other than UAC_VERSION_2) has more or less UAC-v1-compatible descriptors. [compile warning fixes by tiwai] Signed-off-by: Clemens Ladisch Cc: Daniel Mack Cc: Signed-off-by: Takashi Iwai --- sound/usb/card.c | 9 +++++---- sound/usb/clock.c | 3 +-- sound/usb/endpoint.c | 11 ++++++----- sound/usb/format.c | 22 ++++++++++------------ sound/usb/mixer.c | 10 +++++++++- sound/usb/pcm.c | 3 +-- 6 files changed, 32 insertions(+), 26 deletions(-) (limited to 'sound/usb') diff --git a/sound/usb/card.c b/sound/usb/card.c index b443a33d31c9..32e4be8a187c 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -216,6 +216,11 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) } switch (protocol) { + default: + snd_printdd(KERN_WARNING "unknown interface protocol %#02x, assuming v1\n", + protocol); + /* fall through */ + case UAC_VERSION_1: { struct uac1_ac_header_descriptor *h1 = control_header; @@ -253,10 +258,6 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) break; } - - default: - snd_printk(KERN_ERR "unknown protocol version 0x%02x\n", protocol); - return -EINVAL; } return 0; diff --git a/sound/usb/clock.c b/sound/usb/clock.c index b853f8df794f..7754a1034545 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -295,12 +295,11 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, switch (altsd->bInterfaceProtocol) { case UAC_VERSION_1: + default: return set_sample_rate_v1(chip, iface, alts, fmt, rate); case UAC_VERSION_2: return set_sample_rate_v2(chip, iface, alts, fmt, rate); } - - return -EINVAL; } diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 1a701f1e8f50..ef0a07e34844 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -275,6 +275,12 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) /* get audio formats */ switch (protocol) { + default: + snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n", + dev->devnum, iface_no, altno, protocol); + protocol = UAC_VERSION_1; + /* fall through */ + case UAC_VERSION_1: { struct uac1_as_header_descriptor *as = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); @@ -336,11 +342,6 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) dev->devnum, iface_no, altno, as->bTerminalLink); continue; } - - default: - snd_printk(KERN_ERR "%d:%u:%d : unknown interface protocol %04x\n", - dev->devnum, iface_no, altno, protocol); - continue; } /* get format type */ diff --git a/sound/usb/format.c b/sound/usb/format.c index 3a1375459c06..69148212aa70 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -49,7 +49,8 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, u64 pcm_formats; switch (protocol) { - case UAC_VERSION_1: { + case UAC_VERSION_1: + default: { struct uac_format_type_i_discrete_descriptor *fmt = _fmt; sample_width = fmt->bBitResolution; sample_bytes = fmt->bSubframeSize; @@ -64,9 +65,6 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, format <<= 1; break; } - - default: - return -EINVAL; } pcm_formats = 0; @@ -384,6 +382,10 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, * audio class v2 uses class specific EP0 range requests for that. */ switch (protocol) { + default: + snd_printdd(KERN_WARNING "%d:%u:%d : invalid protocol version %d, assuming v1\n", + chip->dev->devnum, fp->iface, fp->altsetting, protocol); + /* fall through */ case UAC_VERSION_1: fp->channels = fmt->bNrChannels; ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7); @@ -392,10 +394,6 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, /* fp->channels is already set in this case */ ret = parse_audio_format_rates_v2(chip, fp); break; - default: - snd_printk(KERN_ERR "%d:%u:%d : invalid protocol version %d\n", - chip->dev->devnum, fp->iface, fp->altsetting, protocol); - return -EINVAL; } if (fp->channels < 1) { @@ -438,6 +436,10 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, fp->channels = 1; switch (protocol) { + default: + snd_printdd(KERN_WARNING "%d:%u:%d : invalid protocol version %d, assuming v1\n", + chip->dev->devnum, fp->iface, fp->altsetting, protocol); + /* fall through */ case UAC_VERSION_1: { struct uac_format_type_ii_discrete_descriptor *fmt = _fmt; brate = le16_to_cpu(fmt->wMaxBitRate); @@ -456,10 +458,6 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, ret = parse_audio_format_rates_v2(chip, fp); break; } - default: - snd_printk(KERN_ERR "%d:%u:%d : invalid protocol version %d\n", - chip->dev->devnum, fp->iface, fp->altsetting, protocol); - return -EINVAL; } return ret; diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index c166db0057d3..3ed3901369ce 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2175,7 +2175,15 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, } host_iface = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0]; - mixer->protocol = get_iface_desc(host_iface)->bInterfaceProtocol; + switch (get_iface_desc(host_iface)->bInterfaceProtocol) { + case UAC_VERSION_1: + default: + mixer->protocol = UAC_VERSION_1; + break; + case UAC_VERSION_2: + mixer->protocol = UAC_VERSION_2; + break; + } if ((err = snd_usb_mixer_controls(mixer)) < 0 || (err = snd_usb_mixer_status_create(mixer)) < 0) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 3634cedf9306..3b5135c93062 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -173,13 +173,12 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, switch (altsd->bInterfaceProtocol) { case UAC_VERSION_1: + default: return init_pitch_v1(chip, iface, alts, fmt); case UAC_VERSION_2: return init_pitch_v2(chip, iface, alts, fmt); } - - return -EINVAL; } /* -- cgit v1.2.3