1/* $NetBSD: umidi_quirks.c,v 1.20 2016/04/23 10:15:32 skrll Exp $ */
2
3/*
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Takuya SHIOZAKI (tshiozak@NetBSD.org).
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: umidi_quirks.c,v 1.20 2016/04/23 10:15:32 skrll Exp $");
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/kernel.h>
38#include <sys/device.h>
39#include <sys/ioctl.h>
40#include <sys/conf.h>
41#include <sys/file.h>
42#include <sys/select.h>
43#include <sys/proc.h>
44#include <sys/vnode.h>
45#include <sys/poll.h>
46
47#include <dev/usb/usb.h>
48#include <dev/usb/usbdi.h>
49#include <dev/usb/usbdi_util.h>
50
51#include <dev/auconv.h>
52#include <dev/usb/usbdevs.h>
53#include <dev/usb/uaudioreg.h>
54#include <dev/usb/umidi_quirks.h>
55
56/*
57 * quirk codes for UMIDI
58 */
59
60#ifdef UMIDIQUIRK_DEBUG
61#define DPRINTF(x) if (umidiquirkdebug) printf x
62#define DPRINTFN(n,x) if (umidiquirkdebug >= (n)) printf x
63int umidiquirkdebug = 1;
64#else
65#define DPRINTF(x)
66#define DPRINTFN(n,x)
67#endif
68
69
70/*
71 * YAMAHA UX-256
72 * --- this is a typical yamaha device, but has a broken descriptor :-<
73 */
74
75UMQ_FIXED_EP_DATA_DEF(YAMAHA, YAMAHA_UX256, ANYIFACE, 1, 1) = {
76 /* out */
77 { 0, 16 },
78 /* in */
79 { 1, 8 }
80};
81UMQ_FIXED_EP_DEF(YAMAHA, YAMAHA_UX256, ANYIFACE, 1, 1);
82
83UMQ_DEF(YAMAHA, YAMAHA_UX256, ANYIFACE) = {
84 UMQ_FIXED_EP_REG(YAMAHA, YAMAHA_UX256, ANYIFACE),
85#if 0
86 UMQ_YAMAHA_REG(YAMAHA, ANYPRODUCT, ANYIFACE),
87#endif
88 UMQ_TERMINATOR
89};
90
91
92/*
93 * YAMAHA generic
94 */
95UMQ_DEF(YAMAHA, ANYPRODUCT, ANYIFACE) = {
96 UMQ_YAMAHA_REG(YAMAHA, ANYPRODUCT, ANYIFACE),
97 UMQ_TERMINATOR
98};
99
100
101/*
102 * ROLAND UM-1
103 */
104UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UM1, 2, 1, 1) = {
105 /* out */
106 { 0, 1 },
107 /* in */
108 { 1, 1 }
109};
110UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM1, 2, 1, 1);
111
112UMQ_DEF(ROLAND, ROLAND_UM1, 2) = {
113 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM1, 2),
114 UMQ_TERMINATOR
115};
116
117/*
118 * ROLAND SC-8850
119 */
120UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_SC8850, 2, 1, 1) = {
121 /* out */
122 { 0, 6 },
123 /* in */
124 { 1, 6 }
125};
126UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SC8850, 2, 1, 1);
127
128UMQ_DEF(ROLAND, ROLAND_SC8850, 2) = {
129 UMQ_FIXED_EP_REG(ROLAND, ROLAND_SC8850, 2),
130 UMQ_TERMINATOR
131};
132
133/*
134 * ROLAND SD-90
135 */
136UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_SD90, 2, 1, 1) = {
137 /* out */
138 { 0, 4 },
139 /* in */
140 { 1, 4 }
141};
142UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SD90, 2, 1, 1);
143
144UMQ_DEF(ROLAND, ROLAND_SD90, 2) = {
145 UMQ_FIXED_EP_REG(ROLAND, ROLAND_SD90, 2),
146 UMQ_TERMINATOR
147};
148
149
150/*
151 * ROLAND UM-880 (native mode)
152 */
153UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UM880N, 0, 1, 1) = {
154 /* out */
155 { 0, 9 },
156 /* in */
157 { 1, 9 }
158};
159UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM880N, 0, 1, 1);
160
161UMQ_DEF(ROLAND, ROLAND_UM880N, 0) = {
162 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM880N, 0),
163 UMQ_TERMINATOR
164};
165
166/*
167 * ROLAND UA-100
168 */
169UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UA100, 2, 1, 1) = {
170 /* out */
171 { 0, 3 },
172 /* in */
173 { 1, 3 }
174};
175UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA100, 2, 1, 1);
176
177UMQ_DEF(ROLAND, ROLAND_UA100, 2) = {
178 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA100, 2),
179 UMQ_TERMINATOR
180};
181
182/*
183 * ROLAND UM-4
184 */
185UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UM4, 2, 1, 1) = {
186 /* out */
187 { 0, 4 },
188 /* in */
189 { 1, 4 }
190};
191UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM4, 2, 1, 1);
192
193UMQ_DEF(ROLAND, ROLAND_UM4, 2) = {
194 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM4, 2),
195 UMQ_TERMINATOR
196};
197
198/*
199 * ROLAND U-8
200 */
201UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_U8, 2, 1, 1) = {
202 /* out */
203 { 0, 2 },
204 /* in */
205 { 1, 2 }
206};
207UMQ_FIXED_EP_DEF(ROLAND, ROLAND_U8, 2, 1, 1);
208
209UMQ_DEF(ROLAND, ROLAND_U8, 2) = {
210 UMQ_FIXED_EP_REG(ROLAND, ROLAND_U8, 2),
211 UMQ_TERMINATOR
212};
213
214/*
215 * ROLAND UM-2
216 */
217UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UM2, 2, 1, 1) = {
218 /* out */
219 { 0, 2 },
220 /* in */
221 { 1, 2 }
222};
223UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM2, 2, 1, 1);
224
225UMQ_DEF(ROLAND, ROLAND_UM2, 2) = {
226 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM2, 2),
227 UMQ_TERMINATOR
228};
229
230/*
231 * ROLAND SC-8820
232 */
233UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_SC8820, 2, 1, 1) = {
234 /* out */
235 { 0, 5 }, /* cables 0, 1, 4 only */
236 /* in */
237 { 1, 5 } /* do. */
238};
239UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SC8820, 2, 1, 1);
240
241UMQ_DEF(ROLAND, ROLAND_SC8820, 2) = {
242 UMQ_FIXED_EP_REG(ROLAND, ROLAND_SC8820, 2),
243 UMQ_TERMINATOR
244};
245
246/*
247 * ROLAND PC-300
248 */
249UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_PC300, 2, 1, 1) = {
250 /* out */
251 { 0, 1 },
252 /* in */
253 { 1, 1 }
254};
255UMQ_FIXED_EP_DEF(ROLAND, ROLAND_PC300, 2, 1, 1);
256
257UMQ_DEF(ROLAND, ROLAND_PC300, 2) = {
258 UMQ_FIXED_EP_REG(ROLAND, ROLAND_PC300, 2),
259 UMQ_TERMINATOR
260};
261
262/*
263 * ROLAND SK-500
264 */
265UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_SK500, 2, 1, 1) = {
266 /* out */
267 { 0, 5 }, /* cables 0, 1, 4 only */
268 /* in */
269 { 1, 5 } /* do. */
270};
271UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SK500, 2, 1, 1);
272
273UMQ_DEF(ROLAND, ROLAND_SK500, 2) = {
274 UMQ_FIXED_EP_REG(ROLAND, ROLAND_SK500, 2),
275 UMQ_TERMINATOR
276};
277
278/*
279 * ROLAND SC-D70
280 */
281UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_SCD70, 2, 1, 1) = {
282 /* out */
283 { 0, 3 },
284 /* in */
285 { 1, 3 }
286};
287UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SCD70, 2, 1, 1);
288
289UMQ_DEF(ROLAND, ROLAND_SCD70, 2) = {
290 UMQ_FIXED_EP_REG(ROLAND, ROLAND_SCD70, 2),
291 UMQ_TERMINATOR
292};
293
294/*
295 * ROLAND XV-5050
296 */
297UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_XV5050, 0, 1, 1) = {
298 /* out */
299 { 0, 1 },
300 /* in */
301 { 1, 1 }
302};
303UMQ_FIXED_EP_DEF(ROLAND, ROLAND_XV5050, 0, 1, 1);
304
305UMQ_DEF(ROLAND, ROLAND_XV5050, 0) = {
306 UMQ_FIXED_EP_REG(ROLAND, ROLAND_XV5050, 0),
307 UMQ_TERMINATOR
308};
309
310/*
311 * ROLAND UM-550
312 */
313UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UM550, 0, 1, 1) = {
314 /* out */
315 { 0, 6 },
316 /* in */
317 { 1, 6 }
318};
319UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM550, 0, 1, 1);
320
321UMQ_DEF(ROLAND, ROLAND_UM550, 0) = {
322 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM550, 0),
323 UMQ_TERMINATOR
324};
325
326/*
327 * ROLAND SD-20
328 */
329UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_SD20, 0, 1, 1) = {
330 /* out */
331 { 0, 2 },
332 /* in */
333 { 1, 3 }
334};
335UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SD20, 0, 1, 1);
336
337UMQ_DEF(ROLAND, ROLAND_SD20, 0) = {
338 UMQ_FIXED_EP_REG(ROLAND, ROLAND_SD20, 0),
339 UMQ_TERMINATOR
340};
341
342/*
343 * ROLAND SD-80
344 */
345UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_SD80, 0, 1, 1) = {
346 /* out */
347 { 0, 4 },
348 /* in */
349 { 1, 4 }
350};
351UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SD80, 0, 1, 1);
352
353UMQ_DEF(ROLAND, ROLAND_SD80, 0) = {
354 UMQ_FIXED_EP_REG(ROLAND, ROLAND_SD80, 0),
355 UMQ_TERMINATOR
356};
357
358/*
359 * ROLAND UA-700
360 */
361UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UA700, 3, 1, 1) = {
362 /* out */
363 { 0, 2 },
364 /* in */
365 { 1, 2 }
366};
367UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA700, 3, 1, 1);
368
369UMQ_DEF(ROLAND, ROLAND_UA700, 3) = {
370 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA700, 3),
371 UMQ_TERMINATOR
372};
373
374/*
375 * ROLAND UA-1000
376 */
377UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UA1000, 3, 1, 1) = {
378 /* out */
379 { 0, 2 },
380 /* in */
381 { 1, 2 }
382};
383UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA1000, 3, 1, 1);
384
385UMQ_DEF(ROLAND, ROLAND_UA1000, 3) = {
386 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA1000, 3),
387 UMQ_TERMINATOR
388};
389
390/*
391 * ROLAND UA-101
392 */
393UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UA101, 2, 1, 1) = {
394 /* out */
395 { 0, 2 },
396 /* in */
397 { 1, 2 }
398};
399UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA101, 2, 1, 1);
400
401UMQ_DEF(ROLAND, ROLAND_UA101, 2) = {
402 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA101, 2),
403 UMQ_TERMINATOR
404};
405
406UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UA101F, 2, 1, 1) = {
407 /* out */
408 { 0, 2 },
409 /* in */
410 { 1, 2 }
411};
412UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA101F, 2, 1, 1);
413
414UMQ_DEF(ROLAND, ROLAND_UA101F, 2) = {
415 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA101F, 2),
416 UMQ_TERMINATOR
417};
418
419/*
420 * ROLAND Fantom-X
421 */
422UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_FANTOMX, 0, 1, 1) = {
423 /* out */
424 { 0, 1 },
425 /* in */
426 { 1, 1 }
427};
428UMQ_FIXED_EP_DEF(ROLAND, ROLAND_FANTOMX, 0, 1, 1);
429
430UMQ_DEF(ROLAND, ROLAND_FANTOMX, 0) = {
431 UMQ_FIXED_EP_REG(ROLAND, ROLAND_FANTOMX, 0),
432 UMQ_TERMINATOR
433};
434
435/*
436 * ROLAND PCR
437 */
438UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_PCR, 0, 1, 1) = {
439 /* out */
440 { 0, 3 },
441 /* in */
442 { 1, 3 }
443};
444UMQ_FIXED_EP_DEF(ROLAND, ROLAND_PCR, 0, 1, 1);
445
446UMQ_DEF(ROLAND, ROLAND_PCR, 0) = {
447 UMQ_FIXED_EP_REG(ROLAND, ROLAND_PCR, 0),
448 UMQ_TERMINATOR
449};
450
451/*
452 * ROLAND UM-3EX
453 */
454UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UM3, 0, 1, 1) = {
455 /* out */
456 { 0, 3 },
457 /* in */
458 { 1, 3 }
459};
460UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM3, 0, 1, 1);
461
462UMQ_DEF(ROLAND, ROLAND_UM3, 0) = {
463 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM3, 0),
464 UMQ_TERMINATOR
465};
466
467/*
468 * ROLAND UA-25
469 */
470UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UA25, 2, 1, 1) = {
471 /* out */
472 { 0, 1 },
473 /* in */
474 { 1, 1 }
475};
476UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA25, 2, 1, 1);
477
478UMQ_DEF(ROLAND, ROLAND_UA25, 2) = {
479 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA25, 2),
480 UMQ_TERMINATOR
481};
482
483/*
484 * ROLAND UA-4FX
485 */
486UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UA4FX, 2, 1, 1) = {
487 /* out */
488 { 0, 1 },
489 /* in */
490 { 1, 1 }
491};
492UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA4FX, 2, 1, 1);
493
494UMQ_DEF(ROLAND, ROLAND_UA4FX, 2) = {
495 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA4FX, 2),
496 UMQ_TERMINATOR
497};
498
499/*
500 * ROLAND SonicCell
501 */
502UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_SONICCELL, 2, 1, 1) = {
503 /* out */
504 { 0, 1 },
505 /* in */
506 { 1, 1 }
507};
508UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SONICCELL, 2, 1, 1);
509
510UMQ_DEF(ROLAND, ROLAND_SONICCELL, 2) = {
511 UMQ_FIXED_EP_REG(ROLAND, ROLAND_SONICCELL, 2),
512 UMQ_TERMINATOR
513};
514
515/*
516 * ROLAND UM-ONE
517 */
518UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UMONE, ANYIFACE, 1, 1) = {
519 /* out */
520 { 0, 1 },
521 /* in */
522 { 1, 1 }
523};
524UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UMONE, ANYIFACE, 1, 1);
525
526UMQ_DEF(ROLAND, ROLAND_UMONE, ANYIFACE) = {
527 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UMONE, ANYIFACE),
528 UMQ_TERMINATOR
529};
530
531/*
532 * Midiman Midisport 2x4. This has 2 physical MIDI IN jacks that are read
533 * on endpoint 0x81 (descriptor index 0). It has 4 physical MIDI OUT jacks
534 * that can be written on endpoints 2 or 4 (at descriptor index 2 or 4,
535 * coincidentally) interchangeably: either endpoint will accept a Cable Number
536 * field of 0 to 3, and data for a given CN will be routed to the same
537 * physical output regardless of the endpoint used for the transfer. But
538 * there's a catch: flow-control feedback only goes to endpoint 2 for
539 * CN 0 and 2, and only to endpoint 4 for CN 1 and 3. If you send output at
540 * high rates for CN 0 or 2 over endpoint 4, or for CN 1 or 3 over endpoint 2,
541 * the USB transfers complete as fast as possible, giving you an apparent data
542 * rate much higher than MIDI's 3125 cps (easy to measure using dd to blast a
543 * bunch of midi data to the rmidi device). Of course that isn't a way to make
544 * MIDI faster, just a way to overrun the device buffer and spray bits on the
545 * floor. So this device needs the fixed endpoint quirk, the fixed cable number
546 * quirk (to make sure CNs 0 and 2 are put on the first endpoint and 1 and 3
547 * on the other), and then the fixed mididev-assignment quirk (to match jacks
548 * to mididevs so the rmidi devices match the order of the blinkenlights).
549 */
550UMQ_FIXED_EP_DATA_DEF(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE, 2, 1) = {
551 /* out: ep# jacks */
552 { 2, 2 },
553 { 4, 2 },
554 /* in: ep# jacks */
555 { 0, 2 }
556};
557UMQ_FIXED_EP_DEF(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE, 2, 1);
558UMQ_FIXED_CN_DEF(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE) = {
559 0, 2, 1, 3, 0, 1
560};
561UMQ_FIXED_MD_DEF(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE) = {
562 0, 0, 2, 1, 1, -1, 3, -1
563};
564UMQ_DEF(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE) = {
565 UMQ_FIXED_EP_REG(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE),
566 UMQ_FIXED_CN_REG(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE),
567 UMQ_FIXED_MD_REG(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE),
568 UMQ_TYPE(MIDIMAN_GARBLE),
569 UMQ_TERMINATOR
570};
571
572/*
573 * quirk list
574 */
575static struct umidi_quirk umidi_quirklist[] = {
576 UMQ_REG(YAMAHA, YAMAHA_UX256, ANYIFACE),
577 UMQ_REG(YAMAHA, ANYPRODUCT, ANYIFACE),
578 UMQ_REG(ROLAND, ROLAND_UM1, 2),
579 UMQ_REG(ROLAND, ROLAND_SC8850, 2),
580 UMQ_REG(ROLAND, ROLAND_SD90, 2),
581 UMQ_REG(ROLAND, ROLAND_UM880N, 0),
582 UMQ_REG(ROLAND, ROLAND_UA100, 2),
583 UMQ_REG(ROLAND, ROLAND_UM4, 2),
584 UMQ_REG(ROLAND, ROLAND_U8, 2),
585 UMQ_REG(ROLAND, ROLAND_UM2, 2),
586 UMQ_REG(ROLAND, ROLAND_SC8820, 2),
587 UMQ_REG(ROLAND, ROLAND_PC300, 2),
588 UMQ_REG(ROLAND, ROLAND_SK500, 2),
589 UMQ_REG(ROLAND, ROLAND_SCD70, 2),
590 UMQ_REG(ROLAND, ROLAND_XV5050, 0),
591 UMQ_REG(ROLAND, ROLAND_UM550, 0),
592 UMQ_REG(ROLAND, ROLAND_SD20, 0),
593 UMQ_REG(ROLAND, ROLAND_SD80, 0),
594 UMQ_REG(ROLAND, ROLAND_UA700, 3),
595 UMQ_REG(ROLAND, ROLAND_UA1000, 3),
596 UMQ_REG(ROLAND, ROLAND_UA101, 2),
597 UMQ_REG(ROLAND, ROLAND_UA101F, 2),
598 UMQ_REG(ROLAND, ROLAND_FANTOMX, 0),
599 UMQ_REG(ROLAND, ROLAND_PCR, 0),
600 UMQ_REG(ROLAND, ROLAND_UM3, 0),
601 UMQ_REG(ROLAND, ROLAND_UA25, 2),
602 UMQ_REG(ROLAND, ROLAND_UA4FX, 2),
603 UMQ_REG(ROLAND, ROLAND_SONICCELL, 2),
604 UMQ_REG(ROLAND, ROLAND_UMONE, ANYIFACE),
605 UMQ_REG(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE),
606 { .vendor = 0 },
607};
608
609
610/*
611 * quirk utilities
612 */
613
614const struct umidi_quirk *
615umidi_search_quirk(int vendor, int product, int ifaceno)
616{
617 struct umidi_quirk *p;
618 const struct umq_data *q;
619
620 DPRINTF(("umidi_search_quirk: v=%d, p=%d, i=%d\n",
621 vendor, product, ifaceno));
622
623 for (p=&umidi_quirklist[0]; p->vendor; p++) {
624 DPRINTFN(10, ("\tv=%d, p=%d, i=%d",
625 p->vendor, p->product, p->iface));
626 if ((p->vendor==vendor || p->vendor==ANYVENDOR) &&
627 (p->product==product || p->product==ANYPRODUCT) &&
628 (p->iface==ifaceno || p->iface==ANYIFACE)) {
629 DPRINTFN(10, (" found\n"));
630 if (!p->type_mask)
631 /* make quirk mask */
632 for (q=p->quirks; q->type; q++)
633 p->type_mask |= 1<<(q->type-1);
634 return p;
635 }
636 DPRINTFN(10, ("\n"));
637 }
638
639 return NULL;
640}
641
642static const char *quirk_name[] = {
643 "NULL",
644 "Fixed Endpoint",
645 "Yamaha Specific",
646 "Midiman Packet Garbling",
647 "Cable Numbers per Endpoint",
648 "Cable Numbers Global",
649 "Cable Numbers Fixed",
650 "Unit Mapping Fixed",
651};
652
653void
654umidi_print_quirk(const struct umidi_quirk *q)
655{
656 const struct umq_data *qd;
657 if (q) {
658 printf("(");
659 for (qd=q->quirks; qd->type; qd++)
660 printf("%s%s", quirk_name[qd->type],
661 (qd+1)->type?", ":")\n");
662 } else {
663 printf("(genuine USB-MIDI)\n");
664 }
665}
666
667const void *
668umidi_get_quirk_data_from_type(const struct umidi_quirk *q, uint32_t type)
669{
670 const struct umq_data *qd;
671 if (q) {
672 for (qd=q->quirks; qd->type; qd++)
673 if (qd->type == type)
674 return qd->data;
675 }
676 return NULL;
677}
678