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