All of lore.kernel.org
 help / color / mirror / Atom feed
* sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
@ 2010-11-24 12:59 Damien Zammit
  2010-11-25 21:39 ` Daniel Mack
  0 siblings, 1 reply; 27+ messages in thread
From: Damien Zammit @ 2010-11-24 12:59 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: alsa-devel

Hi folks,

I have put together full support for Digidesign Mbox 2, but it needs
someone to help me merge it into alsa.  I haven't seen the latest
snd-usb-audio code since last year, it seems to have branched into
multiple files.

I have worked out how the Digidesign Mbox 2 needs to be configured, it
supports SPDIF i/o simultaneously with analogue but can be toggled on
and off by using different altsettings.
Also the sample clock rate must be configured via a special method.

Therefore I have provided for this in a device_setup parameter with 4 settings:
48Khz Spdif+analog = 0
44.1Khz Spdif+analog = 1
48Khz Analog only = 2
44.1Khz Analog only = 3

###### audio

        /* Digidesign Mbox 2 workaround:
         * supports S24_3BE BIG ENDIAN in an unusual way */
        if (chip->usb_id == USB_ID(0x0dba, 0x3000))
            pcm_format = SNDRV_PCM_FORMAT_S24_3BE;

static int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
                                        int iface, int altno);
static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
{
 .....
.....
            /* Digidesign Mbox 2: skip altsets incompatible with device_setup
                 */
                if (chip->usb_id == USB_ID(0x0dba, 0x3000) &&
                    mbox2_skip_setting_quirk(chip, iface_no, altno))
                        continue;
.....
}


#define MBOX2_SET_48K_SPDIF            0
#define MBOX2_SET_44K_SPDIF            1
#define MBOX2_SET_48K_ANALOG           2
#define MBOX2_SET_44K_ANALOG           3

static int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
                                        int iface, int altno)
{
        u8 srate[3];
        /* Reset ifaces 2-5 to 0 altsetting. */
        usb_set_interface(chip->dev, iface, 0);

    if (device_setup[chip->index] == MBOX2_SET_48K_SPDIF ||
        device_setup[chip->index] == MBOX2_SET_48K_ANALOG) {
            //setup 48k
                        srate[0]=0x80;
                        srate[1]=0xbb;
                        srate[2]=0x00;

                        /* Send the magic! */
                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
                                0x01, 0x22, 0x0100, 0x0085, &srate,
0x0003, 1000);

                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
                                0x81, 0xa2, 0x0100, 0x0085, &srate,
0x0003, 1000);

                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
                                0x81, 0xa2, 0x0100, 0x0086, &srate,
0x0003, 1000);

                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
                                0x81, 0xa2, 0x0100, 0x0003, &srate,
0x0003, 1000);
            snd_printk(KERN_INFO "Digidesign Mbox 2: 24 Bit 48000Hz");
        if (device_setup[chip->index] == MBOX2_SET_48K_SPDIF) {
            //setup spdif
            snd_printk(KERN_INFO ", SPDIF\n");
            if (altno != 2) return 1;
        } else {
            //setup analog
            snd_printk(KERN_INFO ", ANALOGUE\n");
            if (altno != 3) return 1;
        }
    } else {
            //setup 44k
                        srate[0]=0x44;
                        srate[1]=0xac;
                        srate[2]=0x00;

                        /* Send the magic! */
                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
                                0x01, 0x22, 0x0100, 0x0085, &srate,
0x0003, 1000);

                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
                                0x81, 0xa2, 0x0100, 0x0085, &srate,
0x0003, 1000);

                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
                                0x81, 0xa2, 0x0100, 0x0086, &srate,
0x0003, 1000);

                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
                                0x81, 0xa2, 0x0100, 0x0003, &srate,
0x0003, 1000);

            snd_printk(KERN_INFO "Digidesign Mbox 2: 24 Bit 44100Hz");
                        if (device_setup[chip->index] == MBOX2_SET_44K_SPDIF ||
                        device_setup[chip->index] == MBOX2_SET_44K_ANALOG) {

            //setup spdif
            snd_printk(KERN_INFO ", SPDIF\n");
            if (altno != 2) return 1;
        } else {
            //setup analog
            snd_printk(KERN_INFO ", ANALOGUE\n");
            if (altno != 3) return 1;
        }
    }

    return 0;
}


#define MBOX2_FIRMWARE_SIZE    646
#define MBOX2_BOOT_LOADING     0x01 /* Hard coded into the device */
#define MBOX2_BOOT_READY       0x02 /* Hard coded into the device */

static int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
{
        struct usb_host_config *config = dev->actconfig;
        int err;
        u8 enablemagic[3];
        u8 bootresponse;
        int fwsize;

        if ((fwsize = le16_to_cpu(get_cfg_desc(config)->wTotalLength))
== MBOX2_FIRMWARE_SIZE) {
                snd_printdd("Sending Digidesign Mbox 2 boot sequence...\n");

                        /* From USB Snoop,
                         *
                         * SetupPacket = RT RQ VHVL INDX SIZE
                         * RT = 0xRT Request Type
                         * RQ = 0xRQ Request
                         * VHVL = 0xVLVH Value in reverse byte order
                         * INDX = 0xDXIN Index in reverse byte order
                         * SIZE = 0xZESI Size in reverse byte order
                         *
                         * Magic boot code setup packet: c0 85 01 00 00 00 12 00
                         *           RQ    RT    VLVH    DXIN
       ZESI
                         * becomes 0x85, 0xc0, 0x0001, 0x0000,
&RETURNDATA, 0x0012, TIMEOUT
                         * for snd_usb_ctl_msg()
                         */

mbox2_reboot:
                snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
                        0x85, 0xc0, 0x0001, 0x0000, &bootresponse,
0x0012, 1000);

                if (bootresponse == MBOX2_BOOT_LOADING) {
                        snd_printdd("device not ready, resending boot
sequence...\n");
                        goto mbox2_reboot;
                }

                if (bootresponse == MBOX2_BOOT_READY) {
                        snd_printdd("device initialised!\n");

                        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));

                        /* Successful boot, (should reset all
altsettings to 0 like windows does, but works without it)
                         * but now we will try sending
capture/playback enable magic
                         *
                         * 80 bb 00 = 24bit mode - S24_3BE
                         * 44 ac 00 = 16bit mode?
                         *
                         */

                        /* We want 48khz mode for now */
                        enablemagic[0]=0x80;
                        enablemagic[1]=0xbb;
                        enablemagic[2]=0x00;

                        /* Send the magic! */
                        snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
                                0x01, 0x22, 0x0100, 0x0085,
&enablemagic, 0x0003, 1000);

                        snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
                                0x81, 0xa2, 0x0100, 0x0085,
&enablemagic, 0x0003, 1000);

                        snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
                                0x81, 0xa2, 0x0100, 0x0086,
&enablemagic, 0x0003, 1000);

                        snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
                                0x81, 0xa2, 0x0100, 0x0003,
&enablemagic, 0x0003, 1000);

                        return 0; /* Succesful boot */
                }

                snd_printdd("unknown bootresponse, ignoring device:
%d\n",bootresponse);
                return -ENODEV;
        }
        snd_printk("Invalid firmware size: %d\n",fwsize);
        return -ENODEV;
}


#######   quirk:
{

       USB_DEVICE(0x0dba, 0x3000),
       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
               .vendor_name = "Digidesign",
               .product_name = "Mbox 2",
               .ifnum = QUIRK_ANY_INTERFACE,
               .type = QUIRK_COMPOSITE,
               .data = (const struct snd_usb_audio_quirk[]) {
                       {
                               .ifnum = 0,
                               .type = QUIRK_IGNORE_INTERFACE
                       },
                       {
                               .ifnum = 1,
                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
                       },
                       {
                               .ifnum = 2,
                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
                       },
                       {
                               .ifnum = 3,
                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
                       },
                       {
                                .ifnum = 4,
                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
                       },
                       {
                                .ifnum = 5,
                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
                       },
                       {
                               .ifnum = 6,
                               .type = QUIRK_MIDI_MBOX2,
                               .data = & (const struct
snd_usb_midi_endpoint_info) {
                                       .out_ep =  0x02,
                                       .out_cables = 0x0001,
                                       .in_ep = 0x81,
                                       .in_interval = 0x01,
                                       .in_cables = 0x0001
                               }

                       },
                       {
                               .ifnum = -1
                       }
               }
       }
},

##### midi

        case QUIRK_MIDI_MBOX2:
                /* Digidesign Mbox 2 uses MIDIMAN MIDI protocol */
                umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
                /*
                 * We have to make sure that the USB core looks
                 * again at interface 6 by calling usb_set_interface() on it.
                 */
                usb_set_interface(umidi->chip->dev, 6, 0);
                memcpy(&endpoints[0], quirk->data,
                       sizeof(struct snd_usb_midi_endpoint_info));
                err = 0;
                break;


Damien

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2010-11-24 12:59 sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2 Damien Zammit
@ 2010-11-25 21:39 ` Daniel Mack
  2010-11-29 13:03   ` Damien Zammit
  0 siblings, 1 reply; 27+ messages in thread
From: Daniel Mack @ 2010-11-25 21:39 UTC (permalink / raw)
  To: alsa-devel

On 11/24/2010 04:59 AM, Damien Zammit wrote:
> I have put together full support for Digidesign Mbox 2, but it needs
> someone to help me merge it into alsa.  I haven't seen the latest
> snd-usb-audio code since last year, it seems to have branched into
> multiple files.
> 
> I have worked out how the Digidesign Mbox 2 needs to be configured, it
> supports SPDIF i/o simultaneously with analogue but can be toggled on
> and off by using different altsettings.
> Also the sample clock rate must be configured via a special method.

Cool, thanks for sharing this.

Could you put your changes into a real patch, preferably generated by
git, and post it again please? That makes reviewing much easier.


Thanks,
Daniel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2010-11-25 21:39 ` Daniel Mack
@ 2010-11-29 13:03   ` Damien Zammit
  2010-11-29 14:50     ` Takashi Iwai
  0 siblings, 1 reply; 27+ messages in thread
From: Damien Zammit @ 2010-11-29 13:03 UTC (permalink / raw)
  To: Daniel Mack; +Cc: alsa-devel

Hi Daniel,

I am confused by the git repository of alsa.  There seems to be two
copies of it, one in alsa-kernel and one in alsa-driver.  alsa-driver
seems to "patch" the alsa-kernel and then build it.  I have taken one
of the latest snapshots of alsa-driver and modified the alsa-kernel
directory and it now compiles and the device works.  What do I
generate the patch against?

I can't be expected to fill in all the detail regarding #if
KERNEL_VERSION < .... etc I am not that familiar with the kernel.
What do you suggest to make your life easier for reviewing?

Thanks,
Damien

On Fri, Nov 26, 2010 at 8:39 AM, Daniel Mack <zonque@gmail.com> wrote:
> On 11/24/2010 04:59 AM, Damien Zammit wrote:
>> I have put together full support for Digidesign Mbox 2, but it needs
>> someone to help me merge it into alsa.  I haven't seen the latest
>> snd-usb-audio code since last year, it seems to have branched into
>> multiple files.
>>
>> I have worked out how the Digidesign Mbox 2 needs to be configured, it
>> supports SPDIF i/o simultaneously with analogue but can be toggled on
>> and off by using different altsettings.
>> Also the sample clock rate must be configured via a special method.
>
> Cool, thanks for sharing this.
>
> Could you put your changes into a real patch, preferably generated by
> git, and post it again please? That makes reviewing much easier.
>
>
> Thanks,
> Daniel
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2010-11-29 13:03   ` Damien Zammit
@ 2010-11-29 14:50     ` Takashi Iwai
  2010-11-30 11:09       ` Damien Zammit
  0 siblings, 1 reply; 27+ messages in thread
From: Takashi Iwai @ 2010-11-29 14:50 UTC (permalink / raw)
  To: Damien Zammit; +Cc: alsa-devel, Daniel Mack

At Tue, 30 Nov 2010 00:03:26 +1100,
Damien Zammit wrote:
> 
> Hi Daniel,
> 
> I am confused by the git repository of alsa.  There seems to be two
> copies of it, one in alsa-kernel and one in alsa-driver.  alsa-driver
> seems to "patch" the alsa-kernel and then build it.  I have taken one
> of the latest snapshots of alsa-driver and modified the alsa-kernel
> directory and it now compiles and the device works.  What do I
> generate the patch against?

You can use sound git repo below.
    git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git

Base on topic/misc branch or master branch.


Takashi

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2010-11-29 14:50     ` Takashi Iwai
@ 2010-11-30 11:09       ` Damien Zammit
  2010-11-30 15:26         ` Clemens Ladisch
  0 siblings, 1 reply; 27+ messages in thread
From: Damien Zammit @ 2010-11-30 11:09 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Daniel Mack

Hi all,

I have generated a patch against sound-2.6 git for the Digidesign Mbox 2.
I did a git commit -a and then git diff HEAD^1 to generate this patch.
Unfortunately I am sending this email from gmail, so I'm not sure
about line formatting, yikes.

Damien

diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 25bce7e..5dace7e 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -2122,6 +2122,18 @@ 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;
+		/*
+		 * We have to make sure that the USB core looks
+		 * again at interface 6 by calling usb_set_interface() on it.
+		 */
+		usb_set_interface(umidi->dev, 6, 0);
+		memcpy(&endpoints[0], quirk->data,
+			sizeof(struct snd_usb_midi_endpoint_info));
+		err = 0;
+		break;
 	case QUIRK_MIDI_RAW_BYTES:
 		umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
 		/*
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index ad7079d..f0b6520 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2477,6 +2477,60 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 },

+/* DIGIDESIGN MBOX 2 */
+{
+       /* Damien Zammit <damien.zammit@gmail.com> */
+
+       USB_DEVICE(0x0dba, 0x3000),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               .vendor_name = "Digidesign",
+               .product_name = "Mbox 2",
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 3,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                                .ifnum = 4,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                                .ifnum = 5,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 6,
+                               .type = QUIRK_MIDI_MBOX2,
+                               .data = & (const struct
snd_usb_midi_endpoint_info) {
+                                       .out_ep =  0x02,
+                                       .out_cables = 0x0001,
+                                       .in_ep = 0x81,
+                                       .in_interval = 0x01,
+                                       .in_cables = 0x0001
+                               }
+
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
+
 {
 	/*
 	 * Some USB MIDI devices don't have an audio control interface,
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index cf8bf08..d66a638 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -287,6 +287,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
 		[QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
 		[QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
 		[QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
+		[QUIRK_MIDI_MBOX2] = create_any_midi_quirk,
 		[QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,
 		[QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
 		[QUIRK_MIDI_CME] = create_any_midi_quirk,
@@ -479,6 +480,9 @@ int snd_usb_apply_interface_quirk(struct
snd_usb_audio *chip,
 	if (chip->usb_id == USB_ID(0x0763, 0x2003))
 		return audiophile_skip_setting_quirk(chip, iface, altno);

+	if (chip->usb_id == USB_ID(0x0dba, 0x3000))
+        	return mbox2_skip_setting_quirk(chip, iface, altno);
+
 	return 0;
 }

@@ -510,6 +514,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 	if (id == USB_ID(0x133e, 0x0815))
 		return snd_usb_accessmusic_boot_quirk(dev);

+	/* Digidesign Mbox 2 */
+	if (id == USB_ID(0x0dba, 0x3000))
+		return snd_usb_mbox2_boot_quirk(dev);
+
 	return 0;
 }

@@ -527,6 +535,9 @@ int snd_usb_is_big_endian_format(struct
snd_usb_audio *chip, struct audioformat
 		if (chip->setup == 0x00 ||
 		    fp->altsetting==1 || fp->altsetting==2 || fp->altsetting==3)
 			return 1;
+		break;	
+	case USB_ID(0x0dba, 0x3000): /* Digidesign Mbox 2 */
+		return 1;
 	}
 	return 0;
 }
