* snd-usb-audio for Radikal Technologies SAC-2K
@ 2010-10-20 8:04 Raphaël Doursenaud
2010-10-20 9:29 ` Clemens Ladisch
0 siblings, 1 reply; 3+ messages in thread
From: Raphaël Doursenaud @ 2010-10-20 8:04 UTC (permalink / raw)
To: alsa-devel
[-- Attachment #1: Type: text/plain, Size: 1677 bytes --]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi,
I'm working on getting the usb part of this very nice control surface to
work with alsa. I sniffed the usb traffic of the windows driver then
browsed the snd-usb-audio source code for clues.
I managed to get it partially working using a modified QUIRK_MIDI_EMAGIC
since the protocols are fairly similar (at least the 0xF5 port switching
part).
Please find attached the patch I came up to.
I have a few problems and dark areas I hope you'll be able to light up a
little :
First, I more or less get the picture of what the code is doing but
there's one part I fiddled with that I don't understand fully. What are
the .out_cables and .in_cables bitmasks doing besides defining the
number of ports ?
Next, the input part seem to work flawlessly on all ports, but I have
what seems to be a buffer overflow on the device when outputting midi
data. Comparing the windows and linux usb traffic, something obvious
shows up : the windows driver seem to be waiting for the device's
acknowledgment after each sent byte before sending the next one while
the snd-usb-audio module sends a bunch of bytes at once that ends up
confusing the device _and_ module. How can I make it behave like the
windows driver ?
I have traffic and error logs available if needed.
Thanks.
- --
Raphaël Doursenaud
http://raphael.doursenaud.fr
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.16 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAky+oqQACgkQaZKmNAdXaVUopgCgifnK+eSsCNpR5rx21iUqmXBQ
wJIAoJlt4h7Tp8tYYSbg9ZfLekE1QQfL
=d7vi
-----END PGP SIGNATURE-----
[-- Attachment #2: sac-2K.patch --]
[-- Type: text/plain, Size: 6950 bytes --]
diff -Nurp linux-2.6.36-rc6/sound/usb/midi.c linux-2.6.36-rc6.patched/sound/usb/midi.c
--- linux-2.6.36-rc6/sound/usb/midi.c 2010-09-29 03:01:22.000000000 +0200
+++ linux-2.6.36-rc6.patched/sound/usb/midi.c 2010-10-18 00:16:43.146000091 +0200
@@ -59,7 +59,7 @@
/*
* define this to log all USB packets
*/
-/* #define DUMP_PACKETS */
+#define DUMP_PACKETS
/*
* how long to wait after some USB errors, so that khubd can disconnect() us
@@ -987,6 +987,108 @@ static struct usb_protocol_ops snd_usbmi
.finish_out_endpoint = snd_usbmidi_emagic_finish_out,
};
+/*
+ * Radikal USB MIDI protocol: raw MIDI with "F5 xx" port switching and "FF" padded data.
+ */
+
+static void snd_usbmidi_radikal_input(struct snd_usb_midi_in_endpoint* ep,
+ uint8_t* buffer, int buffer_length)
+{
+ int i;
+
+ /* 0xFF indicates end of valid data */
+ for (i = 0; i < buffer_length; ++i)
+ if (buffer[i] == 0xff) {
+ buffer_length = i;
+ break;
+ }
+
+ /* handle 0xF5 at end of last buffer */
+ if (ep->seen_f5)
+ goto switch_port;
+
+ while (buffer_length > 0) {
+ /* determine size of data until next 0xF5 */
+ for (i = 0; i < buffer_length; ++i)
+ if (buffer[i] == 0xf5)
+ break;
+ snd_usbmidi_input_data(ep, ep->current_port, buffer, i);
+ buffer += i;
+ buffer_length -= i;
+
+ if (buffer_length <= 0)
+ break;
+ ep->seen_f5 = 1;
+ ++buffer;
+ --buffer_length;
+
+ switch_port:
+ if (buffer_length <= 0)
+ break;
+ if (buffer[0] < 0x80) {
+ ep->current_port = (buffer[0] - 1) & 15;
+ ++buffer;
+ --buffer_length;
+ }
+ ep->seen_f5 = 0;
+ }
+}
+
+static void snd_usbmidi_radikal_output(struct snd_usb_midi_out_endpoint* ep,
+ struct urb *urb)
+{
+ int port0 = ep->current_port;
+ uint8_t* buf = urb->transfer_buffer;
+ int buf_free = ep->max_transfer;
+ int length, i;
+
+ for (i = 0; i < 0x10; ++i) {
+ /* round-robin, starting at the last current port */
+ int portnum = (port0 + i) & 15;
+ struct usbmidi_out_port* port = &ep->ports[portnum];
+
+ if (!port->active)
+ continue;
+ if (snd_rawmidi_transmit_peek(port->substream, buf, 1) != 1) {
+ port->active = 0;
+ continue;
+ }
+
+ if (portnum != ep->current_port) {
+ if (buf_free < 2)
+ break;
+ ep->current_port = portnum;
+ buf[0] = 0xf5;
+ buf[1] = (portnum + 1) & 15;
+ buf += 2;
+ buf_free -= 2;
+ }
+
+ if (buf_free < 1)
+ break;
+ length = snd_rawmidi_transmit(port->substream, buf, buf_free);
+ if (length > 0) {
+ buf += length;
+ buf_free -= length;
+ if (buf_free < 1)
+ break;
+ }
+ }
+
+ /* pad remaining bytes with 0xFF */
+ while (buf_free < ep->max_transfer && buf_free > 0) {
+ *buf = 0xff;
+ ++buf;
+ --buf_free;
+ }
+ urb->transfer_buffer_length = ep->max_transfer - buf_free;
+}
+
+static struct usb_protocol_ops snd_usbmidi_radikal_ops = {
+ .input = snd_usbmidi_radikal_input,
+ .output = snd_usbmidi_radikal_output,
+};
+
static void update_roland_altsetting(struct snd_usb_midi* umidi)
{
@@ -1533,6 +1635,13 @@ 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"),
+ /* Radikal Technologies */
+ CONTROL_PORT(0x0a35, 0x002a, 0, "%s Control"),
+ EXTERNAL_PORT(0x0a35, 0x002a, 1, "%s MIDI"),
+ CONTROL_PORT(0x0a35, 0x002a, 2, "%s Instrument 3"),
+ CONTROL_PORT(0x0a35, 0x002a, 3, "%s Instrument 4"),
+ CONTROL_PORT(0x0a35, 0x002a, 4, "%s Instrument 5"),
+ CONTROL_PORT(0x0a35, 0x002a, 5, "%s Config"),
/* Akai MPD16 */
CONTROL_PORT(0x09e8, 0x0062, 0, "%s Control"),
PORT_INFO(0x09e8, 0x0062, 1, "%s MIDI", 0,
@@ -2134,6 +2243,12 @@ int snd_usbmidi_create(struct snd_card *
memcpy(&endpoints[0], quirk->data,
sizeof(struct snd_usb_midi_endpoint_info));
err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1);
+ break;
+ case QUIRK_MIDI_RADIKAL:
+ umidi->usb_protocol_ops = &snd_usbmidi_radikal_ops;
+ memcpy(&endpoints[0], quirk->data,
+ sizeof(struct snd_usb_midi_endpoint_info));
+ err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1);
break;
case QUIRK_MIDI_CME:
umidi->usb_protocol_ops = &snd_usbmidi_cme_ops;
diff -Nurp linux-2.6.36-rc6/sound/usb/midi.h linux-2.6.36-rc6.patched/sound/usb/midi.h
--- linux-2.6.36-rc6/sound/usb/midi.h 2010-09-29 03:01:22.000000000 +0200
+++ linux-2.6.36-rc6.patched/sound/usb/midi.h 2010-10-17 03:54:25.066000034 +0200
@@ -35,6 +35,9 @@ struct snd_usb_midi_endpoint_info {
/* for QUIRK_MIDI_EMAGIC, data points to a snd_usb_midi_endpoint_info
* structure (out_cables and in_cables only) */
+/* for QUIRK_MIDI_RADIKAL, data points to a snd_usb_midi_endpoint_info
+ * structure (out_cables and in_cables only) */
+
/* for QUIRK_MIDI_CME, data is NULL */
/* for QUIRK_MIDI_AKAI, data is NULL */
diff -Nurp linux-2.6.36-rc6/sound/usb/quirks-table.h linux-2.6.36-rc6.patched/sound/usb/quirks-table.h
--- linux-2.6.36-rc6/sound/usb/quirks-table.h 2010-09-29 03:01:22.000000000 +0200
+++ linux-2.6.36-rc6.patched/sound/usb/quirks-table.h 2010-10-17 04:39:49.509000034 +0200
@@ -1972,6 +1972,37 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
}
},
+/* Radikal Technologies devices */
+{
+ USB_DEVICE(0x0a35, 0x002a),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ .vendor_name = "Radikal Technologies",
+ .product_name = "SAC-2K",
+ .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_MIDI_RADIKAL,
+ .data = & (const struct snd_usb_midi_endpoint_info) {
+ .out_cables = 0x801f,
+ .in_cables = 0x801f
+ }
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
/* AKAI devices */
{
diff -Nurp linux-2.6.36-rc6/sound/usb/quirks.c linux-2.6.36-rc6.patched/sound/usb/quirks.c
--- linux-2.6.36-rc6/sound/usb/quirks.c 2010-09-29 03:01:22.000000000 +0200
+++ linux-2.6.36-rc6.patched/sound/usb/quirks.c 2010-10-17 03:54:28.202000034 +0200
@@ -289,6 +289,7 @@ int snd_usb_create_quirk(struct snd_usb_
[QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
[QUIRK_MIDI_FASTLANE] = create_any_midi_quirk,
[QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
+ [QUIRK_MIDI_RADIKAL] = create_any_midi_quirk,
[QUIRK_MIDI_CME] = create_any_midi_quirk,
[QUIRK_MIDI_AKAI] = create_any_midi_quirk,
[QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
diff -Nurp linux-2.6.36-rc6/sound/usb/usbaudio.h linux-2.6.36-rc6.patched/sound/usb/usbaudio.h
--- linux-2.6.36-rc6/sound/usb/usbaudio.h 2010-09-29 03:01:22.000000000 +0200
+++ linux-2.6.36-rc6.patched/sound/usb/usbaudio.h 2010-10-17 03:54:37.210000034 +0200
@@ -72,6 +72,7 @@ enum quirk_type {
QUIRK_MIDI_NOVATION,
QUIRK_MIDI_FASTLANE,
QUIRK_MIDI_EMAGIC,
+ QUIRK_MIDI_RADIKAL,
QUIRK_MIDI_CME,
QUIRK_MIDI_AKAI,
QUIRK_MIDI_US122L,
[-- Attachment #3: rdoursenaud.vcf --]
[-- Type: text/x-vcard, Size: 200 bytes --]
begin:vcard
fn;quoted-printable:Rapha=C3=ABl Doursenaud
n;quoted-printable:Doursenaud;Rapha=C3=ABl
email;internet:raphael@doursenaud.fr
url:http://raphael.doursenaud.fr
version:2.1
end:vcard
[-- Attachment #4: Type: text/plain, Size: 160 bytes --]
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: snd-usb-audio for Radikal Technologies SAC-2K
2010-10-20 8:04 snd-usb-audio for Radikal Technologies SAC-2K Raphaël Doursenaud
@ 2010-10-20 9:29 ` Clemens Ladisch
2010-10-20 11:10 ` Raphaël Doursenaud
0 siblings, 1 reply; 3+ messages in thread
From: Clemens Ladisch @ 2010-10-20 9:29 UTC (permalink / raw)
To: Raphaël Doursenaud; +Cc: alsa-devel
Raphaël Doursenaud wrote:
> First, I more or less get the picture of what the code is doing but
> there's one part I fiddled with that I don't understand fully. What are
> the .out_cables and .in_cables bitmasks doing besides defining the
> number of ports ?
The also define the port numbers.
> Next, the input part seem to work flawlessly on all ports, but I have
> what seems to be a buffer overflow on the device when outputting midi
> data. Comparing the windows and linux usb traffic, something obvious
> shows up : the windows driver seem to be waiting for the device's
> acknowledgment after each sent byte before sending the next one while
> the snd-usb-audio module sends a bunch of bytes at once that ends up
> confusing the device _and_ module.
Do you mean that the Windows driver does not submit more than one URB
at once? And that it never puts more than one byte for a port into
one packet? Is it possible that the device want a F5 port number at
the beginning of every packet?
Anyway, all bulk packets must be explicitly accepted by a device,
so if the SAC-2K accepts a packet and then does something wrong,
it's the device's fault.
To force the driver to submit no more than one packet at once,
replace OUTPUT_URBS with a variable and set it to 1 for this device.
Regards,
Clemens
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: snd-usb-audio for Radikal Technologies SAC-2K
2010-10-20 9:29 ` Clemens Ladisch
@ 2010-10-20 11:10 ` Raphaël Doursenaud
0 siblings, 0 replies; 3+ messages in thread
From: Raphaël Doursenaud @ 2010-10-20 11:10 UTC (permalink / raw)
To: Clemens Ladisch; +Cc: alsa-devel
[-- Attachment #1: Type: text/plain, Size: 6620 bytes --]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Le 20/10/2010 11:29, Clemens Ladisch a écrit :
> Raphaël Doursenaud wrote:
>> First, I more or less get the picture of what the code is doing but
>> there's one part I fiddled with that I don't understand fully. What are
>> the .out_cables and .in_cables bitmasks doing besides defining the
>> number of ports ?
>
> The also define the port numbers.
Could you be more explicit ? What's the format ? How is it interpreted ?
I just don't have a clue of how it works, I just set it by trial and
errors… Not really good.
>> Next, the input part seem to work flawlessly on all ports, but I have
>> what seems to be a buffer overflow on the device when outputting midi
>> data. Comparing the windows and linux usb traffic, something obvious
>> shows up : the windows driver seem to be waiting for the device's
>> acknowledgment after each sent byte before sending the next one while
>> the snd-usb-audio module sends a bunch of bytes at once that ends up
>> confusing the device _and_ module.
>
> Do you mean that the Windows driver does not submit more than one URB
> at once? And that it never puts more than one byte for a port into
> one packet? Is it possible that the device want a F5 port number at
> the beginning of every packet?
AFAIK the F5 pn is only sent once. Everything seems good to that respect.
> Anyway, all bulk packets must be explicitly accepted by a device,
> so if the SAC-2K accepts a packet and then does something wrong,
> it's the device's fault.
>
> To force the driver to submit no more than one packet at once,
> replace OUTPUT_URBS with a variable and set it to 1 for this device.
I've investigated with OUTPUT_URBS set to "1" and while the transfer
pattern now looks like the windows one, the device still reacts the same.
Please find the wireshark sniffed USB transfers playing the same MIDI
file from both midi-ox on windows under QEMU and aplaymidi on linux at :
http://raphael.doursenaud.fr/wp-content/uploads/Midi-file-playing-windows.txt
http://raphael.doursenaud.fr/wp-content/uploads/Midi-file-playing-linux.txt
See how the transfers look the same until the device throws a "FE0100"
message at frame 88. From there the device goes wild blinking and
displaying a cryptic error message on its numerical display and stops
outputting midi signal.
If playing long enough, the module throws "MIDI output buffer overrun"
messages before the device disconnects to finally error and lock with that :
seq_lock: timeout [1 left] in sound/core/seq/seq_ports.c:263
rawmidi drain error (avail = 28, buffer_size = 4096)
general protection fault: 0000 [#5] PREEMPT SMP
last sysfs file:
/sys/devices/pci0000:00/0000:00:1f.2/host3/target3:0:0/3:0:0:0/block/sdf/sdf1/stat
CPU 2
Modules linked in: snd_usb_audio snd_usbmidi_lib blackmagic(P) [last
unloaded: snd_usbmidi_lib]
Pid: 27, comm: khubd Tainted: P D 2.6.36-rc8 #1
EP35C-DS3R/EP35C-DS3R
RIP: 0010:[<ffffffff8162d35f>] [<ffffffff8162d35f>]
clear_subscriber_list+0x19f/0x200
RSP: 0018:ffff88011fe3d890 EFLAGS: 00010246
RAX: ffff8800c0910a80 RBX: ffff8800c68afb40 RCX: dead000000100100
RDX: dead000000200200 RSI: 0000000000000282 RDI: ffff8800c0910a80
RBP: ffff8800c0910a00 R08: 0000000000000000 R09: dead000000100100
R10: 0000000000000000 R11: 0000000000000000 R12: ffff8800c0aa62b8
R13: 0000000000000001 R14: ffff8800c0aa62b8 R15: ffff8800c0aa6200
FS: 0000000000000000(0000) GS:ffff880001f00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 00007fb37da18000 CR3: 000000011ddc9000 CR4: 00000000000006f0
DR0: 0000000000000003 DR1: 00000000000000b0 DR2: 0000000000000001
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process khubd (pid: 27, threadinfo ffff88011fe3c000, task ffff88011fe3b8d0)
Stack:
ffff88011fe3d8f0 ffff8800c0910a80 ffff8800c0910a68 ffff88011bbd1880
<0> ffff88011bab0c00 ffff88011b2a9cc0 ffffffff819a94c3 ffff8800c0aa6200
<0> ffff88011bbd1880 0000000000000002 ffff88011bab0c50 0000000000000006
Call Trace:
[<ffffffff8162d410>] ? port_delete+0x50/0x80
[<ffffffff81628f1c>] ? snd_seq_ioctl_delete_port+0x4c/0x70
[<ffffffff81625e60>] ? snd_seq_kernel_client_ctl+0x60/0x70
[<ffffffff8162c940>] ? snd_seq_event_port_detach+0x30/0x40
[<ffffffff81633ae8>] ? snd_seq_midisynth_delete+0x18/0x40
[<ffffffff81633ba3>] ? snd_seq_midisynth_unregister_port+0x93/0x120
[<ffffffff8162dd64>] ? free_device+0x34/0xb0
[<ffffffff8162e3b5>] ? snd_seq_device_dev_disconnect+0x35/0x50
[<ffffffff816068e2>] ? snd_device_disconnect+0x42/0x80
[<ffffffff81606954>] ? snd_device_disconnect_all+0x34/0x60
[<ffffffff816019af>] ? snd_card_disconnect+0x19f/0x230
[<ffffffffa002117c>] ? usb_audio_disconnect+0xac/0x1c0 [snd_usb_audio]
[<ffffffff8155bdb4>] ? usb_unbind_interface+0xc4/0x120
[<ffffffff814d0560>] ? __device_release_driver+0x60/0xd0
[<ffffffff814d06a5>] ? device_release_driver+0x25/0x40
[<ffffffff814cf7ad>] ? bus_remove_device+0x9d/0xe0
[<ffffffff814cd720>] ? device_del+0x120/0x1c0
[<ffffffff8155945a>] ? usb_disable_device+0x9a/0x120
[<ffffffff815530db>] ? usb_disconnect+0x8b/0x130
[<ffffffff815531d9>] ? hub_quiesce+0x59/0xc0
[<ffffffff8155325a>] ? hub_pre_reset+0x1a/0x30
[<ffffffff81554135>] ? usb_reset_device+0x45/0x160
[<ffffffff81555072>] ? hub_thread+0xcd2/0x10e0
[<ffffffff810618af>] ? dequeue_task_fair+0x4f/0x190
[<ffffffff81082ac0>] ? autoremove_wake_function+0x0/0x30
[<ffffffff815543a0>] ? hub_thread+0x0/0x10e0
[<ffffffff815543a0>] ? hub_thread+0x0/0x10e0
[<ffffffff81082646>] ? kthread+0x96/0xa0
[<ffffffff8102ad94>] ? kernel_thread_helper+0x4/0x10
[<ffffffff810825b0>] ? kthread+0x0/0xa0
[<ffffffff8102ad90>] ? kernel_thread_helper+0x0/0x10
Code: 48 89 44 24 10 48 8d 85 80 00 00 00 48 89 c7 48 89 44 24 08 e8 23
d3 15 00 48 8b 4b 50 48 8b 53 58 49 b9 00 01 10 00 00 00 ad de <48> 89
51 08 49 b8 00 02 20 00 00 00 ad de 48 89 0a 4c 89 4b 50
RIP [<ffffffff8162d35f>] clear_subscriber_list+0x19f/0x200
RSP <ffff88011fe3d890>
- ---[ end trace 4d12c4e83f4f7bf8 ]---
seq_lock: timeout [1 left] in sound/core/seq/seq_clientmgr.c:277
I'm scratching my head now… Any clues on what might be going on ?
Thanks !
- --
Raphaël Doursenaud
http://raphael.doursenaud.fr
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.16 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAky+zgsACgkQaZKmNAdXaVVibQCcDVMf+pgQsMQ9ji4WSwZr0OpT
0xgAn339wFljNSX1LXPZsUQYo/sYUNXN
=gY01
-----END PGP SIGNATURE-----
[-- Attachment #2: rdoursenaud.vcf --]
[-- Type: text/x-vcard, Size: 200 bytes --]
begin:vcard
fn;quoted-printable:Rapha=C3=ABl Doursenaud
n;quoted-printable:Doursenaud;Rapha=C3=ABl
email;internet:raphael@doursenaud.fr
url:http://raphael.doursenaud.fr
version:2.1
end:vcard
[-- Attachment #3: Type: text/plain, Size: 160 bytes --]
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2010-10-20 11:12 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-20 8:04 snd-usb-audio for Radikal Technologies SAC-2K Raphaël Doursenaud
2010-10-20 9:29 ` Clemens Ladisch
2010-10-20 11:10 ` Raphaël Doursenaud
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.