Home | History | Annotate | Line # | Download | only in usb
umidi_quirks.c revision 1.16
      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 (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.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
     65 int	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 
     77 UMQ_FIXED_EP_DATA_DEF(YAMAHA, YAMAHA_UX256, ANYIFACE, 1, 1) = {
     78 	/* out */
     79 	{ 0, 16 },
     80 	/* in */
     81 	{ 1, 8 }
     82 };
     83 UMQ_FIXED_EP_DEF(YAMAHA, YAMAHA_UX256, ANYIFACE, 1, 1);
     84 
     85 UMQ_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  */
     97 UMQ_DEF(YAMAHA, ANYPRODUCT, ANYIFACE) = {
     98 	UMQ_YAMAHA_REG(YAMAHA, ANYPRODUCT, ANYIFACE),
     99 	UMQ_TERMINATOR
    100 };
    101 
    102 
    103 /*
    104  * ROLAND UM-1
    105  */
    106 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UM1, 2, 1, 1) = {
    107 	/* out */
    108 	{ 0, 1 },
    109 	/* in */
    110 	{ 1, 1 }
    111 };
    112 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM1, 2, 1, 1);
    113 
    114 UMQ_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  */
    122 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_SC8850, 2, 1, 1) = {
    123 	/* out */
    124 	{ 0, 6 },
    125 	/* in */
    126 	{ 1, 6 }
    127 };
    128 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SC8850, 2, 1, 1);
    129 
    130 UMQ_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  */
    138 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_SD90, 2, 1, 1) = {
    139 	/* out */
    140 	{ 0, 4 },
    141 	/* in */
    142 	{ 1, 4 }
    143 };
    144 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SD90, 2, 1, 1);
    145 
    146 UMQ_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  */
    155 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UM880N, 0, 1, 1) = {
    156 	/* out */
    157 	{ 0, 9 },
    158 	/* in */
    159 	{ 1, 9 }
    160 };
    161 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM880N, 0, 1, 1);
    162 
    163 UMQ_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  */
    171 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UA100, 2, 1, 1) = {
    172 	/* out */
    173 	{ 0, 3 },
    174 	/* in */
    175 	{ 1, 3 }
    176 };
    177 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA100, 2, 1, 1);
    178 
    179 UMQ_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  */
    187 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UM4, 2, 1, 1) = {
    188 	/* out */
    189 	{ 0, 4 },
    190 	/* in */
    191 	{ 1, 4 }
    192 };
    193 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM4, 2, 1, 1);
    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_DATA_DEF(ROLAND, ROLAND_U8, 2, 1, 1) = {
    204 	/* out */
    205 	{ 0, 2 },
    206 	/* in */
    207 	{ 1, 2 }
    208 };
    209 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_U8, 2, 1, 1);
    210 
    211 UMQ_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  */
    219 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UM2, 2, 1, 1) = {
    220 	/* out */
    221 	{ 0, 2 },
    222 	/* in */
    223 	{ 1, 2 }
    224 };
    225 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM2, 2, 1, 1);
    226 
    227 UMQ_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  */
    235 UMQ_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 };
    241 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SC8820, 2, 1, 1);
    242 
    243 UMQ_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  */
    251 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_PC300, 2, 1, 1) = {
    252 	/* out */
    253 	{ 0, 1 },
    254 	/* in */
    255 	{ 1, 1 }
    256 };
    257 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_PC300, 2, 1, 1);
    258 
    259 UMQ_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  */
    267 UMQ_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 };
    273 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SK500, 2, 1, 1);
    274 
    275 UMQ_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  */
    283 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_SCD70, 2, 1, 1) = {
    284 	/* out */
    285 	{ 0, 3 },
    286 	/* in */
    287 	{ 1, 3 }
    288 };
    289 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SCD70, 2, 1, 1);
    290 
    291 UMQ_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  */
    299 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_XV5050, 0, 1, 1) = {
    300 	/* out */
    301 	{ 0, 1 },
    302 	/* in */
    303 	{ 1, 1 }
    304 };
    305 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_XV5050, 0, 1, 1);
    306 
    307 UMQ_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  */
    315 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UM550, 0, 1, 1) = {
    316 	/* out */
    317 	{ 0, 6 },
    318 	/* in */
    319 	{ 1, 6 }
    320 };
    321 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM550, 0, 1, 1);
    322 
    323 UMQ_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  */
    331 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_SD20, 0, 1, 1) = {
    332 	/* out */
    333 	{ 0, 2 },
    334 	/* in */
    335 	{ 1, 3 }
    336 };
    337 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SD20, 0, 1, 1);
    338 
    339 UMQ_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  */
    347 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_SD80, 0, 1, 1) = {
    348 	/* out */
    349 	{ 0, 4 },
    350 	/* in */
    351 	{ 1, 4 }
    352 };
    353 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SD80, 0, 1, 1);
    354 
    355 UMQ_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  */
    363 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UA700, 3, 1, 1) = {
    364 	/* out */
    365 	{ 0, 2 },
    366 	/* in */
    367 	{ 1, 2 }
    368 };
    369 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA700, 3, 1, 1);
    370 
    371 UMQ_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  */
    379 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UA1000, 3, 1, 1) = {
    380 	/* out */
    381 	{ 0, 2 },
    382 	/* in */
    383 	{ 1, 2 }
    384 };
    385 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA1000, 3, 1, 1);
    386 
    387 UMQ_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  */
    395 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UA101, 2, 1, 1) = {
    396 	/* out */
    397 	{ 0, 2 },
    398 	/* in */
    399 	{ 1, 2 }
    400 };
    401 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA101, 2, 1, 1);
    402 
    403 UMQ_DEF(ROLAND, ROLAND_UA101, 2) = {
    404 	UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA101, 2),
    405 	UMQ_TERMINATOR
    406 };
    407 
    408 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UA101F, 2, 1, 1) = {
    409 	/* out */
    410 	{ 0, 2 },
    411 	/* in */
    412 	{ 1, 2 }
    413 };
    414 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA101F, 2, 1, 1);
    415 
    416 UMQ_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  */
    424 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_FANTOMX, 0, 1, 1) = {
    425 	/* out */
    426 	{ 0, 1 },
    427 	/* in */
    428 	{ 1, 1 }
    429 };
    430 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_FANTOMX, 0, 1, 1);
    431 
    432 UMQ_DEF(ROLAND, ROLAND_FANTOMX, 0) = {
    433 	UMQ_FIXED_EP_REG(ROLAND, ROLAND_FANTOMX, 0),
    434 	UMQ_TERMINATOR
    435 };
    436 
    437 /*
    438  * ROLAND PCR
    439  */
    440 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_PCR, 0, 1, 1) = {
    441 	/* out */
    442 	{ 0, 3 },
    443 	/* in */
    444 	{ 1, 3 }
    445 };
    446 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_PCR, 0, 1, 1);
    447 
    448 UMQ_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  */
    456 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UM3, 0, 1, 1) = {
    457 	/* out */
    458 	{ 0, 3 },
    459 	/* in */
    460 	{ 1, 3 }
    461 };
    462 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM3, 0, 1, 1);
    463 
    464 UMQ_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  */
    472 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UA25, 2, 1, 1) = {
    473 	/* out */
    474 	{ 0, 1 },
    475 	/* in */
    476 	{ 1, 1 }
    477 };
    478 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA25, 2, 1, 1);
    479 
    480 UMQ_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  */
    488 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_UA4FX, 2, 1, 1) = {
    489 	/* out */
    490 	{ 0, 1 },
    491 	/* in */
    492 	{ 1, 1 }
    493 };
    494 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA4FX, 2, 1, 1);
    495 
    496 UMQ_DEF(ROLAND, ROLAND_UA4FX, 2) = {
    497 	UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA4FX, 2),
    498 	UMQ_TERMINATOR
    499 };
    500 
    501 /*
    502  * ROLAND SonicCell
    503  */
    504 UMQ_FIXED_EP_DATA_DEF(ROLAND, ROLAND_SONICCELL, 2, 1, 1) = {
    505 	/* out */
    506 	{ 0, 1 },
    507 	/* in */
    508 	{ 1, 1 }
    509 };
    510 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SONICCELL, 2, 1, 1);
    511 
    512 UMQ_DEF(ROLAND, ROLAND_SONICCELL, 2) = {
    513 	UMQ_FIXED_EP_REG(ROLAND, ROLAND_SONICCELL, 2),
    514 	UMQ_TERMINATOR
    515 };
    516 
    517 /*
    518  * Midiman Midisport 2x4. This has 2 physical MIDI IN jacks that are read
    519  * on endpoint 0x81 (descriptor index 0). It has 4 physical MIDI OUT jacks
    520  * that can be written on endpoints 2 or 4 (at descriptor index 2 or 4,
    521  * coincidentally) interchangeably: either endpoint will accept a Cable Number
    522  * field of 0 to 3, and data for a given CN will be routed to the same
    523  * physical output regardless of the endpoint used for the transfer. But
    524  * there's a catch: flow-control feedback only goes to endpoint 2 for
    525  * CN 0 and 2, and only to endpoint 4 for CN 1 and 3. If you send output at
    526  * high rates for CN 0 or 2 over endpoint 4, or for CN 1 or 3 over endpoint 2,
    527  * the USB transfers complete as fast as possible, giving you an apparent data
    528  * rate much higher than MIDI's 3125 cps (easy to measure using dd to blast a
    529  * bunch of midi data to the rmidi device). Of course that isn't a way to make
    530  * MIDI faster, just a way to overrun the device buffer and spray bits on the
    531  * floor. So this device needs the fixed endpoint quirk, the fixed cable number
    532  * quirk (to make sure CNs 0 and 2 are put on the first endpoint and 1 and 3
    533  * on the other), and then the fixed mididev-assignment quirk (to match jacks
    534  * to mididevs so the rmidi devices match the order of the blinkenlights).
    535  */
    536 UMQ_FIXED_EP_DATA_DEF(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE, 2, 1) = {
    537 	/* out: ep# jacks */
    538 	{ 2, 2 },
    539 	{ 4, 2 },
    540 	/* in: ep# jacks */
    541 	{ 0, 2 }
    542 };
    543 UMQ_FIXED_EP_DEF(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE, 2, 1);
    544 UMQ_FIXED_CN_DEF(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE) = {
    545 	0, 2, 1, 3, 0, 1
    546 };
    547 UMQ_FIXED_MD_DEF(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE) = {
    548 	 0, 0, 2, 1, 1, -1, 3, -1
    549 };
    550 UMQ_DEF(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE) = {
    551 	UMQ_FIXED_EP_REG(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE),
    552 	UMQ_FIXED_CN_REG(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE),
    553 	UMQ_FIXED_MD_REG(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE),
    554 	UMQ_TYPE(MIDIMAN_GARBLE),
    555 	UMQ_TERMINATOR
    556 };
    557 
    558 /*
    559  * quirk list
    560  */
    561 static struct umidi_quirk umidi_quirklist[] = {
    562 	UMQ_REG(YAMAHA, YAMAHA_UX256, ANYIFACE),
    563 	UMQ_REG(YAMAHA, ANYPRODUCT, ANYIFACE),
    564 	UMQ_REG(ROLAND, ROLAND_UM1, 2),
    565 	UMQ_REG(ROLAND, ROLAND_SC8850, 2),
    566 	UMQ_REG(ROLAND, ROLAND_SD90, 2),
    567 	UMQ_REG(ROLAND, ROLAND_UM880N, 0),
    568 	UMQ_REG(ROLAND, ROLAND_UA100, 2),
    569 	UMQ_REG(ROLAND, ROLAND_UM4, 2),
    570 	UMQ_REG(ROLAND, ROLAND_U8, 2),
    571 	UMQ_REG(ROLAND, ROLAND_UM2, 2),
    572 	UMQ_REG(ROLAND, ROLAND_SC8820, 2),
    573 	UMQ_REG(ROLAND, ROLAND_PC300, 2),
    574 	UMQ_REG(ROLAND, ROLAND_SK500, 2),
    575 	UMQ_REG(ROLAND, ROLAND_SCD70, 2),
    576 	UMQ_REG(ROLAND, ROLAND_XV5050, 0),
    577 	UMQ_REG(ROLAND, ROLAND_UM550, 0),
    578 	UMQ_REG(ROLAND, ROLAND_SD20, 0),
    579 	UMQ_REG(ROLAND, ROLAND_SD80, 0),
    580 	UMQ_REG(ROLAND, ROLAND_UA700, 3),
    581 	UMQ_REG(ROLAND, ROLAND_UA1000, 3),
    582 	UMQ_REG(ROLAND, ROLAND_UA101, 2),
    583 	UMQ_REG(ROLAND, ROLAND_UA101F, 2),
    584 	UMQ_REG(ROLAND, ROLAND_FANTOMX, 0),
    585 	UMQ_REG(ROLAND, ROLAND_PCR, 0),
    586 	UMQ_REG(ROLAND, ROLAND_UM3, 0),
    587 	UMQ_REG(ROLAND, ROLAND_UA25, 2),
    588 	UMQ_REG(ROLAND, ROLAND_UA4FX, 2),
    589 	UMQ_REG(ROLAND, ROLAND_SONICCELL, 2),
    590 	UMQ_REG(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE),
    591 	{ .vendor = 0 },
    592 };
    593 
    594 
    595 /*
    596  * quirk utilities
    597  */
    598 
    599 const struct umidi_quirk *
    600 umidi_search_quirk(int vendor, int product, int ifaceno)
    601 {
    602 	struct umidi_quirk *p;
    603 	const struct umq_data *q;
    604 
    605 	DPRINTF(("umidi_search_quirk: v=%d, p=%d, i=%d\n",
    606 		 vendor, product, ifaceno));
    607 
    608 	for (p=&umidi_quirklist[0]; p->vendor; p++) {
    609 		DPRINTFN(10, ("\tv=%d, p=%d, i=%d",
    610 			      p->vendor, p->product, p->iface));
    611 		if ((p->vendor==vendor || p->vendor==ANYVENDOR) &&
    612 		    (p->product==product || p->product==ANYPRODUCT) &&
    613 		    (p->iface==ifaceno || p->iface==ANYIFACE)) {
    614 			DPRINTFN(10, (" found\n"));
    615 			if (!p->type_mask)
    616 				/* make quirk mask */
    617 				for (q=p->quirks; q->type; q++)
    618 					p->type_mask |= 1<<(q->type-1);
    619 			return p;
    620 		}
    621 		DPRINTFN(10, ("\n"));
    622 	}
    623 
    624 	return NULL;
    625 }
    626 
    627 static const char *quirk_name[] = {
    628 	"NULL",
    629 	"Fixed Endpoint",
    630 	"Yamaha Specific",
    631 	"Midiman Packet Garbling",
    632 	"Cable Numbers per Endpoint",
    633 	"Cable Numbers Global",
    634 	"Cable Numbers Fixed",
    635 	"Unit Mapping Fixed",
    636 };
    637 
    638 void
    639 umidi_print_quirk(const struct umidi_quirk *q)
    640 {
    641 	const struct umq_data *qd;
    642 	if (q) {
    643 		printf("(");
    644 		for (qd=q->quirks; qd->type; qd++)
    645 			printf("%s%s", quirk_name[qd->type],
    646 			       (qd+1)->type?", ":")\n");
    647 	} else {
    648 		printf("(genuine USB-MIDI)\n");
    649 	}
    650 }
    651 
    652 const void *
    653 umidi_get_quirk_data_from_type(const struct umidi_quirk *q, u_int32_t type)
    654 {
    655 	const struct umq_data *qd;
    656 	if (q) {
    657 		for (qd=q->quirks; qd->type; qd++)
    658 			if (qd->type == type)
    659 				return qd->data;
    660 	}
    661 	return NULL;
    662 }
    663