diff options
Diffstat (limited to 'sound/usb/midi.c')
-rw-r--r-- | sound/usb/midi.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/sound/usb/midi.c b/sound/usb/midi.c index 7661616f3636..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 | */ | ||
476 | static 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 | ||
698 | static 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 | * |
@@ -1341,6 +1382,7 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi, | |||
1341 | * Various chips declare a packet size larger than 4 bytes, but | 1382 | * Various chips declare a packet size larger than 4 bytes, but |
1342 | * do not actually work with larger packets: | 1383 | * do not actually work with larger packets: |
1343 | */ | 1384 | */ |
1385 | case USB_ID(0x0a67, 0x5011): /* Medeli DD305 */ | ||
1344 | case USB_ID(0x0a92, 0x1020): /* ESI M4U */ | 1386 | case USB_ID(0x0a92, 0x1020): /* ESI M4U */ |
1345 | case USB_ID(0x1430, 0x474b): /* RedOctane GH MIDI INTERFACE */ | 1387 | case USB_ID(0x1430, 0x474b): /* RedOctane GH MIDI INTERFACE */ |
1346 | case USB_ID(0x15ca, 0x0101): /* Textech USB Midi Cable */ | 1388 | case USB_ID(0x15ca, 0x0101): /* Textech USB Midi Cable */ |
@@ -2378,6 +2420,10 @@ int snd_usbmidi_create(struct snd_card *card, | |||
2378 | 2420 | ||
2379 | err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); | 2421 | err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); |
2380 | break; | 2422 | break; |
2423 | case QUIRK_MIDI_CH345: | ||
2424 | umidi->usb_protocol_ops = &snd_usbmidi_ch345_broken_sysex_ops; | ||
2425 | err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); | ||
2426 | break; | ||
2381 | default: | 2427 | default: |
2382 | dev_err(&umidi->dev->dev, "invalid quirk type %d\n", | 2428 | dev_err(&umidi->dev->dev, "invalid quirk type %d\n", |
2383 | quirk->type); | 2429 | quirk->type); |