1 | /* $NetBSD: umidi.c,v 1.71 2016/07/07 06:55:42 msaitoh Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 2001, 2012, 2014 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@NetBSD.org), (full-size transfers, extended |
9 | * hw_if) Chapman Flack (chap@NetBSD.org), and Matthew R. Green |
10 | * (mrg@eterna.com.au). |
11 | * |
12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions |
14 | * are met: |
15 | * 1. Redistributions of source code must retain the above copyright |
16 | * notice, this list of conditions and the following disclaimer. |
17 | * 2. Redistributions in binary form must reproduce the above copyright |
18 | * notice, this list of conditions and the following disclaimer in the |
19 | * documentation and/or other materials provided with the distribution. |
20 | * |
21 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
31 | * POSSIBILITY OF SUCH DAMAGE. |
32 | */ |
33 | |
34 | #include <sys/cdefs.h> |
35 | __KERNEL_RCSID(0, "$NetBSD: umidi.c,v 1.71 2016/07/07 06:55:42 msaitoh Exp $" ); |
36 | |
37 | #include <sys/types.h> |
38 | #include <sys/param.h> |
39 | #include <sys/systm.h> |
40 | #include <sys/kernel.h> |
41 | #include <sys/kmem.h> |
42 | #include <sys/device.h> |
43 | #include <sys/ioctl.h> |
44 | #include <sys/conf.h> |
45 | #include <sys/file.h> |
46 | #include <sys/select.h> |
47 | #include <sys/proc.h> |
48 | #include <sys/vnode.h> |
49 | #include <sys/poll.h> |
50 | #include <sys/intr.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/auconv.h> |
57 | #include <dev/usb/usbdevs.h> |
58 | #include <dev/usb/umidi_quirks.h> |
59 | #include <dev/midi_if.h> |
60 | |
61 | /* Jack Descriptor */ |
62 | #define 0x01 |
63 | #define UMIDI_IN_JACK 0x02 |
64 | #define UMIDI_OUT_JACK 0x03 |
65 | |
66 | /* Jack Type */ |
67 | #define UMIDI_EMBEDDED 0x01 |
68 | #define UMIDI_EXTERNAL 0x02 |
69 | |
70 | /* generic, for iteration */ |
71 | typedef struct { |
72 | uByte bLength; |
73 | uByte bDescriptorType; |
74 | uByte bDescriptorSubtype; |
75 | } UPACKED umidi_cs_descriptor_t; |
76 | |
77 | typedef struct { |
78 | uByte bLength; |
79 | uByte bDescriptorType; |
80 | uByte bDescriptorSubtype; |
81 | uWord bcdMSC; |
82 | uWord wTotalLength; |
83 | } UPACKED umidi_cs_interface_descriptor_t; |
84 | #define UMIDI_CS_INTERFACE_DESCRIPTOR_SIZE 7 |
85 | |
86 | typedef struct { |
87 | uByte bLength; |
88 | uByte bDescriptorType; |
89 | uByte bDescriptorSubtype; |
90 | uByte bNumEmbMIDIJack; |
91 | } UPACKED umidi_cs_endpoint_descriptor_t; |
92 | #define UMIDI_CS_ENDPOINT_DESCRIPTOR_SIZE 4 |
93 | |
94 | typedef struct { |
95 | uByte bLength; |
96 | uByte bDescriptorType; |
97 | uByte bDescriptorSubtype; |
98 | uByte bJackType; |
99 | uByte bJackID; |
100 | } UPACKED umidi_jack_descriptor_t; |
101 | #define UMIDI_JACK_DESCRIPTOR_SIZE 5 |
102 | |
103 | |
104 | #define TO_D(p) ((usb_descriptor_t *)(p)) |
105 | #define NEXT_D(desc) TO_D((char *)(desc)+(desc)->bLength) |
106 | #define TO_IFD(desc) ((usb_interface_descriptor_t *)(desc)) |
107 | #define TO_CSIFD(desc) ((umidi_cs_interface_descriptor_t *)(desc)) |
108 | #define TO_EPD(desc) ((usb_endpoint_descriptor_t *)(desc)) |
109 | #define TO_CSEPD(desc) ((umidi_cs_endpoint_descriptor_t *)(desc)) |
110 | |
111 | |
112 | #define UMIDI_PACKET_SIZE 4 |
113 | |
114 | /* |
115 | * hierarchie |
116 | * |
117 | * <-- parent child --> |
118 | * |
119 | * umidi(sc) -> endpoint -> jack <- (dynamically assignable) - mididev |
120 | * ^ | ^ | |
121 | * +-----+ +-----+ |
122 | */ |
123 | |
124 | /* midi device */ |
125 | struct umidi_mididev { |
126 | struct umidi_softc *sc; |
127 | device_t mdev; |
128 | /* */ |
129 | struct umidi_jack *in_jack; |
130 | struct umidi_jack *out_jack; |
131 | char *label; |
132 | size_t label_len; |
133 | /* */ |
134 | int opened; |
135 | int closing; |
136 | int flags; |
137 | }; |
138 | |
139 | /* Jack Information */ |
140 | struct umidi_jack { |
141 | struct umidi_endpoint *endpoint; |
142 | /* */ |
143 | int cable_number; |
144 | void *arg; |
145 | int bound; |
146 | int opened; |
147 | unsigned char *midiman_ppkt; |
148 | union { |
149 | struct { |
150 | void (*intr)(void *); |
151 | } out; |
152 | struct { |
153 | void (*intr)(void *, int); |
154 | } in; |
155 | } u; |
156 | }; |
157 | |
158 | #define UMIDI_MAX_EPJACKS 16 |
159 | typedef unsigned char (*umidi_packet_bufp)[UMIDI_PACKET_SIZE]; |
160 | /* endpoint data */ |
161 | struct umidi_endpoint { |
162 | struct umidi_softc *sc; |
163 | /* */ |
164 | int addr; |
165 | struct usbd_pipe *pipe; |
166 | struct usbd_xfer *xfer; |
167 | umidi_packet_bufp buffer; |
168 | umidi_packet_bufp next_slot; |
169 | uint32_t buffer_size; |
170 | int num_scheduled; |
171 | int num_open; |
172 | int num_jacks; |
173 | int soliciting; |
174 | void *solicit_cookie; |
175 | int armed; |
176 | struct umidi_jack *jacks[UMIDI_MAX_EPJACKS]; |
177 | uint16_t this_schedule; /* see UMIDI_MAX_EPJACKS */ |
178 | uint16_t next_schedule; |
179 | }; |
180 | |
181 | /* software context */ |
182 | struct umidi_softc { |
183 | device_t sc_dev; |
184 | struct usbd_device *sc_udev; |
185 | struct usbd_interface *sc_iface; |
186 | const struct umidi_quirk *sc_quirk; |
187 | |
188 | int sc_dying; |
189 | |
190 | int sc_out_num_jacks; |
191 | struct umidi_jack *sc_out_jacks; |
192 | int sc_in_num_jacks; |
193 | struct umidi_jack *sc_in_jacks; |
194 | struct umidi_jack *sc_jacks; |
195 | |
196 | int sc_num_mididevs; |
197 | struct umidi_mididev *sc_mididevs; |
198 | |
199 | int sc_out_num_endpoints; |
200 | struct umidi_endpoint *sc_out_ep; |
201 | int sc_in_num_endpoints; |
202 | struct umidi_endpoint *sc_in_ep; |
203 | struct umidi_endpoint *sc_endpoints; |
204 | size_t sc_endpoints_len; |
205 | int cblnums_global; |
206 | |
207 | kmutex_t sc_lock; |
208 | kcondvar_t sc_cv; |
209 | kcondvar_t sc_detach_cv; |
210 | |
211 | int sc_refcnt; |
212 | }; |
213 | |
214 | #ifdef UMIDI_DEBUG |
215 | #define DPRINTF(x) if (umididebug) printf x |
216 | #define DPRINTFN(n,x) if (umididebug >= (n)) printf x |
217 | #include <sys/time.h> |
218 | static struct timeval umidi_tv; |
219 | int umididebug = 0; |
220 | #else |
221 | #define DPRINTF(x) |
222 | #define DPRINTFN(n,x) |
223 | #endif |
224 | |
225 | #define UMIDI_ENDPOINT_SIZE(sc) (sizeof(*(sc)->sc_out_ep) * \ |
226 | (sc->sc_out_num_endpoints + \ |
227 | sc->sc_in_num_endpoints)) |
228 | |
229 | |
230 | static int umidi_open(void *, int, |
231 | void (*)(void *, int), void (*)(void *), void *); |
232 | static void umidi_close(void *); |
233 | static int umidi_channelmsg(void *, int, int, u_char *, int); |
234 | static int umidi_commonmsg(void *, int, u_char *, int); |
235 | static int umidi_sysex(void *, u_char *, int); |
236 | static int umidi_rtmsg(void *, int); |
237 | static void umidi_getinfo(void *, struct midi_info *); |
238 | static void umidi_get_locks(void *, kmutex_t **, kmutex_t **); |
239 | |
240 | static usbd_status alloc_pipe(struct umidi_endpoint *); |
241 | static void free_pipe(struct umidi_endpoint *); |
242 | |
243 | static usbd_status alloc_all_endpoints(struct umidi_softc *); |
244 | static void free_all_endpoints(struct umidi_softc *); |
245 | |
246 | static usbd_status alloc_all_jacks(struct umidi_softc *); |
247 | static void free_all_jacks(struct umidi_softc *); |
248 | static usbd_status bind_jacks_to_mididev(struct umidi_softc *, |
249 | struct umidi_jack *, |
250 | struct umidi_jack *, |
251 | struct umidi_mididev *); |
252 | static void unbind_jacks_from_mididev(struct umidi_mididev *); |
253 | static void unbind_all_jacks(struct umidi_softc *); |
254 | static usbd_status assign_all_jacks_automatically(struct umidi_softc *); |
255 | static usbd_status open_out_jack(struct umidi_jack *, void *, |
256 | void (*)(void *)); |
257 | static usbd_status open_in_jack(struct umidi_jack *, void *, |
258 | void (*)(void *, int)); |
259 | static void close_out_jack(struct umidi_jack *); |
260 | static void close_in_jack(struct umidi_jack *); |
261 | |
262 | static usbd_status attach_mididev(struct umidi_softc *, struct umidi_mididev *); |
263 | static usbd_status detach_mididev(struct umidi_mididev *, int); |
264 | static void deactivate_mididev(struct umidi_mididev *); |
265 | static usbd_status alloc_all_mididevs(struct umidi_softc *, int); |
266 | static void free_all_mididevs(struct umidi_softc *); |
267 | static usbd_status attach_all_mididevs(struct umidi_softc *); |
268 | static usbd_status detach_all_mididevs(struct umidi_softc *, int); |
269 | static void deactivate_all_mididevs(struct umidi_softc *); |
270 | static void describe_mididev(struct umidi_mididev *); |
271 | |
272 | #ifdef UMIDI_DEBUG |
273 | static void dump_sc(struct umidi_softc *); |
274 | static void dump_ep(struct umidi_endpoint *); |
275 | static void dump_jack(struct umidi_jack *); |
276 | #endif |
277 | |
278 | static usbd_status start_input_transfer(struct umidi_endpoint *); |
279 | static usbd_status start_output_transfer(struct umidi_endpoint *); |
280 | static int out_jack_output(struct umidi_jack *, u_char *, int, int); |
281 | static void in_intr(struct usbd_xfer *, void *, usbd_status); |
282 | static void out_intr(struct usbd_xfer *, void *, usbd_status); |
283 | static void out_solicit(void *); /* struct umidi_endpoint* for softintr */ |
284 | static void out_solicit_locked(void *); /* pre-locked version */ |
285 | |
286 | |
287 | const struct midi_hw_if umidi_hw_if = { |
288 | .open = umidi_open, |
289 | .close = umidi_close, |
290 | .output = umidi_rtmsg, |
291 | .getinfo = umidi_getinfo, |
292 | .get_locks = umidi_get_locks, |
293 | }; |
294 | |
295 | struct midi_hw_if_ext umidi_hw_if_ext = { |
296 | .channel = umidi_channelmsg, |
297 | .common = umidi_commonmsg, |
298 | .sysex = umidi_sysex, |
299 | }; |
300 | |
301 | struct midi_hw_if_ext umidi_hw_if_mm = { |
302 | .channel = umidi_channelmsg, |
303 | .common = umidi_commonmsg, |
304 | .sysex = umidi_sysex, |
305 | .compress = 1, |
306 | }; |
307 | |
308 | int umidi_match(device_t, cfdata_t, void *); |
309 | void umidi_attach(device_t, device_t, void *); |
310 | void umidi_childdet(device_t, device_t); |
311 | int umidi_detach(device_t, int); |
312 | int umidi_activate(device_t, enum devact); |
313 | extern struct cfdriver umidi_cd; |
314 | CFATTACH_DECL2_NEW(umidi, sizeof(struct umidi_softc), umidi_match, |
315 | umidi_attach, umidi_detach, umidi_activate, NULL, umidi_childdet); |
316 | |
317 | int |
318 | umidi_match(device_t parent, cfdata_t match, void *aux) |
319 | { |
320 | struct usbif_attach_arg *uiaa = aux; |
321 | |
322 | DPRINTFN(1,("umidi_match\n" )); |
323 | |
324 | if (umidi_search_quirk(uiaa->uiaa_vendor, uiaa->uiaa_product, |
325 | uiaa->uiaa_ifaceno)) |
326 | return UMATCH_IFACECLASS_IFACESUBCLASS; |
327 | |
328 | if (uiaa->uiaa_class == UICLASS_AUDIO && |
329 | uiaa->uiaa_subclass == UISUBCLASS_MIDISTREAM) |
330 | return UMATCH_IFACECLASS_IFACESUBCLASS; |
331 | |
332 | return UMATCH_NONE; |
333 | } |
334 | |
335 | void |
336 | umidi_attach(device_t parent, device_t self, void *aux) |
337 | { |
338 | usbd_status err; |
339 | struct umidi_softc *sc = device_private(self); |
340 | struct usbif_attach_arg *uiaa = aux; |
341 | char *devinfop; |
342 | |
343 | DPRINTFN(1,("umidi_attach\n" )); |
344 | |
345 | sc->sc_dev = self; |
346 | |
347 | aprint_naive("\n" ); |
348 | aprint_normal("\n" ); |
349 | |
350 | devinfop = usbd_devinfo_alloc(uiaa->uiaa_device, 0); |
351 | aprint_normal_dev(self, "%s\n" , devinfop); |
352 | usbd_devinfo_free(devinfop); |
353 | |
354 | sc->sc_iface = uiaa->uiaa_iface; |
355 | sc->sc_udev = uiaa->uiaa_device; |
356 | |
357 | sc->sc_quirk = umidi_search_quirk(uiaa->uiaa_vendor, |
358 | uiaa->uiaa_product, uiaa->uiaa_ifaceno); |
359 | |
360 | aprint_normal_dev(self, "" ); |
361 | umidi_print_quirk(sc->sc_quirk); |
362 | |
363 | mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB); |
364 | cv_init(&sc->sc_cv, "umidopcl" ); |
365 | cv_init(&sc->sc_detach_cv, "umidetcv" ); |
366 | sc->sc_refcnt = 0; |
367 | |
368 | err = alloc_all_endpoints(sc); |
369 | if (err != USBD_NORMAL_COMPLETION) { |
370 | aprint_error_dev(self, |
371 | "alloc_all_endpoints failed. (err=%d)\n" , err); |
372 | goto out; |
373 | } |
374 | err = alloc_all_jacks(sc); |
375 | if (err != USBD_NORMAL_COMPLETION) { |
376 | aprint_error_dev(self, "alloc_all_jacks failed. (err=%d)\n" , |
377 | err); |
378 | goto out_free_endpoints; |
379 | } |
380 | aprint_normal_dev(self, "out=%d, in=%d\n" , |
381 | sc->sc_out_num_jacks, sc->sc_in_num_jacks); |
382 | |
383 | err = assign_all_jacks_automatically(sc); |
384 | if (err != USBD_NORMAL_COMPLETION) { |
385 | aprint_error_dev(self, |
386 | "assign_all_jacks_automatically failed. (err=%d)\n" , err); |
387 | goto out_free_jacks; |
388 | } |
389 | err = attach_all_mididevs(sc); |
390 | if (err != USBD_NORMAL_COMPLETION) { |
391 | aprint_error_dev(self, |
392 | "attach_all_mididevs failed. (err=%d)\n" , err); |
393 | goto out_free_jacks; |
394 | } |
395 | |
396 | #ifdef UMIDI_DEBUG |
397 | dump_sc(sc); |
398 | #endif |
399 | |
400 | usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); |
401 | |
402 | return; |
403 | |
404 | out_free_jacks: |
405 | unbind_all_jacks(sc); |
406 | free_all_jacks(sc); |
407 | |
408 | out_free_endpoints: |
409 | free_all_endpoints(sc); |
410 | |
411 | out: |
412 | aprint_error_dev(self, "disabled.\n" ); |
413 | sc->sc_dying = 1; |
414 | KERNEL_UNLOCK_ONE(curlwp); |
415 | return; |
416 | } |
417 | |
418 | void |
419 | umidi_childdet(device_t self, device_t child) |
420 | { |
421 | int i; |
422 | struct umidi_softc *sc = device_private(self); |
423 | |
424 | KASSERT(sc->sc_mididevs != NULL); |
425 | |
426 | for (i = 0; i < sc->sc_num_mididevs; i++) { |
427 | if (sc->sc_mididevs[i].mdev == child) |
428 | break; |
429 | } |
430 | KASSERT(i < sc->sc_num_mididevs); |
431 | sc->sc_mididevs[i].mdev = NULL; |
432 | } |
433 | |
434 | int |
435 | umidi_activate(device_t self, enum devact act) |
436 | { |
437 | struct umidi_softc *sc = device_private(self); |
438 | |
439 | switch (act) { |
440 | case DVACT_DEACTIVATE: |
441 | DPRINTFN(1,("umidi_activate (deactivate)\n" )); |
442 | sc->sc_dying = 1; |
443 | deactivate_all_mididevs(sc); |
444 | return 0; |
445 | default: |
446 | DPRINTFN(1,("umidi_activate (%d)\n" , act)); |
447 | return EOPNOTSUPP; |
448 | } |
449 | } |
450 | |
451 | int |
452 | umidi_detach(device_t self, int flags) |
453 | { |
454 | struct umidi_softc *sc = device_private(self); |
455 | |
456 | DPRINTFN(1,("umidi_detach\n" )); |
457 | |
458 | mutex_enter(&sc->sc_lock); |
459 | sc->sc_dying = 1; |
460 | if (--sc->sc_refcnt >= 0) |
461 | usb_detach_wait(sc->sc_dev, &sc->sc_detach_cv, &sc->sc_lock); |
462 | mutex_exit(&sc->sc_lock); |
463 | |
464 | detach_all_mididevs(sc, flags); |
465 | free_all_mididevs(sc); |
466 | free_all_jacks(sc); |
467 | free_all_endpoints(sc); |
468 | |
469 | usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); |
470 | |
471 | mutex_destroy(&sc->sc_lock); |
472 | cv_destroy(&sc->sc_detach_cv); |
473 | cv_destroy(&sc->sc_cv); |
474 | |
475 | return 0; |
476 | } |
477 | |
478 | |
479 | /* |
480 | * midi_if stuffs |
481 | */ |
482 | int |
483 | umidi_open(void *addr, |
484 | int flags, |
485 | void (*iintr)(void *, int), |
486 | void (*ointr)(void *), |
487 | void *arg) |
488 | { |
489 | struct umidi_mididev *mididev = addr; |
490 | struct umidi_softc *sc = mididev->sc; |
491 | usbd_status err; |
492 | |
493 | KASSERT(mutex_owned(&sc->sc_lock)); |
494 | DPRINTF(("umidi_open: sc=%p\n" , sc)); |
495 | |
496 | if (mididev->opened) |
497 | return EBUSY; |
498 | if (sc->sc_dying) |
499 | return EIO; |
500 | |
501 | mididev->opened = 1; |
502 | mididev->flags = flags; |
503 | if ((mididev->flags & FWRITE) && mididev->out_jack) { |
504 | err = open_out_jack(mididev->out_jack, arg, ointr); |
505 | if (err != USBD_NORMAL_COMPLETION) |
506 | goto bad; |
507 | } |
508 | if ((mididev->flags & FREAD) && mididev->in_jack) { |
509 | err = open_in_jack(mididev->in_jack, arg, iintr); |
510 | KASSERT(mididev->opened); |
511 | if (err != USBD_NORMAL_COMPLETION && |
512 | err != USBD_IN_PROGRESS) { |
513 | if (mididev->out_jack) |
514 | close_out_jack(mididev->out_jack); |
515 | goto bad; |
516 | } |
517 | } |
518 | |
519 | return 0; |
520 | bad: |
521 | mididev->opened = 0; |
522 | DPRINTF(("umidi_open: usbd_status %d\n" , err)); |
523 | KASSERT(mutex_owned(&sc->sc_lock)); |
524 | return USBD_IN_USE == err ? EBUSY : EIO; |
525 | } |
526 | |
527 | void |
528 | umidi_close(void *addr) |
529 | { |
530 | struct umidi_mididev *mididev = addr; |
531 | struct umidi_softc *sc = mididev->sc; |
532 | |
533 | KASSERT(mutex_owned(&sc->sc_lock)); |
534 | |
535 | if (mididev->closing) |
536 | return; |
537 | |
538 | mididev->closing = 1; |
539 | |
540 | sc->sc_refcnt++; |
541 | |
542 | if ((mididev->flags & FWRITE) && mididev->out_jack) |
543 | close_out_jack(mididev->out_jack); |
544 | if ((mididev->flags & FREAD) && mididev->in_jack) |
545 | close_in_jack(mididev->in_jack); |
546 | |
547 | if (--sc->sc_refcnt < 0) |
548 | usb_detach_broadcast(sc->sc_dev, &sc->sc_detach_cv); |
549 | |
550 | mididev->opened = 0; |
551 | mididev->closing = 0; |
552 | } |
553 | |
554 | int |
555 | umidi_channelmsg(void *addr, int status, int channel, u_char *msg, |
556 | int len) |
557 | { |
558 | struct umidi_mididev *mididev = addr; |
559 | |
560 | KASSERT(mutex_owned(&mididev->sc->sc_lock)); |
561 | |
562 | if (!mididev->out_jack || !mididev->opened || mididev->closing) |
563 | return EIO; |
564 | |
565 | return out_jack_output(mididev->out_jack, msg, len, (status>>4)&0xf); |
566 | } |
567 | |
568 | int |
569 | umidi_commonmsg(void *addr, int status, u_char *msg, int len) |
570 | { |
571 | struct umidi_mididev *mididev = addr; |
572 | int cin; |
573 | |
574 | KASSERT(mutex_owned(&mididev->sc->sc_lock)); |
575 | |
576 | if (!mididev->out_jack || !mididev->opened || mididev->closing) |
577 | return EIO; |
578 | |
579 | switch ( len ) { |
580 | case 1: cin = 5; break; |
581 | case 2: cin = 2; break; |
582 | case 3: cin = 3; break; |
583 | default: return EIO; /* or gcc warns of cin uninitialized */ |
584 | } |
585 | |
586 | return out_jack_output(mididev->out_jack, msg, len, cin); |
587 | } |
588 | |
589 | int |
590 | umidi_sysex(void *addr, u_char *msg, int len) |
591 | { |
592 | struct umidi_mididev *mididev = addr; |
593 | int cin; |
594 | |
595 | KASSERT(mutex_owned(&mididev->sc->sc_lock)); |
596 | |
597 | if (!mididev->out_jack || !mididev->opened || mididev->closing) |
598 | return EIO; |
599 | |
600 | switch ( len ) { |
601 | case 1: cin = 5; break; |
602 | case 2: cin = 6; break; |
603 | case 3: cin = (msg[2] == 0xf7) ? 7 : 4; break; |
604 | default: return EIO; /* or gcc warns of cin uninitialized */ |
605 | } |
606 | |
607 | return out_jack_output(mididev->out_jack, msg, len, cin); |
608 | } |
609 | |
610 | int |
611 | umidi_rtmsg(void *addr, int d) |
612 | { |
613 | struct umidi_mididev *mididev = addr; |
614 | u_char msg = d; |
615 | |
616 | KASSERT(mutex_owned(&mididev->sc->sc_lock)); |
617 | |
618 | if (!mididev->out_jack || !mididev->opened || mididev->closing) |
619 | return EIO; |
620 | |
621 | return out_jack_output(mididev->out_jack, &msg, 1, 0xf); |
622 | } |
623 | |
624 | void |
625 | umidi_getinfo(void *addr, struct midi_info *mi) |
626 | { |
627 | struct umidi_mididev *mididev = addr; |
628 | struct umidi_softc *sc = mididev->sc; |
629 | int mm = UMQ_ISTYPE(sc, UMQ_TYPE_MIDIMAN_GARBLE); |
630 | |
631 | KASSERT(mutex_owned(&sc->sc_lock)); |
632 | |
633 | mi->name = mididev->label; |
634 | mi->props = MIDI_PROP_OUT_INTR; |
635 | if (mididev->in_jack) |
636 | mi->props |= MIDI_PROP_CAN_INPUT; |
637 | midi_register_hw_if_ext(mm? &umidi_hw_if_mm : &umidi_hw_if_ext); |
638 | } |
639 | |
640 | static void |
641 | umidi_get_locks(void *addr, kmutex_t **thread, kmutex_t **intr) |
642 | { |
643 | struct umidi_mididev *mididev = addr; |
644 | struct umidi_softc *sc = mididev->sc; |
645 | |
646 | *intr = NULL; |
647 | *thread = &sc->sc_lock; |
648 | } |
649 | |
650 | /* |
651 | * each endpoint stuffs |
652 | */ |
653 | |
654 | /* alloc/free pipe */ |
655 | static usbd_status |
656 | alloc_pipe(struct umidi_endpoint *ep) |
657 | { |
658 | struct umidi_softc *sc = ep->sc; |
659 | usbd_status err; |
660 | usb_endpoint_descriptor_t *epd; |
661 | |
662 | epd = usbd_get_endpoint_descriptor(sc->sc_iface, ep->addr); |
663 | /* |
664 | * For output, an improvement would be to have a buffer bigger than |
665 | * wMaxPacketSize by num_jacks-1 additional packet slots; that would |
666 | * allow out_solicit to fill the buffer to the full packet size in |
667 | * all cases. But to use usbd_create_xfer to get a slightly larger |
668 | * buffer would not be a good way to do that, because if the addition |
669 | * would make the buffer exceed USB_MEM_SMALL then a substantially |
670 | * larger block may be wastefully allocated. Some flavor of double |
671 | * buffering could serve the same purpose, but would increase the |
672 | * code complexity, so for now I will live with the current slight |
673 | * penalty of reducing max transfer size by (num_open-num_scheduled) |
674 | * packet slots. |
675 | */ |
676 | ep->buffer_size = UGETW(epd->wMaxPacketSize); |
677 | ep->buffer_size -= ep->buffer_size % UMIDI_PACKET_SIZE; |
678 | |
679 | DPRINTF(("%s: alloc_pipe %p, buffer size %u\n" , |
680 | device_xname(sc->sc_dev), ep, ep->buffer_size)); |
681 | ep->num_scheduled = 0; |
682 | ep->this_schedule = 0; |
683 | ep->next_schedule = 0; |
684 | ep->soliciting = 0; |
685 | ep->armed = 0; |
686 | err = usbd_open_pipe(sc->sc_iface, ep->addr, USBD_MPSAFE, &ep->pipe); |
687 | if (err) |
688 | goto quit; |
689 | int error = usbd_create_xfer(ep->pipe, ep->buffer_size, |
690 | USBD_SHORT_XFER_OK, 0, &ep->xfer); |
691 | if (error) { |
692 | usbd_close_pipe(ep->pipe); |
693 | return USBD_NOMEM; |
694 | } |
695 | ep->buffer = usbd_get_buffer(ep->xfer); |
696 | ep->next_slot = ep->buffer; |
697 | ep->solicit_cookie = softint_establish(SOFTINT_CLOCK | SOFTINT_MPSAFE, |
698 | out_solicit, ep); |
699 | quit: |
700 | return err; |
701 | } |
702 | |
703 | static void |
704 | free_pipe(struct umidi_endpoint *ep) |
705 | { |
706 | DPRINTF(("%s: free_pipe %p\n" , device_xname(ep->sc->sc_dev), ep)); |
707 | usbd_abort_pipe(ep->pipe); |
708 | usbd_destroy_xfer(ep->xfer); |
709 | usbd_close_pipe(ep->pipe); |
710 | softint_disestablish(ep->solicit_cookie); |
711 | } |
712 | |
713 | |
714 | /* alloc/free the array of endpoint structures */ |
715 | |
716 | static usbd_status alloc_all_endpoints_fixed_ep(struct umidi_softc *); |
717 | static usbd_status alloc_all_endpoints_yamaha(struct umidi_softc *); |
718 | static usbd_status alloc_all_endpoints_genuine(struct umidi_softc *); |
719 | |
720 | static usbd_status |
721 | alloc_all_endpoints(struct umidi_softc *sc) |
722 | { |
723 | usbd_status err; |
724 | struct umidi_endpoint *ep; |
725 | int i; |
726 | |
727 | if (UMQ_ISTYPE(sc, UMQ_TYPE_FIXED_EP)) { |
728 | err = alloc_all_endpoints_fixed_ep(sc); |
729 | } else if (UMQ_ISTYPE(sc, UMQ_TYPE_YAMAHA)) { |
730 | err = alloc_all_endpoints_yamaha(sc); |
731 | } else { |
732 | err = alloc_all_endpoints_genuine(sc); |
733 | } |
734 | if (err != USBD_NORMAL_COMPLETION) |
735 | return err; |
736 | |
737 | ep = sc->sc_endpoints; |
738 | for (i = sc->sc_out_num_endpoints+sc->sc_in_num_endpoints; i > 0; i--) { |
739 | err = alloc_pipe(ep++); |
740 | if (err != USBD_NORMAL_COMPLETION) { |
741 | for (; ep != sc->sc_endpoints; ep--) |
742 | free_pipe(ep-1); |
743 | kmem_free(sc->sc_endpoints, sc->sc_endpoints_len); |
744 | sc->sc_endpoints = sc->sc_out_ep = sc->sc_in_ep = NULL; |
745 | break; |
746 | } |
747 | } |
748 | return err; |
749 | } |
750 | |
751 | static void |
752 | free_all_endpoints(struct umidi_softc *sc) |
753 | { |
754 | int i; |
755 | |
756 | for (i=0; i<sc->sc_in_num_endpoints+sc->sc_out_num_endpoints; i++) |
757 | free_pipe(&sc->sc_endpoints[i]); |
758 | if (sc->sc_endpoints != NULL) |
759 | kmem_free(sc->sc_endpoints, sc->sc_endpoints_len); |
760 | sc->sc_endpoints = sc->sc_out_ep = sc->sc_in_ep = NULL; |
761 | } |
762 | |
763 | static usbd_status |
764 | alloc_all_endpoints_fixed_ep(struct umidi_softc *sc) |
765 | { |
766 | usbd_status err; |
767 | const struct umq_fixed_ep_desc *fp; |
768 | struct umidi_endpoint *ep; |
769 | usb_endpoint_descriptor_t *epd; |
770 | int i; |
771 | |
772 | fp = umidi_get_quirk_data_from_type(sc->sc_quirk, |
773 | UMQ_TYPE_FIXED_EP); |
774 | sc->sc_out_num_jacks = 0; |
775 | sc->sc_in_num_jacks = 0; |
776 | sc->sc_out_num_endpoints = fp->num_out_ep; |
777 | sc->sc_in_num_endpoints = fp->num_in_ep; |
778 | sc->sc_endpoints_len = UMIDI_ENDPOINT_SIZE(sc); |
779 | sc->sc_endpoints = kmem_zalloc(sc->sc_endpoints_len, KM_SLEEP); |
780 | if (!sc->sc_endpoints) |
781 | return USBD_NOMEM; |
782 | |
783 | sc->sc_out_ep = sc->sc_out_num_endpoints ? sc->sc_endpoints : NULL; |
784 | sc->sc_in_ep = |
785 | sc->sc_in_num_endpoints ? |
786 | sc->sc_endpoints+sc->sc_out_num_endpoints : NULL; |
787 | |
788 | ep = &sc->sc_out_ep[0]; |
789 | for (i = 0; i < sc->sc_out_num_endpoints; i++) { |
790 | epd = usbd_interface2endpoint_descriptor( |
791 | sc->sc_iface, |
792 | fp->out_ep[i].ep); |
793 | if (!epd) { |
794 | aprint_error_dev(sc->sc_dev, |
795 | "cannot get endpoint descriptor(out:%d)\n" , |
796 | fp->out_ep[i].ep); |
797 | err = USBD_INVAL; |
798 | goto error; |
799 | } |
800 | if (UE_GET_XFERTYPE(epd->bmAttributes)!=UE_BULK || |
801 | UE_GET_DIR(epd->bEndpointAddress)!=UE_DIR_OUT) { |
802 | aprint_error_dev(sc->sc_dev, |
803 | "illegal endpoint(out:%d)\n" , fp->out_ep[i].ep); |
804 | err = USBD_INVAL; |
805 | goto error; |
806 | } |
807 | ep->sc = sc; |
808 | ep->addr = epd->bEndpointAddress; |
809 | ep->num_jacks = fp->out_ep[i].num_jacks; |
810 | sc->sc_out_num_jacks += fp->out_ep[i].num_jacks; |
811 | ep->num_open = 0; |
812 | ep++; |
813 | } |
814 | ep = &sc->sc_in_ep[0]; |
815 | for (i = 0; i < sc->sc_in_num_endpoints; i++) { |
816 | epd = usbd_interface2endpoint_descriptor( |
817 | sc->sc_iface, |
818 | fp->in_ep[i].ep); |
819 | if (!epd) { |
820 | aprint_error_dev(sc->sc_dev, |
821 | "cannot get endpoint descriptor(in:%d)\n" , |
822 | fp->in_ep[i].ep); |
823 | err = USBD_INVAL; |
824 | goto error; |
825 | } |
826 | /* |
827 | * MIDISPORT_2X4 inputs on an interrupt rather than a bulk |
828 | * endpoint. The existing input logic in this driver seems |
829 | * to work successfully if we just stop treating an interrupt |
830 | * endpoint as illegal (or the in_progress status we get on |
831 | * the initial transfer). It does not seem necessary to |
832 | * actually use the interrupt flavor of alloc_pipe or make |
833 | * other serious rearrangements of logic. I like that. |
834 | */ |
835 | switch ( UE_GET_XFERTYPE(epd->bmAttributes) ) { |
836 | case UE_BULK: |
837 | case UE_INTERRUPT: |
838 | if (UE_DIR_IN == UE_GET_DIR(epd->bEndpointAddress)) |
839 | break; |
840 | /*FALLTHROUGH*/ |
841 | default: |
842 | aprint_error_dev(sc->sc_dev, |
843 | "illegal endpoint(in:%d)\n" , fp->in_ep[i].ep); |
844 | err = USBD_INVAL; |
845 | goto error; |
846 | } |
847 | |
848 | ep->sc = sc; |
849 | ep->addr = epd->bEndpointAddress; |
850 | ep->num_jacks = fp->in_ep[i].num_jacks; |
851 | sc->sc_in_num_jacks += fp->in_ep[i].num_jacks; |
852 | ep->num_open = 0; |
853 | ep++; |
854 | } |
855 | |
856 | return USBD_NORMAL_COMPLETION; |
857 | error: |
858 | kmem_free(sc->sc_endpoints, UMIDI_ENDPOINT_SIZE(sc)); |
859 | sc->sc_endpoints = NULL; |
860 | return err; |
861 | } |
862 | |
863 | static usbd_status |
864 | alloc_all_endpoints_yamaha(struct umidi_softc *sc) |
865 | { |
866 | /* This driver currently supports max 1in/1out bulk endpoints */ |
867 | usb_descriptor_t *desc; |
868 | umidi_cs_descriptor_t *udesc; |
869 | usb_endpoint_descriptor_t *epd; |
870 | int out_addr, in_addr, i; |
871 | int dir; |
872 | size_t remain, descsize; |
873 | |
874 | sc->sc_out_num_jacks = sc->sc_in_num_jacks = 0; |
875 | out_addr = in_addr = 0; |
876 | |
877 | /* detect endpoints */ |
878 | desc = TO_D(usbd_get_interface_descriptor(sc->sc_iface)); |
879 | for (i=(int)TO_IFD(desc)->bNumEndpoints-1; i>=0; i--) { |
880 | epd = usbd_interface2endpoint_descriptor(sc->sc_iface, i); |
881 | KASSERT(epd != NULL); |
882 | if (UE_GET_XFERTYPE(epd->bmAttributes) == UE_BULK) { |
883 | dir = UE_GET_DIR(epd->bEndpointAddress); |
884 | if (dir==UE_DIR_OUT && !out_addr) |
885 | out_addr = epd->bEndpointAddress; |
886 | else if (dir==UE_DIR_IN && !in_addr) |
887 | in_addr = epd->bEndpointAddress; |
888 | } |
889 | } |
890 | udesc = (umidi_cs_descriptor_t *)NEXT_D(desc); |
891 | |
892 | /* count jacks */ |
893 | if (!(udesc->bDescriptorType==UDESC_CS_INTERFACE && |
894 | udesc->bDescriptorSubtype==UMIDI_MS_HEADER)) |
895 | return USBD_INVAL; |
896 | remain = (size_t)UGETW(TO_CSIFD(udesc)->wTotalLength) - |
897 | (size_t)udesc->bLength; |
898 | udesc = (umidi_cs_descriptor_t *)NEXT_D(udesc); |
899 | |
900 | while (remain >= sizeof(usb_descriptor_t)) { |
901 | descsize = udesc->bLength; |
902 | if (descsize>remain || descsize==0) |
903 | break; |
904 | if (udesc->bDescriptorType == UDESC_CS_INTERFACE && |
905 | remain >= UMIDI_JACK_DESCRIPTOR_SIZE) { |
906 | if (udesc->bDescriptorSubtype == UMIDI_OUT_JACK) |
907 | sc->sc_out_num_jacks++; |
908 | else if (udesc->bDescriptorSubtype == UMIDI_IN_JACK) |
909 | sc->sc_in_num_jacks++; |
910 | } |
911 | udesc = (umidi_cs_descriptor_t *)NEXT_D(udesc); |
912 | remain -= descsize; |
913 | } |
914 | |
915 | /* validate some parameters */ |
916 | if (sc->sc_out_num_jacks>UMIDI_MAX_EPJACKS) |
917 | sc->sc_out_num_jacks = UMIDI_MAX_EPJACKS; |
918 | if (sc->sc_in_num_jacks>UMIDI_MAX_EPJACKS) |
919 | sc->sc_in_num_jacks = UMIDI_MAX_EPJACKS; |
920 | if (sc->sc_out_num_jacks && out_addr) { |
921 | sc->sc_out_num_endpoints = 1; |
922 | } else { |
923 | sc->sc_out_num_endpoints = 0; |
924 | sc->sc_out_num_jacks = 0; |
925 | } |
926 | if (sc->sc_in_num_jacks && in_addr) { |
927 | sc->sc_in_num_endpoints = 1; |
928 | } else { |
929 | sc->sc_in_num_endpoints = 0; |
930 | sc->sc_in_num_jacks = 0; |
931 | } |
932 | sc->sc_endpoints_len = UMIDI_ENDPOINT_SIZE(sc); |
933 | sc->sc_endpoints = kmem_zalloc(sc->sc_endpoints_len, KM_SLEEP); |
934 | if (!sc->sc_endpoints) |
935 | return USBD_NOMEM; |
936 | if (sc->sc_out_num_endpoints) { |
937 | sc->sc_out_ep = sc->sc_endpoints; |
938 | sc->sc_out_ep->sc = sc; |
939 | sc->sc_out_ep->addr = out_addr; |
940 | sc->sc_out_ep->num_jacks = sc->sc_out_num_jacks; |
941 | sc->sc_out_ep->num_open = 0; |
942 | } else |
943 | sc->sc_out_ep = NULL; |
944 | |
945 | if (sc->sc_in_num_endpoints) { |
946 | sc->sc_in_ep = sc->sc_endpoints+sc->sc_out_num_endpoints; |
947 | sc->sc_in_ep->sc = sc; |
948 | sc->sc_in_ep->addr = in_addr; |
949 | sc->sc_in_ep->num_jacks = sc->sc_in_num_jacks; |
950 | sc->sc_in_ep->num_open = 0; |
951 | } else |
952 | sc->sc_in_ep = NULL; |
953 | |
954 | return USBD_NORMAL_COMPLETION; |
955 | } |
956 | |
957 | static usbd_status |
958 | alloc_all_endpoints_genuine(struct umidi_softc *sc) |
959 | { |
960 | usb_interface_descriptor_t *interface_desc; |
961 | usb_config_descriptor_t *config_desc; |
962 | usb_descriptor_t *desc; |
963 | int num_ep; |
964 | size_t remain, descsize; |
965 | struct umidi_endpoint *p, *q, *lowest, *endep, tmpep; |
966 | int epaddr; |
967 | |
968 | interface_desc = usbd_get_interface_descriptor(sc->sc_iface); |
969 | num_ep = interface_desc->bNumEndpoints; |
970 | sc->sc_endpoints_len = sizeof(struct umidi_endpoint) * num_ep; |
971 | sc->sc_endpoints = p = kmem_zalloc(sc->sc_endpoints_len, KM_SLEEP); |
972 | if (!p) |
973 | return USBD_NOMEM; |
974 | |
975 | sc->sc_out_num_jacks = sc->sc_in_num_jacks = 0; |
976 | sc->sc_out_num_endpoints = sc->sc_in_num_endpoints = 0; |
977 | epaddr = -1; |
978 | |
979 | /* get the list of endpoints for midi stream */ |
980 | config_desc = usbd_get_config_descriptor(sc->sc_udev); |
981 | desc = (usb_descriptor_t *) config_desc; |
982 | remain = (size_t)UGETW(config_desc->wTotalLength); |
983 | while (remain>=sizeof(usb_descriptor_t)) { |
984 | descsize = desc->bLength; |
985 | if (descsize>remain || descsize==0) |
986 | break; |
987 | if (desc->bDescriptorType==UDESC_ENDPOINT && |
988 | remain>=USB_ENDPOINT_DESCRIPTOR_SIZE && |
989 | UE_GET_XFERTYPE(TO_EPD(desc)->bmAttributes) == UE_BULK) { |
990 | epaddr = TO_EPD(desc)->bEndpointAddress; |
991 | } else if (desc->bDescriptorType==UDESC_CS_ENDPOINT && |
992 | remain>=UMIDI_CS_ENDPOINT_DESCRIPTOR_SIZE && |
993 | epaddr!=-1) { |
994 | if (num_ep>0) { |
995 | num_ep--; |
996 | p->sc = sc; |
997 | p->addr = epaddr; |
998 | p->num_jacks = TO_CSEPD(desc)->bNumEmbMIDIJack; |
999 | if (UE_GET_DIR(epaddr)==UE_DIR_OUT) { |
1000 | sc->sc_out_num_endpoints++; |
1001 | sc->sc_out_num_jacks += p->num_jacks; |
1002 | } else { |
1003 | sc->sc_in_num_endpoints++; |
1004 | sc->sc_in_num_jacks += p->num_jacks; |
1005 | } |
1006 | p++; |
1007 | } |
1008 | } else |
1009 | epaddr = -1; |
1010 | desc = NEXT_D(desc); |
1011 | remain-=descsize; |
1012 | } |
1013 | |
1014 | /* sort endpoints */ |
1015 | num_ep = sc->sc_out_num_endpoints + sc->sc_in_num_endpoints; |
1016 | p = sc->sc_endpoints; |
1017 | endep = p + num_ep; |
1018 | while (p<endep) { |
1019 | lowest = p; |
1020 | for (q=p+1; q<endep; q++) { |
1021 | if ((UE_GET_DIR(lowest->addr)==UE_DIR_IN && |
1022 | UE_GET_DIR(q->addr)==UE_DIR_OUT) || |
1023 | ((UE_GET_DIR(lowest->addr)== |
1024 | UE_GET_DIR(q->addr)) && |
1025 | (UE_GET_ADDR(lowest->addr)> |
1026 | UE_GET_ADDR(q->addr)))) |
1027 | lowest = q; |
1028 | } |
1029 | if (lowest != p) { |
1030 | memcpy((void *)&tmpep, (void *)p, sizeof(tmpep)); |
1031 | memcpy((void *)p, (void *)lowest, sizeof(tmpep)); |
1032 | memcpy((void *)lowest, (void *)&tmpep, sizeof(tmpep)); |
1033 | } |
1034 | p->num_open = 0; |
1035 | p++; |
1036 | } |
1037 | |
1038 | sc->sc_out_ep = sc->sc_out_num_endpoints ? sc->sc_endpoints : NULL; |
1039 | sc->sc_in_ep = |
1040 | sc->sc_in_num_endpoints ? |
1041 | sc->sc_endpoints+sc->sc_out_num_endpoints : NULL; |
1042 | |
1043 | return USBD_NORMAL_COMPLETION; |
1044 | } |
1045 | |
1046 | |
1047 | /* |
1048 | * jack stuffs |
1049 | */ |
1050 | |
1051 | static usbd_status |
1052 | alloc_all_jacks(struct umidi_softc *sc) |
1053 | { |
1054 | int i, j; |
1055 | struct umidi_endpoint *ep; |
1056 | struct umidi_jack *jack; |
1057 | const unsigned char *cn_spec; |
1058 | |
1059 | if (UMQ_ISTYPE(sc, UMQ_TYPE_CN_SEQ_PER_EP)) |
1060 | sc->cblnums_global = 0; |
1061 | else if (UMQ_ISTYPE(sc, UMQ_TYPE_CN_SEQ_GLOBAL)) |
1062 | sc->cblnums_global = 1; |
1063 | else { |
1064 | /* |
1065 | * I don't think this default is correct, but it preserves |
1066 | * the prior behavior of the code. That's why I defined two |
1067 | * complementary quirks. Any device for which the default |
1068 | * behavior is wrong can be made to work by giving it an |
1069 | * explicit quirk, and if a pattern ever develops (as I suspect |
1070 | * it will) that a lot of otherwise standard USB MIDI devices |
1071 | * need the CN_SEQ_PER_EP "quirk," then this default can be |
1072 | * changed to 0, and the only devices that will break are those |
1073 | * listing neither quirk, and they'll easily be fixed by giving |
1074 | * them the CN_SEQ_GLOBAL quirk. |
1075 | */ |
1076 | sc->cblnums_global = 1; |
1077 | } |
1078 | |
1079 | if (UMQ_ISTYPE(sc, UMQ_TYPE_CN_FIXED)) |
1080 | cn_spec = umidi_get_quirk_data_from_type(sc->sc_quirk, |
1081 | UMQ_TYPE_CN_FIXED); |
1082 | else |
1083 | cn_spec = NULL; |
1084 | |
1085 | /* allocate/initialize structures */ |
1086 | sc->sc_jacks = |
1087 | kmem_zalloc(sizeof(*sc->sc_out_jacks)*(sc->sc_in_num_jacks |
1088 | + sc->sc_out_num_jacks), KM_SLEEP); |
1089 | if (!sc->sc_jacks) |
1090 | return USBD_NOMEM; |
1091 | sc->sc_out_jacks = |
1092 | sc->sc_out_num_jacks ? sc->sc_jacks : NULL; |
1093 | sc->sc_in_jacks = |
1094 | sc->sc_in_num_jacks ? sc->sc_jacks+sc->sc_out_num_jacks : NULL; |
1095 | |
1096 | jack = &sc->sc_out_jacks[0]; |
1097 | for (i = 0; i < sc->sc_out_num_jacks; i++) { |
1098 | jack->opened = 0; |
1099 | jack->bound = 0; |
1100 | jack->arg = NULL; |
1101 | jack->u.out.intr = NULL; |
1102 | jack->midiman_ppkt = NULL; |
1103 | if (sc->cblnums_global) |
1104 | jack->cable_number = i; |
1105 | jack++; |
1106 | } |
1107 | jack = &sc->sc_in_jacks[0]; |
1108 | for (i = 0; i < sc->sc_in_num_jacks; i++) { |
1109 | jack->opened = 0; |
1110 | jack->bound = 0; |
1111 | jack->arg = NULL; |
1112 | jack->u.in.intr = NULL; |
1113 | if (sc->cblnums_global) |
1114 | jack->cable_number = i; |
1115 | jack++; |
1116 | } |
1117 | |
1118 | /* assign each jacks to each endpoints */ |
1119 | jack = &sc->sc_out_jacks[0]; |
1120 | ep = &sc->sc_out_ep[0]; |
1121 | for (i = 0; i < sc->sc_out_num_endpoints; i++) { |
1122 | for (j = 0; j < ep->num_jacks; j++) { |
1123 | jack->endpoint = ep; |
1124 | if (cn_spec != NULL) |
1125 | jack->cable_number = *cn_spec++; |
1126 | else if (!sc->cblnums_global) |
1127 | jack->cable_number = j; |
1128 | ep->jacks[jack->cable_number] = jack; |
1129 | jack++; |
1130 | } |
1131 | ep++; |
1132 | } |
1133 | jack = &sc->sc_in_jacks[0]; |
1134 | ep = &sc->sc_in_ep[0]; |
1135 | for (i = 0; i < sc->sc_in_num_endpoints; i++) { |
1136 | for (j = 0; j < ep->num_jacks; j++) { |
1137 | jack->endpoint = ep; |
1138 | if (cn_spec != NULL) |
1139 | jack->cable_number = *cn_spec++; |
1140 | else if (!sc->cblnums_global) |
1141 | jack->cable_number = j; |
1142 | ep->jacks[jack->cable_number] = jack; |
1143 | jack++; |
1144 | } |
1145 | ep++; |
1146 | } |
1147 | |
1148 | return USBD_NORMAL_COMPLETION; |
1149 | } |
1150 | |
1151 | static void |
1152 | free_all_jacks(struct umidi_softc *sc) |
1153 | { |
1154 | struct umidi_jack *jacks; |
1155 | size_t len; |
1156 | |
1157 | mutex_enter(&sc->sc_lock); |
1158 | jacks = sc->sc_jacks; |
1159 | len = sizeof(*sc->sc_out_jacks) |
1160 | * (sc->sc_in_num_jacks + sc->sc_out_num_jacks); |
1161 | sc->sc_jacks = sc->sc_in_jacks = sc->sc_out_jacks = NULL; |
1162 | mutex_exit(&sc->sc_lock); |
1163 | |
1164 | if (jacks) |
1165 | kmem_free(jacks, len); |
1166 | } |
1167 | |
1168 | static usbd_status |
1169 | bind_jacks_to_mididev(struct umidi_softc *sc, |
1170 | struct umidi_jack *out_jack, |
1171 | struct umidi_jack *in_jack, |
1172 | struct umidi_mididev *mididev) |
1173 | { |
1174 | if ((out_jack && out_jack->bound) || (in_jack && in_jack->bound)) |
1175 | return USBD_IN_USE; |
1176 | if (mididev->out_jack || mididev->in_jack) |
1177 | return USBD_IN_USE; |
1178 | |
1179 | if (out_jack) |
1180 | out_jack->bound = 1; |
1181 | if (in_jack) |
1182 | in_jack->bound = 1; |
1183 | mididev->in_jack = in_jack; |
1184 | mididev->out_jack = out_jack; |
1185 | |
1186 | mididev->closing = 0; |
1187 | |
1188 | return USBD_NORMAL_COMPLETION; |
1189 | } |
1190 | |
1191 | static void |
1192 | unbind_jacks_from_mididev(struct umidi_mididev *mididev) |
1193 | { |
1194 | KASSERT(mutex_owned(&mididev->sc->sc_lock)); |
1195 | |
1196 | mididev->closing = 1; |
1197 | |
1198 | if ((mididev->flags & FWRITE) && mididev->out_jack) |
1199 | close_out_jack(mididev->out_jack); |
1200 | if ((mididev->flags & FREAD) && mididev->in_jack) |
1201 | close_in_jack(mididev->in_jack); |
1202 | |
1203 | if (mididev->out_jack) { |
1204 | mididev->out_jack->bound = 0; |
1205 | mididev->out_jack = NULL; |
1206 | } |
1207 | if (mididev->in_jack) { |
1208 | mididev->in_jack->bound = 0; |
1209 | mididev->in_jack = NULL; |
1210 | } |
1211 | } |
1212 | |
1213 | static void |
1214 | unbind_all_jacks(struct umidi_softc *sc) |
1215 | { |
1216 | int i; |
1217 | |
1218 | mutex_enter(&sc->sc_lock); |
1219 | if (sc->sc_mididevs) |
1220 | for (i = 0; i < sc->sc_num_mididevs; i++) |
1221 | unbind_jacks_from_mididev(&sc->sc_mididevs[i]); |
1222 | mutex_exit(&sc->sc_lock); |
1223 | } |
1224 | |
1225 | static usbd_status |
1226 | assign_all_jacks_automatically(struct umidi_softc *sc) |
1227 | { |
1228 | usbd_status err; |
1229 | int i; |
1230 | struct umidi_jack *out, *in; |
1231 | const signed char *asg_spec; |
1232 | |
1233 | err = |
1234 | alloc_all_mididevs(sc, |
1235 | max(sc->sc_out_num_jacks, sc->sc_in_num_jacks)); |
1236 | if (err!=USBD_NORMAL_COMPLETION) |
1237 | return err; |
1238 | |
1239 | if (UMQ_ISTYPE(sc, UMQ_TYPE_MD_FIXED)) |
1240 | asg_spec = umidi_get_quirk_data_from_type(sc->sc_quirk, |
1241 | UMQ_TYPE_MD_FIXED); |
1242 | else |
1243 | asg_spec = NULL; |
1244 | |
1245 | for (i = 0; i < sc->sc_num_mididevs; i++) { |
1246 | if (asg_spec != NULL) { |
1247 | if (*asg_spec == -1) |
1248 | out = NULL; |
1249 | else |
1250 | out = &sc->sc_out_jacks[*asg_spec]; |
1251 | ++ asg_spec; |
1252 | if (*asg_spec == -1) |
1253 | in = NULL; |
1254 | else |
1255 | in = &sc->sc_in_jacks[*asg_spec]; |
1256 | ++ asg_spec; |
1257 | } else { |
1258 | out = (i<sc->sc_out_num_jacks) ? &sc->sc_out_jacks[i] |
1259 | : NULL; |
1260 | in = (i<sc->sc_in_num_jacks) ? &sc->sc_in_jacks[i] |
1261 | : NULL; |
1262 | } |
1263 | err = bind_jacks_to_mididev(sc, out, in, &sc->sc_mididevs[i]); |
1264 | if (err != USBD_NORMAL_COMPLETION) { |
1265 | free_all_mididevs(sc); |
1266 | return err; |
1267 | } |
1268 | } |
1269 | |
1270 | return USBD_NORMAL_COMPLETION; |
1271 | } |
1272 | |
1273 | static usbd_status |
1274 | open_out_jack(struct umidi_jack *jack, void *arg, void (*intr)(void *)) |
1275 | { |
1276 | struct umidi_endpoint *ep = jack->endpoint; |
1277 | struct umidi_softc *sc = ep->sc; |
1278 | umidi_packet_bufp end; |
1279 | int err; |
1280 | |
1281 | KASSERT(mutex_owned(&sc->sc_lock)); |
1282 | |
1283 | if (jack->opened) |
1284 | return USBD_IN_USE; |
1285 | |
1286 | jack->arg = arg; |
1287 | jack->u.out.intr = intr; |
1288 | jack->midiman_ppkt = NULL; |
1289 | end = ep->buffer + ep->buffer_size / sizeof(*ep->buffer); |
1290 | jack->opened = 1; |
1291 | ep->num_open++; |
1292 | /* |
1293 | * out_solicit maintains an invariant that there will always be |
1294 | * (num_open - num_scheduled) slots free in the buffer. as we have |
1295 | * just incremented num_open, the buffer may be too full to satisfy |
1296 | * the invariant until a transfer completes, for which we must wait. |
1297 | */ |
1298 | while (end - ep->next_slot < ep->num_open - ep->num_scheduled) { |
1299 | err = cv_timedwait_sig(&sc->sc_cv, &sc->sc_lock, |
1300 | mstohz(10)); |
1301 | if (err) { |
1302 | ep->num_open--; |
1303 | jack->opened = 0; |
1304 | return USBD_IOERROR; |
1305 | } |
1306 | } |
1307 | |
1308 | return USBD_NORMAL_COMPLETION; |
1309 | } |
1310 | |
1311 | static usbd_status |
1312 | open_in_jack(struct umidi_jack *jack, void *arg, void (*intr)(void *, int)) |
1313 | { |
1314 | usbd_status err = USBD_NORMAL_COMPLETION; |
1315 | struct umidi_endpoint *ep = jack->endpoint; |
1316 | |
1317 | KASSERT(mutex_owned(&ep->sc->sc_lock)); |
1318 | |
1319 | if (jack->opened) |
1320 | return USBD_IN_USE; |
1321 | |
1322 | jack->arg = arg; |
1323 | jack->u.in.intr = intr; |
1324 | jack->opened = 1; |
1325 | if (ep->num_open++ == 0 && UE_GET_DIR(ep->addr)==UE_DIR_IN) { |
1326 | /* |
1327 | * Can't hold the interrupt lock while calling into USB, |
1328 | * but we can safely drop it here. |
1329 | */ |
1330 | mutex_exit(&ep->sc->sc_lock); |
1331 | err = start_input_transfer(ep); |
1332 | if (err != USBD_NORMAL_COMPLETION && |
1333 | err != USBD_IN_PROGRESS) { |
1334 | ep->num_open--; |
1335 | } |
1336 | mutex_enter(&ep->sc->sc_lock); |
1337 | } |
1338 | |
1339 | return err; |
1340 | } |
1341 | |
1342 | static void |
1343 | close_out_jack(struct umidi_jack *jack) |
1344 | { |
1345 | struct umidi_endpoint *ep; |
1346 | struct umidi_softc *sc; |
1347 | uint16_t mask; |
1348 | int err; |
1349 | |
1350 | if (jack->opened) { |
1351 | ep = jack->endpoint; |
1352 | sc = ep->sc; |
1353 | |
1354 | KASSERT(mutex_owned(&sc->sc_lock)); |
1355 | mask = 1 << (jack->cable_number); |
1356 | while (mask & (ep->this_schedule | ep->next_schedule)) { |
1357 | err = cv_timedwait_sig(&sc->sc_cv, &sc->sc_lock, |
1358 | mstohz(10)); |
1359 | if (err) |
1360 | break; |
1361 | } |
1362 | /* |
1363 | * We can re-enter this function from both close() and |
1364 | * detach(). Make sure only one of them does this part. |
1365 | */ |
1366 | if (jack->opened) { |
1367 | jack->opened = 0; |
1368 | jack->endpoint->num_open--; |
1369 | ep->this_schedule &= ~mask; |
1370 | ep->next_schedule &= ~mask; |
1371 | } |
1372 | } |
1373 | } |
1374 | |
1375 | static void |
1376 | close_in_jack(struct umidi_jack *jack) |
1377 | { |
1378 | if (jack->opened) { |
1379 | struct umidi_softc *sc = jack->endpoint->sc; |
1380 | |
1381 | KASSERT(mutex_owned(&sc->sc_lock)); |
1382 | |
1383 | jack->opened = 0; |
1384 | if (--jack->endpoint->num_open == 0) { |
1385 | /* |
1386 | * We have to drop the (interrupt) lock so that |
1387 | * the USB thread lock can be safely taken by |
1388 | * the abort operation. This is safe as this |
1389 | * either closing or dying will be set proerly. |
1390 | */ |
1391 | mutex_exit(&sc->sc_lock); |
1392 | usbd_abort_pipe(jack->endpoint->pipe); |
1393 | mutex_enter(&sc->sc_lock); |
1394 | } |
1395 | } |
1396 | } |
1397 | |
1398 | static usbd_status |
1399 | attach_mididev(struct umidi_softc *sc, struct umidi_mididev *mididev) |
1400 | { |
1401 | if (mididev->sc) |
1402 | return USBD_IN_USE; |
1403 | |
1404 | mididev->sc = sc; |
1405 | |
1406 | describe_mididev(mididev); |
1407 | |
1408 | mididev->mdev = midi_attach_mi(&umidi_hw_if, mididev, sc->sc_dev); |
1409 | |
1410 | return USBD_NORMAL_COMPLETION; |
1411 | } |
1412 | |
1413 | static usbd_status |
1414 | detach_mididev(struct umidi_mididev *mididev, int flags) |
1415 | { |
1416 | struct umidi_softc *sc = mididev->sc; |
1417 | |
1418 | if (!sc) |
1419 | return USBD_NO_ADDR; |
1420 | |
1421 | mutex_enter(&sc->sc_lock); |
1422 | if (mididev->opened) { |
1423 | umidi_close(mididev); |
1424 | } |
1425 | unbind_jacks_from_mididev(mididev); |
1426 | mutex_exit(&sc->sc_lock); |
1427 | |
1428 | if (mididev->mdev != NULL) |
1429 | config_detach(mididev->mdev, flags); |
1430 | |
1431 | if (NULL != mididev->label) { |
1432 | kmem_free(mididev->label, mididev->label_len); |
1433 | mididev->label = NULL; |
1434 | } |
1435 | |
1436 | mididev->sc = NULL; |
1437 | |
1438 | return USBD_NORMAL_COMPLETION; |
1439 | } |
1440 | |
1441 | static void |
1442 | deactivate_mididev(struct umidi_mididev *mididev) |
1443 | { |
1444 | if (mididev->out_jack) |
1445 | mididev->out_jack->bound = 0; |
1446 | if (mididev->in_jack) |
1447 | mididev->in_jack->bound = 0; |
1448 | } |
1449 | |
1450 | static usbd_status |
1451 | alloc_all_mididevs(struct umidi_softc *sc, int nmidi) |
1452 | { |
1453 | sc->sc_num_mididevs = nmidi; |
1454 | sc->sc_mididevs = kmem_zalloc(sizeof(*sc->sc_mididevs)*nmidi, KM_SLEEP); |
1455 | if (!sc->sc_mididevs) |
1456 | return USBD_NOMEM; |
1457 | |
1458 | return USBD_NORMAL_COMPLETION; |
1459 | } |
1460 | |
1461 | static void |
1462 | free_all_mididevs(struct umidi_softc *sc) |
1463 | { |
1464 | struct umidi_mididev *mididevs; |
1465 | size_t len; |
1466 | |
1467 | mutex_enter(&sc->sc_lock); |
1468 | mididevs = sc->sc_mididevs; |
1469 | if (mididevs) |
1470 | len = sizeof(*sc->sc_mididevs )* sc->sc_num_mididevs; |
1471 | sc->sc_mididevs = NULL; |
1472 | sc->sc_num_mididevs = 0; |
1473 | mutex_exit(&sc->sc_lock); |
1474 | |
1475 | if (mididevs) |
1476 | kmem_free(mididevs, len); |
1477 | } |
1478 | |
1479 | static usbd_status |
1480 | attach_all_mididevs(struct umidi_softc *sc) |
1481 | { |
1482 | usbd_status err; |
1483 | int i; |
1484 | |
1485 | if (sc->sc_mididevs) |
1486 | for (i = 0; i < sc->sc_num_mididevs; i++) { |
1487 | err = attach_mididev(sc, &sc->sc_mididevs[i]); |
1488 | if (err != USBD_NORMAL_COMPLETION) |
1489 | return err; |
1490 | } |
1491 | |
1492 | return USBD_NORMAL_COMPLETION; |
1493 | } |
1494 | |
1495 | static usbd_status |
1496 | detach_all_mididevs(struct umidi_softc *sc, int flags) |
1497 | { |
1498 | usbd_status err; |
1499 | int i; |
1500 | |
1501 | if (sc->sc_mididevs) |
1502 | for (i = 0; i < sc->sc_num_mididevs; i++) { |
1503 | err = detach_mididev(&sc->sc_mididevs[i], flags); |
1504 | if (err != USBD_NORMAL_COMPLETION) |
1505 | return err; |
1506 | } |
1507 | |
1508 | return USBD_NORMAL_COMPLETION; |
1509 | } |
1510 | |
1511 | static void |
1512 | deactivate_all_mididevs(struct umidi_softc *sc) |
1513 | { |
1514 | int i; |
1515 | |
1516 | if (sc->sc_mididevs) { |
1517 | for (i = 0; i < sc->sc_num_mididevs; i++) |
1518 | deactivate_mididev(&sc->sc_mididevs[i]); |
1519 | } |
1520 | } |
1521 | |
1522 | /* |
1523 | * TODO: the 0-based cable numbers will often not match the labeling of the |
1524 | * equipment. Ideally: |
1525 | * For class-compliant devices: get the iJack string from the jack descriptor. |
1526 | * Otherwise: |
1527 | * - support a DISPLAY_BASE_CN quirk (add the value to each internal cable |
1528 | * number for display) |
1529 | * - support an array quirk explictly giving a char * for each jack. |
1530 | * For now, you get 0-based cable numbers. If there are multiple endpoints and |
1531 | * the CNs are not globally unique, each is shown with its associated endpoint |
1532 | * address in hex also. That should not be necessary when using iJack values |
1533 | * or a quirk array. |
1534 | */ |
1535 | void |
1536 | describe_mididev(struct umidi_mididev *md) |
1537 | { |
1538 | char in_label[16]; |
1539 | char out_label[16]; |
1540 | const char *unit_label; |
1541 | char *final_label; |
1542 | struct umidi_softc *sc; |
1543 | int show_ep_in; |
1544 | int show_ep_out; |
1545 | size_t len; |
1546 | |
1547 | sc = md->sc; |
1548 | show_ep_in = sc-> sc_in_num_endpoints > 1 && !sc->cblnums_global; |
1549 | show_ep_out = sc->sc_out_num_endpoints > 1 && !sc->cblnums_global; |
1550 | |
1551 | if (NULL == md->in_jack) |
1552 | in_label[0] = '\0'; |
1553 | else if (show_ep_in) |
1554 | snprintf(in_label, sizeof(in_label), "<%d(%x) " , |
1555 | md->in_jack->cable_number, md->in_jack->endpoint->addr); |
1556 | else |
1557 | snprintf(in_label, sizeof(in_label), "<%d " , |
1558 | md->in_jack->cable_number); |
1559 | |
1560 | if (NULL == md->out_jack) |
1561 | out_label[0] = '\0'; |
1562 | else if (show_ep_out) |
1563 | snprintf(out_label, sizeof(out_label), ">%d(%x) " , |
1564 | md->out_jack->cable_number, md->out_jack->endpoint->addr); |
1565 | else |
1566 | snprintf(out_label, sizeof(out_label), ">%d " , |
1567 | md->out_jack->cable_number); |
1568 | |
1569 | unit_label = device_xname(sc->sc_dev); |
1570 | |
1571 | len = strlen(in_label) + strlen(out_label) + strlen(unit_label) + 4; |
1572 | |
1573 | final_label = kmem_alloc(len, KM_SLEEP); |
1574 | |
1575 | snprintf(final_label, len, "%s%son %s" , |
1576 | in_label, out_label, unit_label); |
1577 | |
1578 | md->label = final_label; |
1579 | md->label_len = len; |
1580 | } |
1581 | |
1582 | #ifdef UMIDI_DEBUG |
1583 | static void |
1584 | dump_sc(struct umidi_softc *sc) |
1585 | { |
1586 | int i; |
1587 | |
1588 | DPRINTFN(10, ("%s: dump_sc\n" , device_xname(sc->sc_dev))); |
1589 | for (i=0; i<sc->sc_out_num_endpoints; i++) { |
1590 | DPRINTFN(10, ("\tout_ep(%p):\n" , &sc->sc_out_ep[i])); |
1591 | dump_ep(&sc->sc_out_ep[i]); |
1592 | } |
1593 | for (i=0; i<sc->sc_in_num_endpoints; i++) { |
1594 | DPRINTFN(10, ("\tin_ep(%p):\n" , &sc->sc_in_ep[i])); |
1595 | dump_ep(&sc->sc_in_ep[i]); |
1596 | } |
1597 | } |
1598 | |
1599 | static void |
1600 | dump_ep(struct umidi_endpoint *ep) |
1601 | { |
1602 | int i; |
1603 | for (i=0; i<UMIDI_MAX_EPJACKS; i++) { |
1604 | if (NULL==ep->jacks[i]) |
1605 | continue; |
1606 | DPRINTFN(10, ("\t\tjack[%d]:%p:\n" , i, ep->jacks[i])); |
1607 | dump_jack(ep->jacks[i]); |
1608 | } |
1609 | } |
1610 | static void |
1611 | dump_jack(struct umidi_jack *jack) |
1612 | { |
1613 | DPRINTFN(10, ("\t\t\tep=%p\n" , |
1614 | jack->endpoint)); |
1615 | } |
1616 | |
1617 | #endif /* UMIDI_DEBUG */ |
1618 | |
1619 | |
1620 | |
1621 | /* |
1622 | * MUX MIDI PACKET |
1623 | */ |
1624 | |
1625 | static const int packet_length[16] = { |
1626 | /*0*/ -1, |
1627 | /*1*/ -1, |
1628 | /*2*/ 2, |
1629 | /*3*/ 3, |
1630 | /*4*/ 3, |
1631 | /*5*/ 1, |
1632 | /*6*/ 2, |
1633 | /*7*/ 3, |
1634 | /*8*/ 3, |
1635 | /*9*/ 3, |
1636 | /*A*/ 3, |
1637 | /*B*/ 3, |
1638 | /*C*/ 2, |
1639 | /*D*/ 2, |
1640 | /*E*/ 3, |
1641 | /*F*/ 1, |
1642 | }; |
1643 | |
1644 | #define GET_CN(p) (((unsigned char)(p)>>4)&0x0F) |
1645 | #define GET_CIN(p) ((unsigned char)(p)&0x0F) |
1646 | #define MIX_CN_CIN(cn, cin) \ |
1647 | ((unsigned char)((((unsigned char)(cn)&0x0F)<<4)| \ |
1648 | ((unsigned char)(cin)&0x0F))) |
1649 | |
1650 | static usbd_status |
1651 | start_input_transfer(struct umidi_endpoint *ep) |
1652 | { |
1653 | usbd_setup_xfer(ep->xfer, ep, ep->buffer, ep->buffer_size, |
1654 | USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, in_intr); |
1655 | return usbd_transfer(ep->xfer); |
1656 | } |
1657 | |
1658 | static usbd_status |
1659 | start_output_transfer(struct umidi_endpoint *ep) |
1660 | { |
1661 | usbd_status rv; |
1662 | uint32_t length; |
1663 | int i; |
1664 | |
1665 | length = (ep->next_slot - ep->buffer) * sizeof(*ep->buffer); |
1666 | DPRINTFN(200,("umidi out transfer: start %p end %p length %u\n" , |
1667 | ep->buffer, ep->next_slot, length)); |
1668 | |
1669 | usbd_setup_xfer(ep->xfer, ep, ep->buffer, length, 0, |
1670 | USBD_NO_TIMEOUT, out_intr); |
1671 | rv = usbd_transfer(ep->xfer); |
1672 | |
1673 | /* |
1674 | * Once the transfer is scheduled, no more adding to partial |
1675 | * packets within it. |
1676 | */ |
1677 | if (UMQ_ISTYPE(ep->sc, UMQ_TYPE_MIDIMAN_GARBLE)) { |
1678 | for (i=0; i<UMIDI_MAX_EPJACKS; ++i) |
1679 | if (NULL != ep->jacks[i]) |
1680 | ep->jacks[i]->midiman_ppkt = NULL; |
1681 | } |
1682 | |
1683 | return rv; |
1684 | } |
1685 | |
1686 | #ifdef UMIDI_DEBUG |
1687 | #define DPR_PACKET(dir, sc, p) \ |
1688 | if ((unsigned char)(p)[1]!=0xFE) \ |
1689 | DPRINTFN(500, \ |
1690 | ("%s: umidi packet(" #dir "): %02X %02X %02X %02X\n", \ |
1691 | device_xname(sc->sc_dev), \ |
1692 | (unsigned char)(p)[0], \ |
1693 | (unsigned char)(p)[1], \ |
1694 | (unsigned char)(p)[2], \ |
1695 | (unsigned char)(p)[3])); |
1696 | #else |
1697 | #define DPR_PACKET(dir, sc, p) |
1698 | #endif |
1699 | |
1700 | /* |
1701 | * A 4-byte Midiman packet superficially resembles a 4-byte USB MIDI packet |
1702 | * with the cable number and length in the last byte instead of the first, |
1703 | * but there the resemblance ends. Where a USB MIDI packet is a semantic |
1704 | * unit, a Midiman packet is just a wrapper for 1 to 3 bytes of raw MIDI |
1705 | * with a cable nybble and a length nybble (which, unlike the CIN of a |
1706 | * real USB MIDI packet, has no semantics at all besides the length). |
1707 | * A packet received from a Midiman may contain part of a MIDI message, |
1708 | * more than one MIDI message, or parts of more than one MIDI message. A |
1709 | * three-byte MIDI message may arrive in three packets of data length 1, and |
1710 | * running status may be used. Happily, the midi(4) driver above us will put |
1711 | * it all back together, so the only cost is in USB bandwidth. The device |
1712 | * has an easier time with what it receives from us: we'll pack messages in |
1713 | * and across packets, but filling the packets whenever possible and, |
1714 | * as midi(4) hands us a complete message at a time, we'll never send one |
1715 | * in a dribble of short packets. |
1716 | */ |
1717 | |
1718 | static int |
1719 | out_jack_output(struct umidi_jack *out_jack, u_char *src, int len, int cin) |
1720 | { |
1721 | struct umidi_endpoint *ep = out_jack->endpoint; |
1722 | struct umidi_softc *sc = ep->sc; |
1723 | unsigned char *packet; |
1724 | int plen; |
1725 | int poff; |
1726 | |
1727 | KASSERT(mutex_owned(&sc->sc_lock)); |
1728 | |
1729 | if (sc->sc_dying) |
1730 | return EIO; |
1731 | |
1732 | if (!out_jack->opened) |
1733 | return ENODEV; /* XXX as it was, is this the right errno? */ |
1734 | |
1735 | sc->sc_refcnt++; |
1736 | |
1737 | #ifdef UMIDI_DEBUG |
1738 | if (umididebug >= 100) |
1739 | microtime(&umidi_tv); |
1740 | #endif |
1741 | DPRINTFN(100, ("umidi out: %" PRIu64".%06" PRIu64 |
1742 | "s ep=%p cn=%d len=%d cin=%#x\n" , umidi_tv.tv_sec%100, |
1743 | (uint64_t)umidi_tv.tv_usec, ep, out_jack->cable_number, len, cin)); |
1744 | |
1745 | packet = *ep->next_slot++; |
1746 | KASSERT(ep->buffer_size >= |
1747 | (ep->next_slot - ep->buffer) * sizeof(*ep->buffer)); |
1748 | memset(packet, 0, UMIDI_PACKET_SIZE); |
1749 | if (UMQ_ISTYPE(sc, UMQ_TYPE_MIDIMAN_GARBLE)) { |
1750 | if (NULL != out_jack->midiman_ppkt) { /* fill out a prev pkt */ |
1751 | poff = 0x0f & (out_jack->midiman_ppkt[3]); |
1752 | plen = 3 - poff; |
1753 | if (plen > len) |
1754 | plen = len; |
1755 | memcpy(out_jack->midiman_ppkt+poff, src, plen); |
1756 | src += plen; |
1757 | len -= plen; |
1758 | plen += poff; |
1759 | out_jack->midiman_ppkt[3] = |
1760 | MIX_CN_CIN(out_jack->cable_number, plen); |
1761 | DPR_PACKET(out+, sc, out_jack->midiman_ppkt); |
1762 | if (3 == plen) |
1763 | out_jack->midiman_ppkt = NULL; /* no more */ |
1764 | } |
1765 | if (0 == len) |
1766 | ep->next_slot--; /* won't be needed, nevermind */ |
1767 | else { |
1768 | memcpy(packet, src, len); |
1769 | packet[3] = MIX_CN_CIN(out_jack->cable_number, len); |
1770 | DPR_PACKET(out, sc, packet); |
1771 | if (len < 3) |
1772 | out_jack->midiman_ppkt = packet; |
1773 | } |
1774 | } else { /* the nice simple USB class-compliant case */ |
1775 | packet[0] = MIX_CN_CIN(out_jack->cable_number, cin); |
1776 | memcpy(packet+1, src, len); |
1777 | DPR_PACKET(out, sc, packet); |
1778 | } |
1779 | ep->next_schedule |= 1<<(out_jack->cable_number); |
1780 | ++ ep->num_scheduled; |
1781 | if (!ep->armed && !ep->soliciting) { |
1782 | /* |
1783 | * It would be bad to call out_solicit directly here (the |
1784 | * caller need not be reentrant) but a soft interrupt allows |
1785 | * solicit to run immediately the caller exits its critical |
1786 | * section, and if the caller has more to write we can get it |
1787 | * before starting the USB transfer, and send a longer one. |
1788 | */ |
1789 | ep->soliciting = 1; |
1790 | kpreempt_disable(); |
1791 | softint_schedule(ep->solicit_cookie); |
1792 | kpreempt_enable(); |
1793 | } |
1794 | |
1795 | if (--sc->sc_refcnt < 0) |
1796 | usb_detach_broadcast(sc->sc_dev, &sc->sc_detach_cv); |
1797 | |
1798 | return 0; |
1799 | } |
1800 | |
1801 | static void |
1802 | in_intr(struct usbd_xfer *xfer, void *priv, |
1803 | usbd_status status) |
1804 | { |
1805 | int cn, len, i; |
1806 | struct umidi_endpoint *ep = (struct umidi_endpoint *)priv; |
1807 | struct umidi_softc *sc = ep->sc; |
1808 | struct umidi_jack *jack; |
1809 | unsigned char *packet; |
1810 | umidi_packet_bufp slot; |
1811 | umidi_packet_bufp end; |
1812 | unsigned char *data; |
1813 | uint32_t count; |
1814 | |
1815 | if (ep->sc->sc_dying || !ep->num_open) |
1816 | return; |
1817 | |
1818 | mutex_enter(&sc->sc_lock); |
1819 | usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); |
1820 | if (0 == count % UMIDI_PACKET_SIZE) { |
1821 | DPRINTFN(200,("%s: input endpoint %p transfer length %u\n" , |
1822 | device_xname(ep->sc->sc_dev), ep, count)); |
1823 | } else { |
1824 | DPRINTF(("%s: input endpoint %p odd transfer length %u\n" , |
1825 | device_xname(ep->sc->sc_dev), ep, count)); |
1826 | } |
1827 | |
1828 | slot = ep->buffer; |
1829 | end = slot + count / sizeof(*slot); |
1830 | |
1831 | for (packet = *slot; slot < end; packet = *++slot) { |
1832 | |
1833 | if (UMQ_ISTYPE(ep->sc, UMQ_TYPE_MIDIMAN_GARBLE)) { |
1834 | cn = (0xf0&(packet[3]))>>4; |
1835 | len = 0x0f&(packet[3]); |
1836 | data = packet; |
1837 | } else { |
1838 | cn = GET_CN(packet[0]); |
1839 | len = packet_length[GET_CIN(packet[0])]; |
1840 | data = packet + 1; |
1841 | } |
1842 | /* 0 <= cn <= 15 by inspection of above code */ |
1843 | if (!(jack = ep->jacks[cn]) || cn != jack->cable_number) { |
1844 | DPRINTF(("%s: stray input endpoint %p cable %d len %d: " |
1845 | "%02X %02X %02X (try CN_SEQ quirk?)\n" , |
1846 | device_xname(ep->sc->sc_dev), ep, cn, len, |
1847 | (unsigned)data[0], |
1848 | (unsigned)data[1], |
1849 | (unsigned)data[2])); |
1850 | mutex_exit(&sc->sc_lock); |
1851 | return; |
1852 | } |
1853 | |
1854 | if (!jack->bound || !jack->opened) |
1855 | continue; |
1856 | |
1857 | DPRINTFN(500,("%s: input endpoint %p cable %d len %d: " |
1858 | "%02X %02X %02X\n" , |
1859 | device_xname(ep->sc->sc_dev), ep, cn, len, |
1860 | (unsigned)data[0], |
1861 | (unsigned)data[1], |
1862 | (unsigned)data[2])); |
1863 | |
1864 | if (jack->u.in.intr) { |
1865 | for (i = 0; i < len; i++) { |
1866 | (*jack->u.in.intr)(jack->arg, data[i]); |
1867 | } |
1868 | } |
1869 | |
1870 | } |
1871 | |
1872 | (void)start_input_transfer(ep); |
1873 | mutex_exit(&sc->sc_lock); |
1874 | } |
1875 | |
1876 | static void |
1877 | out_intr(struct usbd_xfer *xfer, void *priv, |
1878 | usbd_status status) |
1879 | { |
1880 | struct umidi_endpoint *ep = (struct umidi_endpoint *)priv; |
1881 | struct umidi_softc *sc = ep->sc; |
1882 | uint32_t count; |
1883 | |
1884 | if (sc->sc_dying) |
1885 | return; |
1886 | |
1887 | mutex_enter(&sc->sc_lock); |
1888 | #ifdef UMIDI_DEBUG |
1889 | if (umididebug >= 200) |
1890 | microtime(&umidi_tv); |
1891 | #endif |
1892 | usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); |
1893 | if (0 == count % UMIDI_PACKET_SIZE) { |
1894 | DPRINTFN(200, ("%s: %" PRIu64".%06" PRIu64"s out ep %p xfer " |
1895 | "length %u\n" , device_xname(ep->sc->sc_dev), |
1896 | umidi_tv.tv_sec%100, (uint64_t)umidi_tv.tv_usec, ep, |
1897 | count)); |
1898 | } else { |
1899 | DPRINTF(("%s: output endpoint %p odd transfer length %u\n" , |
1900 | device_xname(ep->sc->sc_dev), ep, count)); |
1901 | } |
1902 | count /= UMIDI_PACKET_SIZE; |
1903 | |
1904 | /* |
1905 | * If while the transfer was pending we buffered any new messages, |
1906 | * move them to the start of the buffer. |
1907 | */ |
1908 | ep->next_slot -= count; |
1909 | if (ep->buffer < ep->next_slot) { |
1910 | memcpy(ep->buffer, ep->buffer + count, |
1911 | (char *)ep->next_slot - (char *)ep->buffer); |
1912 | } |
1913 | cv_broadcast(&sc->sc_cv); |
1914 | /* |
1915 | * Do not want anyone else to see armed <- 0 before soliciting <- 1. |
1916 | * Running at IPL_USB so the following should happen to be safe. |
1917 | */ |
1918 | ep->armed = 0; |
1919 | if (!ep->soliciting) { |
1920 | ep->soliciting = 1; |
1921 | out_solicit_locked(ep); |
1922 | } |
1923 | mutex_exit(&sc->sc_lock); |
1924 | } |
1925 | |
1926 | /* |
1927 | * A jack on which we have received a packet must be called back on its |
1928 | * out.intr handler before it will send us another; it is considered |
1929 | * 'scheduled'. It is nice and predictable - as long as it is scheduled, |
1930 | * we need no extra buffer space for it. |
1931 | * |
1932 | * In contrast, a jack that is open but not scheduled may supply us a packet |
1933 | * at any time, driven by the top half, and we must be able to accept it, no |
1934 | * excuses. So we must ensure that at any point in time there are at least |
1935 | * (num_open - num_scheduled) slots free. |
1936 | * |
1937 | * As long as there are more slots free than that minimum, we can loop calling |
1938 | * scheduled jacks back on their "interrupt" handlers, soliciting more |
1939 | * packets, starting the USB transfer only when the buffer space is down to |
1940 | * the minimum or no jack has any more to send. |
1941 | */ |
1942 | |
1943 | static void |
1944 | out_solicit_locked(void *arg) |
1945 | { |
1946 | struct umidi_endpoint *ep = arg; |
1947 | umidi_packet_bufp end; |
1948 | uint16_t which; |
1949 | struct umidi_jack *jack; |
1950 | |
1951 | KASSERT(mutex_owned(&ep->sc->sc_lock)); |
1952 | |
1953 | end = ep->buffer + ep->buffer_size / sizeof(*ep->buffer); |
1954 | |
1955 | for ( ;; ) { |
1956 | if (end - ep->next_slot <= ep->num_open - ep->num_scheduled) |
1957 | break; /* at IPL_USB */ |
1958 | if (ep->this_schedule == 0) { |
1959 | if (ep->next_schedule == 0) |
1960 | break; /* at IPL_USB */ |
1961 | ep->this_schedule = ep->next_schedule; |
1962 | ep->next_schedule = 0; |
1963 | } |
1964 | /* |
1965 | * At least one jack is scheduled. Find and mask off the least |
1966 | * set bit in this_schedule and decrement num_scheduled. |
1967 | * Convert mask to bit index to find the corresponding jack, |
1968 | * and call its intr handler. If it has a message, it will call |
1969 | * back one of the output methods, which will set its bit in |
1970 | * next_schedule (not copied into this_schedule until the |
1971 | * latter is empty). In this way we round-robin the jacks that |
1972 | * have messages to send, until the buffer is as full as we |
1973 | * dare, and then start a transfer. |
1974 | */ |
1975 | which = ep->this_schedule; |
1976 | which &= (~which)+1; /* now mask of least set bit */ |
1977 | ep->this_schedule &= ~which; |
1978 | --ep->num_scheduled; |
1979 | |
1980 | --which; /* now 1s below mask - count 1s to get index */ |
1981 | which -= ((which >> 1) & 0x5555);/* SWAR credit aggregate.org */ |
1982 | which = (((which >> 2) & 0x3333) + (which & 0x3333)); |
1983 | which = (((which >> 4) + which) & 0x0f0f); |
1984 | which += (which >> 8); |
1985 | which &= 0x1f; /* the bit index a/k/a jack number */ |
1986 | |
1987 | jack = ep->jacks[which]; |
1988 | if (jack->u.out.intr) |
1989 | (*jack->u.out.intr)(jack->arg); |
1990 | } |
1991 | /* intr lock held at loop exit */ |
1992 | if (!ep->armed && ep->next_slot > ep->buffer) { |
1993 | /* |
1994 | * Can't hold the interrupt lock while calling into USB, |
1995 | * but we can safely drop it here. |
1996 | */ |
1997 | mutex_exit(&ep->sc->sc_lock); |
1998 | ep->armed = (USBD_IN_PROGRESS == start_output_transfer(ep)); |
1999 | mutex_enter(&ep->sc->sc_lock); |
2000 | } |
2001 | ep->soliciting = 0; |
2002 | } |
2003 | |
2004 | /* Entry point for the softintr. */ |
2005 | static void |
2006 | out_solicit(void *arg) |
2007 | { |
2008 | struct umidi_endpoint *ep = arg; |
2009 | struct umidi_softc *sc = ep->sc; |
2010 | |
2011 | mutex_enter(&sc->sc_lock); |
2012 | out_solicit_locked(arg); |
2013 | mutex_exit(&sc->sc_lock); |
2014 | } |
2015 | |