diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2013-03-31 17:43:12 -0400 |
---|---|---|
committer | Clemens Ladisch <clemens@ladisch.de> | 2013-06-27 15:59:48 -0400 |
commit | aafe77cc45a595ca1d4536f2412ddf671ea9108c (patch) | |
tree | f21cc9256d40ece84da14b0c10d097fe859d4cdb /sound/usb | |
parent | ba7c2be114243fa4cfcbc66a81db18e1d55abf4b (diff) |
ALSA: usb-audio: add support for many Roland/Yamaha devices
Add quirks to detect the various vendor-specific descriptors used by
Roland and Yamaha in most of their recent USB audio and MIDI devices.
Together with the previous patch, this should add audio/MIDI support for
the following USB devices:
- Edirol motion dive .tokyo performance package
- Roland MC-808 Synthesizer
- Roland BK-7m Synthesizer
- Roland VIMA JM-5/8 Synthesizer
- Roland SP-555 Sequencer
- Roland V-Synth GT Synthesizer
- Roland Music Atelier AT-75/100/300/350C/500/800/900/900C Organ
- Edirol V-Mixer M-200i/300/380/400/480/R-1000
- BOSS GT-10B Effects Processor
- Roland Fantom G6/G7/G8 Keyboard
- Cakewalk Sonar V-Studio 20/100/700 Audio Interface
- Roland GW-8 Keyboard
- Roland AX-Synth Keyboard
- Roland JUNO-Di/STAGE/Gi Keyboard
- Roland VB-99 Effects Processor
- Cakewalk UM-2G MIDI Interface
- Roland A-500S Keyboard
- Roland SD-50 Synthesizer
- Roland OCTAPAD SPD-30 Controller
- Roland Lucina AX-09 Synthesizer
- BOSS BR-800 Digital Recorder
- Roland DUO/TRI-CAPTURE (EX) Audio Interface
- BOSS RC-300 Loop Station
- Roland JUPITER-50/80 Keyboard
- Roland R-26 Recorder
- Roland SPD-SX Controller
- BOSS JS-10 Audio Player
- Roland TD-11/15/30 Drum Module
- Roland A-49/88 Keyboard
- Roland INTEGRA-7 Synthesizer
- Roland R-88 Recorder
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/midi.c | 41 | ||||
-rw-r--r-- | sound/usb/quirks-table.h | 22 | ||||
-rw-r--r-- | sound/usb/quirks.c | 175 | ||||
-rw-r--r-- | sound/usb/stream.c | 15 | ||||
-rw-r--r-- | sound/usb/usbaudio.h | 2 |
5 files changed, 252 insertions, 3 deletions
diff --git a/sound/usb/midi.c b/sound/usb/midi.c index 8e01fa4991c5..63dd0545a672 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c | |||
@@ -1948,6 +1948,44 @@ static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi, | |||
1948 | } | 1948 | } |
1949 | 1949 | ||
1950 | /* | 1950 | /* |
1951 | * Detects the endpoints and ports of Roland devices. | ||
1952 | */ | ||
1953 | static int snd_usbmidi_detect_roland(struct snd_usb_midi* umidi, | ||
1954 | struct snd_usb_midi_endpoint_info* endpoint) | ||
1955 | { | ||
1956 | struct usb_interface* intf; | ||
1957 | struct usb_host_interface *hostif; | ||
1958 | u8* cs_desc; | ||
1959 | |||
1960 | intf = umidi->iface; | ||
1961 | if (!intf) | ||
1962 | return -ENOENT; | ||
1963 | hostif = intf->altsetting; | ||
1964 | /* | ||
1965 | * Some devices have a descriptor <06 24 F1 02 <inputs> <outputs>>, | ||
1966 | * some have standard class descriptors, or both kinds, or neither. | ||
1967 | */ | ||
1968 | for (cs_desc = hostif->extra; | ||
1969 | cs_desc < hostif->extra + hostif->extralen && cs_desc[0] >= 2; | ||
1970 | cs_desc += cs_desc[0]) { | ||
1971 | if (cs_desc[0] >= 6 && | ||
1972 | cs_desc[1] == USB_DT_CS_INTERFACE && | ||
1973 | cs_desc[2] == 0xf1 && | ||
1974 | cs_desc[3] == 0x02) { | ||
1975 | endpoint->in_cables = (1 << cs_desc[4]) - 1; | ||
1976 | endpoint->out_cables = (1 << cs_desc[5]) - 1; | ||
1977 | return snd_usbmidi_detect_endpoints(umidi, endpoint, 1); | ||
1978 | } else if (cs_desc[0] >= 7 && | ||
1979 | cs_desc[1] == USB_DT_CS_INTERFACE && | ||
1980 | cs_desc[2] == UAC_HEADER) { | ||
1981 | return snd_usbmidi_get_ms_info(umidi, endpoint); | ||
1982 | } | ||
1983 | } | ||
1984 | |||
1985 | return -ENODEV; | ||
1986 | } | ||
1987 | |||
1988 | /* | ||
1951 | * Creates the endpoints and their ports for Midiman devices. | 1989 | * Creates the endpoints and their ports for Midiman devices. |
1952 | */ | 1990 | */ |
1953 | static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi, | 1991 | static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi, |
@@ -2162,6 +2200,9 @@ int snd_usbmidi_create(struct snd_card *card, | |||
2162 | case QUIRK_MIDI_YAMAHA: | 2200 | case QUIRK_MIDI_YAMAHA: |
2163 | err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]); | 2201 | err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]); |
2164 | break; | 2202 | break; |
2203 | case QUIRK_MIDI_ROLAND: | ||
2204 | err = snd_usbmidi_detect_roland(umidi, &endpoints[0]); | ||
2205 | break; | ||
2165 | case QUIRK_MIDI_MIDIMAN: | 2206 | case QUIRK_MIDI_MIDIMAN: |
2166 | umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops; | 2207 | umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops; |
2167 | memcpy(&endpoints[0], quirk->data, | 2208 | memcpy(&endpoints[0], quirk->data, |
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 7f1722f82c89..b47517d47b08 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h | |||
@@ -455,6 +455,17 @@ YAMAHA_DEVICE(0x7000, "DTX"), | |||
455 | YAMAHA_DEVICE(0x7010, "UB99"), | 455 | YAMAHA_DEVICE(0x7010, "UB99"), |
456 | #undef YAMAHA_DEVICE | 456 | #undef YAMAHA_DEVICE |
457 | #undef YAMAHA_INTERFACE | 457 | #undef YAMAHA_INTERFACE |
458 | /* this catches most recent vendor-specific Yamaha devices */ | ||
459 | { | ||
460 | .match_flags = USB_DEVICE_ID_MATCH_VENDOR | | ||
461 | USB_DEVICE_ID_MATCH_INT_CLASS, | ||
462 | .idVendor = 0x0499, | ||
463 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
464 | .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { | ||
465 | .ifnum = QUIRK_ANY_INTERFACE, | ||
466 | .type = QUIRK_AUTODETECT | ||
467 | } | ||
468 | }, | ||
458 | 469 | ||
459 | /* | 470 | /* |
460 | * Roland/RolandED/Edirol/BOSS devices | 471 | * Roland/RolandED/Edirol/BOSS devices |
@@ -2031,6 +2042,17 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
2031 | } | 2042 | } |
2032 | } | 2043 | } |
2033 | }, | 2044 | }, |
2045 | /* this catches most recent vendor-specific Roland devices */ | ||
2046 | { | ||
2047 | .match_flags = USB_DEVICE_ID_MATCH_VENDOR | | ||
2048 | USB_DEVICE_ID_MATCH_INT_CLASS, | ||
2049 | .idVendor = 0x0582, | ||
2050 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
2051 | .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { | ||
2052 | .ifnum = QUIRK_ANY_INTERFACE, | ||
2053 | .type = QUIRK_AUTODETECT | ||
2054 | } | ||
2055 | }, | ||
2034 | 2056 | ||
2035 | /* Guillemot devices */ | 2057 | /* Guillemot devices */ |
2036 | { | 2058 | { |
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 3879eae7e874..5363bcca9494 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/usb.h> | 19 | #include <linux/usb.h> |
20 | #include <linux/usb/audio.h> | 20 | #include <linux/usb/audio.h> |
21 | #include <linux/usb/midi.h> | ||
21 | 22 | ||
22 | #include <sound/control.h> | 23 | #include <sound/control.h> |
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
@@ -175,6 +176,178 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, | |||
175 | return 0; | 176 | return 0; |
176 | } | 177 | } |
177 | 178 | ||
179 | static int create_auto_pcm_quirk(struct snd_usb_audio *chip, | ||
180 | struct usb_interface *iface, | ||
181 | struct usb_driver *driver) | ||
182 | { | ||
183 | struct usb_host_interface *alts; | ||
184 | struct usb_interface_descriptor *altsd; | ||
185 | struct usb_endpoint_descriptor *epd; | ||
186 | struct uac1_as_header_descriptor *ashd; | ||
187 | struct uac_format_type_i_discrete_descriptor *fmtd; | ||
188 | |||
189 | /* | ||
190 | * Most Roland/Yamaha audio streaming interfaces have more or less | ||
191 | * standard descriptors, but older devices might lack descriptors, and | ||
192 | * future ones might change, so ensure that we fail silently if the | ||
193 | * interface doesn't look exactly right. | ||
194 | */ | ||
195 | |||
196 | /* must have a non-zero altsetting for streaming */ | ||
197 | if (iface->num_altsetting < 2) | ||
198 | return -ENODEV; | ||
199 | alts = &iface->altsetting[1]; | ||
200 | altsd = get_iface_desc(alts); | ||
201 | |||
202 | /* must have an isochronous endpoint for streaming */ | ||
203 | if (altsd->bNumEndpoints < 1) | ||
204 | return -ENODEV; | ||
205 | epd = get_endpoint(alts, 0); | ||
206 | if (!usb_endpoint_xfer_isoc(epd)) | ||
207 | return -ENODEV; | ||
208 | |||
209 | /* must have format descriptors */ | ||
210 | ashd = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, | ||
211 | UAC_AS_GENERAL); | ||
212 | fmtd = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, | ||
213 | UAC_FORMAT_TYPE); | ||
214 | if (!ashd || ashd->bLength < 7 || | ||
215 | !fmtd || fmtd->bLength < 8) | ||
216 | return -ENODEV; | ||
217 | |||
218 | return create_standard_audio_quirk(chip, iface, driver, NULL); | ||
219 | } | ||
220 | |||
221 | static int create_yamaha_midi_quirk(struct snd_usb_audio *chip, | ||
222 | struct usb_interface *iface, | ||
223 | struct usb_driver *driver, | ||
224 | struct usb_host_interface *alts) | ||
225 | { | ||
226 | static const struct snd_usb_audio_quirk yamaha_midi_quirk = { | ||
227 | .type = QUIRK_MIDI_YAMAHA | ||
228 | }; | ||
229 | struct usb_midi_in_jack_descriptor *injd; | ||
230 | struct usb_midi_out_jack_descriptor *outjd; | ||
231 | |||
232 | /* must have some valid jack descriptors */ | ||
233 | injd = snd_usb_find_csint_desc(alts->extra, alts->extralen, | ||
234 | NULL, USB_MS_MIDI_IN_JACK); | ||
235 | outjd = snd_usb_find_csint_desc(alts->extra, alts->extralen, | ||
236 | NULL, USB_MS_MIDI_OUT_JACK); | ||
237 | if (!injd && !outjd) | ||
238 | return -ENODEV; | ||
239 | if (injd && (injd->bLength < 5 || | ||
240 | (injd->bJackType != USB_MS_EMBEDDED && | ||
241 | injd->bJackType != USB_MS_EXTERNAL))) | ||
242 | return -ENODEV; | ||
243 | if (outjd && (outjd->bLength < 6 || | ||
244 | (outjd->bJackType != USB_MS_EMBEDDED && | ||
245 | outjd->bJackType != USB_MS_EXTERNAL))) | ||
246 | return -ENODEV; | ||
247 | return create_any_midi_quirk(chip, iface, driver, &yamaha_midi_quirk); | ||
248 | } | ||
249 | |||
250 | static int create_roland_midi_quirk(struct snd_usb_audio *chip, | ||
251 | struct usb_interface *iface, | ||
252 | struct usb_driver *driver, | ||
253 | struct usb_host_interface *alts) | ||
254 | { | ||
255 | static const struct snd_usb_audio_quirk roland_midi_quirk = { | ||
256 | .type = QUIRK_MIDI_ROLAND | ||
257 | }; | ||
258 | u8 *roland_desc = NULL; | ||
259 | |||
260 | /* might have a vendor-specific descriptor <06 24 F1 02 ...> */ | ||
261 | for (;;) { | ||
262 | roland_desc = snd_usb_find_csint_desc(alts->extra, | ||
263 | alts->extralen, | ||
264 | roland_desc, 0xf1); | ||
265 | if (!roland_desc) | ||
266 | return -ENODEV; | ||
267 | if (roland_desc[0] < 6 || roland_desc[3] != 2) | ||
268 | continue; | ||
269 | return create_any_midi_quirk(chip, iface, driver, | ||
270 | &roland_midi_quirk); | ||
271 | } | ||
272 | } | ||
273 | |||
274 | static int create_std_midi_quirk(struct snd_usb_audio *chip, | ||
275 | struct usb_interface *iface, | ||
276 | struct usb_driver *driver, | ||
277 | struct usb_host_interface *alts) | ||
278 | { | ||
279 | struct usb_ms_header_descriptor *mshd; | ||
280 | struct usb_ms_endpoint_descriptor *msepd; | ||
281 | |||
282 | /* must have the MIDIStreaming interface header descriptor*/ | ||
283 | mshd = (struct usb_ms_header_descriptor *)alts->extra; | ||
284 | if (alts->extralen < 7 || | ||
285 | mshd->bLength < 7 || | ||
286 | mshd->bDescriptorType != USB_DT_CS_INTERFACE || | ||
287 | mshd->bDescriptorSubtype != USB_MS_HEADER) | ||
288 | return -ENODEV; | ||
289 | /* must have the MIDIStreaming endpoint descriptor*/ | ||
290 | msepd = (struct usb_ms_endpoint_descriptor *)alts->endpoint[0].extra; | ||
291 | if (alts->endpoint[0].extralen < 4 || | ||
292 | msepd->bLength < 4 || | ||
293 | msepd->bDescriptorType != USB_DT_CS_ENDPOINT || | ||
294 | msepd->bDescriptorSubtype != UAC_MS_GENERAL || | ||
295 | msepd->bNumEmbMIDIJack < 1 || | ||
296 | msepd->bNumEmbMIDIJack > 16) | ||
297 | return -ENODEV; | ||
298 | |||
299 | return create_any_midi_quirk(chip, iface, driver, NULL); | ||
300 | } | ||
301 | |||
302 | static int create_auto_midi_quirk(struct snd_usb_audio *chip, | ||
303 | struct usb_interface *iface, | ||
304 | struct usb_driver *driver) | ||
305 | { | ||
306 | struct usb_host_interface *alts; | ||
307 | struct usb_interface_descriptor *altsd; | ||
308 | struct usb_endpoint_descriptor *epd; | ||
309 | int err; | ||
310 | |||
311 | alts = &iface->altsetting[0]; | ||
312 | altsd = get_iface_desc(alts); | ||
313 | |||
314 | /* must have at least one bulk/interrupt endpoint for streaming */ | ||
315 | if (altsd->bNumEndpoints < 1) | ||
316 | return -ENODEV; | ||
317 | epd = get_endpoint(alts, 0); | ||
318 | if (!usb_endpoint_xfer_bulk(epd) || | ||
319 | !usb_endpoint_xfer_int(epd)) | ||
320 | return -ENODEV; | ||
321 | |||
322 | switch (USB_ID_VENDOR(chip->usb_id)) { | ||
323 | case 0x0499: /* Yamaha */ | ||
324 | err = create_yamaha_midi_quirk(chip, iface, driver, alts); | ||
325 | if (err < 0 && err != -ENODEV) | ||
326 | return err; | ||
327 | break; | ||
328 | case 0x0582: /* Roland */ | ||
329 | err = create_roland_midi_quirk(chip, iface, driver, alts); | ||
330 | if (err < 0 && err != -ENODEV) | ||
331 | return err; | ||
332 | break; | ||
333 | } | ||
334 | |||
335 | return create_std_midi_quirk(chip, iface, driver, alts); | ||
336 | } | ||
337 | |||
338 | static int create_autodetect_quirk(struct snd_usb_audio *chip, | ||
339 | struct usb_interface *iface, | ||
340 | struct usb_driver *driver, | ||
341 | const struct snd_usb_audio_quirk *quirk) | ||
342 | { | ||
343 | int err; | ||
344 | |||
345 | err = create_auto_pcm_quirk(chip, iface, driver); | ||
346 | if (err == -ENODEV) | ||
347 | err = create_auto_midi_quirk(chip, iface, driver); | ||
348 | return err; | ||
349 | } | ||
350 | |||
178 | /* | 351 | /* |
179 | * Create a stream for an Edirol UA-700/UA-25/UA-4FX interface. | 352 | * Create a stream for an Edirol UA-700/UA-25/UA-4FX interface. |
180 | * The only way to detect the sample rate is by looking at wMaxPacketSize. | 353 | * The only way to detect the sample rate is by looking at wMaxPacketSize. |
@@ -303,9 +476,11 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip, | |||
303 | static const quirk_func_t quirk_funcs[] = { | 476 | static const quirk_func_t quirk_funcs[] = { |
304 | [QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk, | 477 | [QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk, |
305 | [QUIRK_COMPOSITE] = create_composite_quirk, | 478 | [QUIRK_COMPOSITE] = create_composite_quirk, |
479 | [QUIRK_AUTODETECT] = create_autodetect_quirk, | ||
306 | [QUIRK_MIDI_STANDARD_INTERFACE] = create_any_midi_quirk, | 480 | [QUIRK_MIDI_STANDARD_INTERFACE] = create_any_midi_quirk, |
307 | [QUIRK_MIDI_FIXED_ENDPOINT] = create_any_midi_quirk, | 481 | [QUIRK_MIDI_FIXED_ENDPOINT] = create_any_midi_quirk, |
308 | [QUIRK_MIDI_YAMAHA] = create_any_midi_quirk, | 482 | [QUIRK_MIDI_YAMAHA] = create_any_midi_quirk, |
483 | [QUIRK_MIDI_ROLAND] = create_any_midi_quirk, | ||
309 | [QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk, | 484 | [QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk, |
310 | [QUIRK_MIDI_NOVATION] = create_any_midi_quirk, | 485 | [QUIRK_MIDI_NOVATION] = create_any_midi_quirk, |
311 | [QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk, | 486 | [QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk, |
diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 1ea5871cb980..c4339f97226b 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c | |||
@@ -493,10 +493,10 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) | |||
493 | altsd = get_iface_desc(alts); | 493 | altsd = get_iface_desc(alts); |
494 | protocol = altsd->bInterfaceProtocol; | 494 | protocol = altsd->bInterfaceProtocol; |
495 | /* skip invalid one */ | 495 | /* skip invalid one */ |
496 | if ((altsd->bInterfaceClass != USB_CLASS_AUDIO && | 496 | if (((altsd->bInterfaceClass != USB_CLASS_AUDIO || |
497 | (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING && | ||
498 | altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC)) && | ||
497 | altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || | 499 | altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || |
498 | (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING && | ||
499 | altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) || | ||
500 | altsd->bNumEndpoints < 1 || | 500 | altsd->bNumEndpoints < 1 || |
501 | le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0) | 501 | le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0) |
502 | continue; | 502 | continue; |
@@ -512,6 +512,15 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) | |||
512 | if (snd_usb_apply_interface_quirk(chip, iface_no, altno)) | 512 | if (snd_usb_apply_interface_quirk(chip, iface_no, altno)) |
513 | continue; | 513 | continue; |
514 | 514 | ||
515 | /* | ||
516 | * Roland audio streaming interfaces are marked with protocols | ||
517 | * 0/1/2, but are UAC 1 compatible. | ||
518 | */ | ||
519 | if (USB_ID_VENDOR(chip->usb_id) == 0x0582 && | ||
520 | altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC && | ||
521 | protocol <= 2) | ||
522 | protocol = UAC_VERSION_1; | ||
523 | |||
515 | chconfig = 0; | 524 | chconfig = 0; |
516 | /* get audio formats */ | 525 | /* get audio formats */ |
517 | switch (protocol) { | 526 | switch (protocol) { |
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index bc43bcaddf4d..caabe9b3af49 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h | |||
@@ -72,9 +72,11 @@ struct snd_usb_audio { | |||
72 | enum quirk_type { | 72 | enum quirk_type { |
73 | QUIRK_IGNORE_INTERFACE, | 73 | QUIRK_IGNORE_INTERFACE, |
74 | QUIRK_COMPOSITE, | 74 | QUIRK_COMPOSITE, |
75 | QUIRK_AUTODETECT, | ||
75 | QUIRK_MIDI_STANDARD_INTERFACE, | 76 | QUIRK_MIDI_STANDARD_INTERFACE, |
76 | QUIRK_MIDI_FIXED_ENDPOINT, | 77 | QUIRK_MIDI_FIXED_ENDPOINT, |
77 | QUIRK_MIDI_YAMAHA, | 78 | QUIRK_MIDI_YAMAHA, |
79 | QUIRK_MIDI_ROLAND, | ||
78 | QUIRK_MIDI_MIDIMAN, | 80 | QUIRK_MIDI_MIDIMAN, |
79 | QUIRK_MIDI_NOVATION, | 81 | QUIRK_MIDI_NOVATION, |
80 | QUIRK_MIDI_RAW_BYTES, | 82 | QUIRK_MIDI_RAW_BYTES, |