aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2015-11-15 16:39:08 -0500
committerTakashi Iwai <tiwai@suse.de>2015-11-16 02:59:29 -0500
commita91e627e3f0ed820b11d86cdc04df38f65f33a70 (patch)
tree5c37641e048d18b480c2fcaf03136f2ca455317c
parent1ca8b201309d842642f221db7f02f71c0af5be2d (diff)
ALSA: usb-audio: work around CH345 input SysEx corruption
One of the many faults of the QinHeng CH345 USB MIDI interface chip is that it does not handle received SysEx messages correctly -- every second event packet has a wrong code index number, which is the one from the last seen message, instead of 4. For example, the two messages "FE F0 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E F7" result in the following event packets: correct: CH345: 0F FE 00 00 0F FE 00 00 04 F0 01 02 04 F0 01 02 04 03 04 05 0F 03 04 05 04 06 07 08 04 06 07 08 04 09 0A 0B 0F 09 0A 0B 04 0C 0D 0E 04 0C 0D 0E 05 F7 00 00 05 F7 00 00 A class-compliant driver must interpret an event packet with CIN 15 as having a single data byte, so the other two bytes would be ignored. The message received by the host would then be missing two bytes out of six; in this example, "F0 01 02 03 06 07 08 09 0C 0D 0E F7". These corrupted SysEx event packages contain only data bytes, while the CH345 uses event packets with a correct CIN value only for messages with a status byte, so it is possible to distinguish between these two cases by checking for the presence of this status byte. (Other bugs in the CH345's input handling, such as the corruption resulting from running status, cannot be worked around.) Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Cc: stable@vger.kernel.org Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/usb/midi.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 010094abf752..5b4c58c3e2c5 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -174,6 +174,8 @@ struct snd_usb_midi_in_endpoint {
174 u8 running_status_length; 174 u8 running_status_length;
175 } ports[0x10]; 175 } ports[0x10];
176 u8 seen_f5; 176 u8 seen_f5;
177 bool in_sysex;
178 u8 last_cin;
177 u8 error_resubmit; 179 u8 error_resubmit;
178 int current_port; 180 int current_port;
179}; 181};
@@ -468,6 +470,39 @@ static void snd_usbmidi_maudio_broken_running_status_input(
468} 470}
469 471
470/* 472/*
473 * QinHeng CH345 is buggy: every second packet inside a SysEx has not CIN 4
474 * but the previously seen CIN, but still with three data bytes.
475 */
476static void ch345_broken_sysex_input(struct snd_usb_midi_in_endpoint *ep,
477 uint8_t *buffer, int buffer_length)
478{
479 unsigned int i, cin, length;
480
481 for (i = 0; i + 3 < buffer_length; i += 4) {
482 if (buffer[i] == 0 && i > 0)
483 break;
484 cin = buffer[i] & 0x0f;
485 if (ep->in_sysex &&
486 cin == ep->last_cin &&
487 (buffer[i + 1 + (cin == 0x6)] & 0x80) == 0)
488 cin = 0x4;
489#if 0
490 if (buffer[i + 1] == 0x90) {
491 /*
492 * Either a corrupted running status or a real note-on
493 * message; impossible to detect reliably.
494 */
495 }
496#endif
497 length = snd_usbmidi_cin_length[cin];
498 snd_usbmidi_input_data(ep, 0, &buffer[i + 1], length);
499 ep->in_sysex = cin == 0x4;
500 if (!ep->in_sysex)
501 ep->last_cin = cin;
502 }
503}
504
505/*
471 * CME protocol: like the standard protocol, but SysEx commands are sent as a 506 * CME protocol: like the standard protocol, but SysEx commands are sent as a
472 * single USB packet preceded by a 0x0F byte. 507 * single USB packet preceded by a 0x0F byte.
473 */ 508 */
@@ -660,6 +695,12 @@ static struct usb_protocol_ops snd_usbmidi_cme_ops = {
660 .output_packet = snd_usbmidi_output_standard_packet, 695 .output_packet = snd_usbmidi_output_standard_packet,
661}; 696};
662 697
698static struct usb_protocol_ops snd_usbmidi_ch345_broken_sysex_ops = {
699 .input = ch345_broken_sysex_input,
700 .output = snd_usbmidi_standard_output,
701 .output_packet = snd_usbmidi_output_standard_packet,
702};
703
663/* 704/*
664 * AKAI MPD16 protocol: 705 * AKAI MPD16 protocol:
665 * 706 *
@@ -2380,6 +2421,7 @@ int snd_usbmidi_create(struct snd_card *card,
2380 err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); 2421 err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
2381 break; 2422 break;
2382 case QUIRK_MIDI_CH345: 2423 case QUIRK_MIDI_CH345:
2424 umidi->usb_protocol_ops = &snd_usbmidi_ch345_broken_sysex_ops;
2383 err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); 2425 err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
2384 break; 2426 break;
2385 default: 2427 default: