Commit 1c826792 authored by Alexander Tsoy's avatar Alexander Tsoy Committed by Takashi Iwai
Browse files

ALSA: usb-audio: Filter out unsupported sample rates on Focusrite devices



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: default avatarAlexey Skobkin <skobkin-ru@ya.ru>
Signed-off-by: default avatarAlexander Tsoy <alexander@tsoy.me>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20200418175815.12211-1-alexander@tsoy.me


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent b392350e
Loading
Loading
Loading
Loading
+51 −0
Original line number Diff line number Diff line
@@ -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
@@ -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)