@@ -594,3 +605,170 @@ void snd_usb_set_format_quirk(struct
snd_usb_substream *subs,
 	}
 }

+#define MBOX2_FIRMWARE_SIZE    646
+#define MBOX2_BOOT_LOADING     0x01 /* Hard coded into the device */
+#define MBOX2_BOOT_READY       0x02 /* Hard coded into the device */
+
+static int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
+{
+        struct usb_host_config *config = dev->actconfig;
+        int err;
+        u8 enablemagic[3];
+        u8 bootresponse;
+        int fwsize;
+
+        if ((fwsize =
le16_to_cpu(get_cfg_desc(config)->wTotalLength)) ==
MBOX2_FIRMWARE_SIZE) {
+                snd_printdd("Sending Digidesign Mbox 2 boot sequence...\n");
+
+                        /* From USB Snoop,
+                         *
+                         * SetupPacket = RT RQ VHVL INDX SIZE
+                         * RT = 0xRT Request Type
+                         * RQ = 0xRQ Request
+                         * VHVL = 0xVLVH Value in reverse byte order
+                         * INDX = 0xDXIN Index in reverse byte order
+                         * SIZE = 0xZESI Size in reverse byte order
+                         *
+                         * Magic boot code setup packet: c0 85 01 00
00 00 12 00
+                         *           RQ    RT    VLVH    DXIN
        ZESI
+                         * becomes 0x85, 0xc0, 0x0001, 0x0000,
&RETURNDATA, 0x0012, TIMEOUT
+                         * for snd_usb_ctl_msg()
+                         */
+
+mbox2_reboot:
+                snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
+                        0x85, 0xc0, 0x0001, 0x0000, &bootresponse,
0x0012, 1000);
+
+                if (bootresponse == MBOX2_BOOT_LOADING) {
+                        snd_printdd("device not ready, resending boot
sequence...\n");
+                        goto mbox2_reboot;
+                }
+
+                if (bootresponse == MBOX2_BOOT_READY) {
+                        snd_printdd("device initialised!\n");
+
+                        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));
+
+                        /* Successful boot, (should reset all
altsettings to 0 like windows does, but works without it)
+                         * but now we will try sending
capture/playback enable magic
+                         *
+                         * 80 bb 00 = 24bit mode - S24_3BE
+                         * 44 ac 00 = 16bit mode?
+                         *
+                         */
+                        //enablemagic[0]=0x44;
+                        //enablemagic[1]=0xac;
+                        //enablemagic[2]=0x00;
+
+                        /* 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_sndctrlpipe(dev, 0),
+                                0x01, 0x22, 0x0100, 0x0085,
&enablemagic, 0x0003, 1000);
+
+                        snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+                                0x81, 0xa2, 0x0100, 0x0085,
&enablemagic, 0x0003, 1000);
+
+                        snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+                                0x81, 0xa2, 0x0100, 0x0086,
&enablemagic, 0x0003, 1000);
+
+                        snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+                                0x81, 0xa2, 0x0100, 0x0003,
&enablemagic, 0x0003, 1000);
+
+                        return 0; /* Succesful boot */
+                }
+
+                snd_printdd("unknown bootresponse, ignoring device:
%d\n",bootresponse);
+                return -ENODEV;
+        }
+        snd_printk("Invalid firmware size: %d\n",fwsize);
+        return -ENODEV;
+}
+
+#define MBOX2_SET_48K_SPDIF            0
+#define MBOX2_SET_44K_SPDIF            1
+#define MBOX2_SET_48K_ANALOG           2
+#define MBOX2_SET_44K_ANALOG           3
+
+static int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
+                                        int iface, int altno)
+{
+        u8 srate[3];
+        /* Reset ifaces 2-5 to 0 altsetting. */
+        usb_set_interface(chip->dev, iface, 0);
+
+	if (chip->setup == MBOX2_SET_48K_SPDIF ||
+	    chip->setup == MBOX2_SET_48K_ANALOG) {
+			//setup 48k
+                        srate[0]=0x80;
+                        srate[1]=0xbb;
+                        srate[2]=0x00;
+
+                        /* Send the magic! */
+                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
+                                0x01, 0x22, 0x0100, 0x0085, &srate,
0x0003, 1000);
+
+                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
+                                0x81, 0xa2, 0x0100, 0x0085, &srate,
0x0003, 1000);
+
+                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
+                                0x81, 0xa2, 0x0100, 0x0086, &srate,
0x0003, 1000);
+
+                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
+                                0x81, 0xa2, 0x0100, 0x0003, &srate,
0x0003, 1000);
+			snd_printk(KERN_INFO "Digidesign Mbox 2: 24 Bit 48000Hz");
+		if (chip->setup == MBOX2_SET_48K_SPDIF) {
+			//setup spdif
+			snd_printk(KERN_INFO ", SPDIF\n");
+			if (altno != 2) return 1;
+		} else {
+			//setup analog
+			snd_printk(KERN_INFO ", ANALOGUE\n");
+			if (altno != 3) return 1;
+		}
+	} else {
+			//setup 44k
+                        srate[0]=0x44;
+                        srate[1]=0xac;
+                        srate[2]=0x00;
+
+                        /* Send the magic! */
+                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
+                                0x01, 0x22, 0x0100, 0x0085, &srate,
0x0003, 1000);
+
+                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
+                                0x81, 0xa2, 0x0100, 0x0085, &srate,
0x0003, 1000);
+
+                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
+                                0x81, 0xa2, 0x0100, 0x0086, &srate,
0x0003, 1000);
+
+                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
+                                0x81, 0xa2, 0x0100, 0x0003, &srate,
0x0003, 1000);
+		
+			snd_printk(KERN_INFO "Digidesign Mbox 2: 24 Bit 44100Hz");
+                        if (chip->setup == MBOX2_SET_44K_SPDIF ||
+	                    chip->setup == MBOX2_SET_44K_ANALOG) {
+
+			//setup spdif
+			snd_printk(KERN_INFO ", SPDIF\n");
+			if (altno != 2) return 1;
+		} else {
+			//setup analog
+			snd_printk(KERN_INFO ", ANALOGUE\n");
+			if (altno != 3) return 1;
+		}
+	}
+	return 0;
+}
+
+
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
index 03e5e94..13fd3ad 100644
--- a/sound/usb/quirks.h
+++ b/sound/usb/quirks.h
@@ -20,4 +20,9 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
 int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
 				 struct audioformat *fp);

+static int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
+                                       int iface, int altno);
+
+static int snd_usb_mbox2_boot_quirk(struct usb_device *dev);
+
 #endif /* __USBAUDIO_QUIRKS_H */
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index db3eb21..128c3f4 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -70,6 +70,7 @@ enum quirk_type {
 	QUIRK_MIDI_YAMAHA,
 	QUIRK_MIDI_MIDIMAN,
 	QUIRK_MIDI_NOVATION,
+	QUIRK_MIDI_MBOX2,
 	QUIRK_MIDI_RAW_BYTES,
 	QUIRK_MIDI_EMAGIC,
 	QUIRK_MIDI_CME,

On Tue, Nov 30, 2010 at 1:50 AM, Takashi Iwai <tiwai@suse.de> wrote:
> At Tue, 30 Nov 2010 00:03:26 +1100,
> Damien Zammit wrote:
>>
>> Hi Daniel,
>>
>> I am confused by the git repository of alsa.  There seems to be two
>> copies of it, one in alsa-kernel and one in alsa-driver.  alsa-driver
>> seems to "patch" the alsa-kernel and then build it.  I have taken one
>> of the latest snapshots of alsa-driver and modified the alsa-kernel
>> directory and it now compiles and the device works.  What do I
>> generate the patch against?
>
> You can use sound git repo below.
>    git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
>
> Base on topic/misc branch or master branch.
>
>
> Takashi
>

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2010-11-30 11:09       ` Damien Zammit
@ 2010-11-30 15:26         ` Clemens Ladisch
  2010-12-14  9:57           ` Damien Zammit
  0 siblings, 1 reply; 27+ messages in thread
From: Clemens Ladisch @ 2010-11-30 15:26 UTC (permalink / raw)
  To: Damien Zammit; +Cc: Takashi Iwai, alsa-devel, Daniel Mack

Damien Zammit wrote:
> Unfortunately I am sending this email from gmail, so I'm not sure
> about line formatting, yikes.

Long lines are wrapped.

> +		/*
> +		 * We have to make sure that the USB core looks
> +		 * again at interface 6 by calling usb_set_interface() on it.
> +		 */
> +		usb_set_interface(umidi->dev, 6, 0);

Why?  Is this another duplicate endpoint number?

> +		memcpy(&endpoints[0], quirk->data,
> +			sizeof(struct snd_usb_midi_endpoint_info));

I think you should be able to call snd_usbmidi_detect_per_port_endpoints
here.

> +/* DIGIDESIGN MBOX 2 */
> +{
> +       /* Damien Zammit <damien.zammit@gmail.com> */

This usually goes into the commit log.

> +       USB_DEVICE(0x0dba, 0x3000),

The entries are supposed to be ordered by their IDs.

> +                         * but now we will try sending
> capture/playback enable magic
> +                         *
> +                         * 80 bb 00 = 24bit mode - S24_3BE
> +                         * 44 ac 00 = 16bit mode?

Why the question mark?

> +                        //enablemagic[0]=0x44;
> +                        //enablemagic[1]=0xac;
> +                        //enablemagic[2]=0x00;

Why is this commented out?

> +#define MBOX2_SET_48K_SPDIF            0
> +#define MBOX2_SET_44K_SPDIF            1
> +#define MBOX2_SET_48K_ANALOG           2
> +#define MBOX2_SET_44K_ANALOG           3

In theory, this should be some control instead of a module parameter.

> +static int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
> +                                        int iface, int altno)

This function isn't consistently indented with tabs.


Regards,
Clemens

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2010-11-30 15:26         ` Clemens Ladisch
@ 2010-12-14  9:57           ` Damien Zammit
  2010-12-27 14:50             ` Damien Zammit
  0 siblings, 1 reply; 27+ messages in thread
From: Damien Zammit @ 2010-12-14  9:57 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: Takashi Iwai, alsa-devel, Daniel Mack

My previous patch did not enable capture, this patch works and duplex
mode is flawless.

diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 25bce7e..5dace7e 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -2122,6 +2122,18 @@ 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;
+		/*
+		 * We have to make sure that the USB core looks
+		 * again at interface 6 by calling usb_set_interface() on it.
+		 */
+		usb_set_interface(umidi->dev, 6, 0);
+		memcpy(&endpoints[0], quirk->data,
+			sizeof(struct snd_usb_midi_endpoint_info));
+		err = 0;
+		break;
 	case QUIRK_MIDI_RAW_BYTES:
 		umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
 		/*
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index ad7079d..2ea3636 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2477,6 +2477,58 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 },

+/* DIGIDESIGN MBOX 2 */
+{
+       USB_DEVICE(0x0dba, 0x3000),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               .vendor_name = "Digidesign",
+               .product_name = "Mbox 2",
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 3,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                                .ifnum = 4,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                                .ifnum = 5,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 6,
+                               .type = QUIRK_MIDI_MBOX2,
+                               .data = & (const struct
snd_usb_midi_endpoint_info) {
+                                       .out_ep =  0x02,
+                                       .out_cables = 0x0001,
+                                       .in_ep = 0x81,
+                                       .in_interval = 0x01,
+                                       .in_cables = 0x0001
+                               }
+
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
+
 {
 	/*
 	 * Some USB MIDI devices don't have an audio control interface,
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index cf8bf08..fe4b8e2 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -287,6 +287,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
 		[QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
 		[QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
 		[QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
+		[QUIRK_MIDI_MBOX2] = create_any_midi_quirk,
 		[QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,
 		[QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
 		[QUIRK_MIDI_CME] = create_any_midi_quirk,
@@ -479,6 +480,9 @@ int snd_usb_apply_interface_quirk(struct
snd_usb_audio *chip,
 	if (chip->usb_id == USB_ID(0x0763, 0x2003))
 		return audiophile_skip_setting_quirk(chip, iface, altno);

+	if (chip->usb_id == USB_ID(0x0dba, 0x3000))
+        	return mbox2_skip_setting_quirk(chip, iface, altno);
+
 	return 0;
 }

@@ -510,6 +514,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 	if (id == USB_ID(0x133e, 0x0815))
 		return snd_usb_accessmusic_boot_quirk(dev);

+	/* Digidesign Mbox 2 */
+	if (id == USB_ID(0x0dba, 0x3000))
+		return snd_usb_mbox2_boot_quirk(dev);
+
 	return 0;
 }

@@ -527,6 +535,9 @@ int snd_usb_is_big_endian_format(struct
snd_usb_audio *chip, struct audioformat
 		if (chip->setup == 0x00 ||
 		    fp->altsetting==1 || fp->altsetting==2 || fp->altsetting==3)
 			return 1;
+		break;	
+	case USB_ID(0x0dba, 0x3000): /* Digidesign Mbox 2 */
+		return 1;
 	}
 	return 0;
 }
@@ -594,3 +605,170 @@ void snd_usb_set_format_quirk(struct
snd_usb_substream *subs,
 	}
 }

