Hi,
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.
Regards,
Sebastien Alaiwan
Signed-off-by: Sebastien Alaiwan <[email protected]>
--------------
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 9edef46..bb82ee9 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -3327,6 +3327,26 @@ static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
}
/*
+ * 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 aknowledge
+ * 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;
+ u8 seq[] = { 0x4e, 0x73, 0x52, 0x01 }; // "midi send" enable
+
+ err = usb_interrupt_msg(dev, usb_sndintpipe(dev, 0x05), seq,
+ ARRAY_SIZE(seq), &actual_length, 1000);
+ if(err < 0) {
+ return err;
+ }
+
+ return 0;
+}
+
+/*
* Setup quirks
*/
#define AUDIOPHILE_SET 0x01 /* if set, parse device_setup */
@@ -3403,6 +3423,7 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip,
[QUIRK_MIDI_FASTLANE] = create_any_midi_quirk,
[QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
[QUIRK_MIDI_CME] = create_any_midi_quirk,
+ [QUIRK_MIDI_ACCESSMUSIC] = create_any_midi_quirk,
[QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
[QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
[QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk,
@@ -3624,6 +3645,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
*/
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 40ba811..b69b5bf 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -156,6 +156,7 @@ enum quirk_type {
QUIRK_MIDI_EMAGIC,
QUIRK_MIDI_CME,
QUIRK_MIDI_US122L,
+ QUIRK_MIDI_ACCESSMUSIC,
QUIRK_AUDIO_STANDARD_INTERFACE,
QUIRK_AUDIO_FIXED_ENDPOINT,
QUIRK_AUDIO_EDIROL_UA1000,
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 6e89b83..3db92e0 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -1724,6 +1724,28 @@ static int snd_usbmidi_detect_per_port_endpoints(struct snd_usb_midi* umidi,
}
/*
+ * Detects the endpoints for Access Music Virus TI
+ */
+static int snd_usbmidi_detect_two_cables_per_endpoint(struct snd_usb_midi* umidi,
+ struct snd_usb_midi_endpoint_info* endpoints)
+{
+ int err, i;
+
+ err = snd_usbmidi_detect_endpoints(umidi, endpoints, MIDI_MAX_ENDPOINTS);
+ for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
+ if (endpoints[i].in_ep) {
+ printk("Creating two in cables for input EP 0x%.2X\n", endpoints[i].in_ep);
+ endpoints[i].in_cables = 0x0003;
+ }
+ if (endpoints[i].out_ep) {
+ printk("Creating two out cables for output EP 0x%.2X\n", endpoints[i].out_ep);
+ endpoints[i].out_cables = 0x0003;
+ }
+ }
+ return err;
+}
+
+/*
* Detects the endpoints and ports of Yamaha devices.
*/
static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi,
@@ -2002,6 +2024,9 @@ int snd_usbmidi_create(struct snd_card *card,
umidi->usb_protocol_ops = &snd_usbmidi_cme_ops;
err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
break;
+ case QUIRK_MIDI_ACCESSMUSIC:
+ err = snd_usbmidi_detect_two_cables_per_endpoint(umidi, endpoints);
+ break;
default:
snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
err = -ENXIO;
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index a892bda..709e076 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -2105,6 +2105,28 @@ 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) {
+ .vendor_name = "AccessMusic",
+ .product_name = "Virus TI",
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = & (const struct snd_usb_audio_quirk[]) {
+ {
+ // "Virus TI MIDI" and "Virus TI Synth"
+ .ifnum = 3,
+ .type = QUIRK_MIDI_ACCESSMUSIC,
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
+
{
/*
* Some USB MIDI devices don't have an audio control interface,
Sebastien Alaiwan wrote:
> here's a patch that adds MIDI support through USB for one of the
> Access Music synths, the VirusTI.
Thanks!
Please run the checkpatch script on your patch.
> + u8 seq[] = { 0x4e, 0x73, 0x52, 0x01 }; // "midi send" enable
> +
> + err = usb_interrupt_msg(dev, usb_sndintpipe(dev, 0x05), seq,
> + ARRAY_SIZE(seq), &actual_length, 1000);
There are architectures where doing DMA with data on the stack is not
possible. Have a look at send_bulk_static_data.
> /*
> + * Detects the endpoints for Access Music Virus TI
> + */
> +static int snd_usbmidi_detect_two_cables_per_endpoint(struct snd_usb_midi* umidi,
> + struct snd_usb_midi_endpoint_info* endpoints)
> +{
> + int err, i;
> +
> + err = snd_usbmidi_detect_endpoints(umidi, endpoints, MIDI_MAX_ENDPOINTS);
> + for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
> + if (endpoints[i].in_ep) {
> + printk("Creating two in cables for input EP 0x%.2X\n", endpoints[i].in_ep);
If this is just for debugging, use snd_printdd.
> + endpoints[i].in_cables = 0x0003;
> + }
> + if (endpoints[i].out_ep) {
> + printk("Creating two out cables for output EP 0x%.2X\n", endpoints[i].out_ep);
> + endpoints[i].out_cables = 0x0003;
> + }
> + }
> + return err;
> +}
Does this device use more than one endpoint per direction? If not, this
could be done with QUIRK_MIDI_FIXED_ENDPOINT.
> +++ b/sound/usb/usbquirks.h
> @@ -2105,6 +2105,28 @@
> }
> },
>
> +/* Access Music devices */
> +{
> + /* VirusTI Desktop */
> + USB_DEVICE_VENDOR_SPEC(0x133e, 0x0815),
Please keep the list sorted (as much as possible).
> + .vendor_name = "AccessMusic",
> + .product_name = "Virus TI",
These are needed only if the device hasn't vendor/product strings.
> + // "Virus TI MIDI" and "Virus TI Synth"
If these are port names, put them into the snd_usbmidi_port_info array.
Regards,
Clemens
Clemens Ladisch wrote:
> Sebastien Alaiwan wrote:
>> here's a patch that adds MIDI support through USB for one of the
>> Access Music synths, the VirusTI.
>
> Thanks!
>
> Please run the checkpatch script on your patch.
Done!
I did not know such a tool did exist, thank you for pointing this out. Is there
a document I could read about such rules of thumb?
>> + endpoints[i].in_cables = 0x0003;
>> + }
>> + if (endpoints[i].out_ep) {
>> + printk("Creating two out cables for output EP 0x%.2X\n", endpoints[i].out_ep);
>> + endpoints[i].out_cables = 0x0003;
>> + }
>> + }
>> + return err;
>> +}
>
> Does this device use more than one endpoint per direction? If not, this
> could be done with QUIRK_MIDI_FIXED_ENDPOINT.
There's only one endpoint per direction, but there are two cables per endpoint:
endpoint 0x05, cable 0 : physical MIDI output port of the device.
endpoint 0x05, cable 1 : synth (output: send note-on, etc...)
endpoint 0x85, cable 0 : physical MIDI input port of the device.
endpoint 0x85, cable 1 : synth (input: recv sysex, controller changes)
Please correct me if I'm wrong, but it seems QUIRK_MIDI_FIXED_ENDPOINT would not
do the job, otherwise where do I signal the number of cables?
Here's an updated patch below.
Regards,
Sebastien Alaiwan
-------------
Signed-off-by: Sebastien Alaiwan <[email protected]>
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 9edef46..0e54e93 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -3327,6 +3327,29 @@ static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
}
/*
+ * 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 aknowledge
+ * 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;
+ u8 seq[] = { 0x4e, 0x73, 0x52, 0x01 }; /* "midi send" enable */
+
+ 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
*/
#define AUDIOPHILE_SET 0x01 /* if set, parse device_setup */
@@ -3403,6 +3426,7 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip,
[QUIRK_MIDI_FASTLANE] = create_any_midi_quirk,
[QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
[QUIRK_MIDI_CME] = create_any_midi_quirk,
+ [QUIRK_MIDI_ACCESSMUSIC] = create_any_midi_quirk,
[QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
[QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
[QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk,
@@ -3624,6 +3648,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
*/
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 40ba811..b69b5bf 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -156,6 +156,7 @@ enum quirk_type {
QUIRK_MIDI_EMAGIC,
QUIRK_MIDI_CME,
QUIRK_MIDI_US122L,
+ QUIRK_MIDI_ACCESSMUSIC,
QUIRK_AUDIO_STANDARD_INTERFACE,
QUIRK_AUDIO_FIXED_ENDPOINT,
QUIRK_AUDIO_EDIROL_UA1000,
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 6e89b83..6e48606 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -1407,6 +1407,9 @@ 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"),
+ CONTROL_PORT(0x133e, 0x0815, 1, "%s Control"),
};
static struct port_info *find_port_info(struct snd_usb_midi* umidi, int number)
@@ -1724,6 +1727,32 @@ static int snd_usbmidi_detect_per_port_endpoints(struct snd_usb_midi* umidi,
}
/*
+ * Detects the endpoints for Access Music Virus TI
+ */
+static int snd_usbmidi_detect_two_cables_per_endpoint(
+ struct snd_usb_midi *umidi,
+ struct snd_usb_midi_endpoint_info *endpoints)
+{
+ int err, i;
+
+ err = snd_usbmidi_detect_endpoints(umidi, endpoints,
+ MIDI_MAX_ENDPOINTS);
+ for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
+ if (endpoints[i].in_ep) {
+ snd_printdd("Creating 2 cables for input EP 0x%.2X\n",
+ endpoints[i].in_ep);
+ endpoints[i].in_cables = 0x0003;
+ }
+ if (endpoints[i].out_ep) {
+ snd_printdd("Creating 2 cables for output EP 0x%.2X\n",
+ endpoints[i].out_ep);
+ endpoints[i].out_cables = 0x0003;
+ }
+ }
+ return err;
+}
+
+/*
* Detects the endpoints and ports of Yamaha devices.
*/
static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi,
@@ -2002,6 +2031,10 @@ int snd_usbmidi_create(struct snd_card *card,
umidi->usb_protocol_ops = &snd_usbmidi_cme_ops;
err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
break;
+ case QUIRK_MIDI_ACCESSMUSIC:
+ err = snd_usbmidi_detect_two_cables_per_endpoint(umidi,
+ endpoints);
+ break;
default:
snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
err = -ENXIO;
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index a892bda..759f824 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -2073,6 +2073,26 @@ 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[]) {
+ {
+ /* "Virus TI MIDI" and "Virus TI Synth" */
+ .ifnum = 3,
+ .type = QUIRK_MIDI_ACCESSMUSIC,
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
+
/* */
{
/* aka. Serato Scratch Live DJ Box */
Sebastien Alaiwan wrote:
> Clemens Ladisch wrote:
>> Please run the checkpatch script on your patch.
>
> Done!
> I did not know such a tool did exist, thank you for pointing this out. Is there
> a document I could read about such rules of thumb?
Documentation/CodingStyle
Documentation/SubmitChecklist
Documentation/SubmittingDrivers
Documentation/SubmittingPatches
>> Does this device use more than one endpoint per direction? If not, this
>> could be done with QUIRK_MIDI_FIXED_ENDPOINT.
>
> There's only one endpoint per direction, but there are two cables per endpoint:
> endpoint 0x05, cable 0 : physical MIDI output port of the device.
> endpoint 0x05, cable 1 : synth (output: send note-on, etc...)
> endpoint 0x85, cable 0 : physical MIDI input port of the device.
> endpoint 0x85, cable 1 : synth (input: recv sysex, controller changes)
>
> Please correct me if I'm wrong, but it seems QUIRK_MIDI_FIXED_ENDPOINT would not
> do the job, otherwise where do I signal the number of cables?
With the bits in the out/in_cables fields.
> + u8 seq[] = { 0x4e, 0x73, 0x52, 0x01 }; /* "midi send" enable */
This should be static const.
> @@ -1407,6 +1407,9 @@ 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"),
> + CONTROL_PORT(0x133e, 0x0815, 1, "%s Control"),
According to your description, this is not a control port but should be
called "Synth". There is no helper macro for a generic MIDI port; use
something like this:
PORT_INFO(0x133e, 0x0815, 1, "%s Synth", numberofvoices,
SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
SNDRV_SEQ_PORT_TYPE_MIDI_GM |
SNDRV_SEQ_PORT_TYPE_HARDWARE |
SNDRV_SEQ_PORT_TYPE_SYNTHESIZER),
and add flags for any other supported MIDI standards.
> + /* 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[]) {
> + {
> + /* "Virus TI MIDI" and "Virus TI Synth" */
> + .ifnum = 3,
> + .type = QUIRK_MIDI_ACCESSMUSIC,
> + },
> + {
> + .ifnum = -1
> + }
> + }
> + }
> +},
For only one interface, you don't need to use QUIRK_COMPOSITE; see the
entry for the UM-880.
Regards,
Clemens
Hello,
Thanks for your advice!
Clemens Ladisch wrote:
> For only one interface, you don't need to use QUIRK_COMPOSITE; see the
> entry for the UM-880.
I've replaced the QUIRK_COMPOSITE by a QUIRK_MIDI_FIXED_ENDPOINT, the module also probes (and fails) the USB interface 4 (I don't know what this interface is for on this device) which results in the printing of an error in the kernel log. How can I inform the snd-usb-audio driver that the USB interface 4 should be left alone?
Please find an updated (and shrinked!) patch below.
Signed-off-by: Sebastien Alaiwan <[email protected]>
---
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 9edef46..aaf8f7c 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -3327,6 +3327,31 @@ static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
}
/*
+ * 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 aknowledge
+ * 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
*/
#define AUDIOPHILE_SET 0x01 /* if set, parse device_setup */
@@ -3624,6 +3649,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
*/
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 6e89b83..8f5bc1e 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -1407,6 +1407,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)
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index a892bda..853788d 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -2073,6 +2073,20 @@ 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 = 3,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = &(const struct snd_usb_midi_endpoint_info) {
+ .out_cables = 0x0003,
+ .in_cables = 0x0003
+ }
+ }
+},
+
/* */
{
/* aka. Serato Scratch Live DJ Box */
Sebastien Alaiwan wrote:
> I've replaced the QUIRK_COMPOSITE by a QUIRK_MIDI_FIXED_ENDPOINT, the
> module also probes (and fails) the USB interface 4 (I don't know
> what this interface is for on this device) which results in the
> printing of an error in the kernel log. How can I inform the
> snd-usb-audio driver that the USB interface 4 should be left alone?
With a QUIRK_IGNORE_INTERFACE for that interface. This means you need
QUIRK_COMPOSITE again.
HTH
Clemens
Clemens Ladisch wrote:
> Sebastien Alaiwan wrote:
>> I've replaced the QUIRK_COMPOSITE by a QUIRK_MIDI_FIXED_ENDPOINT, the
>> module also probes (and fails) the USB interface 4 (I don't know
>> what this interface is for on this device) which results in the
>> printing of an error in the kernel log. How can I inform the
>> snd-usb-audio driver that the USB interface 4 should be left alone?
>
> With a QUIRK_IGNORE_INTERFACE for that interface. This means you need
> QUIRK_COMPOSITE again.
>
>
> HTH
> Clemens
Ok, this is done.
Here's an updated patch.
Thank you for your help!
Sebastien Alaiwan
---
Signed-off-by: Sebastien Alaiwan <[email protected]>
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 9edef46..aaf8f7c 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -3327,6 +3327,31 @@ static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
}
/*
+ * 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 aknowledge
+ * 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
*/
#define AUDIOPHILE_SET 0x01 /* if set, parse device_setup */
@@ -3624,6 +3649,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
*/
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 6e89b83..8f5bc1e 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -1407,6 +1407,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)
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index a892bda..ef8f96c 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -2073,6 +2073,31 @@ 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
+ },
+ }
+ }
+},
+
/* */
{
/* aka. Serato Scratch Live DJ Box */
Sebastien Alaiwan wrote:
> Clemens Ladisch wrote:
>> Sebastien Alaiwan wrote:
>>> How can I inform the
>>> snd-usb-audio driver that the USB interface 4 should be left alone?
>>
>> With a QUIRK_IGNORE_INTERFACE for that interface. This means you need
>> QUIRK_COMPOSITE again.
>
> Ok, this is done.
> Here's an updated patch.
Applied; thanks!
Clemens