[alsa-devel] [RESENT] [PATCH - Fix Fast Track Ultra series: 44.1/88.1 kHz 1/Fix playback/capture issues and related chrashes at 44100 Hz and 88200 Hz for M-Audio Fast Track Ultra series.

Daniel Mack daniel at caiaq.de
Fri Sep 3 15:34:14 CEST 2010


On Thu, Sep 02, 2010 at 01:13:48PM +0200, Clemens Ladisch wrote:
> Daniel Mack wrote:
> > On Thu, Sep 02, 2010 at 11:12:59AM +0200, Clemens Ladisch wrote:
> > > > > Also, the Interface Class protocol for the device defaults to Vendor 
> > > > > Specific Class, but the driver only recognizes Class 1 or 2. The device 
> > > > > is really Class 1, so we have to force it to reflect this. There are 4 
> > > > > places that we need to set this."
> > > 
> > > Daniel, this seems to be a regression introduced with the UAC2 changes.
> > > The old driver accepted vendor-specific interfaces, if some quirk forced
> > > it to look at them.
> > 
> > Hmm, I don't follow. What's the problem, and why should that be caused
> > by the UAC2 changes? Sorry, but I seem to have missed that thread.
> 
> I've got several reports that devices no longer work since UAC2 support got
> added.  But I've just noticed this is not related to the interface class
> but to the interface protocol: the new code added checks for UAC_VERSION_1
> or _2, but real devices apparently write just random junk into this field.
> (For vendor-specific interfaces, they are actually justified to do so.)

Grr. So what about cases where this "random junk" is 0x20 by coincidence?

> We need something like the following (untested), unless you have a better
> idea:

We could also fix up such devices with quirks tables, but your approach
is probably better as it catches all devices right away.


Thanks,
Daniel

> 
> diff --git a/sound/usb/card.c b/sound/usb/card.c
> index 9feb00c..d5141a1 100644
> --- a/sound/usb/card.c
> +++ b/sound/usb/card.c
> @@ -216,6 +216,10 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
>  	}
>  
>  	switch (protocol) {
> +	default:
> +		snd_printdd(KERN_WARN "unknown interface protocol %#02x, assuming v1\n");
> +		/* fall through */
> +
>  	case UAC_VERSION_1: {
>  		struct uac1_ac_header_descriptor *h1 = control_header;
>  
> @@ -253,10 +257,6 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
>  
>  		break;
>  	}
> -
> -	default:
> -		snd_printk(KERN_ERR "unknown protocol version 0x%02x\n", protocol);
> -		return -EINVAL;
>  	}
>  
>  	return 0;
> diff --git a/sound/usb/clock.c b/sound/usb/clock.c
> index b853f8d..7754a10 100644
> --- a/sound/usb/clock.c
> +++ b/sound/usb/clock.c
> @@ -295,12 +295,11 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
>  
>  	switch (altsd->bInterfaceProtocol) {
>  	case UAC_VERSION_1:
> +	default:
>  		return set_sample_rate_v1(chip, iface, alts, fmt, rate);
>  
>  	case UAC_VERSION_2:
>  		return set_sample_rate_v2(chip, iface, alts, fmt, rate);
>  	}
> -
> -	return -EINVAL;
>  }
>  
> diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
> index bb9f938..22589b5 100644
> --- a/sound/usb/endpoint.c
> +++ b/sound/usb/endpoint.c
> @@ -275,6 +275,12 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
>  
>  		/* get audio formats */
>  		switch (protocol) {
> +		default:
> +			snd_printdd(KERN_WARN "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n",
> +				    dev->devnum, iface_no, altno, protocol);
> +			protocol = UAC_VERSION_1;
> +			/* fall through */
> +
>  		case UAC_VERSION_1: {
>  			struct uac1_as_header_descriptor *as =
>  				snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
> @@ -336,11 +342,6 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
>  				   dev->devnum, iface_no, altno, as->bTerminalLink);
>  			continue;
>  		}
> -
> -		default:
> -			snd_printk(KERN_ERR "%d:%u:%d : unknown interface protocol %04x\n",
> -				   dev->devnum, iface_no, altno, protocol);
> -			continue;
>  		}
>  
>  		/* get format type */
> diff --git a/sound/usb/format.c b/sound/usb/format.c
> index 4387f54..2ec73dd 100644
> --- a/sound/usb/format.c
> +++ b/sound/usb/format.c
> @@ -49,7 +49,8 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
>  	u64 pcm_formats;
>  
>  	switch (protocol) {
> -	case UAC_VERSION_1: {
> +	case UAC_VERSION_1:
> +	default: {
>  		struct uac_format_type_i_discrete_descriptor *fmt = _fmt;
>  		sample_width = fmt->bBitResolution;
>  		sample_bytes = fmt->bSubframeSize;
> @@ -64,9 +65,6 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
>  		format <<= 1;
>  		break;
>  	}
> -
> -	default:
> -		return -EINVAL;
>  	}
>  
>  	pcm_formats = 0;
> @@ -385,6 +383,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
>  	 */
>  	switch (protocol) {
>  	case UAC_VERSION_1:
> +	default:
>  		fp->channels = fmt->bNrChannels;
>  		ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7);
>  		break;
> @@ -434,7 +433,8 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,
>  	fp->channels = 1;
>  
>  	switch (protocol) {
> -	case UAC_VERSION_1: {
> +	case UAC_VERSION_1:
> +	default: {
>  		struct uac_format_type_ii_discrete_descriptor *fmt = _fmt;
>  		brate = le16_to_cpu(fmt->wMaxBitRate);
>  		framesize = le16_to_cpu(fmt->wSamplesPerFrame);
> diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
> index c166db0..0478fa3 100644
> --- a/sound/usb/mixer.c
> +++ b/sound/usb/mixer.c
> @@ -365,7 +365,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
>  
>  static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
>  {
> -	return (cval->mixer->protocol == UAC_VERSION_1) ?
> +	return (cval->mixer->protocol != UAC_VERSION_2) ?
>  		get_ctl_value_v1(cval, request, validx, value_ret) :
>  		get_ctl_value_v2(cval, request, validx, value_ret);
>  }
> @@ -415,7 +415,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
>  	unsigned char buf[2];
>  	int val_len, timeout = 10;
>  
> -	if (cval->mixer->protocol == UAC_VERSION_1) {
> +	if (cval->mixer->protocol != UAC_VERSION_2) {
>  		val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
>  	} else { /* UAC_VERSION_2 */
>  		/* audio class v2 controls are always 2 bytes in size */
> @@ -642,7 +642,7 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
>  		term->id = id;
>  		switch (hdr[2]) {
>  		case UAC_INPUT_TERMINAL:
> -			if (state->mixer->protocol == UAC_VERSION_1) {
> +			if (state->mixer->protocol != UAC_VERSION_2) {
>  				struct uac_input_terminal_descriptor *d = p1;
>  				term->type = le16_to_cpu(d->wTerminalType);
>  				term->channels = d->bNrChannels;
> @@ -1159,7 +1159,7 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
>  	struct uac_feature_unit_descriptor *hdr = _ftr;
>  	__u8 *bmaControls;
>  
> -	if (state->mixer->protocol == UAC_VERSION_1) {
> +	if (state->mixer->protocol != UAC_VERSION_2) {
>  		csize = hdr->bControlSize;
>  		channels = (hdr->bLength - 7) / csize - 1;
>  		bmaControls = hdr->bmaControls;
> @@ -1198,7 +1198,7 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
>  	else
>  		first_ch_bits = 0;
>  
> -	if (state->mixer->protocol == UAC_VERSION_1) {
> +	if (state->mixer->protocol != UAC_VERSION_2) {
>  		/* check all control types */
>  		for (i = 0; i < 10; i++) {
>  			unsigned int ch_bits = 0;
> @@ -1865,13 +1865,13 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
>  		return parse_audio_feature_unit(state, unitid, p1);
>  	case UAC1_PROCESSING_UNIT:
>  	/*   UAC2_EFFECT_UNIT has the same value */
> -		if (state->mixer->protocol == UAC_VERSION_1)
> +		if (state->mixer->protocol != UAC_VERSION_2)
>  			return parse_audio_processing_unit(state, unitid, p1);
>  		else
>  			return 0; /* FIXME - effect units not implemented yet */
>  	case UAC1_EXTENSION_UNIT:
>  	/*   UAC2_PROCESSING_UNIT_V2 has the same value */
> -		if (state->mixer->protocol == UAC_VERSION_1)
> +		if (state->mixer->protocol != UAC_VERSION_2)
>  			return parse_audio_extension_unit(state, unitid, p1);
>  		else /* UAC_VERSION_2 */
>  			return parse_audio_processing_unit(state, unitid, p1);
> @@ -1932,7 +1932,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
>  
>  	p = NULL;
>  	while ((p = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, p, UAC_OUTPUT_TERMINAL)) != NULL) {
> -		if (mixer->protocol == UAC_VERSION_1) {
> +		if (mixer->protocol != UAC_VERSION_2) {
>  			struct uac1_output_terminal_descriptor *desc = p;
>  
>  			if (desc->bLength < sizeof(*desc))
> @@ -2070,7 +2070,7 @@ static void snd_usb_mixer_interrupt(struct urb *urb)
>  	if (urb->status != 0)
>  		goto requeue;
>  
> -	if (mixer->protocol == UAC_VERSION_1) {
> +	if (mixer->protocol != UAC_VERSION_2) {
>  		struct uac1_status_word *status;
>  
>  		for (status = urb->transfer_buffer;
> diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
> index 3634ced..3b5135c 100644
> --- a/sound/usb/pcm.c
> +++ b/sound/usb/pcm.c
> @@ -173,13 +173,12 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
>  
>  	switch (altsd->bInterfaceProtocol) {
>  	case UAC_VERSION_1:
> +	default:
>  		return init_pitch_v1(chip, iface, alts, fmt);
>  
>  	case UAC_VERSION_2:
>  		return init_pitch_v2(chip, iface, alts, fmt);
>  	}
> -
> -	return -EINVAL;
>  }
>  
>  /*


More information about the Alsa-devel mailing list