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