Skip to content

Commit

Permalink
ALSA: usb-audio: Filter out unsupported sample rates on Focusrite dev…
Browse files Browse the repository at this point in the history
…ices

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 <[email protected]>
Signed-off-by: Alexander Tsoy <[email protected]>
Cc: <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Takashi Iwai <[email protected]>
  • Loading branch information
puleglot authored and tiwai committed Apr 18, 2020
1 parent b392350 commit 1c82679
Showing 1 changed file with 51 additions and 0 deletions.
51 changes: 51 additions & 0 deletions sound/usb/format.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,52 @@ static bool s1810c_valid_sample_rate(struct audioformat *fp,
return false;
}

/*
* 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
Expand Down Expand Up @@ -319,6 +365,11 @@ static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip,
!s1810c_valid_sample_rate(fp, rate))
goto skip_rate;

/* 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)
Expand Down

0 comments on commit 1c82679

Please sign in to comment.