+#define MBOX2_FIRMWARE_SIZE    646
+#define MBOX2_BOOT_LOADING     0x01 /* Hard coded into the device */
+#define MBOX2_BOOT_READY       0x02 /* Hard coded into the device */
+
+static 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;
+
+        if ((fwsize =
le16_to_cpu(get_cfg_desc(config)->wTotalLength)) ==
MBOX2_FIRMWARE_SIZE) {
+                snd_printdd("Sending Digidesign Mbox 2 boot sequence...\n");
+
+                        /* From USB Snoop,
+                         *
+                         * SetupPacket = RT RQ VHVL INDX SIZE
+                         * RT = 0xRT Request Type
+                         * RQ = 0xRQ Request
+                         * VHVL = 0xVLVH Value in reverse byte order
+                         * INDX = 0xDXIN Index in reverse byte order
+                         * SIZE = 0xZESI Size in reverse byte order
+                         *
+                         * Magic boot code setup packet: c0 85 01 00
00 00 12 00
+                         *           RQ    RT    VLVH    DXIN
        ZESI
+                         * becomes 0x85, 0xc0, 0x0001, 0x0000,
&RETURNDATA, 0x0012, TIMEOUT
+                         * for snd_usb_ctl_msg()
+                         */
+
+mbox2_reboot:
+                snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
+                        0x85, 0xc0, 0x0001, 0x0000, &bootresponse,
0x0012, 1000);
+
+                if (bootresponse == MBOX2_BOOT_LOADING) {
+                        snd_printdd("device not ready, resending boot
sequence...\n");
+                        goto mbox2_reboot;
+                }
+
+                if (bootresponse == MBOX2_BOOT_READY) {
+                        snd_printdd("device initialised!\n");
+
+                        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));
+
+                        /* Successful boot, (should reset all
altsettings to 0 like windows does, but works without it)
+                         * but now we will try sending
capture/playback enable magic
+                         *
+                         * 80 bb 00 = 48kHz
+                         * 44 ac 00 = 44.1kHz
+                         *
+                         */
+                        /* 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, 1000);
+
+                        snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+                                0x81, 0xa2, 0x0100, 0x0085,
&enablemagic, 0x0003, 1000);
+
+                        snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+                                0x81, 0xa2, 0x0100, 0x0086,
&enablemagic, 0x0003, 1000);
+
+                        snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+                                0x81, 0xa2, 0x0100, 0x0003,
&enablemagic, 0x0003, 1000);
+
+                        return 0; /* Succesful boot */
+                }
+
+                snd_printdd("unknown bootresponse, ignoring device:
%d\n",bootresponse);
+                return -ENODEV;
+        }
+        snd_printk("Invalid firmware size: %d\n",fwsize);
+        return -ENODEV;
+}
+
+#define MBOX2_SET_48K_SPDIF            0
+#define MBOX2_SET_44K_SPDIF            1
+#define MBOX2_SET_48K_ANALOG           2
+#define MBOX2_SET_44K_ANALOG           3
+
+static int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
+                                        int iface, int altno)
+{
+        u8 srate[3];
+        u8 temp[12];
+
+        /* Reset ifaces 2-5 to 0 altsetting. */
+        usb_set_interface(chip->dev, iface, 0);
+
+        if (chip->setup == MBOX2_SET_48K_SPDIF ||
+            chip->setup == MBOX2_SET_48K_ANALOG) {
+                //setup 48k
+                srate[0]=0x80;
+                srate[1]=0xbb;
+                srate[2]=0x00;
+
+                /* Send the magic! */
+                snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
+                        0x01, 0x22, 0x0100, 0x0085, &temp, 0x0003, 1000);
+
+                snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+                        0x81, 0xa2, 0x0100, 0x0085, &srate, 0x0003, 1000);
+
+                snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+                        0x81, 0xa2, 0x0100, 0x0086, &srate, 0x0003, 1000);
+
+                snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+                        0x81, 0xa2, 0x0100, 0x0003, &srate, 0x0003, 1000);
+
+		snd_printk(KERN_INFO "Digidesign Mbox 2: 24 Bit 48000Hz");
+
+                if (chip->setup == MBOX2_SET_48K_SPDIF) {
+                        //setup spdif
+                        snd_printk(KERN_INFO ", SPDIF\n");
+                        if (altno != 2) return 1;
+                } else {
+                        //setup analog
+                        snd_printk(KERN_INFO ", ANALOGUE\n");
+                        if (altno != 3) return 1;
+                }
+        } else {
+                //setup 44k
+                srate[0]=0x44;
+                srate[1]=0xac;
+                srate[2]=0x00;
+
+                /* Send the magic! */
+                snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
+                        0x01, 0x22, 0x0100, 0x0085, &temp, 0x0003, 1000);
+
+                snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+                        0x81, 0xa2, 0x0100, 0x0085, &srate, 0x0003, 1000);
+
+                snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+                        0x81, 0xa2, 0x0100, 0x0086, &srate, 0x0003, 1000);
+
+                snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+                        0x81, 0xa2, 0x0100, 0x0003, &srate, 0x0003, 1000);
+
+                snd_printk(KERN_INFO "Digidesign Mbox 2: 24 Bit 44100Hz");
+                if (chip->setup == MBOX2_SET_44K_SPDIF ||
+	            chip->setup == MBOX2_SET_44K_ANALOG) {
+                        //setup spdif
+                        snd_printk(KERN_INFO ", SPDIF\n");
+                        if (altno != 2) return 1;
+                } else {
+                        //setup analog
+                        snd_printk(KERN_INFO ", ANALOGUE\n");
+                        if (altno != 3) return 1;
+                }
+        }
+        return 0;
+}
+
+
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
index 03e5e94..13fd3ad 100644
--- a/sound/usb/quirks.h
+++ b/sound/usb/quirks.h
@@ -20,4 +20,9 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
 int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
 				 struct audioformat *fp);

+static int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
+                                       int iface, int altno);
+
+static int snd_usb_mbox2_boot_quirk(struct usb_device *dev);
+
 #endif /* __USBAUDIO_QUIRKS_H */
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index db3eb21..128c3f4 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -70,6 +70,7 @@ enum quirk_type {
 	QUIRK_MIDI_YAMAHA,
 	QUIRK_MIDI_MIDIMAN,
 	QUIRK_MIDI_NOVATION,
+	QUIRK_MIDI_MBOX2,
 	QUIRK_MIDI_RAW_BYTES,
 	QUIRK_MIDI_EMAGIC,
 	QUIRK_MIDI_CME,


On Wed, Dec 1, 2010 at 2:26 AM, Clemens Ladisch <clemens@ladisch.de> wrote:
> Damien Zammit wrote:
>> Unfortunately I am sending this email from gmail, so I'm not sure
>> about line formatting, yikes.
>
> Long lines are wrapped.
>
>> +             /*
>> +              * We have to make sure that the USB core looks
>> +              * again at interface 6 by calling usb_set_interface() on it.
>> +              */
>> +             usb_set_interface(umidi->dev, 6, 0);
>
> Why?  Is this another duplicate endpoint number?
>
>> +             memcpy(&endpoints[0], quirk->data,
>> +                     sizeof(struct snd_usb_midi_endpoint_info));
>
> I think you should be able to call snd_usbmidi_detect_per_port_endpoints
> here.
>
>> +/* DIGIDESIGN MBOX 2 */
>> +{
>> +       /* Damien Zammit <damien.zammit@gmail.com> */
>
> This usually goes into the commit log.
>
>> +       USB_DEVICE(0x0dba, 0x3000),
>
> The entries are supposed to be ordered by their IDs.
>
>> +                         * but now we will try sending
>> capture/playback enable magic
>> +                         *
>> +                         * 80 bb 00 = 24bit mode - S24_3BE
>> +                         * 44 ac 00 = 16bit mode?
>
> Why the question mark?
>
>> +                        //enablemagic[0]=0x44;
>> +                        //enablemagic[1]=0xac;
>> +                        //enablemagic[2]=0x00;
>
> Why is this commented out?
>
>> +#define MBOX2_SET_48K_SPDIF            0
>> +#define MBOX2_SET_44K_SPDIF            1
>> +#define MBOX2_SET_48K_ANALOG           2
>> +#define MBOX2_SET_44K_ANALOG           3
>
> In theory, this should be some control instead of a module parameter.
>
>> +static int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
>> +                                        int iface, int altno)
>
> This function isn't consistently indented with tabs.
>
>
> Regards,
> Clemens
>

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2010-12-14  9:57           ` Damien Zammit
@ 2010-12-27 14:50             ` Damien Zammit
  2012-12-13  6:21               ` Damien Zammit
  0 siblings, 1 reply; 27+ messages in thread
From: Damien Zammit @ 2010-12-27 14:50 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: Takashi Iwai, alsa-devel, Daniel Mack

> On Wed, Dec 1, 2010 at 2:26 AM, Clemens Ladisch <clemens@ladisch.de> wrote:
>> Damien Zammit wrote:
>>> Unfortunately I am sending this email from gmail, so I'm not sure
>>> about line formatting, yikes.
>>
>> Long lines are wrapped.

Not much i can do about that, i dont have a plain text email client.

>>
>>> +             /*
>>> +              * We have to make sure that the USB core looks
>>> +              * again at interface 6 by calling usb_set_interface() on it.
>>> +              */
>>> +             usb_set_interface(umidi->dev, 6, 0);
>>
>> Why?  Is this another duplicate endpoint number?

The windows driver did this, and it doesn't work unless this code is here.

>>
>>> +             memcpy(&endpoints[0], quirk->data,
>>> +                     sizeof(struct snd_usb_midi_endpoint_info));
>>
>> I think you should be able to call snd_usbmidi_detect_per_port_endpoints
>> here.

Can you explain this a bit further, i'm not sure what this means.


>>
>>> +/* DIGIDESIGN MBOX 2 */
>>> +{
>>> +       /* Damien Zammit <damien.zammit@gmail.com> */
>>
>> This usually goes into the commit log.

I removed this from my patch

>>
>>> +       USB_DEVICE(0x0dba, 0x3000),
>>
>> The entries are supposed to be ordered by their IDs.
>>

I put this in order

>>> +                         * but now we will try sending
>>> capture/playback enable magic
>>> +                         *
>>> +                         * 80 bb 00 = 24bit mode - S24_3BE
>>> +                         * 44 ac 00 = 16bit mode?
>>
>> Why the question mark?

These are actually old comments which are irrelevant, i have removed this.

>>
>>> +                        //enablemagic[0]=0x44;
>>> +                        //enablemagic[1]=0xac;
>>> +                        //enablemagic[2]=0x00;
>>
>> Why is this commented out?
>>

Again, i was testing different sample rates, this is unnecessary and
has been removed.

>>> +#define MBOX2_SET_48K_SPDIF            0
>>> +#define MBOX2_SET_44K_SPDIF            1
>>> +#define MBOX2_SET_48K_ANALOG           2
>>> +#define MBOX2_SET_44K_ANALOG           3
>>
>> In theory, this should be some control instead of a module parameter.

I have removed support for spdif mode because the rest of the driver
doesnt support sending the full spdif frames anyway.

>>
>>> +static int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
>>> +                                        int iface, int altno)
>>
>> This function isn't consistently indented with tabs.
>>

I fixed the tab indentation


Clemens wrote last year:
>> +mbox2_reboot:
>> +                snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
>> +                        0x85, 0xc0, 0x0001, 0x0000, &bootresponse, 0x0012, 1000);
>> +
>> +                if (bootresponse == MBOX2_BOOT_LOADING) {
>> +                        snd_printdd("device not ready, resending boot sequence...\n");
>> +                        goto mbox2_reboot;
>> +                }

>This could be made a loop.  And it could run infinitely long; maybe you
>should add a timeout.  (How long does it usually need?)

Can you help me write a loop with a timeout that is RT safe? I don't
know how to "sleep" for say 300ms in a safe way for all kernel
versions.  The device responds before 5 seconds from zero power to
bootup.

I am eager to get support into the kernel for this device because it
is very popular among audio enthusiasts.
SPDIF isnt all that important i think, but I made duplex mode work a
few weeks ago and could just enable that by default without the
device_setup parameter if that is preferred by the kernel developers.

Damien

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2010-12-27 14:50             ` Damien Zammit
@ 2012-12-13  6:21               ` Damien Zammit
  2012-12-13  7:01                 ` Takashi Iwai
  0 siblings, 1 reply; 27+ messages in thread
From: Damien Zammit @ 2012-12-13  6:21 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: Takashi Iwai, alsa-devel, Daniel Mack

Hi I thought I would post an update on this thread.
I realise it is quite old but what I have now is relevant.

/*
 * Digidesign Mbox 2
 *
 * Interface list:
 * 0    Firmware
 * 1    Control
 * 2    Playback        (Async)
 * 3    IEC958                  (Ignore)
 * 4    Record          (Sync)
 * 5    Record          (Async) (Ignore)
 * 6    MIDI
 *
 */

My previous posts may have demonstrated a lack of understanding of how
USB audio devices work, but I believe I have learnt a bit more since
last time I posted.

I have determined that there is a combination of altsettings for this
device that allows hardcoding of them and still provides duplex
support, ie, the fact that it supports multiple endpoints is
irrelevant.
If you use interfaces 2 and 4 both with #2 altsetting, hardcode the
samplerate to 48000Hz (max) and the bit depth at 24 (max) and send
some control magic to set it up, it works great!

It also requires a boot quirk to load firmware into the device from an
onboard memory chip.  I determined the control sequence to do so but
it also needs a 3 second delay while the firmware activates and I dont
have the knowledge to do a proper in-kernel delay.

In summary there are 3 parts to make this device work:
1) Boot quirk - load firmware and wait 3 seconds
2) Set up samplerate/bitrate in the device once and force S24_3BE format.
3) Select interfaces 2 and 4 both with altsetting 2, and interface 6 for midi.

I can provide working code for all three steps (except the waiting
part is dodgey).  I can't submit a proper patch.  I hope we can get
this accepted into your alsa usb driver soon because maintaining a
small quirk is time consuming for me.  I don't feel right cloning your
entire code and attaching a tiny quirk to it and releasing it on my
website for others, but so far it's the only way people have been able
to use this device in linux.  I have about 200 valid comments on my
blog post about it.

Here is the quirk part:

{
	USB_DEVICE(0x0dba, 0x3000),
	.driver_info = (unsigned long) & (const struct snd_mbox2_quirk) {
		.vendor_name = "Digidesign",
		.product_name = "Mbox 2",
		.ifnum = QUIRK_ANY_INTERFACE,
		.type = QUIRK_COMPOSITE,
		.data = (const struct snd_mbox2_quirk[]) {
			{
				.ifnum = 0,
				.type = QUIRK_IGNORE_INTERFACE
			},
			{
				.ifnum = 1,
				.type = QUIRK_IGNORE_INTERFACE
			},
			{
				.ifnum = 2,
				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
				.data = & (const struct audioformat) {
					.formats = SNDRV_PCM_FMTBIT_S24_3BE,
					.channels = 2,
					.iface = 2,
					.altsetting = 2,
					.altset_idx = 1,
					.attributes = 0x00,
					.endpoint = 0x03,
					.ep_attr = USB_ENDPOINT_SYNC_ASYNC,
					.maxpacksize = 0x128,
					.rates = SNDRV_PCM_RATE_48000,
					.rate_min = 48000,
					.rate_max = 48000,
					.nr_rates = 1,
					.rate_table = (unsigned int[]) {
						48000
					}
				}
			},
			{
				.ifnum = 3,
				.type = QUIRK_IGNORE_INTERFACE
			},
			{
				.ifnum = 4,
				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
                               	.data = & (const struct audioformat) {
                                        .formats = SNDRV_PCM_FMTBIT_S24_3BE,
                                        .channels = 2,
                                        .iface = 4,
                                        .altsetting = 2,
                                        .altset_idx = 1,
                                        .attributes =
UAC_EP_CS_ATTR_SAMPLE_RATE,
                                        .endpoint = 0x85,
                                        .ep_attr = USB_ENDPOINT_SYNC_SYNC,
                                        .maxpacksize = 0x128,
                                        .rates = SNDRV_PCM_RATE_48000,
                                        .rate_min = 48000,
                                        .rate_max = 48000,
                                        .nr_rates = 1,
                                        .rate_table = (unsigned int[]) {
                                                48000
                                        }
                                }
			},
			{
				.ifnum = 5,
				.type = QUIRK_IGNORE_INTERFACE
			},
			{
				.ifnum = 6,
				.type = QUIRK_MIDI_MBOX2,
				.data = & (const struct snd_usb_midi_endpoint_info) {
					.out_ep =  0x02,
					.out_cables = 0x0001,
					.in_ep = 0x81,
					.in_interval = 0x01,
					.in_cables = 0x0001
				}
			},
			{
				.ifnum = -1
			}
		}
	}
},

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2012-12-13  6:21               ` Damien Zammit
@ 2012-12-13  7:01                 ` Takashi Iwai
  2012-12-13 13:09                   ` Damien Zammit
  0 siblings, 1 reply; 27+ messages in thread
From: Takashi Iwai @ 2012-12-13  7:01 UTC (permalink / raw)
  To: Damien Zammit; +Cc: alsa-devel, Clemens Ladisch, Daniel Mack

At Thu, 13 Dec 2012 17:21:55 +1100,
Damien Zammit wrote:
> 
> Hi I thought I would post an update on this thread.
> I realise it is quite old but what I have now is relevant.
> 
> /*
>  * Digidesign Mbox 2
>  *
>  * Interface list:
>  * 0    Firmware
>  * 1    Control
>  * 2    Playback        (Async)
>  * 3    IEC958                  (Ignore)
>  * 4    Record          (Sync)
>  * 5    Record          (Async) (Ignore)
>  * 6    MIDI
>  *
>  */
> 
> My previous posts may have demonstrated a lack of understanding of how
> USB audio devices work, but I believe I have learnt a bit more since
> last time I posted.
> 
> I have determined that there is a combination of altsettings for this
> device that allows hardcoding of them and still provides duplex
> support, ie, the fact that it supports multiple endpoints is
> irrelevant.
> If you use interfaces 2 and 4 both with #2 altsetting, hardcode the
> samplerate to 48000Hz (max) and the bit depth at 24 (max) and send
> some control magic to set it up, it works great!
> 
> It also requires a boot quirk to load firmware into the device from an
> onboard memory chip.  I determined the control sequence to do so but
> it also needs a 3 second delay while the firmware activates and I dont
> have the knowledge to do a proper in-kernel delay.
> 
> In summary there are 3 parts to make this device work:
> 1) Boot quirk - load firmware and wait 3 seconds
> 2) Set up samplerate/bitrate in the device once and force S24_3BE format.
> 3) Select interfaces 2 and 4 both with altsetting 2, and interface 6 for midi.
> 
> I can provide working code for all three steps (except the waiting
> part is dodgey).  I can't submit a proper patch.

Why not...?


Takashi

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2012-12-13  7:01                 ` Takashi Iwai
@ 2012-12-13 13:09                   ` Damien Zammit
  2012-12-13 13:18                     ` Takashi Iwai
  0 siblings, 1 reply; 27+ messages in thread
From: Damien Zammit @ 2012-12-13 13:09 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Clemens Ladisch, Daniel Mack

[-- Attachment #1: Type: text/plain, Size: 9173 bytes --]

Here is a patch based on for-next that does the job.

I haven't tested this particular merge on the hardware because I would
have to recompile the whole kernel, but it does compile without
warnings out of tree, and I haven't changed anything much from my
version other than semantics to make it fit with your newer code.

Please find attached the actual patch in case gmail wraps my lines.


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;
 	case QUIRK_MIDI_RAW_BYTES:
 		umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
 		/*
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 49f9af9..dde20f4 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -3078,6 +3078,93 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 },

+/* DIGIDESIGN MBOX 2 */
+{
+	USB_DEVICE(0x0dba, 0x3000),
+	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+		.vendor_name = "Digidesign",
+		.product_name = "Mbox 2",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = & (const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S24_3BE,
+					.channels = 2,
+					.iface = 2,
+					.altsetting = 2,
+					.altset_idx = 1,
+					.attributes = 0x00,
+					.endpoint = 0x03,
+					.ep_attr = USB_ENDPOINT_SYNC_ASYNC,
+					.maxpacksize = 0x128,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 3,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 4,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               	.data = & (const struct audioformat) {
+                                        .formats = SNDRV_PCM_FMTBIT_S24_3BE,
+                                        .channels = 2,
+                                        .iface = 4,
+                                        .altsetting = 2,
+                                        .altset_idx = 1,
+                                        .attributes =
UAC_EP_CS_ATTR_SAMPLE_RATE,
+                                        .endpoint = 0x85,
+                                        .ep_attr = USB_ENDPOINT_SYNC_SYNC,
+                                        .maxpacksize = 0x128,
+                                        .rates = SNDRV_PCM_RATE_48000,
+                                        .rate_min = 48000,
+                                        .rate_max = 48000,
+                                        .nr_rates = 1,
+                                        .rate_table = (unsigned int[]) {
+                                                48000
+                                        }
+                                }
+			},
+			{
+				.ifnum = 5,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 6,
+				.type = QUIRK_MIDI_MBOX2,
+				.data = & (const struct snd_usb_midi_endpoint_info) {
+					.out_ep =  0x02,
+					.out_cables = 0x0001,
+					.in_ep = 0x81,
+					.in_interval = 0x01,
+					.in_cables = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
+
 {
 	/*
 	 * Some USB MIDI devices don't have an audio control interface,
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 0f58b4b..9803962 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -306,6 +306,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
 		[QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
 		[QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
 		[QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
+		[QUIRK_MIDI_MBOX2] = create_any_midi_quirk,
 		[QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,
 		[QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
 		[QUIRK_MIDI_CME] = create_any_midi_quirk,
@@ -655,6 +656,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 	case USB_ID(0x0ccd, 0x00b1): /* Terratec Aureon 7.1 USB */
 		return snd_usb_cm6206_boot_quirk(dev);

+	case USB_ID(0x0dba, 0x3000):
+		/* Digidesign Mbox 2 */
+		return snd_usb_mbox2_boot_quirk(dev);
+
 	case USB_ID(0x133e, 0x0815):
 		/* Access Music VirusTI Desktop */
 		return snd_usb_accessmusic_boot_quirk(dev);
@@ -761,6 +766,107 @@ void snd_usb_set_format_quirk(struct
snd_usb_substream *subs,
 	}
 }

+/* Digidesign Mbox 2 needs to load firmware onboard
+ * and driver must wait a few seconds for initialisation.
+ */
+
+#define MBOX2_FIRMWARE_SIZE    646
+#define MBOX2_BOOT_LOADING     0x01 /* Hard coded into the device */
+#define MBOX2_BOOT_READY       0x02 /* Hard coded into the device */
+
+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;
+
+	if ((fwsize = le16_to_cpu(get_cfg_desc(config)->wTotalLength)) ==
MBOX2_FIRMWARE_SIZE) {
+		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 */
+			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) {
+			snd_printk("device initialised!\n");
+
+			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);
+			snd_printk(KERN_INFO "Digidesign Mbox 2: 24 Bit 48kHz Analogue");
+
+			return 0; /* Succesful boot */
+		}
+
+		snd_printk("Unknown bootresponse, or timed out, ignoring device:
%d\n",bootresponse);
+		return -ENODEV;
+	}
+	snd_printk("Invalid firmware size: %d\n",fwsize);
+	return -ENODEV;
+}
+
+int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
+					int iface, int altno)
+{
+	u8 srate[3];
+	u8 temp[12];
+
+	/* Reset ifaces 2,4 to 0 altsetting like the Windows driver does */
+	usb_set_interface(chip->dev, iface, 0);
+
+	/* Choose 48000Hz permanently */
+	srate[0]=0x80;
+	srate[1]=0xbb;
+	srate[2]=0x00;
+
+	/* Send the magic! */
+	snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
+		0x01, 0x22, 0x0100, 0x0085, &temp, 0x0003);
+	snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+		0x81, 0xa2, 0x0100, 0x0085, &srate, 0x0003);
+	snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+		0x81, 0xa2, 0x0100, 0x0086, &srate, 0x0003);
+	snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+		0x81, 0xa2, 0x0100, 0x0003, &srate, 0x0003);
+
+	if (altno != 3) return 1;
+
+	return 0;
+}
+
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
 {
 	/*
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
index 0ca9e91..087a5b6 100644
--- a/sound/usb/quirks.h
+++ b/sound/usb/quirks.h
@@ -24,6 +24,11 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
 int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
 				 struct audioformat *fp);

+int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
+				    int iface, int altno);
+
+int snd_usb_mbox2_boot_quirk(struct usb_device *dev);
+
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep);

 void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 1ac3fd9..a8172c1 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -76,6 +76,7 @@ enum quirk_type {
 	QUIRK_MIDI_YAMAHA,
 	QUIRK_MIDI_MIDIMAN,
 	QUIRK_MIDI_NOVATION,
+	QUIRK_MIDI_MBOX2,
 	QUIRK_MIDI_RAW_BYTES,
 	QUIRK_MIDI_EMAGIC,
 	QUIRK_MIDI_CME,

[-- Attachment #2: patch_for-next_dz.txt --]
[-- Type: text/plain, Size: 8787 bytes --]

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;
 	case QUIRK_MIDI_RAW_BYTES:
 		umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
 		/*
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 49f9af9..dde20f4 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -3078,6 +3078,93 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 },
 
+/* DIGIDESIGN MBOX 2 */
+{
+	USB_DEVICE(0x0dba, 0x3000),
+	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+		.vendor_name = "Digidesign",
+		.product_name = "Mbox 2",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = & (const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S24_3BE,
+					.channels = 2,
+					.iface = 2,
+					.altsetting = 2,
+					.altset_idx = 1,
+					.attributes = 0x00,
+					.endpoint = 0x03,
+					.ep_attr = USB_ENDPOINT_SYNC_ASYNC,
+					.maxpacksize = 0x128,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 3,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 4,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               	.data = & (const struct audioformat) {
+                                        .formats = SNDRV_PCM_FMTBIT_S24_3BE,
+                                        .channels = 2,
+                                        .iface = 4,
+                                        .altsetting = 2,
+                                        .altset_idx = 1,
+                                        .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+                                        .endpoint = 0x85,
+                                        .ep_attr = USB_ENDPOINT_SYNC_SYNC,
+                                        .maxpacksize = 0x128,
+                                        .rates = SNDRV_PCM_RATE_48000,
+                                        .rate_min = 48000,
+                                        .rate_max = 48000,
+                                        .nr_rates = 1,
+                                        .rate_table = (unsigned int[]) {
+                                                48000
+                                        }
+                                }
+			},
+			{
+				.ifnum = 5,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 6,
+				.type = QUIRK_MIDI_MBOX2,
+				.data = & (const struct snd_usb_midi_endpoint_info) {
+					.out_ep =  0x02,
+					.out_cables = 0x0001,
+					.in_ep = 0x81,
+					.in_interval = 0x01,
+					.in_cables = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
+
 {
 	/*
 	 * Some USB MIDI devices don't have an audio control interface,
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 0f58b4b..9803962 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -306,6 +306,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
 		[QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
 		[QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
 		[QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
+		[QUIRK_MIDI_MBOX2] = create_any_midi_quirk,
 		[QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,
 		[QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
 		[QUIRK_MIDI_CME] = create_any_midi_quirk,
@@ -655,6 +656,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 	case USB_ID(0x0ccd, 0x00b1): /* Terratec Aureon 7.1 USB */
 		return snd_usb_cm6206_boot_quirk(dev);
 
+	case USB_ID(0x0dba, 0x3000):
+		/* Digidesign Mbox 2 */
+		return snd_usb_mbox2_boot_quirk(dev);
+
 	case USB_ID(0x133e, 0x0815):
 		/* Access Music VirusTI Desktop */
 		return snd_usb_accessmusic_boot_quirk(dev);
@@ -761,6 +766,107 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
 	}
 }
 
+/* Digidesign Mbox 2 needs to load firmware onboard 
+ * and driver must wait a few seconds for initialisation.
+ */
+
+#define MBOX2_FIRMWARE_SIZE    646
+#define MBOX2_BOOT_LOADING     0x01 /* Hard coded into the device */
+#define MBOX2_BOOT_READY       0x02 /* Hard coded into the device */
+
+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;
+
+	if ((fwsize = le16_to_cpu(get_cfg_desc(config)->wTotalLength)) == MBOX2_FIRMWARE_SIZE) {
+		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 */
+			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) {
+			snd_printk("device initialised!\n");
+
+			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);
+			snd_printk(KERN_INFO "Digidesign Mbox 2: 24 Bit 48kHz Analogue");
+
+			return 0; /* Succesful boot */
+		}
+
+		snd_printk("Unknown bootresponse, or timed out, ignoring device: %d\n",bootresponse);
+		return -ENODEV;
+	}
+	snd_printk("Invalid firmware size: %d\n",fwsize);
+	return -ENODEV;
+}
+
+int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
+					int iface, int altno)
+{
+	u8 srate[3];
+	u8 temp[12];
+
+	/* Reset ifaces 2,4 to 0 altsetting like the Windows driver does */
+	usb_set_interface(chip->dev, iface, 0);
+
+	/* Choose 48000Hz permanently */
+	srate[0]=0x80;
+	srate[1]=0xbb;
+	srate[2]=0x00;
+
+	/* Send the magic! */
+	snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
+		0x01, 0x22, 0x0100, 0x0085, &temp, 0x0003);
+	snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+		0x81, 0xa2, 0x0100, 0x0085, &srate, 0x0003);
+	snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+		0x81, 0xa2, 0x0100, 0x0086, &srate, 0x0003);
+	snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+		0x81, 0xa2, 0x0100, 0x0003, &srate, 0x0003);
+
+	if (altno != 3) return 1;
+
+	return 0;
+}
+
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
 {
 	/*
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
index 0ca9e91..087a5b6 100644
--- a/sound/usb/quirks.h
+++ b/sound/usb/quirks.h
@@ -24,6 +24,11 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
 int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
 				 struct audioformat *fp);
 
+int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
+				    int iface, int altno);
+
+int snd_usb_mbox2_boot_quirk(struct usb_device *dev);
+
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep);
 
 void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 1ac3fd9..a8172c1 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -76,6 +76,7 @@ enum quirk_type {
 	QUIRK_MIDI_YAMAHA,
 	QUIRK_MIDI_MIDIMAN,
 	QUIRK_MIDI_NOVATION,
+	QUIRK_MIDI_MBOX2,
 	QUIRK_MIDI_RAW_BYTES,
 	QUIRK_MIDI_EMAGIC,
 	QUIRK_MIDI_CME,

[-- Attachment #3: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2012-12-13 13:09                   ` Damien Zammit
@ 2012-12-13 13:18                     ` Takashi Iwai
  2012-12-13 13:27                       ` Takashi Iwai
  0 siblings, 1 reply; 27+ messages in thread
From: Takashi Iwai @ 2012-12-13 13:18 UTC (permalink / raw)
  To: Damien Zammit; +Cc: alsa-devel, Clemens Ladisch, Daniel Mack

At Fri, 14 Dec 2012 00:09:08 +1100,
Damien Zammit wrote:
> 
> Here is a patch based on for-next that does the job.
> 
> I haven't tested this particular merge on the hardware because I would
> have to recompile the whole kernel, but it does compile without
> warnings out of tree, and I haven't changed anything much from my
> version other than semantics to make it fit with your newer code.
> 
> Please find attached the actual patch in case gmail wraps my lines.

Thanks.  Through a quick look, no serious problem is seen but could
you fix the coding style?  Try scripts/checkpatch.pl against your
patch, and fix as much as possible.

Some errors like space around '&' can be ignored.  Also 80 chars width
warnings can be ignored.  But most of other errors should be
corrected.


Takashi

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2012-12-13 13:18                     ` Takashi Iwai
@ 2012-12-13 13:27                       ` Takashi Iwai
  2012-12-13 14:20                         ` Damien Zammit
  0 siblings, 1 reply; 27+ messages in thread
From: Takashi Iwai @ 2012-12-13 13:27 UTC (permalink / raw)
  To: Damien Zammit; +Cc: alsa-devel, Clemens Ladisch, Daniel Mack

At Thu, 13 Dec 2012 14:18:16 +0100,
Takashi Iwai wrote:
> 
> At Fri, 14 Dec 2012 00:09:08 +1100,
> Damien Zammit wrote:
> > 
> > Here is a patch based on for-next that does the job.
> > 
> > I haven't tested this particular merge on the hardware because I would
> > have to recompile the whole kernel, but it does compile without
> > warnings out of tree, and I haven't changed anything much from my
> > version other than semantics to make it fit with your newer code.
> > 
> > Please find attached the actual patch in case gmail wraps my lines.
> 
> Thanks.  Through a quick look, no serious problem is seen but could
> you fix the coding style?  Try scripts/checkpatch.pl against your
> patch, and fix as much as possible.
> 
> Some errors like space around '&' can be ignored.  Also 80 chars width
> warnings can be ignored.  But most of other errors should be
> corrected.

Oh and a big missing thing: please give your sign off and a proper
changelog text.  The sign-off is a line containing like

	Signed-off-by: Your Name <foo@bar.com>

The details about the sign off is found in
Documentation/SubmittingPatches, section "Sign your work".

The changelog is one of the most important part in a patch process.
Describe what the patch actually does and is provided for which
purpose.  In your case, which functionality works, what not, etc, are
good to mention, too.  It should be concise, but should provide enough
information.


Takashi

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2012-12-13 13:27                       ` Takashi Iwai
@ 2012-12-13 14:20                         ` Damien Zammit
  2012-12-13 14:59                           ` Takashi Iwai
  0 siblings, 1 reply; 27+ messages in thread
From: Damien Zammit @ 2012-12-13 14:20 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Clemens Ladisch, Daniel Mack

[-- Attachment #1: Type: text/plain, Size: 9149 bytes --]

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@zamaudio.com>

---

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;
 	case QUIRK_MIDI_RAW_BYTES:
 		umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
 		/*
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 49f9af9..c60eea2 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -3078,6 +3078,93 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 },

+/* DIGIDESIGN MBOX 2 */
+{
+	USB_DEVICE(0x0dba, 0x3000),
+	.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+		.vendor_name = "Digidesign",
+		.product_name = "Mbox 2",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S24_3BE,
+					.channels = 2,
+					.iface = 2,
+					.altsetting = 2,
+					.altset_idx = 1,
+					.attributes = 0x00,
+					.endpoint = 0x03,
+					.ep_attr = USB_ENDPOINT_SYNC_ASYNC,
+					.maxpacksize = 0x128,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 3,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 4,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+				.formats = SNDRV_PCM_FMTBIT_S24_3BE,
+					.channels = 2,
+					.iface = 4,
+					.altsetting = 2,
+					.altset_idx = 1,
+					.attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+					.endpoint = 0x85,
+					.ep_attr = USB_ENDPOINT_SYNC_SYNC,
+					.maxpacksize = 0x128,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 5,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 6,
+				.type = QUIRK_MIDI_MBOX2,
+				.data = &(const struct snd_usb_midi_endpoint_info) {
+					.out_ep =  0x02,
+					.out_cables = 0x0001,
+					.in_ep = 0x81,
+					.in_interval = 0x01,
+					.in_cables = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
+
 {
 	/*
 	 * Some USB MIDI devices don't have an audio control interface,
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 0f58b4b..3510f87 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -306,6 +306,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
 		[QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
 		[QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
 		[QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
+		[QUIRK_MIDI_MBOX2] = create_any_midi_quirk,
 		[QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,
 		[QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
 		[QUIRK_MIDI_CME] = create_any_midi_quirk,
@@ -655,6 +656,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 	case USB_ID(0x0ccd, 0x00b1): /* Terratec Aureon 7.1 USB */
 		return snd_usb_cm6206_boot_quirk(dev);

+	case USB_ID(0x0dba, 0x3000):
+		/* Digidesign Mbox 2 */
+		return snd_usb_mbox2_boot_quirk(dev);
+
 	case USB_ID(0x133e, 0x0815):
 		/* Access Music VirusTI Desktop */
 		return snd_usb_accessmusic_boot_quirk(dev);
@@ -761,6 +766,112 @@ void snd_usb_set_format_quirk(struct
snd_usb_substream *subs,
 	}
 }

+/* Digidesign Mbox 2 needs to load firmware onboard
+ * and driver must wait a few seconds for initialisation.
+ */
+
+#define MBOX2_FIRMWARE_SIZE    646
+#define MBOX2_BOOT_LOADING     0x01 /* Hard coded into the device */
+#define MBOX2_BOOT_READY       0x02 /* Hard coded into the device */
+
+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) {
+		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 */
+			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) {
+			snd_printk("device initialised!\n");
+
+			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);
+			snd_printk(KERN_INFO "Digidesign Mbox 2: 24 Bit 48kHz Analogue");
+
+			return 0; /* Successful boot */
+		}
+
+		snd_printk("Unknown bootresponse, or timed out, ignoring device:
%d\n", bootresponse);
+		return -ENODEV;
+	}
+	snd_printk("Invalid firmware size: %d\n", fwsize);
+	return -ENODEV;
+}
+
+int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
+					int iface, int altno)
+{
+	u8 srate[3];
+	u8 temp[12];
+
+	/* Reset ifaces 2,4 to 0 altsetting like the Windows driver does */
+	usb_set_interface(chip->dev, iface, 0);
+
+	/* Choose 48000Hz permanently */
+	srate[0] = 0x80;
+	srate[1] = 0xbb;
+	srate[2] = 0x00;
+
+	/* Send the magic! */
+	snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
+		0x01, 0x22, 0x0100, 0x0085, &temp, 0x0003);
+	snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+		0x81, 0xa2, 0x0100, 0x0085, &srate, 0x0003);
+	snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+		0x81, 0xa2, 0x0100, 0x0086, &srate, 0x0003);
+	snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+		0x81, 0xa2, 0x0100, 0x0003, &srate, 0x0003);
+
+	if (altno != 3)
+		return 1;
+
+	return 0;
+}
+
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
 {
 	/*
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
index 0ca9e91..087a5b6 100644
--- a/sound/usb/quirks.h
+++ b/sound/usb/quirks.h
@@ -24,6 +24,11 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
 int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
 				 struct audioformat *fp);

+int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
+				    int iface, int altno);
+
+int snd_usb_mbox2_boot_quirk(struct usb_device *dev);
+
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep);

 void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 1ac3fd9..a8172c1 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -76,6 +76,7 @@ enum quirk_type {
 	QUIRK_MIDI_YAMAHA,
 	QUIRK_MIDI_MIDIMAN,
 	QUIRK_MIDI_NOVATION,
+	QUIRK_MIDI_MBOX2,
 	QUIRK_MIDI_RAW_BYTES,
 	QUIRK_MIDI_EMAGIC,
 	QUIRK_MIDI_CME,

[-- Attachment #2: patch_for-next_dz2.txt --]
[-- Type: text/plain, Size: 9155 bytes --]

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@zamaudio.com>

---

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;
 	case QUIRK_MIDI_RAW_BYTES:
 		umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
 		/*
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 49f9af9..c60eea2 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -3078,6 +3078,93 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 },
 
+/* DIGIDESIGN MBOX 2 */
+{
+	USB_DEVICE(0x0dba, 0x3000),
+	.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+		.vendor_name = "Digidesign",
+		.product_name = "Mbox 2",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S24_3BE,
+					.channels = 2,
+					.iface = 2,
+					.altsetting = 2,
+					.altset_idx = 1,
+					.attributes = 0x00,
+					.endpoint = 0x03,
+					.ep_attr = USB_ENDPOINT_SYNC_ASYNC,
+					.maxpacksize = 0x128,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 3,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 4,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+				.formats = SNDRV_PCM_FMTBIT_S24_3BE,
+					.channels = 2,
+					.iface = 4,
+					.altsetting = 2,
+					.altset_idx = 1,
+					.attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+					.endpoint = 0x85,
+					.ep_attr = USB_ENDPOINT_SYNC_SYNC,
+					.maxpacksize = 0x128,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 5,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 6,
+				.type = QUIRK_MIDI_MBOX2,
+				.data = &(const struct snd_usb_midi_endpoint_info) {
+					.out_ep =  0x02,
+					.out_cables = 0x0001,
+					.in_ep = 0x81,
+					.in_interval = 0x01,
+					.in_cables = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
+
 {
 	/*
 	 * Some USB MIDI devices don't have an audio control interface,
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 0f58b4b..3510f87 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -306,6 +306,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
 		[QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
 		[QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
 		[QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
+		[QUIRK_MIDI_MBOX2] = create_any_midi_quirk,
 		[QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,
 		[QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
 		[QUIRK_MIDI_CME] = create_any_midi_quirk,
@@ -655,6 +656,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 	case USB_ID(0x0ccd, 0x00b1): /* Terratec Aureon 7.1 USB */
 		return snd_usb_cm6206_boot_quirk(dev);
 
+	case USB_ID(0x0dba, 0x3000):
+		/* Digidesign Mbox 2 */
+		return snd_usb_mbox2_boot_quirk(dev);
+
 	case USB_ID(0x133e, 0x0815):
 		/* Access Music VirusTI Desktop */
 		return snd_usb_accessmusic_boot_quirk(dev);
@@ -761,6 +766,112 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
 	}
 }
 
+/* Digidesign Mbox 2 needs to load firmware onboard
+ * and driver must wait a few seconds for initialisation.
+ */
+
+#define MBOX2_FIRMWARE_SIZE    646
+#define MBOX2_BOOT_LOADING     0x01 /* Hard coded into the device */
+#define MBOX2_BOOT_READY       0x02 /* Hard coded into the device */
+
+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) {
+		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 */
+			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) {
+			snd_printk("device initialised!\n");
+
+			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);
+			snd_printk(KERN_INFO "Digidesign Mbox 2: 24 Bit 48kHz Analogue");
+
+			return 0; /* Successful boot */
+		}
+
+		snd_printk("Unknown bootresponse, or timed out, ignoring device: %d\n", bootresponse);
+		return -ENODEV;
+	}
+	snd_printk("Invalid firmware size: %d\n", fwsize);
+	return -ENODEV;
+}
+
+int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
+					int iface, int altno)
+{
+	u8 srate[3];
+	u8 temp[12];
+
+	/* Reset ifaces 2,4 to 0 altsetting like the Windows driver does */
+	usb_set_interface(chip->dev, iface, 0);
+
+	/* Choose 48000Hz permanently */
+	srate[0] = 0x80;
+	srate[1] = 0xbb;
+	srate[2] = 0x00;
+
+	/* Send the magic! */
+	snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
+		0x01, 0x22, 0x0100, 0x0085, &temp, 0x0003);
+	snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+		0x81, 0xa2, 0x0100, 0x0085, &srate, 0x0003);
+	snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+		0x81, 0xa2, 0x0100, 0x0086, &srate, 0x0003);
+	snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+		0x81, 0xa2, 0x0100, 0x0003, &srate, 0x0003);
+
+	if (altno != 3)
+		return 1;
+
+	return 0;
+}
+
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
 {
 	/*
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
index 0ca9e91..087a5b6 100644
--- a/sound/usb/quirks.h
+++ b/sound/usb/quirks.h
@@ -24,6 +24,11 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
 int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
 				 struct audioformat *fp);
 
+int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
+				    int iface, int altno);
+
+int snd_usb_mbox2_boot_quirk(struct usb_device *dev);
+
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep);
 
 void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 1ac3fd9..a8172c1 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -76,6 +76,7 @@ enum quirk_type {
 	QUIRK_MIDI_YAMAHA,
 	QUIRK_MIDI_MIDIMAN,
 	QUIRK_MIDI_NOVATION,
+	QUIRK_MIDI_MBOX2,
 	QUIRK_MIDI_RAW_BYTES,
 	QUIRK_MIDI_EMAGIC,
 	QUIRK_MIDI_CME,

[-- Attachment #3: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2012-12-13 14:20                         ` Damien Zammit
@ 2012-12-13 14:59                           ` Takashi Iwai
  2012-12-13 15:29                             ` Clemens Ladisch
  2012-12-16 10:49                             ` [PATCH] " Damien Zammit
  0 siblings, 2 replies; 27+ messages in thread
From: Takashi Iwai @ 2012-12-13 14:59 UTC (permalink / raw)
  To: Damien Zammit; +Cc: alsa-devel, Clemens Ladisch, Daniel Mack

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@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

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2012-12-13 14:59                           ` Takashi Iwai
@ 2012-12-13 15:29                             ` Clemens Ladisch
  2012-12-16 10:49                             ` [PATCH] " Damien Zammit
  1 sibling, 0 replies; 27+ messages in thread
From: Clemens Ladisch @ 2012-12-13 15:29 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Damien Zammit, Daniel Mack

Takashi Iwai wrote:
> Damien Zammit wrote:
>> +	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?

The endpoint detection is different; that comment applies only to the
next single line.

But while technically correct, the comment is superfluous because it
doesn't say anything that isn't obvious from the code.


Regards,
Clemens

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2012-12-13 14:59                           ` Takashi Iwai
  2012-12-13 15:29                             ` Clemens Ladisch
@ 2012-12-16 10:49                             ` Damien Zammit
  2012-12-16 11:06                               ` Damien Zammit
  1 sibling, 1 reply; 27+ messages in thread
From: Damien Zammit @ 2012-12-16 10:49 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Clemens Ladisch, Daniel Mack

[-- Attachment #1: Type: text/plain, Size: 1109 bytes --]

On 14 December 2012 01:59, Takashi Iwai <tiwai@suse.de> wrote:
> Some nitpicking about codes below:
>
> Here you can reduce the indentation depth by simply returning the
> error
Check

> (And, as you see, always put KERN_* prefix to *_printk().
>  Not necessarily for snd_printd() and snd_printdd(), if it's a debug
>  message.
Check

> Use msleep() for such a long delay.
Check

> 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.
Check

>> +                     snd_printk("device initialised!\n");
> Isn't it a debug message?
Check

> 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.
Check

Clemens wrote:
> But while technically correct, the comment is superfluous because it
> doesn't say anything that isn't obvious from the code.
Check

See attached revised patch (version 3).

Regards,
Damien

[-- Attachment #2: patch_for-next_dz3.txt --]
[-- Type: text/plain, Size: 8861 bytes --]

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@zamaudio.com>

---

diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 34b9bb7..c183d34 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -2181,6 +2181,10 @@ 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:
+		umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
+		err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
+		break;
 	case QUIRK_MIDI_RAW_BYTES:
 		umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
 		/*
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 579cf6f..cdcf6b4 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2921,6 +2921,93 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 
 	}
 },
+
+/* DIGIDESIGN MBOX 2 */
+{
+	USB_DEVICE(0x0dba, 0x3000),
+	.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+		.vendor_name = "Digidesign",
+		.product_name = "Mbox 2",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S24_3BE,
+					.channels = 2,
+					.iface = 2,
+					.altsetting = 2,
+					.altset_idx = 1,
+					.attributes = 0x00,
+					.endpoint = 0x03,
+					.ep_attr = USB_ENDPOINT_SYNC_ASYNC,
+					.maxpacksize = 0x128,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 3,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 4,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+				.formats = SNDRV_PCM_FMTBIT_S24_3BE,
+					.channels = 2,
+					.iface = 4,
+					.altsetting = 2,
+					.altset_idx = 1,
+					.attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+					.endpoint = 0x85,
+					.ep_attr = USB_ENDPOINT_SYNC_SYNC,
+					.maxpacksize = 0x128,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 5,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 6,
+				.type = QUIRK_MIDI_MBOX2,
+				.data = &(const struct snd_usb_midi_endpoint_info) {
+					.out_ep =  0x02,
+					.out_cables = 0x0001,
+					.in_ep = 0x81,
+					.in_interval = 0x01,
+					.in_cables = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
 {
 	/* Tascam US122 MKII - playback-only support */
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 0f58b4b..c6b8058 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -306,6 +306,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
 		[QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
 		[QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
 		[QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
+		[QUIRK_MIDI_MBOX2] = create_any_midi_quirk,
 		[QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,
 		[QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
 		[QUIRK_MIDI_CME] = create_any_midi_quirk,
@@ -655,6 +656,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 	case USB_ID(0x0ccd, 0x00b1): /* Terratec Aureon 7.1 USB */
 		return snd_usb_cm6206_boot_quirk(dev);
 
+	case USB_ID(0x0dba, 0x3000):
+		/* Digidesign Mbox 2 */
+		return snd_usb_mbox2_boot_quirk(dev);
+
 	case USB_ID(0x133e, 0x0815):
 		/* Access Music VirusTI Desktop */
 		return snd_usb_accessmusic_boot_quirk(dev);
@@ -761,6 +766,108 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
 	}
 }
 
+void mbox2_setup_48_24_magic(struct snd_usb_audio *chip)
+{
+	u8 srate[3];
+	u8 temp[12];
+
+	/* Choose 48000Hz permanently */
+	srate[0] = 0x80;
+	srate[1] = 0xbb;
+	srate[2] = 0x00;
+
+	/* Send the magic! */
+	snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
+		0x01, 0x22, 0x0100, 0x0085, &temp, 0x0003);
+	snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+		0x81, 0xa2, 0x0100, 0x0085, &srate, 0x0003);
+	snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+		0x81, 0xa2, 0x0100, 0x0086, &srate, 0x0003);
+	snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+		0x81, 0xa2, 0x0100, 0x0003, &srate, 0x0003);
+	return;
+}
+
+/* Digidesign Mbox 2 needs to load firmware onboard
+ * and driver must wait a few seconds for initialisation.
+ */
+
+#define MBOX2_FIRMWARE_SIZE    646
+#define MBOX2_BOOT_LOADING     0x01 /* Hard coded into the device */
+#define MBOX2_BOOT_READY       0x02 /* Hard coded into the device */
+
+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) {
+		snd_printk(KERN_ERR "usb-audio: Invalid firmware size=%d.\n", fwsize);
+		return -ENODEV;
+	}
+
+	snd_printd("usb-audio: Sending Digidesign Mbox 2 boot sequence...\n");
+
+	count = 0;
+	bootresponse = MBOX2_BOOT_LOADING;
+	while ((bootresponse == MBOX2_BOOT_LOADING) && (count < 10)) {
+		msleep(500); /* 0.5 second delay */
+		snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
+			/* Control magic - load onboard firmware */
+			0x85, 0xc0, 0x0001, 0x0000, &bootresponse, 0x0012);
+		if (bootresponse == MBOX2_BOOT_READY)
+			break;
+		snd_printd("usb-audio: device not ready, resending boot sequence...\n");
+		count++;
+	}
+
+	if (bootresponse != MBOX2_BOOT_READY) {
+		snd_printk(KERN_ERR "usb-audio: Unknown bootresponse=%d, or timed out, ignoring device.\n", bootresponse);
+		return -ENODEV;
+	}
+
+	snd_printd("usb-audio: device initialised!\n");
+
+	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));
+
+	mbox2_setup_48_24_magic(chip->dev);
+
+	snd_printk(KERN_INFO "usb-audio: Digidesign Mbox 2: 24bit 48kHz");
+
+	return 0; /* Successful boot */
+}
+
+int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
+					int iface, int altno)
+{
+	/* Reset ifaces 2,4 to 0 altsetting like the Windows driver does */
+	usb_set_interface(chip->dev, iface, 0);
+
+	mbox2_setup_48_24_magic(chip->dev);
+
+	if (altno != 3)
+		return 1;
+
+	return 0;
+}
+
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
 {
 	/*
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
index 0ca9e91..7059c89 100644
--- a/sound/usb/quirks.h
+++ b/sound/usb/quirks.h
@@ -24,6 +24,13 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
 int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
 				 struct audioformat *fp);
 
+void mbox2_setup_48_24_magic(struct snd_usb_audio *chip);
+
+int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
+				    int iface, int altno);
+
+int snd_usb_mbox2_boot_quirk(struct usb_device *dev);
+
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep);
 
 void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 1ac3fd9..a8172c1 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -76,6 +76,7 @@ enum quirk_type {
 	QUIRK_MIDI_YAMAHA,
 	QUIRK_MIDI_MIDIMAN,
 	QUIRK_MIDI_NOVATION,
+	QUIRK_MIDI_MBOX2,
 	QUIRK_MIDI_RAW_BYTES,
 	QUIRK_MIDI_EMAGIC,
 	QUIRK_MIDI_CME,

[-- Attachment #3: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH] sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2012-12-16 10:49                             ` [PATCH] " Damien Zammit
@ 2012-12-16 11:06                               ` Damien Zammit
  2012-12-17 10:25                                 ` Takashi Iwai
  0 siblings, 1 reply; 27+ messages in thread
From: Damien Zammit @ 2012-12-16 11:06 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Clemens Ladisch, Daniel Mack

[-- Attachment #1: Type: text/plain, Size: 222 bytes --]

On 16 December 2012 21:49, Damien Zammit <damien.zammit@gmail.com> wrote:
> See attached revised patch (version 3).

Sorry, there was a mistake in version 3, see attached patch (version
4) which compiles.

Regards,
Damien

[-- Attachment #2: patch_for-next_dz4.txt --]
[-- Type: text/plain, Size: 8799 bytes --]

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@zamaudio.com>

---

diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 34b9bb7..c183d34 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -2181,6 +2181,10 @@ 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:
+		umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
+		err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
+		break;
 	case QUIRK_MIDI_RAW_BYTES:
 		umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
 		/*
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 579cf6f..cdcf6b4 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2921,6 +2921,93 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 
 	}
 },
+
+/* DIGIDESIGN MBOX 2 */
+{
+	USB_DEVICE(0x0dba, 0x3000),
+	.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+		.vendor_name = "Digidesign",
+		.product_name = "Mbox 2",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S24_3BE,
+					.channels = 2,
+					.iface = 2,
+					.altsetting = 2,
+					.altset_idx = 1,
+					.attributes = 0x00,
+					.endpoint = 0x03,
+					.ep_attr = USB_ENDPOINT_SYNC_ASYNC,
+					.maxpacksize = 0x128,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 3,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 4,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+				.formats = SNDRV_PCM_FMTBIT_S24_3BE,
+					.channels = 2,
+					.iface = 4,
+					.altsetting = 2,
+					.altset_idx = 1,
+					.attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+					.endpoint = 0x85,
+					.ep_attr = USB_ENDPOINT_SYNC_SYNC,
+					.maxpacksize = 0x128,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 5,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 6,
+				.type = QUIRK_MIDI_MBOX2,
+				.data = &(const struct snd_usb_midi_endpoint_info) {
+					.out_ep =  0x02,
+					.out_cables = 0x0001,
+					.in_ep = 0x81,
+					.in_interval = 0x01,
+					.in_cables = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
 {
 	/* Tascam US122 MKII - playback-only support */
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 0f58b4b..0f8251e 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -306,6 +306,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
 		[QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
 		[QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
 		[QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
+		[QUIRK_MIDI_MBOX2] = create_any_midi_quirk,
 		[QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,
 		[QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
 		[QUIRK_MIDI_CME] = create_any_midi_quirk,
@@ -655,6 +656,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 	case USB_ID(0x0ccd, 0x00b1): /* Terratec Aureon 7.1 USB */
 		return snd_usb_cm6206_boot_quirk(dev);
 
+	case USB_ID(0x0dba, 0x3000):
+		/* Digidesign Mbox 2 */
+		return snd_usb_mbox2_boot_quirk(dev);
+
 	case USB_ID(0x133e, 0x0815):
 		/* Access Music VirusTI Desktop */
 		return snd_usb_accessmusic_boot_quirk(dev);
@@ -761,6 +766,108 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
 	}
 }
 
+void mbox2_setup_48_24_magic(struct usb_device *dev)
+{
+	u8 srate[3];
+	u8 temp[12];
+
+	/* Choose 48000Hz permanently */
+	srate[0] = 0x80;
+	srate[1] = 0xbb;
+	srate[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, &srate, 0x0003);
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+		0x81, 0xa2, 0x0100, 0x0086, &srate, 0x0003);
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+		0x81, 0xa2, 0x0100, 0x0003, &srate, 0x0003);
+	return;
+}
+
+/* Digidesign Mbox 2 needs to load firmware onboard
+ * and driver must wait a few seconds for initialisation.
+ */
+
+#define MBOX2_FIRMWARE_SIZE    646
+#define MBOX2_BOOT_LOADING     0x01 /* Hard coded into the device */
+#define MBOX2_BOOT_READY       0x02 /* Hard coded into the device */
+
+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) {
+		snd_printk(KERN_ERR "usb-audio: Invalid firmware size=%d.\n", fwsize);
+		return -ENODEV;
+	}
+
+	snd_printd("usb-audio: Sending Digidesign Mbox 2 boot sequence...\n");
+
+	count = 0;
+	bootresponse = MBOX2_BOOT_LOADING;
+	while ((bootresponse == MBOX2_BOOT_LOADING) && (count < 10)) {
+		msleep(500); /* 0.5 second delay */
+		snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
+			/* Control magic - load onboard firmware */
+			0x85, 0xc0, 0x0001, 0x0000, &bootresponse, 0x0012);
+		if (bootresponse == MBOX2_BOOT_READY)
+			break;
+		snd_printd("usb-audio: device not ready, resending boot sequence...\n");
+		count++;
+	}
+
+	if (bootresponse != MBOX2_BOOT_READY) {
+		snd_printk(KERN_ERR "usb-audio: Unknown bootresponse=%d, or timed out, ignoring device.\n", bootresponse);
+		return -ENODEV;
+	}
+
+	snd_printd("usb-audio: device initialised!\n");
+
+	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));
+
+	mbox2_setup_48_24_magic(dev);
+
+	snd_printk(KERN_INFO "usb-audio: Digidesign Mbox 2: 24bit 48kHz");
+
+	return 0; /* Successful boot */
+}
+
+int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
+					int iface, int altno)
+{
+	/* Reset ifaces 2,4 to 0 altsetting like the Windows driver does */
+	usb_set_interface(chip->dev, iface, 0);
+
+	mbox2_setup_48_24_magic(chip->dev);
+
+	if (altno != 3)
+		return 1;
+
+	return 0;
+}
+
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
 {
 	/*
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
index 0ca9e91..fa12a2e 100644
--- a/sound/usb/quirks.h
+++ b/sound/usb/quirks.h
@@ -24,6 +24,13 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
 int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
 				 struct audioformat *fp);
 
+void mbox2_setup_48_24_magic(struct usb_device *dev);
+
+int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
+				    int iface, int altno);
+
+int snd_usb_mbox2_boot_quirk(struct usb_device *dev);
+
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep);
 
 void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 1ac3fd9..a8172c1 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -76,6 +76,7 @@ enum quirk_type {
 	QUIRK_MIDI_YAMAHA,
 	QUIRK_MIDI_MIDIMAN,
 	QUIRK_MIDI_NOVATION,
+	QUIRK_MIDI_MBOX2,
 	QUIRK_MIDI_RAW_BYTES,
 	QUIRK_MIDI_EMAGIC,
 	QUIRK_MIDI_CME,

[-- Attachment #3: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH] sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2012-12-16 11:06                               ` Damien Zammit
@ 2012-12-17 10:25                                 ` Takashi Iwai
  2012-12-18 12:09                                   ` Damien Zammit
  0 siblings, 1 reply; 27+ messages in thread
From: Takashi Iwai @ 2012-12-17 10:25 UTC (permalink / raw)
  To: Damien Zammit; +Cc: alsa-devel, Clemens Ladisch, Daniel Mack

At Sun, 16 Dec 2012 22:06:25 +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@zamaudio.com>

Thanks for the revised patch.
It looks almost good, but just a few things below:

> @@ -761,6 +766,108 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
>  	}
>  }
>  
> +void mbox2_setup_48_24_magic(struct usb_device *dev)

This doesn't have to be global.  Make it static.

> +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];

enablemagic[] and temp[] aren't used in this function.
Remove them.

> +	if (bootresponse != MBOX2_BOOT_READY) {
> +		snd_printk(KERN_ERR "usb-audio: Unknown bootresponse=%d, or timed out, ignoring device.\n", bootresponse);
> +		return -ENODEV;
> +	}
> +
> +	snd_printd("usb-audio: device initialised!\n");

I'd say this could be snd_printdd() (as you'll see anyway the message
below at each time), and...

> +	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);

... make it to snd_printd(), as this is good to know for debugging,


> +	err = usb_reset_configuration(dev);
> +	if (err < 0)
> +		snd_printdd("error usb_reset_configuration: %d\n", err);

... ditto, make snd_printd().

> +	snd_printdd("mbox2_boot: new boot length = %d\n",
> +		le16_to_cpu(get_cfg_desc(config)->wTotalLength));
> +
> +	mbox2_setup_48_24_magic(dev);
> +
> +	snd_printk(KERN_INFO "usb-audio: Digidesign Mbox 2: 24bit 48kHz");
> +
> +	return 0; /* Successful boot */
> +}
> +
> +int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
> +					int iface, int altno)

Where is this function called?  I don't see the caller in your latest
patch.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2012-12-17 10:25                                 ` Takashi Iwai
@ 2012-12-18 12:09                                   ` Damien Zammit
  2012-12-18 13:08                                     ` Takashi Iwai
  0 siblings, 1 reply; 27+ messages in thread
From: Damien Zammit @ 2012-12-18 12:09 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Clemens Ladisch, Daniel Mack

[-- Attachment #1: Type: text/plain, Size: 752 bytes --]

On 17 December 2012 21:25, Takashi Iwai <tiwai@suse.de> wrote:
> Thanks for the revised patch.
No worries! Hope we can get it in soon.

>> +void mbox2_setup_48_24_magic(struct usb_device *dev)
> This doesn't have to be global.  Make it static.
Check

> enablemagic[] and temp[] aren't used in this function.
> Remove them.
Check

(snd_printdd and snd_printd messages)
Check

>> +int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
>> +                                     int iface, int altno)
> Where is this function called?  I don't see the caller in your latest
> patch.
Well spotted! I believe this function is not required anymore because
I have hardcoded the altsettings in the quirk definition.

Patch version 5 attached.

Regards,
Damien

[-- Attachment #2: patch_for-next_dz5.txt --]
[-- Type: text/plain, Size: 8325 bytes --]

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@zamaudio.com>

---

diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 34b9bb7..c183d34 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -2181,6 +2181,10 @@ 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:
+		umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
+		err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
+		break;
 	case QUIRK_MIDI_RAW_BYTES:
 		umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
 		/*
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 579cf6f..cdcf6b4 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2921,6 +2921,93 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 
 	}
 },
+
+/* DIGIDESIGN MBOX 2 */
+{
+	USB_DEVICE(0x0dba, 0x3000),
+	.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+		.vendor_name = "Digidesign",
+		.product_name = "Mbox 2",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S24_3BE,
+					.channels = 2,
+					.iface = 2,
+					.altsetting = 2,
+					.altset_idx = 1,
+					.attributes = 0x00,
+					.endpoint = 0x03,
+					.ep_attr = USB_ENDPOINT_SYNC_ASYNC,
+					.maxpacksize = 0x128,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 3,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 4,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+				.formats = SNDRV_PCM_FMTBIT_S24_3BE,
+					.channels = 2,
+					.iface = 4,
+					.altsetting = 2,
+					.altset_idx = 1,
+					.attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+					.endpoint = 0x85,
+					.ep_attr = USB_ENDPOINT_SYNC_SYNC,
+					.maxpacksize = 0x128,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 5,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 6,
+				.type = QUIRK_MIDI_MBOX2,
+				.data = &(const struct snd_usb_midi_endpoint_info) {
+					.out_ep =  0x02,
+					.out_cables = 0x0001,
+					.in_ep = 0x81,
+					.in_interval = 0x01,
+					.in_cables = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
 {
 	/* Tascam US122 MKII - playback-only support */
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 0f58b4b..8f23af5 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -306,6 +306,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
 		[QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
 		[QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
 		[QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
+		[QUIRK_MIDI_MBOX2] = create_any_midi_quirk,
 		[QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,
 		[QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
 		[QUIRK_MIDI_CME] = create_any_midi_quirk,
@@ -655,6 +656,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 	case USB_ID(0x0ccd, 0x00b1): /* Terratec Aureon 7.1 USB */
 		return snd_usb_cm6206_boot_quirk(dev);
 
+	case USB_ID(0x0dba, 0x3000):
+		/* Digidesign Mbox 2 */
+		return snd_usb_mbox2_boot_quirk(dev);
+
 	case USB_ID(0x133e, 0x0815):
 		/* Access Music VirusTI Desktop */
 		return snd_usb_accessmusic_boot_quirk(dev);
@@ -761,6 +766,92 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
 	}
 }
 
+static void mbox2_setup_48_24_magic(struct usb_device *dev)
+{
+	u8 srate[3];
+	u8 temp[12];
+
+	/* Choose 48000Hz permanently */
+	srate[0] = 0x80;
+	srate[1] = 0xbb;
+	srate[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, &srate, 0x0003);
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+		0x81, 0xa2, 0x0100, 0x0086, &srate, 0x0003);
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+		0x81, 0xa2, 0x0100, 0x0003, &srate, 0x0003);
+	return;
+}
+
+/* Digidesign Mbox 2 needs to load firmware onboard
+ * and driver must wait a few seconds for initialisation.
+ */
+
+#define MBOX2_FIRMWARE_SIZE    646
+#define MBOX2_BOOT_LOADING     0x01 /* Hard coded into the device */
+#define MBOX2_BOOT_READY       0x02 /* Hard coded into the device */
+
+int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
+{
+	struct usb_host_config *config = dev->actconfig;
+	int err;
+	u8 bootresponse;
+	int fwsize;
+	int count;
+
+	fwsize = le16_to_cpu(get_cfg_desc(config)->wTotalLength);
+
+	if (fwsize != MBOX2_FIRMWARE_SIZE) {
+		snd_printk(KERN_ERR "usb-audio: Invalid firmware size=%d.\n", fwsize);
+		return -ENODEV;
+	}
+
+	snd_printd("usb-audio: Sending Digidesign Mbox 2 boot sequence...\n");
+
+	count = 0;
+	bootresponse = MBOX2_BOOT_LOADING;
+	while ((bootresponse == MBOX2_BOOT_LOADING) && (count < 10)) {
+		msleep(500); /* 0.5 second delay */
+		snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
+			/* Control magic - load onboard firmware */
+			0x85, 0xc0, 0x0001, 0x0000, &bootresponse, 0x0012);
+		if (bootresponse == MBOX2_BOOT_READY)
+			break;
+		snd_printd("usb-audio: device not ready, resending boot sequence...\n");
+		count++;
+	}
+
+	if (bootresponse != MBOX2_BOOT_READY) {
+		snd_printk(KERN_ERR "usb-audio: Unknown bootresponse=%d, or timed out, ignoring device.\n", bootresponse);
+		return -ENODEV;
+	}
+
+	snd_printdd("usb-audio: device initialised!\n");
+
+	err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
+		&dev->descriptor, sizeof(dev->descriptor));
+	config = dev->actconfig;
+	if (err < 0)
+		snd_printd("error usb_get_descriptor: %d\n", err);
+
+	err = usb_reset_configuration(dev);
+	if (err < 0)
+		snd_printd("error usb_reset_configuration: %d\n", err);
+	snd_printdd("mbox2_boot: new boot length = %d\n",
+		le16_to_cpu(get_cfg_desc(config)->wTotalLength));
+
+	mbox2_setup_48_24_magic(dev);
+
+	snd_printk(KERN_INFO "usb-audio: Digidesign Mbox 2: 24bit 48kHz");
+
+	return 0; /* Successful boot */
+}
+
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
 {
 	/*
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
index 0ca9e91..e7e9530 100644
--- a/sound/usb/quirks.h
+++ b/sound/usb/quirks.h
@@ -24,6 +24,8 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
 int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
 				 struct audioformat *fp);
 
+int snd_usb_mbox2_boot_quirk(struct usb_device *dev);
+
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep);
 
 void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 1ac3fd9..a8172c1 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -76,6 +76,7 @@ enum quirk_type {
 	QUIRK_MIDI_YAMAHA,
 	QUIRK_MIDI_MIDIMAN,
 	QUIRK_MIDI_NOVATION,
+	QUIRK_MIDI_MBOX2,
 	QUIRK_MIDI_RAW_BYTES,
 	QUIRK_MIDI_EMAGIC,
 	QUIRK_MIDI_CME,

[-- Attachment #3: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH] sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2012-12-18 12:09                                   ` Damien Zammit
@ 2012-12-18 13:08                                     ` Takashi Iwai
  2012-12-19 10:30                                       ` Takashi Iwai
  0 siblings, 1 reply; 27+ messages in thread
From: Takashi Iwai @ 2012-12-18 13:08 UTC (permalink / raw)
  To: Damien Zammit; +Cc: alsa-devel, Clemens Ladisch, Daniel Mack

At Tue, 18 Dec 2012 23:09:54 +1100,
Damien Zammit wrote:
> 
> On 17 December 2012 21:25, Takashi Iwai <tiwai@suse.de> wrote:
> > Thanks for the revised patch.
> No worries! Hope we can get it in soon.
> 
> >> +void mbox2_setup_48_24_magic(struct usb_device *dev)
> > This doesn't have to be global.  Make it static.
> Check
> 
> > enablemagic[] and temp[] aren't used in this function.
> > Remove them.
> Check
> 
> (snd_printdd and snd_printd messages)
> Check
> 
> >> +int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
> >> +                                     int iface, int altno)
> > Where is this function called?  I don't see the caller in your latest
> > patch.
> Well spotted! I believe this function is not required anymore because
> I have hardcoded the altsettings in the quirk definition.
> 
> Patch version 5 attached.

Thanks!  One last favor...

> +int snd_usb_mbox2_boot_quirk(struct usb_device *dev)

This doesn't have to be a global one, as it's called only in the same
file.  You can move this function before the caller for avoiding the
function declaration, and ...

> diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
> index 0ca9e91..e7e9530 100644
> --- a/sound/usb/quirks.h
> +++ b/sound/usb/quirks.h
> @@ -24,6 +24,8 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
>  int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
>  				 struct audioformat *fp);
>  
> +int snd_usb_mbox2_boot_quirk(struct usb_device *dev);
> +

... drop this.


Takashi

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2012-12-18 13:08                                     ` Takashi Iwai
@ 2012-12-19 10:30                                       ` Takashi Iwai
  2012-12-19 10:37                                         ` Damien Zammit
  0 siblings, 1 reply; 27+ messages in thread
From: Takashi Iwai @ 2012-12-19 10:30 UTC (permalink / raw)
  To: Damien Zammit; +Cc: alsa-devel, Clemens Ladisch, Daniel Mack

At Tue, 18 Dec 2012 14:08:12 +0100,
Takashi Iwai wrote:
> 
> At Tue, 18 Dec 2012 23:09:54 +1100,
> Damien Zammit wrote:
> > 
> > On 17 December 2012 21:25, Takashi Iwai <tiwai@suse.de> wrote:
> > > Thanks for the revised patch.
> > No worries! Hope we can get it in soon.
> > 
> > >> +void mbox2_setup_48_24_magic(struct usb_device *dev)
> > > This doesn't have to be global.  Make it static.
> > Check
> > 
> > > enablemagic[] and temp[] aren't used in this function.
> > > Remove them.
> > Check
> > 
> > (snd_printdd and snd_printd messages)
> > Check
> > 
> > >> +int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
> > >> +                                     int iface, int altno)
> > > Where is this function called?  I don't see the caller in your latest
> > > patch.
> > Well spotted! I believe this function is not required anymore because
> > I have hardcoded the altsettings in the quirk definition.
> > 
> > Patch version 5 attached.
> 
> Thanks!  One last favor...
> 
> > +int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
> 
> This doesn't have to be a global one, as it's called only in the same
> file.  You can move this function before the caller for avoiding the
> function declaration, and ...
> 
> > diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
> > index 0ca9e91..e7e9530 100644
> > --- a/sound/usb/quirks.h
> > +++ b/sound/usb/quirks.h
> > @@ -24,6 +24,8 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
> >  int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
> >  				 struct audioformat *fp);
> >  
> > +int snd_usb_mbox2_boot_quirk(struct usb_device *dev);
> > +
> 
> ... drop this.

Never mind, I fixed this by myself and merged the patch now.
It'll be included in 3.8-rc1.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2012-12-19 10:30                                       ` Takashi Iwai
@ 2012-12-19 10:37                                         ` Damien Zammit
  2012-12-22 23:38                                           ` Damien Zammit
  0 siblings, 1 reply; 27+ messages in thread
From: Damien Zammit @ 2012-12-19 10:37 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Clemens Ladisch, Daniel Mack

On 19 December 2012 21:30, Takashi Iwai <tiwai@suse.de> wrote:
> Never mind, I fixed this by myself and merged the patch now.
> It'll be included in 3.8-rc1.

Thanks Takashi!

I will be sure to compile this kernel when it comes out and double
check it on the hardware!

Regards,
Damien

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2012-12-19 10:37                                         ` Damien Zammit
@ 2012-12-22 23:38                                           ` Damien Zammit
  2012-12-23  0:31                                             ` Damien Zammit
  0 siblings, 1 reply; 27+ messages in thread
From: Damien Zammit @ 2012-12-22 23:38 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Clemens Ladisch, Daniel Mack

[-- Attachment #1: Type: text/plain, Size: 499 bytes --]

On 19 December 2012 21:37, Damien Zammit <damien.zammit@gmail.com> wrote:
> I will be sure to compile this kernel when it comes out and double
> check it on the hardware!
Bad news, the kernel panics when I plug in the device on this kernel.
I compiled the kernel yesterday with default options except I changed
HZ=1000 and used generic X86_64 with kernel preemption:

$ uname -a
Linux zamserv 3.8.0-rc1 #1 SMP PREEMPT Sat Dec 22 21:56:06 EST 2012
x86_64 GNU/Linux

Attached is a panic dump.

Damien

[-- Attachment #2: mbox2.panic.txt --]
[-- Type: text/plain, Size: 2830 bytes --]


[  194.445170] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ffffffffa0f1b1af
[  194.445170] 
[  194.445186] Pid: 553, comm: khubd Tainted: P           O 3.8.0-rc1 #1
[  194.445192] Call Trace:
[  194.445203]  [<ffffffff8137917a>] ? panic+0xc8/0x1d1
[  194.445212]  [<ffffffffa0f1b1af>] ? snd_usb_mbox2_boot_quirk+0x1f1/0x1fa [snd_usb_audio]
[  194.445219]  [<ffffffff8103eb8d>] ? __stack_chk_fail+0x15/0x15
[  194.445226]  [<ffffffffa0f1b1af>] ? snd_usb_mbox2_boot_quirk+0x1f1/0x1fa [snd_usb_audio]
[  194.445232]  [<ffffffffa0f1b51e>] ? snd_usb_apply_boot_quirk+0x206/0x307 [snd_usb_audio]
[  194.445239]  [<ffffffff81100c3b>] ? kmem_cache_alloc+0x86/0x103
[  194.445245]  [<ffffffff8115f2f8>] ? sysfs_link_sibling+0x8d/0x9b
[  194.445250]  [<ffffffffa0f123d1>] ? usb_audio_probe+0x82/0x729 [snd_usb_audio]
[  194.445257]  [<ffffffff8137ece4>] ? _raw_spin_lock_irqsave+0x21/0x46
[  194.445263]  [<ffffffff812804ed>] ? __pm_runtime_set_status+0x121/0x14d
[  194.445281]  [<ffffffffa018e73a>] ? usb_probe_interface+0x131/0x1c3 [usbcore]
[  194.445288]  [<ffffffff81277fc6>] ? __driver_attach+0x73/0x73
[  194.445295]  [<ffffffff81277fc6>] ? __driver_attach+0x73/0x73
[  194.445301]  [<ffffffff81277e35>] ? driver_probe_device+0x92/0x1b0
[  194.445307]  [<ffffffff812766bb>] ? bus_for_each_drv+0x43/0x7d
[  194.445314]  [<ffffffff81277d71>] ? device_attach+0x68/0x83
[  194.445320]  [<ffffffff81277437>] ? bus_probe_device+0x25/0x8d
[  194.445325]  [<ffffffff81275e37>] ? device_add+0x3ea/0x5ab
[  194.445330]  [<ffffffff8137ece4>] ? _raw_spin_lock_irqsave+0x21/0x46
[  194.445341]  [<ffffffffa018d2c1>] ? usb_set_configuration+0x5e1/0x63e [usbcore]
[  194.445348]  [<ffffffff81277fc6>] ? __driver_attach+0x73/0x73
[  194.445358]  [<ffffffffa0194877>] ? generic_probe+0x3b/0x68 [usbcore]
[  194.445365]  [<ffffffff81277e35>] ? driver_probe_device+0x92/0x1b0
[  194.445370]  [<ffffffff812766bb>] ? bus_for_each_drv+0x43/0x7d
[  194.445377]  [<ffffffff81277d71>] ? device_attach+0x68/0x83
[  194.445382]  [<ffffffff81277437>] ? bus_probe_device+0x25/0x8d
[  194.445388]  [<ffffffff81275e37>] ? device_add+0x3ea/0x5ab
[  194.445398]  [<ffffffffa0186ebc>] ? usb_new_device+0x1ed/0x284 [usbcore]
[  194.445408]  [<ffffffffa0188090>] ? hub_thread+0x9d3/0xe89 [usbcore]
[  194.445414]  [<ffffffff8137e047>] ? __schedule+0x4cf/0x502
[  194.445421]  [<ffffffff81059abf>] ? abort_exclusive_wait+0x79/0x79
[  194.445430]  [<ffffffffa01876bd>] ? usb_remote_wakeup+0x2f/0x2f [usbcore]
[  194.445439]  [<ffffffffa01876bd>] ? usb_remote_wakeup+0x2f/0x2f [usbcore]
[  194.445444]  [<ffffffff81059116>] ? kthread+0x81/0x89
[  194.445449]  [<ffffffff81059095>] ? __kthread_parkme+0x5c/0x5c
[  194.445455]  [<ffffffff813834bc>] ? ret_from_fork+0x7c/0xb0
[  194.445460]  [<ffffffff81059095>] ? __kthread_parkme+0x5c/0x5c

[-- Attachment #3: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2012-12-22 23:38                                           ` Damien Zammit
@ 2012-12-23  0:31                                             ` Damien Zammit
  2012-12-23  2:18                                               ` Damien Zammit
  0 siblings, 1 reply; 27+ messages in thread
From: Damien Zammit @ 2012-12-23  0:31 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Clemens Ladisch, Daniel Mack

Hi,

Not sure if this is relevant, but when I compile the module with a few
changes, then try to insert the modules snd-usbmidi-lib and
snd-usb-audio, I get

$ sudo insmod ./snd-usbmidi-lib.ko
Error: could not insert module ./snd-usbmidi-lib.ko: Unknown symbol in module

Also, I think I might have found the bug but I cant test it due to the above.

Damien

On 23 December 2012 10:38, Damien Zammit <damien.zammit@gmail.com> wrote:
> On 19 December 2012 21:37, Damien Zammit <damien.zammit@gmail.com> wrote:
>> I will be sure to compile this kernel when it comes out and double
>> check it on the hardware!
> Bad news, the kernel panics when I plug in the device on this kernel.
> I compiled the kernel yesterday with default options except I changed
> HZ=1000 and used generic X86_64 with kernel preemption:
>
> $ uname -a
> Linux zamserv 3.8.0-rc1 #1 SMP PREEMPT Sat Dec 22 21:56:06 EST 2012
> x86_64 GNU/Linux
>
> Attached is a panic dump.
>
> Damien

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2012-12-23  0:31                                             ` Damien Zammit
@ 2012-12-23  2:18                                               ` Damien Zammit
  2012-12-23  3:36                                                 ` Damien Zammit
  0 siblings, 1 reply; 27+ messages in thread
From: Damien Zammit @ 2012-12-23  2:18 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Clemens Ladisch, Daniel Mack

[-- Attachment #1: Type: text/plain, Size: 549 bytes --]

Hi guys,

I fixed the kernel panic, I had forgotten to allocate 12 bytes (I only
allocated 1 byte) for a usb control message return value whose size
was 12.
I used 12 even though I am only reading the first byte because the
windows driver also reads 12 bytes.  Maybe in some strange cases it
might return this many.

See attached patch.

By the way, the sound quality is much much better than it used to be
in older kernels.
I am not getting any hiss or strange noise from other usb devices
being plugged in like with other kernels.

Thanks,
Damien

[-- Attachment #2: patch_for-next_dz6.txt --]
[-- Type: text/plain, Size: 8431 bytes --]

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.

This version of the patch has been compiled on a real machine and tested 
with the hardware.
The previous version of this patch caused a kernel panic due to a small bug 
which has been fixed here. Extensive testing has been done by many users 
of the hardware who believe other versions of my patch have worked since 
circa 2009.

Error messages:
There are some very noisy kernel messages caused during playback on my machine
"urb status = -32", but the device is working now with this particular patch.
I also get a small error message upon plugging the device in but it doesn't 
seem to affect the functionality:
Dec 23 12:33:33 zamserv kernel: [ 7696.829300] usb 1-1.2: Manufacturer: Digidesign
Dec 23 12:33:38 zamserv kernel: [ 7701.419378] 5:4:2: cannot set freq 48000 to ep 0x85
Dec 23 12:34:06 zamserv kernel: [ 7701.338727] usb-audio: Digidesign Mbox 2: 24bit 48kHz

Signed-off-by: Damien Zammit <damien@zamaudio.com>

---

diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 34b9bb7..c183d34 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -2181,6 +2181,10 @@ 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:
+		umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
+		err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
+		break;
 	case QUIRK_MIDI_RAW_BYTES:
 		umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
 		/*
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 579cf6f..cdcf6b4 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2921,6 +2921,93 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 
 	}
 },
+
+/* DIGIDESIGN MBOX 2 */
+{
+	USB_DEVICE(0x0dba, 0x3000),
+	.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+		.vendor_name = "Digidesign",
+		.product_name = "Mbox 2",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S24_3BE,
+					.channels = 2,
+					.iface = 2,
+					.altsetting = 2,
+					.altset_idx = 1,
+					.attributes = 0x00,
+					.endpoint = 0x03,
+					.ep_attr = USB_ENDPOINT_SYNC_ASYNC,
+					.maxpacksize = 0x128,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 3,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 4,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+				.formats = SNDRV_PCM_FMTBIT_S24_3BE,
+					.channels = 2,
+					.iface = 4,
+					.altsetting = 2,
+					.altset_idx = 1,
+					.attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+					.endpoint = 0x85,
+					.ep_attr = USB_ENDPOINT_SYNC_SYNC,
+					.maxpacksize = 0x128,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 5,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 6,
+				.type = QUIRK_MIDI_MBOX2,
+				.data = &(const struct snd_usb_midi_endpoint_info) {
+					.out_ep =  0x02,
+					.out_cables = 0x0001,
+					.in_ep = 0x81,
+					.in_interval = 0x01,
+					.in_cables = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
 {
 	/* Tascam US122 MKII - playback-only support */
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 0f58b4b..924da37 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -306,6 +306,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
 		[QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
 		[QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
 		[QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
+		[QUIRK_MIDI_MBOX2] = create_any_midi_quirk,
 		[QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,
 		[QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
 		[QUIRK_MIDI_CME] = create_any_midi_quirk,
@@ -655,6 +656,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 	case USB_ID(0x0ccd, 0x00b1): /* Terratec Aureon 7.1 USB */
 		return snd_usb_cm6206_boot_quirk(dev);
 
+	case USB_ID(0x0dba, 0x3000):
+		/* Digidesign Mbox 2 */
+		return snd_usb_mbox2_boot_quirk(dev);
+
 	case USB_ID(0x133e, 0x0815):
 		/* Access Music VirusTI Desktop */
 		return snd_usb_accessmusic_boot_quirk(dev);
@@ -761,6 +766,92 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
 	}
 }
 
+static void mbox2_setup_48_24_magic(struct usb_device *dev)
+{
+	u8 srate[3];
+	u8 temp[12];
+
+	/* Choose 48000Hz permanently */
+	srate[0] = 0x80;
+	srate[1] = 0xbb;
+	srate[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, &srate, 0x0003);
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+		0x81, 0xa2, 0x0100, 0x0086, &srate, 0x0003);
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+		0x81, 0xa2, 0x0100, 0x0003, &srate, 0x0003);
+	return;
+}
+
+/* Digidesign Mbox 2 needs to load firmware onboard
+ * and driver must wait a few seconds for initialisation.
+ */
+
+#define MBOX2_FIRMWARE_SIZE    646
+#define MBOX2_BOOT_LOADING     0x01 /* Hard coded into the device */
+#define MBOX2_BOOT_READY       0x02 /* Hard coded into the device */
+
+static int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
+{
+	struct usb_host_config *config = dev->actconfig;
+	int err;
+	u8 bootresponse[12];
+	int fwsize;
+	int count;
+
+	fwsize = le16_to_cpu(get_cfg_desc(config)->wTotalLength);
+
+	if (fwsize != MBOX2_FIRMWARE_SIZE) {
+		snd_printk(KERN_ERR "usb-audio: Invalid firmware size=%d.\n", fwsize);
+		return -ENODEV;
+	}
+
+	snd_printd("usb-audio: Sending Digidesign Mbox 2 boot sequence...\n");
+
+	count = 0;
+	bootresponse[0] = MBOX2_BOOT_LOADING;
+	while ((bootresponse[0] == MBOX2_BOOT_LOADING) && (count < 10)) {
+		msleep(500); /* 0.5 second delay */
+		snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
+			/* Control magic - load onboard firmware */
+			0x85, 0xc0, 0x0001, 0x0000, &bootresponse, 0x0012);
+		if (bootresponse[0] == MBOX2_BOOT_READY)
+			break;
+		snd_printd("usb-audio: device not ready, resending boot sequence...\n");
+		count++;
+	}
+
+	if (bootresponse[0] != MBOX2_BOOT_READY) {
+		snd_printk(KERN_ERR "usb-audio: Unknown bootresponse=%d, or timed out, ignoring device.\n", bootresponse[0]);
+		return -ENODEV;
+	}
+
+	snd_printdd("usb-audio: device initialised!\n");
+
+	err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
+		&dev->descriptor, sizeof(dev->descriptor));
+	config = dev->actconfig;
+	if (err < 0)
+		snd_printd("error usb_get_descriptor: %d\n", err);
+
+	err = usb_reset_configuration(dev);
+	if (err < 0)
+		snd_printd("error usb_reset_configuration: %d\n", err);
+	snd_printdd("mbox2_boot: new boot length = %d\n",
+		le16_to_cpu(get_cfg_desc(config)->wTotalLength));
+
+	mbox2_setup_48_24_magic(dev);
+
+	snd_printk(KERN_INFO "usb-audio: Digidesign Mbox 2: 24bit 48kHz");
+
+	return 0; /* Successful boot */
+}
+
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
 {
 	/*
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 1ac3fd9..a8172c1 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -76,6 +76,7 @@ enum quirk_type {
 	QUIRK_MIDI_YAMAHA,
 	QUIRK_MIDI_MIDIMAN,
 	QUIRK_MIDI_NOVATION,
+	QUIRK_MIDI_MBOX2,
 	QUIRK_MIDI_RAW_BYTES,
 	QUIRK_MIDI_EMAGIC,
 	QUIRK_MIDI_CME,

[-- Attachment #3: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
  2012-12-23  2:18                                               ` Damien Zammit
@ 2012-12-23  3:36                                                 ` Damien Zammit
  0 siblings, 0 replies; 27+ messages in thread
From: Damien Zammit @ 2012-12-23  3:36 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Clemens Ladisch, Daniel Mack

Hi,

I have also fixed the "urb status -32" broken pipe issue that arose
because I had not tested it on the hardware. It was midi related.

I realise you guys have already reviewed version 5 of my patch and accepted it.
Version 6 is identical except for some changes that fix the kernel panic issue.
Sorry, I am a beginner with git.
How do I commit the version 5 changes locally and create a new patch
based on version 5?
It would make it easier to review for you guys I think.

I have fixed both the kernel panic and the broken pipe issue with midi.
I believe this completes the patch, I just don't know how to submit it to you.

Damien

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2012-12-23  3:36 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-11-24 12:59 sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2 Damien Zammit
2010-11-25 21:39 ` Daniel Mack
2010-11-29 13:03   ` Damien Zammit
2010-11-29 14:50     ` Takashi Iwai
2010-11-30 11:09       ` Damien Zammit
2010-11-30 15:26         ` Clemens Ladisch
2010-12-14  9:57           ` Damien Zammit
2010-12-27 14:50             ` Damien Zammit
2012-12-13  6:21               ` Damien Zammit
2012-12-13  7:01                 ` Takashi Iwai
2012-12-13 13:09                   ` Damien Zammit
2012-12-13 13:18                     ` Takashi Iwai
2012-12-13 13:27                       ` Takashi Iwai
2012-12-13 14:20                         ` Damien Zammit
2012-12-13 14:59                           ` Takashi Iwai
2012-12-13 15:29                             ` Clemens Ladisch
2012-12-16 10:49                             ` [PATCH] " Damien Zammit
2012-12-16 11:06                               ` Damien Zammit
2012-12-17 10:25                                 ` Takashi Iwai
2012-12-18 12:09                                   ` Damien Zammit
2012-12-18 13:08                                     ` Takashi Iwai
2012-12-19 10:30                                       ` Takashi Iwai
2012-12-19 10:37                                         ` Damien Zammit
2012-12-22 23:38                                           ` Damien Zammit
2012-12-23  0:31                                             ` Damien Zammit
2012-12-23  2:18                                               ` Damien Zammit
2012-12-23  3:36                                                 ` Damien Zammit

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.