[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