diff options
author | Alexander Tsoy <alexander@tsoy.me> | 2020-04-18 20:58:15 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-05-02 18:20:47 +0300 |
commit | 9ef662faf92cd28f2caad8d0925ce39e5f7e387c (patch) | |
tree | 5497f15063c66f03a553126c1a2f6e24d6b31619 /sound/usb | |
parent | 02f432922ebae3a1fa9e514862a8a67b0ee38138 (diff) | |
download | linux-9ef662faf92cd28f2caad8d0925ce39e5f7e387c.tar.xz |
ALSA: usb-audio: Filter out unsupported sample rates on Focusrite devices
commit 1c826792586f526a5a5cd21d55aad388f5bb0b23 upstream.
Many Focusrite devices supports a limited set of sample rates per
altsetting. These includes audio interfaces with ADAT ports:
- Scarlett 18i6, 18i8 1st gen, 18i20 1st gen;
- Scarlett 18i8 2nd gen, 18i20 2nd gen;
- Scarlett 18i8 3rd gen, 18i20 3rd gen;
- Clarett 2Pre USB, 4Pre USB, 8Pre USB.
Maximum rate is exposed in the last 4 bytes of Format Type descriptor
which has a non-standard bLength = 10.
Tested-by: Alexey Skobkin <skobkin-ru@ya.ru>
Signed-off-by: Alexander Tsoy <alexander@tsoy.me>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20200418175815.12211-1-alexander@tsoy.me
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/format.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/sound/usb/format.c b/sound/usb/format.c index 789d19ec035d..f28a41194d17 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -223,6 +223,52 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof } /* + * Many Focusrite devices supports a limited set of sampling rates per + * altsetting. Maximum rate is exposed in the last 4 bytes of Format Type + * descriptor which has a non-standard bLength = 10. + */ +static bool focusrite_valid_sample_rate(struct snd_usb_audio *chip, + struct audioformat *fp, + unsigned int rate) +{ + struct usb_interface *iface; + struct usb_host_interface *alts; + unsigned char *fmt; + unsigned int max_rate; + + iface = usb_ifnum_to_if(chip->dev, fp->iface); + if (!iface) + return true; + + alts = &iface->altsetting[fp->altset_idx]; + fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, + NULL, UAC_FORMAT_TYPE); + if (!fmt) + return true; + + if (fmt[0] == 10) { /* bLength */ + max_rate = combine_quad(&fmt[6]); + + /* Validate max rate */ + if (max_rate != 48000 && + max_rate != 96000 && + max_rate != 192000 && + max_rate != 384000) { + + usb_audio_info(chip, + "%u:%d : unexpected max rate: %u\n", + fp->iface, fp->altsetting, max_rate); + + return true; + } + + return rate <= max_rate; + } + + return true; +} + +/* * Helper function to walk the array of sample rate triplets reported by * the device. The problem is that we need to parse whole array first to * get to know how many sample rates we have to expect. @@ -258,6 +304,11 @@ static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip, } for (rate = min; rate <= max; rate += res) { + /* Filter out invalid rates on Focusrite devices */ + if (USB_ID_VENDOR(chip->usb_id) == 0x1235 && + !focusrite_valid_sample_rate(chip, fp, rate)) + goto skip_rate; + if (fp->rate_table) fp->rate_table[nr_rates] = rate; if (!fp->rate_min || rate < fp->rate_min) @@ -272,6 +323,7 @@ static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip, break; } +skip_rate: /* avoid endless loop */ if (res == 0) break; |