]>
Commit | Line | Data |
---|---|---|
cdf7fead GKH |
1 | From 1ca8b201309d842642f221db7f02f71c0af5be2d Mon Sep 17 00:00:00 2001 |
2 | From: Clemens Ladisch <clemens@ladisch.de> | |
3 | Date: Sun, 15 Nov 2015 22:38:29 +0100 | |
4 | Subject: ALSA: usb-audio: prevent CH345 multiport output SysEx corruption | |
5 | ||
6 | From: Clemens Ladisch <clemens@ladisch.de> | |
7 | ||
8 | commit 1ca8b201309d842642f221db7f02f71c0af5be2d upstream. | |
9 | ||
10 | The CH345 USB MIDI chip has two output ports. However, they are | |
11 | multiplexed through one pin, and the number of ports cannot be reduced | |
12 | even for hardware that implements only one connector, so for those | |
13 | devices, data sent to either port ends up on the same hardware output. | |
14 | This becomes a problem when both ports are used at the same time, as | |
15 | longer MIDI commands (such as SysEx messages) are likely to be | |
16 | interrupted by messages from the other port, and thus to get lost. | |
17 | ||
18 | It would not be possible for the driver to detect how many ports the | |
19 | device actually has, except that in practice, _all_ devices built with | |
20 | the CH345 have only one port. So we can just ignore the device's | |
21 | descriptors, and hardcode one output port. | |
22 | ||
23 | Signed-off-by: Clemens Ladisch <clemens@ladisch.de> | |
24 | Signed-off-by: Takashi Iwai <tiwai@suse.de> | |
25 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
26 | ||
27 | --- | |
28 | sound/usb/midi.c | 3 +++ | |
29 | sound/usb/quirks-table.h | 11 +++++++++++ | |
30 | sound/usb/quirks.c | 1 + | |
31 | sound/usb/usbaudio.h | 1 + | |
32 | 4 files changed, 16 insertions(+) | |
33 | ||
34 | --- a/sound/usb/midi.c | |
35 | +++ b/sound/usb/midi.c | |
36 | @@ -2217,6 +2217,9 @@ int snd_usbmidi_create(struct snd_card * | |
37 | ||
38 | err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); | |
39 | break; | |
40 | + case QUIRK_MIDI_CH345: | |
41 | + err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); | |
42 | + break; | |
43 | default: | |
44 | snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); | |
45 | err = -ENXIO; | |
46 | --- a/sound/usb/quirks-table.h | |
47 | +++ b/sound/usb/quirks-table.h | |
48 | @@ -3041,6 +3041,17 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |
49 | .idProduct = 0x1020, | |
50 | }, | |
51 | ||
52 | +/* QinHeng devices */ | |
53 | +{ | |
54 | + USB_DEVICE(0x1a86, 0x752d), | |
55 | + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { | |
56 | + .vendor_name = "QinHeng", | |
57 | + .product_name = "CH345", | |
58 | + .ifnum = 1, | |
59 | + .type = QUIRK_MIDI_CH345 | |
60 | + } | |
61 | +}, | |
62 | + | |
63 | /* KeithMcMillen Stringport */ | |
64 | { | |
65 | USB_DEVICE(0x1f38, 0x0001), | |
66 | --- a/sound/usb/quirks.c | |
67 | +++ b/sound/usb/quirks.c | |
68 | @@ -313,6 +313,7 @@ int snd_usb_create_quirk(struct snd_usb_ | |
69 | [QUIRK_MIDI_CME] = create_any_midi_quirk, | |
70 | [QUIRK_MIDI_AKAI] = create_any_midi_quirk, | |
71 | [QUIRK_MIDI_FTDI] = create_any_midi_quirk, | |
72 | + [QUIRK_MIDI_CH345] = create_any_midi_quirk, | |
73 | [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, | |
74 | [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, | |
75 | [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, | |
76 | --- a/sound/usb/usbaudio.h | |
77 | +++ b/sound/usb/usbaudio.h | |
78 | @@ -83,6 +83,7 @@ enum quirk_type { | |
79 | QUIRK_MIDI_AKAI, | |
80 | QUIRK_MIDI_US122L, | |
81 | QUIRK_MIDI_FTDI, | |
82 | + QUIRK_MIDI_CH345, | |
83 | QUIRK_AUDIO_STANDARD_INTERFACE, | |
84 | QUIRK_AUDIO_FIXED_ENDPOINT, | |
85 | QUIRK_AUDIO_EDIROL_UAXX, |