[alsa-devel] [PATCH] ALSA: usb-audio: Add quirk for MOTU MicroBook II
Takashi Iwai
tiwai at suse.de
Wed Feb 27 18:14:22 CET 2019
On Wed, 27 Feb 2019 15:26:01 +0100,
Manuel Reinhardt wrote:
>
> Add an entry to the quirks-table to for usb-audio to recognize the
> Microbook II (although it only exposes vendor interfaces). A simple boot
> quirk is also implemented to set up the sample rate and make sure that
> no audio urbs are sent before the device is ready.
>
> This patch only provides audio playback and capture at 96kHz sample
> rate. Notice the following shortcomings:
>
> - The sample rate is currently hardcoded to 96k although the device also
> supports 48k and 44.1k.
>
> - The various mixer controls of the MicroBook are not made available.
>
> - The keep-iface control should be on by default because the device
> shuts down whenever the altsetting is reset which is usually unwanted.
> (I don't know the best way to do this)
Can be set either in the quirk callback you write.
Or it'd be not bad to create a white list, too.
> +static int snd_usb_motu_microbookii_boot_quirk(struct usb_device *dev)
> +{
> + int err, actual_length, poll_attempts = 0;
> + bool setup_finished = false;
> + static const u8 set_samplerate_seq[] = { 0x00, 0x00, 0x00, 0x00,
> + 0x00, 0x00, 0x0b, 0x14,
> + 0x00, 0x00, 0x00, 0x01 };
> + static const u8 poll_ready_seq[] = { 0x00, 0x04, 0x00, 0x00,
> + 0x00, 0x00, 0x0b, 0x18 };
> + u8 *buf = kzalloc(MICROBOOK_BUF_SIZE, GFP_KERNEL);
> +
> + if (!buf)
> + return -ENOMEM;
> +
> + dev_info(&dev->dev, "Waiting for MOTU Microbook II to boot up...\n");
> +
> + /* First we tell the device which sample rate to use. */
> + memcpy(buf, set_samplerate_seq, ARRAY_SIZE(set_samplerate_seq));
This is about byte-size, so better to use sizeof().
ARRAY_SIZE() confuses readers as if he needs to care about the
type.
> + actual_length = ARRAY_SIZE(set_samplerate_seq);
Ditto here. Also some other codes below, too.
> + err = snd_usb_motu_microbookii_communicate(dev, buf, MICROBOOK_BUF_SIZE,
> + &actual_length);
> +
> + if (err < 0) {
> + kfree(buf);
> + dev_err(&dev->dev,
> + "failed setting the sample rate for Motu MicroBook II: %d\n",
> + err);
> + return err;
Since kfree() is mandatory in the error path, it's better to use goto
and kfree() there, instead of spreading over all places.
> + }
> +
> + /* Then we poll every 100 ms until the device informs of its readiness. */
> + while (!setup_finished) {
> + if (++poll_attempts > 100) {
> + kfree(buf);
> + dev_err(&dev->dev,
> + "failed booting Motu MicroBook II: timeout\n");
> + return -ENODEV;
> + }
> +
> + memset(buf, 0, MICROBOOK_BUF_SIZE);
> + memcpy(buf, poll_ready_seq, ARRAY_SIZE(poll_ready_seq));
> +
> + actual_length = ARRAY_SIZE(poll_ready_seq);
> + err = snd_usb_motu_microbookii_communicate(
> + dev, buf, MICROBOOK_BUF_SIZE, &actual_length);
> + if (err < 0) {
> + kfree(buf);
> + dev_err(&dev->dev,
> + "failed booting Motu MicroBook II: communication error\n");
> + return err;
> + }
> +
> + if (buf[actual_length - 1] == 1)
> + setup_finished = true;
I wouldn't trust the returned value. Let's be paranoid and check
whether the actual_length is within the expected range.
> +
> + msleep(100);
BTW, setup_finished is superfluous. You can just write like
msleep(100);
if (buf[actual_lenght - 1] == 1)
break;
Or if 100ms sleep isn't needed in the successful case, it can be
if (buf[actual_lenght - 1] == 1)
break;
msleep(100);
thanks,
Takashi
More information about the Alsa-devel
mailing list