Home | History | Annotate | Line # | Download | only in usb
      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 (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.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 *
    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
    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 *
    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