[alsa-devel] sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2

Takashi Iwai tiwai at suse.de
Thu Dec 13 15:59:11 CET 2012


At Fri, 14 Dec 2012 01:20:59 +1100,
Damien Zammit wrote:
> 
> Support for Digidesign Mbox 2 USB sound card:
> 
> This patch is the result of a lot of trial and error, since there are no specs
> available for the device.
> 
> Full duplex support is provided, i.e. playback and recording in stereo.
> The format is hardcoded at 48000Hz @ 24 bit, which is the maximum that the
> device supports.  Also, MIDI in and MIDI out both work.
> 
> Users will notice that the S/PDIF light also flashes when playback or recording
> is active.  I believe this means that S/PDIF input/output is simultaneously
> activated with the analogue i/o during use.
> But this particular functionality remains untested.
> 
> Note that this particular version of the patch is so far untested on the
> physical hardware because I have not compiled a full kernel with the changes.
> However, extensive testing has been done by many users of the hardware
> who believe other versions of my patch have worked since circa 2009.
> 
> Signed-off-by: Damien Zammit <damien at zamaudio.com>

Thanks for the quick update.

One more hint: put "[PATCH]" prefix to the subject so that people
notice it's to review or merge more clearly.

Some nitpicking about codes below:

> diff --git a/sound/usb/midi.c b/sound/usb/midi.c
> index 34b9bb7..45532dd 100644
> --- a/sound/usb/midi.c
> +++ b/sound/usb/midi.c
> @@ -2181,6 +2181,11 @@ int snd_usbmidi_create(struct snd_card *card,
>  		umidi->usb_protocol_ops = &snd_usbmidi_novation_ops;
>  		err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
>  		break;
> +	case QUIRK_MIDI_MBOX2:
> +		/* Digidesign Mbox 2 uses MIDIMAN MIDI protocol */
> +		umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
> +		err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
> +		break;

If the quirk handling is as same as QUIRK_MIDI_MIDIMAN, can't we just
reuse it instead of adding yet a new type?


> +int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
> +{
> +	struct usb_host_config *config = dev->actconfig;
> +	int err;
> +	u8 enablemagic[3];
> +	u8 bootresponse;
> +	u8 temp[12];
> +	int fwsize;
> +	int count;
> +
> +	fwsize = le16_to_cpu(get_cfg_desc(config)->wTotalLength);
> +
> +	if (fwsize == MBOX2_FIRMWARE_SIZE) {

Here you can reduce the indentation depth by simply returning the
error like

	if (fwsize != MBOX_FIRMWARE_SIZE) {
		snd_printk(KERN_ERR "usb-audio: Invalid firmware size: %d\n", fwsize);
		return -ENODEV;
	}

	.... // the reset

(And, as you see, always put KERN_* prefix to *_printk().
 Not necessarily for snd_printd() and snd_printdd(), if it's a debug
 message.
 Also better to put some suffix to the message, too.)


> +		snd_printk("Sending Digidesign Mbox 2 boot sequence...\n");
> +
> +		count = 0;
> +		bootresponse = MBOX2_BOOT_LOADING;
> +		while ((bootresponse == MBOX2_BOOT_LOADING) && (count < 10)) {
> +			mdelay(500); /* 0.5 second delay */

Use msleep() for such a long delay.

> +			snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
> +				0x85, 0xc0, 0x0001, 0x0000, &bootresponse, 0x0012);
> +			if (bootresponse == MBOX2_BOOT_READY)
> +				break;
> +
> +			snd_printk("device not ready, resending boot sequence...\n");
> +			count++;
> +		}
> +
> +		if (bootresponse == MBOX2_BOOT_READY) {

The same as firwamre size check.  Handle the short error case and
abort here.  This reduces the indent level and improves the
readability much better -- you don't have to consider a too long
branching in your head while reading the code.

> +			snd_printk("device initialised!\n");

Isn't it a debug message?

> +
> +			err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
> +				&dev->descriptor, sizeof(dev->descriptor));
> +			config = dev->actconfig;
> +			if (err < 0)
> +				snd_printdd("error usb_get_descriptor: %d\n", err);
> +			err = usb_reset_configuration(dev);
> +			if (err < 0)
> +				snd_printdd("error usb_reset_configuration: %d\n", err);
> +			snd_printdd("mbox2_boot: new boot length = %d\n",
> +				le16_to_cpu(get_cfg_desc(config)->wTotalLength));
> +
> +			/* We want 48 kHz mode for now */
> +			enablemagic[0] = 0x80;
> +			enablemagic[1] = 0xbb;
> +			enablemagic[2] = 0x00;
> +
> +			/* Send the magic! */
> +			snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
> +				0x01, 0x22, 0x0100, 0x0085, &temp, 0x0003);
> +			snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +				0x81, 0xa2, 0x0100, 0x0085, &enablemagic, 0x0003);
> +			snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +				0x81, 0xa2, 0x0100, 0x0086, &enablemagic, 0x0003);
> +			snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +				0x81, 0xa2, 0x0100, 0x0003, &enablemagic, 0x0003);

The magic code is same as used in mbox2_skip_setting_quirk().
Move the code to a function and just call it from both places instead
of keeping two open codes.


thanks,

Takashi


More information about the Alsa-devel mailing list