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