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