xref: /openbsd-src/sys/dev/usb/umidi_quirks.c (revision 799f675f6700f14e59124f9825c723e9f2ce19dc)
1 /*	$OpenBSD: umidi_quirks.c,v 1.7 2005/11/21 18:16:44 millert Exp $	*/
2 /*	$NetBSD: umidi_quirks.c,v 1.4 2002/06/19 13:55:30 tshiozak Exp $	*/
3 
4 /*
5  * Copyright (c) 2001 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Takuya SHIOZAKI (tshiozak@netbsd.org).
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	  This product includes software developed by the NetBSD
22  *	  Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/malloc.h>
44 #include <sys/device.h>
45 #include <sys/ioctl.h>
46 #include <sys/conf.h>
47 #include <sys/file.h>
48 #include <sys/selinfo.h>
49 #include <sys/proc.h>
50 #include <sys/vnode.h>
51 #include <sys/poll.h>
52 #include <sys/lock.h>
53 
54 #include <dev/usb/usb.h>
55 #include <dev/usb/usbdi.h>
56 #include <dev/usb/usbdi_util.h>
57 
58 #include <dev/usb/usbdevs.h>
59 #include <dev/usb/uaudioreg.h>
60 #include <dev/usb/umidireg.h>
61 #include <dev/usb/umidivar.h>
62 #include <dev/usb/umidi_quirks.h>
63 
64 /*
65  * quirk codes for UMIDI
66  */
67 
68 #ifdef UMIDIQUIRK_DEBUG
69 #define DPRINTF(x)	if (umidiquirkdebug) printf x
70 #define DPRINTFN(n,x)	if (umidiquirkdebug >= (n)) printf x
71 int	umidiquirkdebug = 1;
72 #else
73 #define DPRINTF(x)
74 #define DPRINTFN(n,x)
75 #endif
76 
77 
78 /*
79  * YAMAHA UX-256
80  *  --- this is a typical yamaha device, but has a broken descriptor :-<
81  */
82 
83 UMQ_FIXED_EP_DEF(YAMAHA, YAMAHA_UX256, ANYIFACE, 1, 1) = {
84 	/* out */
85 	{ 0, 16 },
86 	/* in */
87 	{ 1, 8 }
88 };
89 
90 UMQ_DEF(YAMAHA, YAMAHA_UX256, ANYIFACE) = {
91 	UMQ_FIXED_EP_REG(YAMAHA, YAMAHA_UX256, ANYIFACE),
92 #if 0
93 	UMQ_YAMAHA_REG(YAMAHA, ANYPRODUCT, ANYIFACE),
94 #endif
95 	UMQ_TERMINATOR
96 };
97 
98 
99 /*
100  * YAMAHA generic
101  */
102 UMQ_DEF(YAMAHA, ANYPRODUCT, ANYIFACE) = {
103 	UMQ_YAMAHA_REG(YAMAHA, ANYPRODUCT, ANYIFACE),
104 	UMQ_TERMINATOR
105 };
106 
107 
108 /*
109  * ROLAND UM-1
110  */
111 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM1, 2, 1, 1) = {
112 	/* out */
113 	{ 0, 1 },
114 	/* in */
115 	{ 1, 1 }
116 };
117 
118 UMQ_DEF(ROLAND, ROLAND_UM1, 2) = {
119 	UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM1, 2),
120 	UMQ_TERMINATOR
121 };
122 
123 /*
124  * ROLAND SC-8850
125  */
126 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SC8850, 2, 1, 1) = {
127 	/* out */
128 	{ 0, 6 },
129 	/* in */
130 	{ 1, 6 }
131 };
132 
133 UMQ_DEF(ROLAND, ROLAND_SC8850, 2) = {
134 	UMQ_FIXED_EP_REG(ROLAND, ROLAND_SC8850, 2),
135 	UMQ_TERMINATOR
136 };
137 
138 /*
139  * ROLAND SD-90
140  */
141 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SD90, 2, 1, 1) = {
142 	/* out */
143 	{ 0, 4 },
144 	/* in */
145 	{ 1, 4 }
146 };
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_DEF(ROLAND, ROLAND_UM880N, 0, 1, 1) = {
158 	/* out */
159 	{ 0, 9 },
160 	/* in */
161 	{ 1, 9 }
162 };
163 
164 UMQ_DEF(ROLAND, ROLAND_UM880N, 0) = {
165 	UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM880N, 0),
166 	UMQ_TERMINATOR
167 };
168 
169 /*
170  * ROLAND UA-100
171  */
172 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA100, 2, 1, 1) = {
173 	/* out */
174 	{ 0, 3 },
175 	/* in */
176 	{ 1, 3 }
177 };
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_DEF(ROLAND, ROLAND_UM4, 2, 1, 1) = {
188 	/* out */
189 	{ 0, 4 },
190 	/* in */
191 	{ 1, 4 }
192 };
193 
194 UMQ_DEF(ROLAND, ROLAND_UM4, 2) = {
195 	UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM4, 2),
196 	UMQ_TERMINATOR
197 };
198 
199 /*
200  * ROLAND U-8
201  */
202 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_U8, 2, 1, 1) = {
203 	/* out */
204 	{ 0, 2 },
205 	/* in */
206 	{ 1, 2 }
207 };
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_DEF(ROLAND, ROLAND_UM2, 2, 1, 1) = {
218 	/* out */
219 	{ 0, 2 },
220 	/* in */
221 	{ 1, 2 }
222 };
223 
224 UMQ_DEF(ROLAND, ROLAND_UM2, 2) = {
225 	UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM2, 2),
226 	UMQ_TERMINATOR
227 };
228 
229 /*
230  * ROLAND SC-8820
231  */
232 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SC8820, 2, 1, 1) = {
233 	/* out */
234 	{ 0, 5 }, /* cables 0, 1, 4 only */
235 	/* in */
236 	{ 1, 5 } /* do. */
237 };
238 
239 UMQ_DEF(ROLAND, ROLAND_SC8820, 2) = {
240 	UMQ_FIXED_EP_REG(ROLAND, ROLAND_SC8820, 2),
241 	UMQ_TERMINATOR
242 };
243 
244 /*
245  * ROLAND PC-300
246  */
247 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_PC300, 2, 1, 1) = {
248 	/* out */
249 	{ 0, 1 },
250 	/* in */
251 	{ 1, 1 }
252 };
253 
254 UMQ_DEF(ROLAND, ROLAND_PC300, 2) = {
255 	UMQ_FIXED_EP_REG(ROLAND, ROLAND_PC300, 2),
256 	UMQ_TERMINATOR
257 };
258 
259 /*
260  * ROLAND SK-500
261  */
262 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SK500, 2, 1, 1) = {
263 	/* out */
264 	{ 0, 5 }, /* cables 0, 1, 4 only */
265 	/* in */
266 	{ 1, 5 } /* do. */
267 };
268 
269 UMQ_DEF(ROLAND, ROLAND_SK500, 2) = {
270 	UMQ_FIXED_EP_REG(ROLAND, ROLAND_SK500, 2),
271 	UMQ_TERMINATOR
272 };
273 
274 /*
275  * ROLAND SC-D70
276  */
277 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SCD70, 2, 1, 1) = {
278 	/* out */
279 	{ 0, 3 },
280 	/* in */
281 	{ 1, 3 }
282 };
283 
284 UMQ_DEF(ROLAND, ROLAND_SCD70, 2) = {
285 	UMQ_FIXED_EP_REG(ROLAND, ROLAND_SCD70, 2),
286 	UMQ_TERMINATOR
287 };
288 
289 /*
290  * ROLAND UM-550
291  */
292 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM550, 0, 1, 1) = {
293 	/* out */
294 	{ 0, 6 },
295 	/* in */
296 	{ 1, 6 }
297 };
298 
299 UMQ_DEF(ROLAND, ROLAND_UM550, 0) = {
300 	UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM550, 0),
301 	UMQ_TERMINATOR
302 };
303 
304 /*
305  * ROLAND SD-20
306  */
307 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SD20, 0, 1, 1) = {
308 	/* out */
309 	{ 0, 2 },
310 	/* in */
311 	{ 1, 3 }
312 };
313 
314 UMQ_DEF(ROLAND, ROLAND_SD20, 0) = {
315 	UMQ_FIXED_EP_REG(ROLAND, ROLAND_SD20, 0),
316 	UMQ_TERMINATOR
317 };
318 
319 /*
320  * ROLAND SD-80
321  */
322 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SD80, 0, 1, 1) = {
323 	/* out */
324 	{ 0, 4 },
325 	/* in */
326 	{ 1, 4 }
327 };
328 
329 UMQ_DEF(ROLAND, ROLAND_SD80, 0) = {
330 	UMQ_FIXED_EP_REG(ROLAND, ROLAND_SD80, 0),
331 	UMQ_TERMINATOR
332 };
333 
334 /*
335  * ROLAND UA-700
336  */
337 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA700, 3, 1, 1) = {
338 	/* out */
339 	{ 0, 2 },
340 	/* in */
341 	{ 1, 2 }
342 };
343 
344 UMQ_DEF(ROLAND, ROLAND_UA700, 3) = {
345 	UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA700, 3),
346 	UMQ_TERMINATOR
347 };
348 
349 
350 /*
351  * quirk list
352  */
353 struct umidi_quirk umidi_quirklist[] = {
354 	UMQ_REG(YAMAHA, YAMAHA_UX256, ANYIFACE),
355 	UMQ_REG(YAMAHA, ANYPRODUCT, ANYIFACE),
356 	UMQ_REG(ROLAND, ROLAND_UM1, 2),
357 	UMQ_REG(ROLAND, ROLAND_SC8850, 2),
358 	UMQ_REG(ROLAND, ROLAND_SD90, 2),
359 	UMQ_REG(ROLAND, ROLAND_UM880N, 0),
360 	UMQ_REG(ROLAND, ROLAND_UA100, 2),
361 	UMQ_REG(ROLAND, ROLAND_UM4, 2),
362 	UMQ_REG(ROLAND, ROLAND_U8, 2),
363 	UMQ_REG(ROLAND, ROLAND_UM2, 2),
364 	UMQ_REG(ROLAND, ROLAND_SC8820, 2),
365 	UMQ_REG(ROLAND, ROLAND_PC300, 2),
366 	UMQ_REG(ROLAND, ROLAND_SK500, 2),
367 	UMQ_REG(ROLAND, ROLAND_SCD70, 2),
368 	UMQ_REG(ROLAND, ROLAND_UM550, 0),
369 	UMQ_REG(ROLAND, ROLAND_SD20, 0),
370 	UMQ_REG(ROLAND, ROLAND_SD80, 0),
371 	UMQ_REG(ROLAND, ROLAND_UA700, 3),
372 	UMQ_TERMINATOR
373 };
374 
375 
376 /*
377  * quirk utilities
378  */
379 
380 struct umidi_quirk *
381 umidi_search_quirk(int vendor, int product, int ifaceno)
382 {
383 	struct umidi_quirk *p;
384 	struct umq_data *q;
385 
386 	DPRINTF(("umidi_search_quirk: v=%d, p=%d, i=%d\n",
387 		 vendor, product, ifaceno));
388 
389 	for (p=&umidi_quirklist[0]; p->vendor; p++) {
390 		DPRINTFN(10, ("\tv=%d, p=%d, i=%d",
391 			      p->vendor, p->product, p->iface));
392 		if ((p->vendor==vendor || p->vendor==ANYVENDOR) &&
393 		    (p->product==product || p->product==ANYPRODUCT) &&
394 		    (p->iface==ifaceno || p->iface==ANYIFACE)) {
395 			DPRINTFN(10, (" found\n"));
396 			if (!p->type_mask)
397 				/* make quirk mask */
398 				for (q=p->quirks; q->type; q++)
399 					p->type_mask |= 1<<(q->type-1);
400 			return p;
401                 }
402 		DPRINTFN(10, ("\n"));
403 	}
404 
405 	return NULL;
406 }
407 
408 static char *quirk_name[] = {
409 	"NULL",
410 	"Fixed Endpoint",
411 	"Yamaha Specific",
412 };
413 
414 void
415 umidi_print_quirk(struct umidi_quirk *q)
416 {
417 	struct umq_data *qd;
418 	if (q) {
419 		printf("(");
420 		for (qd=q->quirks; qd->type; qd++)
421 			printf("%s%s", quirk_name[qd->type],
422 			       (qd+1)->type?", ":")\n");
423 	} else {
424 		printf("(genuine USB-MIDI)\n");
425 	}
426 }
427 
428 void *
429 umidi_get_quirk_data_from_type(struct umidi_quirk *q, u_int32_t type)
430 {
431 	struct umq_data *qd;
432 	if (q) {
433 		for (qd=q->quirks; qd->type; qd++)
434 			if (qd->type == type)
435 				return qd->data;
436 	}
437 	return NULL;
438 }
439