ALSA: usb-audio: Filter out unsupported sample rates on Focusrite devices
commit 1c82679258
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>
This commit is contained in:
parent
d5cd821536
commit
387039b250
|
@ -226,6 +226,52 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
@ -262,6 +308,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)
|
||||
|
@ -276,6 +327,7 @@ static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip,
|
|||
break;
|
||||
}
|
||||
|
||||
skip_rate:
|
||||
/* avoid endless loop */
|
||||
if (res == 0)
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue