All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Mack <daniel@caiaq.de>
To: Alex Lee <alexlee188@gmail.com>
Cc: tiwai@suse.de, alsa-devel@alsa-project.org, clemens@ladisch.de
Subject: Re: [PATCH 3/4] ALSA: usb-audio: parse UAC2 sample rate ranges correctly
Date: Fri, 11 Jun 2010 17:04:35 +0200	[thread overview]
Message-ID: <20100611150435.GS2698@buzzloop.caiaq.de> (raw)
In-Reply-To: <AANLkTin3LMCu_f2emsh6kAT8H6G3zKF8Ud-ZUMpZjbmg@mail.gmail.com>

On Fri, Jun 11, 2010 at 10:59:44PM +0800, Alex Lee wrote:
> If the device has a variable clock, it may report a RES of only 1.  So you
> may end up with thousands (and even millions) of sample rates.  It might be
> better to have separate code to cater to discrete clocks vs variable clocks.

AFAIK, ALSA cannot cope with that yet. Am I right?

Daniel



> On Fri, Jun 11, 2010 at 9:33 PM, Daniel Mack <daniel@caiaq.de> wrote:
> 
> > A device may report its supported sample rates in ranges rather than in
> > discrete triplets. The code used to only parse the MIN field instead of
> > properly paying attention to the MAX and RES values.
> >
> > Signed-off-by: Daniel Mack <daniel@caiaq.de>
> > Reported-by: Alex Lee <alexlee188@gmail.com>
> > ---
> >  sound/usb/format.c |   80
> > ++++++++++++++++++++++++++++++++++++++++-----------
> >  1 files changed, 62 insertions(+), 18 deletions(-)
> >
> > diff --git a/sound/usb/format.c b/sound/usb/format.c
> > index 8eccf17..e946db7 100644
> > --- a/sound/usb/format.c
> > +++ b/sound/usb/format.c
> > @@ -206,6 +206,47 @@ static int parse_audio_format_rates_v1(struct
> > snd_usb_audio *chip, struct audiof
> >  }
> >
> >  /*
> > + * 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
> > + * get to know how many sample rates we have to expect.
> > + * Then fp->rate_table can be allocated and filled.
> > + */
> > +static int parse_uac2_sample_rate_range(struct audioformat *fp, int
> > nr_triplets,
> > +                                       const unsigned char *data)
> > +{
> > +       int i, nr_rates = 0;
> > +
> > +       fp->rates = fp->rate_min = fp->rate_max = 0;
> > +
> > +       for (i = 0; i < nr_triplets; i++) {
> > +               int min = combine_quad(&data[2 + 12 * i]);
> > +               int max = combine_quad(&data[6 + 12 * i]);
> > +               int res = combine_quad(&data[10 + 12 * i]);
> > +               int rate;
> > +
> > +               if ((max < 0) || (min < 0) || (res < 0) || (max < min))
> > +                       continue;
> > +
> > +               for (rate = min; rate <= max; rate += res) {
> > +                       if (fp->rate_table)
> > +                               fp->rate_table[nr_rates] = rate;
> > +                       if (!fp->rate_min || rate < fp->rate_min)
> > +                               fp->rate_min = rate;
> > +                       if (!fp->rate_max || rate > fp->rate_max)
> > +                               fp->rate_max = rate;
> > +                       fp->rates |= snd_pcm_rate_to_rate_bit(rate);
> > +                       nr_rates++;
> > +
> > +                       /* avoid endless loop */
> > +                       if (res == 0)
> > +                               break;
> > +               }
> > +       }
> > +
> > +       return nr_rates;
> > +}
> > +
> > +/*
> >  * parse the format descriptor and stores the possible sample rates
> >  * on the audioformat table (audio class v2).
> >  */
> > @@ -215,7 +256,7 @@ static int parse_audio_format_rates_v2(struct
> > snd_usb_audio *chip,
> >  {
> >        struct usb_device *dev = chip->dev;
> >        unsigned char tmp[2], *data;
> > -       int i, nr_rates, data_size, ret = 0;
> > +       int nr_triplets, data_size, ret = 0;
> >        int clock = snd_usb_clock_find_source(chip, chip->ctrl_intf,
> > fp->clock);
> >
> >        if (clock < 0) {
> > @@ -237,8 +278,8 @@ static int parse_audio_format_rates_v2(struct
> > snd_usb_audio *chip,
> >                goto err;
> >        }
> >
> > -       nr_rates = (tmp[1] << 8) | tmp[0];
> > -       data_size = 2 + 12 * nr_rates;
> > +       nr_triplets = (tmp[1] << 8) | tmp[0];
> > +       data_size = 2 + 12 * nr_triplets;
> >        data = kzalloc(data_size, GFP_KERNEL);
> >        if (!data) {
> >                ret = -ENOMEM;
> > @@ -259,26 +300,29 @@ static int parse_audio_format_rates_v2(struct
> > snd_usb_audio *chip,
> >                goto err_free;
> >        }
> >
> > -       fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL);
> > +       /* Call the triplet parser, and make sure fp->rate_table is NULL.
> > +        * We just use the return value to know how many sample rates we
> > +        * will have to deal with. */
> > +       kfree(fp->rate_table);
> > +       fp->rate_table = NULL;
> > +       fp->nr_rates = parse_uac2_sample_rate_range(fp, nr_triplets, data);
> > +
> > +       if (fp->nr_rates == 0) {
> > +               snd_printk(KERN_ERR "%s(): unable to parse sample rate
> > triplets\n",
> > +                               __func__);
> > +               ret = -EINVAL;
> > +               goto err_free;
> > +       }
> > +
> > +       fp->rate_table = kmalloc(sizeof(int) * fp->nr_rates, GFP_KERNEL);
> >        if (!fp->rate_table) {
> >                ret = -ENOMEM;
> >                goto err_free;
> >        }
> >
> > -       fp->nr_rates = 0;
> > -       fp->rate_min = fp->rate_max = 0;
> > -
> > -       for (i = 0; i < nr_rates; i++) {
> > -               int rate = combine_quad(&data[2 + 12 * i]);
> > -
> > -               fp->rate_table[fp->nr_rates] = rate;
> > -               if (!fp->rate_min || rate < fp->rate_min)
> > -                       fp->rate_min = rate;
> > -               if (!fp->rate_max || rate > fp->rate_max)
> > -                       fp->rate_max = rate;
> > -               fp->rates |= snd_pcm_rate_to_rate_bit(rate);
> > -               fp->nr_rates++;
> > -       }
> > +       /* Call the triplet parser again, but this time, fp->rate_table is
> > +        * allocated, so the rates will be stored */
> > +       parse_uac2_sample_rate_range(fp, nr_triplets, data);
> >
> >  err_free:
> >        kfree(data);
> > --
> > 1.7.1
> >
> >

  parent reply	other threads:[~2010-06-11 15:04 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-06-11 13:33 usb-audio: some UAC2 fixes Daniel Mack
2010-06-11 13:33 ` [PATCH 1/4] ALSA: usb-audio: add check for faulty clock in parse_audio_format_rates_v2() Daniel Mack
2010-06-11 13:33 ` [PATCH 2/4] ALSA: usb-audio: fix control messages for USB_RECIP_INTERFACE Daniel Mack
2010-06-11 13:33 ` [PATCH 3/4] ALSA: usb-audio: parse UAC2 sample rate ranges correctly Daniel Mack
     [not found]   ` <AANLkTin3LMCu_f2emsh6kAT8H6G3zKF8Ud-ZUMpZjbmg@mail.gmail.com>
2010-06-11 15:04     ` Daniel Mack [this message]
2010-06-11 15:14       ` Clemens Ladisch
2010-06-11 15:18         ` Daniel Mack
2010-06-11 15:34           ` [PATCH 1/4] ALSA: usb-audio: add check for faulty clock in parse_audio_format_rates_v2() Daniel Mack
2010-06-11 16:10             ` Takashi Iwai
2010-06-11 15:34           ` [PATCH 2/4] ALSA: usb-audio: fix control messages for USB_RECIP_INTERFACE Daniel Mack
2010-06-11 15:34           ` [PATCH 3/4] ALSA: usb-audio: parse UAC2 sample rate ranges correctly Daniel Mack
2010-06-11 15:43             ` Takashi Iwai
2010-06-11 15:46               ` Daniel Mack
2010-06-11 15:54                 ` Takashi Iwai
2010-06-11 15:34           ` [PATCH 4/4] ALSA: usb-audio: fix UAC2 control value queries Daniel Mack
2010-06-11 15:18       ` [PATCH 3/4] ALSA: usb-audio: parse UAC2 sample rate ranges correctly Mark Brown
2010-06-14 12:41     ` Daniel Mack
2010-06-11 13:33 ` [PATCH 4/4] ALSA: usb-audio: fix UAC2 control value queries Daniel Mack
2010-06-11 13:51   ` Daniel Mack

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100611150435.GS2698@buzzloop.caiaq.de \
    --to=daniel@caiaq.de \
    --cc=alexlee188@gmail.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=clemens@ladisch.de \
    --cc=tiwai@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.