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