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;
|
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
|
* 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
|
* 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) {
|
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)
|
if (fp->rate_table)
|
||||||
fp->rate_table[nr_rates] = rate;
|
fp->rate_table[nr_rates] = rate;
|
||||||
if (!fp->rate_min || rate < fp->rate_min)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skip_rate:
|
||||||
/* avoid endless loop */
|
/* avoid endless loop */
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue