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