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