[alsa-devel] [PATCH] ALSA: usb-audio - Capture and duplex support for Digidesign Mbox 1 sound card.
Daniel Mack
daniel at zonque.org
Mon Mar 31 19:58:44 CEST 2014
Hi Damien,
On 03/29/2014 06:35 AM, Damien Zammit wrote:
> A few revisions of this patch have been made. This patch provides support for usb cards
> which have their streams on multiple endpoints within the same interface.
> In particular, it provides duplex mode support for Digidesign Mbox 1.
>
> I followed ALSA dev team's suggestion of making it work for N endpoints
> rather than hardcoding it to two, and improved error handling has been provided.
> An extra parameter has been added as requested to the usbaudio quirk struct 'epmulti'
> to give the number of endpoints within a multi interface.
>
A few style nits below, which you can fix for the next version. Most
important, the error unwinder should be more in-line with other code in
the kernel.
> diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
> index 7c57f22..affbced 100644
> --- a/sound/usb/quirks.c
> +++ b/sound/usb/quirks.c
> @@ -180,6 +180,84 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
> return 0;
> }
>
> +/*
> + * create N streams for an interface without proper descriptors but with multiple endpoints
> + */
> +static int create_fixed_multi_stream_quirk(struct snd_usb_audio *chip,
> + struct usb_interface *iface,
> + struct usb_driver *driver,
> + const struct snd_usb_audio_quirk *quirk)
> +{
> + struct audioformat **fp;
> + struct usb_host_interface *alts = NULL;
> + int *stream;
> + int err, i;
> + unsigned *rate_table = NULL;
> + int rates_found;
> + rates_found = 0;
> +
> + stream = (int*) kmalloc(sizeof(int) * quirk->epmulti, GFP_KERNEL);
No need to cast the result of k[mzc]alloc. Same for other locations below.
> + if (!stream)
> + goto err_mem;
err = -ENOMEM;
goto exit_err;
> + fp = (struct audioformat**) kmalloc(sizeof((const struct audioformat*)quirk->data) * quirk->epmulti, GFP_KERNEL);
> + if (!(fp))
Extra parenthesis not needed.
> + goto err_mem;
> +
> + for (i = 0; i < quirk->epmulti; ++i) {
i++ is prefered if the operation order doesn't matter. It's not
important but a little more common in the kernel.
> + fp[i] = kmemdup((const struct audioformat*)(quirk->data + i*sizeof(const struct audioformat)), sizeof(*fp[i]), GFP_KERNEL);
You need to do something about these overlong lines, as they're also
quite unparsable for humans. One solution is to pre-calculate the size
into a temporary variable.
> + if (!(fp[i])) {
Extra parenthesis not needed.
> + usb_audio_err(chip, "cannot memdup %d\n", i);
err = -ENOMEM;
goto exit_err;
> + goto err_mem;
> + }
> + if (fp[i]->nr_rates > MAX_NR_RATES) {
> + err = -EINVAL;
> + goto err_rates;
> + }
> + if (fp[i]->nr_rates > 0 && !rates_found) {
> + rate_table = kmemdup(fp[i]->rate_table,
> + sizeof(int) * fp[i]->nr_rates, GFP_KERNEL);
> + rates_found = 1;
Not sure if I overlook anything, but isn't the extra variable
rates_found redundant here, as can derive the same information by
checking for (rate_table != NULL)?
> + }
> + if (!rate_table) {
> + err = -ENOMEM;
> + goto err_rates;
> + }
This check makes more sense directly underneath the kmemdup().
> + fp[i]->rate_table = rate_table;
> +
> + stream[i] = (fp[i]->endpoint & USB_DIR_IN)
> + ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
> +
> + err = snd_usb_add_audio_stream(chip, stream[i], fp[i]);
> + if (err < 0)
> + goto err_ratetable;
> +
> + if (fp[i]->iface != get_iface_desc(&iface->altsetting[0])->bInterfaceNumber ||
> + fp[i]->altset_idx >= iface->num_altsetting) {
> + err = -EINVAL;
> + goto err_ratetable;
> + }
> + alts = &iface->altsetting[fp[0]->altset_idx];
> + fp[i]->datainterval = snd_usb_parse_datainterval(chip, alts);
> + fp[i]->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
> + }
> + usb_set_interface(chip->dev, fp[0]->iface, 0);
> + snd_usb_init_pitch(chip, fp[0]->iface, alts, fp[0]);
> + snd_usb_init_sample_rate(chip, fp[0]->iface, alts, fp[0], fp[0]->rate_max);
> + return 0;
> +
> +err_mem:
> + return -ENOMEM;
You can drop this ...
> +err_ratetable:
> + kfree(rate_table);
> +err_rates:
> + for (i = 0; i < quirk->epmulti; ++i)
> + if(fp[i])
> + kfree(fp[i]);
> + kfree(fp);
> + kfree(stream);
... and place another label here:
exit_err:
> + return err;
> +}
> +
Thanks,
Daniel
More information about the Alsa-devel
mailing list