ALSA: USB MIDI support for Access Music VirusTI
authorSebastien Alaiwan <sebastien.alaiwan@gmail.com>
Tue, 16 Feb 2010 07:55:08 +0000 (08:55 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 15 Mar 2010 15:49:49 +0000 (08:49 -0700)
commit d39e82db73eb876c60d00f00219d767b3be30307 upstream.

Here's a patch that adds MIDI support through USB for one of the Access
Music synths, the VirusTI.

The synth uses standard USBMIDI protocol on its USB interface 3, although
it does signal "vendor specific" class. A magic string has to be sent on
interface 3 to enable the sending of MIDI from the synth (this string was
found by sniffing usb communication of the Windows driver). This is all
my patch does, and it works on my computer.

Please note that the synth can also do standard usb audio I/O on its
interfaces 2&3, which already works with the current snd-usb-audio driver,
except for the audio input from the synth. I'm going to work on it when I
have some time.

Signed-off-by: Sebastien Alaiwan <sebastien.alaiwan@gmail.com>
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
sound/usb/usbaudio.c
sound/usb/usbmidi.c
sound/usb/usbquirks.h

index f26a1254b0bb595a1d3e260d694655e7ba662573..79633eae6439a5948b0a663ce61ea86e1f4624a6 100644 (file)
@@ -3325,6 +3325,32 @@ static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
        return err;
 }
 
+/*
+ * This call will put the synth in "USB send" mode, i.e it will send MIDI
+ * messages through USB (this is disabled at startup). The synth will
+ * acknowledge by sending a sysex on endpoint 0x85 and by displaying a USB
+ * sign on its LCD. Values here are chosen based on sniffing USB traffic
+ * under Windows.
+ */
+static int snd_usb_accessmusic_boot_quirk(struct usb_device *dev)
+{
+       int err, actual_length;
+
+       /* "midi send" enable */
+       static const u8 seq[] = { 0x4e, 0x73, 0x52, 0x01 };
+
+       void *buf = kmemdup(seq, ARRAY_SIZE(seq), GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+       err = usb_interrupt_msg(dev, usb_sndintpipe(dev, 0x05), buf,
+                       ARRAY_SIZE(seq), &actual_length, 1000);
+       kfree(buf);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
 /*
  * Setup quirks
  */
@@ -3616,6 +3642,12 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
                        goto __err_val;
        }
 
+       /* Access Music VirusTI Desktop */
+       if (id == USB_ID(0x133e, 0x0815)) {
+               if (snd_usb_accessmusic_boot_quirk(dev) < 0)
+                       goto __err_val;
+       }
+
        /*
         * found a config.  now register to ALSA
         */
index 0eff19ceb7e1f9d74653d80c402d3930a6be8bf8..b8958f9e18608a80e136b03cfbf41adb95c5516b 100644 (file)
@@ -1360,6 +1360,12 @@ static struct port_info {
        EXTERNAL_PORT(0x086a, 0x0001, 8, "%s Broadcast"),
        EXTERNAL_PORT(0x086a, 0x0002, 8, "%s Broadcast"),
        EXTERNAL_PORT(0x086a, 0x0003, 4, "%s Broadcast"),
+       /* Access Music Virus TI */
+       EXTERNAL_PORT(0x133e, 0x0815, 0, "%s MIDI"),
+       PORT_INFO(0x133e, 0x0815, 1, "%s Synth", 0,
+               SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
+               SNDRV_SEQ_PORT_TYPE_HARDWARE |
+               SNDRV_SEQ_PORT_TYPE_SYNTHESIZER),
 };
 
 static struct port_info *find_port_info(struct snd_usb_midi* umidi, int number)
index f6f201eb24ceeb00145b406d6fbf18bf09d08817..391e02f5b1996ac0e829b77c6fc306faaf543add 100644 (file)
@@ -2050,6 +2050,33 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 
+/* Access Music devices */
+{
+       /* VirusTI Desktop */
+       USB_DEVICE_VENDOR_SPEC(0x133e, 0x0815),
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = &(const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 3,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = &(const struct snd_usb_midi_endpoint_info) {
+                                       .out_cables = 0x0003,
+                                       .in_cables  = 0x0003
+                               }
+                       },
+                       {
+                               .ifnum = 4,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
+
 /* */
 {
        /* aka. Serato Scratch Live DJ Box */