Line data Source code
1 : /* $OpenBSD: umidi.c,v 1.49 2018/09/07 04:03:30 miko Exp $ */
2 : /* $NetBSD: umidi.c,v 1.16 2002/07/11 21:14:32 augustss Exp $ */
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@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/param.h>
33 : #include <sys/systm.h>
34 : #include <sys/kernel.h>
35 : #include <sys/malloc.h>
36 : #include <sys/device.h>
37 : #include <sys/ioctl.h>
38 : #include <sys/conf.h>
39 : #include <sys/fcntl.h>
40 : #include <sys/selinfo.h>
41 : #include <sys/poll.h>
42 :
43 : #include <dev/usb/usb.h>
44 : #include <dev/usb/usbdi.h>
45 : #include <dev/usb/usbdi_util.h>
46 :
47 : #include <dev/usb/uaudioreg.h>
48 : #include <dev/usb/umidireg.h>
49 : #include <dev/usb/umidivar.h>
50 : #include <dev/usb/umidi_quirks.h>
51 :
52 : #include <dev/audio_if.h>
53 : #include <dev/midi_if.h>
54 :
55 : #ifdef UMIDI_DEBUG
56 : #define DPRINTF(x) if (umididebug) printf x
57 : #define DPRINTFN(n,x) if (umididebug >= (n)) printf x
58 : int umididebug = 0;
59 : #else
60 : #define DPRINTF(x)
61 : #define DPRINTFN(n,x)
62 : #endif
63 :
64 :
65 : static int umidi_open(void *, int,
66 : void (*)(void *, int), void (*)(void *), void *);
67 : static void umidi_close(void *);
68 : static int umidi_output(void *, int);
69 : static void umidi_flush(void *);
70 : static void umidi_getinfo(void *, struct midi_info *);
71 :
72 : static usbd_status alloc_pipe(struct umidi_endpoint *);
73 : static void free_pipe(struct umidi_endpoint *);
74 :
75 : static usbd_status alloc_all_endpoints(struct umidi_softc *);
76 : static void free_all_endpoints(struct umidi_softc *);
77 :
78 : static usbd_status alloc_all_jacks(struct umidi_softc *);
79 : static void free_all_jacks(struct umidi_softc *);
80 : static usbd_status bind_jacks_to_mididev(struct umidi_softc *,
81 : struct umidi_jack *,
82 : struct umidi_jack *,
83 : struct umidi_mididev *);
84 : static void unbind_jacks_from_mididev(struct umidi_mididev *);
85 : static void unbind_all_jacks(struct umidi_softc *);
86 : static usbd_status assign_all_jacks_automatically(struct umidi_softc *);
87 : static usbd_status open_out_jack(struct umidi_jack *, void *,
88 : void (*)(void *));
89 : static usbd_status open_in_jack(struct umidi_jack *, void *,
90 : void (*)(void *, int));
91 : static void close_jack(struct umidi_jack *);
92 :
93 : static usbd_status attach_mididev(struct umidi_softc *,
94 : struct umidi_mididev *);
95 : static usbd_status detach_mididev(struct umidi_mididev *, int);
96 : static usbd_status deactivate_mididev(struct umidi_mididev *);
97 : static usbd_status alloc_all_mididevs(struct umidi_softc *, int);
98 : static void free_all_mididevs(struct umidi_softc *);
99 : static usbd_status attach_all_mididevs(struct umidi_softc *);
100 : static usbd_status detach_all_mididevs(struct umidi_softc *, int);
101 : static usbd_status deactivate_all_mididevs(struct umidi_softc *);
102 :
103 : #ifdef UMIDI_DEBUG
104 : static void dump_sc(struct umidi_softc *);
105 : static void dump_ep(struct umidi_endpoint *);
106 : static void dump_jack(struct umidi_jack *);
107 : #endif
108 :
109 : static void init_packet(struct umidi_packet *);
110 :
111 : static usbd_status start_input_transfer(struct umidi_endpoint *);
112 : static usbd_status start_output_transfer(struct umidi_endpoint *);
113 : static int out_jack_output(struct umidi_jack *, int);
114 : static void out_jack_flush(struct umidi_jack *);
115 : static void in_intr(struct usbd_xfer *, void *, usbd_status);
116 : static void out_intr(struct usbd_xfer *, void *, usbd_status);
117 : static int out_build_packet(int, struct umidi_packet *, uByte, u_char *);
118 :
119 :
120 : struct midi_hw_if umidi_hw_if = {
121 : umidi_open,
122 : umidi_close,
123 : umidi_output,
124 : umidi_flush, /* flush */
125 : umidi_getinfo,
126 : 0, /* ioctl */
127 : };
128 :
129 : int umidi_match(struct device *, void *, void *);
130 : void umidi_attach(struct device *, struct device *, void *);
131 : int umidi_detach(struct device *, int);
132 : int umidi_activate(struct device *, int);
133 :
134 : struct cfdriver umidi_cd = {
135 : NULL, "umidi", DV_DULL
136 : };
137 :
138 : const struct cfattach umidi_ca = {
139 : sizeof(struct umidi_softc),
140 : umidi_match,
141 : umidi_attach,
142 : umidi_detach,
143 : umidi_activate,
144 : };
145 :
146 : int
147 0 : umidi_match(struct device *parent, void *match, void *aux)
148 : {
149 0 : struct usb_attach_arg *uaa = aux;
150 : usb_interface_descriptor_t *id;
151 :
152 : DPRINTFN(1,("%s\n", __func__));
153 :
154 0 : if (uaa->iface == NULL)
155 0 : return UMATCH_NONE;
156 :
157 0 : if (umidi_search_quirk(uaa->vendor, uaa->product, uaa->ifaceno))
158 0 : return UMATCH_IFACECLASS_IFACESUBCLASS;
159 :
160 0 : id = usbd_get_interface_descriptor(uaa->iface);
161 0 : if (id!=NULL &&
162 0 : id->bInterfaceClass==UICLASS_AUDIO &&
163 0 : id->bInterfaceSubClass==UISUBCLASS_MIDISTREAM)
164 0 : return UMATCH_IFACECLASS_IFACESUBCLASS;
165 :
166 0 : return UMATCH_NONE;
167 0 : }
168 :
169 : void
170 0 : umidi_attach(struct device *parent, struct device *self, void *aux)
171 : {
172 : usbd_status err;
173 0 : struct umidi_softc *sc = (struct umidi_softc *)self;
174 0 : struct usb_attach_arg *uaa = aux;
175 : int i;
176 :
177 : DPRINTFN(1,("%s\n", __func__));
178 :
179 0 : sc->sc_iface = uaa->iface;
180 0 : sc->sc_udev = uaa->device;
181 :
182 0 : sc->sc_quirk =
183 0 : umidi_search_quirk(uaa->vendor, uaa->product, uaa->ifaceno);
184 0 : printf("%s: ", sc->sc_dev.dv_xname);
185 0 : umidi_print_quirk(sc->sc_quirk);
186 :
187 0 : err = alloc_all_endpoints(sc);
188 0 : if (err!=USBD_NORMAL_COMPLETION)
189 : goto error;
190 0 : err = alloc_all_jacks(sc);
191 0 : if (err!=USBD_NORMAL_COMPLETION) {
192 0 : free_all_endpoints(sc);
193 0 : goto error;
194 : }
195 0 : printf("%s: out=%d, in=%d\n",
196 : sc->sc_dev.dv_xname,
197 0 : sc->sc_out_num_jacks, sc->sc_in_num_jacks);
198 :
199 0 : err = assign_all_jacks_automatically(sc);
200 0 : if (err!=USBD_NORMAL_COMPLETION) {
201 0 : unbind_all_jacks(sc);
202 0 : free_all_jacks(sc);
203 0 : free_all_endpoints(sc);
204 0 : goto error;
205 : }
206 0 : err = attach_all_mididevs(sc);
207 0 : if (err!=USBD_NORMAL_COMPLETION) {
208 0 : unbind_all_jacks(sc);
209 0 : free_all_jacks(sc);
210 0 : free_all_endpoints(sc);
211 0 : goto error;
212 : }
213 :
214 : #ifdef UMIDI_DEBUG
215 : dump_sc(sc);
216 : #endif
217 :
218 0 : for (i = 0; i < sc->sc_in_num_endpoints; i++)
219 0 : (void)start_input_transfer(&sc->sc_in_ep[i]);
220 0 : return;
221 : error:
222 0 : printf("%s: disabled.\n", sc->sc_dev.dv_xname);
223 0 : usbd_deactivate(sc->sc_udev);
224 0 : }
225 :
226 : int
227 0 : umidi_activate(struct device *self, int act)
228 : {
229 0 : struct umidi_softc *sc = (struct umidi_softc *)self;
230 :
231 0 : if (act == DVACT_DEACTIVATE) {
232 : DPRINTFN(1,("%s (deactivate)\n", __func__));
233 0 : usbd_deactivate(sc->sc_udev);
234 0 : deactivate_all_mididevs(sc);
235 0 : }
236 0 : return 0;
237 : }
238 :
239 : int
240 0 : umidi_detach(struct device *self, int flags)
241 : {
242 0 : struct umidi_softc *sc = (struct umidi_softc *)self;
243 :
244 : DPRINTFN(1,("%s\n", __func__));
245 :
246 0 : detach_all_mididevs(sc, flags);
247 0 : free_all_mididevs(sc);
248 0 : free_all_jacks(sc);
249 0 : free_all_endpoints(sc);
250 :
251 0 : return 0;
252 : }
253 :
254 :
255 : /*
256 : * midi_if stuffs
257 : */
258 : int
259 0 : umidi_open(void *addr,
260 : int flags,
261 : void (*iintr)(void *, int),
262 : void (*ointr)(void *),
263 : void *arg)
264 : {
265 0 : struct umidi_mididev *mididev = addr;
266 0 : struct umidi_softc *sc = mididev->sc;
267 :
268 : DPRINTF(("%s: sc=%p\n", __func__, sc));
269 :
270 0 : if (!sc)
271 0 : return ENXIO;
272 0 : if (mididev->opened)
273 0 : return EBUSY;
274 0 : if (usbd_is_dying(sc->sc_udev))
275 0 : return EIO;
276 :
277 0 : mididev->opened = 1;
278 0 : mididev->flags = flags;
279 0 : if ((mididev->flags & FWRITE) && mididev->out_jack)
280 0 : open_out_jack(mididev->out_jack, arg, ointr);
281 0 : if ((mididev->flags & FREAD) && mididev->in_jack)
282 0 : open_in_jack(mididev->in_jack, arg, iintr);
283 0 : return 0;
284 0 : }
285 :
286 : void
287 0 : umidi_close(void *addr)
288 : {
289 : int s;
290 0 : struct umidi_mididev *mididev = addr;
291 :
292 0 : s = splusb();
293 0 : if ((mididev->flags & FWRITE) && mididev->out_jack)
294 0 : close_jack(mididev->out_jack);
295 0 : if ((mididev->flags & FREAD) && mididev->in_jack)
296 0 : close_jack(mididev->in_jack);
297 0 : mididev->opened = 0;
298 0 : splx(s);
299 0 : }
300 :
301 : int
302 0 : umidi_output(void *addr, int d)
303 : {
304 0 : struct umidi_mididev *mididev = addr;
305 :
306 0 : if (!mididev->out_jack || !mididev->opened)
307 0 : return 1;
308 :
309 0 : return out_jack_output(mididev->out_jack, d);
310 0 : }
311 :
312 : void
313 0 : umidi_flush(void *addr)
314 : {
315 0 : struct umidi_mididev *mididev = addr;
316 :
317 0 : if (!mididev->out_jack || !mididev->opened)
318 0 : return;
319 :
320 0 : return out_jack_flush(mididev->out_jack);
321 0 : }
322 :
323 : void
324 0 : umidi_getinfo(void *addr, struct midi_info *mi)
325 : {
326 0 : struct umidi_mididev *mididev = addr;
327 :
328 0 : mi->name = "USB MIDI I/F"; /* XXX: model name */
329 0 : mi->props = MIDI_PROP_OUT_INTR;
330 0 : if (mididev->in_jack)
331 0 : mi->props |= MIDI_PROP_CAN_INPUT;
332 0 : }
333 :
334 :
335 : /*
336 : * each endpoint stuffs
337 : */
338 :
339 : /* alloc/free pipe */
340 : static usbd_status
341 0 : alloc_pipe(struct umidi_endpoint *ep)
342 : {
343 0 : struct umidi_softc *sc = ep->sc;
344 : usbd_status err;
345 :
346 : DPRINTF(("%s: alloc_pipe %p\n", sc->sc_dev.dv_xname, ep));
347 0 : SIMPLEQ_INIT(&ep->intrq);
348 0 : ep->pending = 0;
349 0 : ep->busy = 0;
350 0 : ep->used = 0;
351 0 : ep->xfer = usbd_alloc_xfer(sc->sc_udev);
352 0 : if (ep->xfer == NULL)
353 0 : return USBD_NOMEM;
354 0 : ep->buffer = usbd_alloc_buffer(ep->xfer, ep->packetsize);
355 0 : if (ep->buffer == NULL) {
356 0 : usbd_free_xfer(ep->xfer);
357 0 : return USBD_NOMEM;
358 : }
359 0 : err = usbd_open_pipe(sc->sc_iface, ep->addr, 0, &ep->pipe);
360 0 : if (err != USBD_NORMAL_COMPLETION) {
361 0 : usbd_free_xfer(ep->xfer);
362 0 : return err;
363 : }
364 0 : return USBD_NORMAL_COMPLETION;
365 0 : }
366 :
367 : static void
368 0 : free_pipe(struct umidi_endpoint *ep)
369 : {
370 : DPRINTF(("%s: %s %p\n", ep->sc->sc_dev.dv_xname, __func__, ep));
371 0 : usbd_abort_pipe(ep->pipe);
372 0 : usbd_close_pipe(ep->pipe);
373 0 : usbd_free_xfer(ep->xfer);
374 0 : }
375 :
376 :
377 : /* alloc/free the array of endpoint structures */
378 :
379 : static usbd_status alloc_all_endpoints_fixed_ep(struct umidi_softc *);
380 : static usbd_status alloc_all_endpoints_yamaha(struct umidi_softc *);
381 : static usbd_status alloc_all_endpoints_genuine(struct umidi_softc *);
382 :
383 : static usbd_status
384 0 : alloc_all_endpoints(struct umidi_softc *sc)
385 : {
386 : usbd_status err;
387 : struct umidi_endpoint *ep;
388 : int i;
389 :
390 0 : sc->sc_out_num_jacks = sc->sc_in_num_jacks = 0;
391 :
392 0 : if (UMQ_ISTYPE(sc, UMQ_TYPE_FIXED_EP))
393 0 : err = alloc_all_endpoints_fixed_ep(sc);
394 0 : else if (UMQ_ISTYPE(sc, UMQ_TYPE_YAMAHA))
395 0 : err = alloc_all_endpoints_yamaha(sc);
396 : else
397 0 : err = alloc_all_endpoints_genuine(sc);
398 0 : if (err!=USBD_NORMAL_COMPLETION)
399 0 : return err;
400 :
401 0 : ep = sc->sc_endpoints;
402 0 : for (i=sc->sc_out_num_endpoints+sc->sc_in_num_endpoints; i>0; i--) {
403 0 : err = alloc_pipe(ep);
404 0 : if (err!=USBD_NORMAL_COMPLETION) {
405 0 : while(ep != sc->sc_endpoints) {
406 0 : ep--;
407 0 : free_pipe(ep);
408 : }
409 0 : free(sc->sc_endpoints, M_USBDEV, 0);
410 0 : sc->sc_endpoints = sc->sc_out_ep = sc->sc_in_ep = NULL;
411 0 : break;
412 : }
413 0 : ep++;
414 : }
415 0 : return err;
416 0 : }
417 :
418 : static void
419 0 : free_all_endpoints(struct umidi_softc *sc)
420 : {
421 : int i;
422 :
423 0 : for (i=0; i<sc->sc_in_num_endpoints+sc->sc_out_num_endpoints; i++)
424 0 : free_pipe(&sc->sc_endpoints[i]);
425 0 : if (sc->sc_endpoints != NULL)
426 0 : free(sc->sc_endpoints, M_USBDEV, 0);
427 0 : sc->sc_endpoints = sc->sc_out_ep = sc->sc_in_ep = NULL;
428 0 : }
429 :
430 : static usbd_status
431 0 : alloc_all_endpoints_fixed_ep(struct umidi_softc *sc)
432 : {
433 : struct umq_fixed_ep_desc *fp;
434 : struct umidi_endpoint *ep;
435 : usb_endpoint_descriptor_t *epd;
436 : int i;
437 :
438 0 : fp = umidi_get_quirk_data_from_type(sc->sc_quirk,
439 : UMQ_TYPE_FIXED_EP);
440 0 : sc->sc_out_num_endpoints = fp->num_out_ep;
441 0 : sc->sc_in_num_endpoints = fp->num_in_ep;
442 0 : sc->sc_endpoints = mallocarray(sc->sc_out_num_endpoints +
443 : sc->sc_in_num_endpoints, sizeof(*sc->sc_out_ep), M_USBDEV,
444 : M_WAITOK | M_CANFAIL);
445 0 : if (!sc->sc_endpoints)
446 0 : return USBD_NOMEM;
447 0 : sc->sc_out_ep = sc->sc_out_num_endpoints ? sc->sc_endpoints : NULL;
448 0 : sc->sc_in_ep =
449 0 : sc->sc_in_num_endpoints ?
450 0 : sc->sc_endpoints+sc->sc_out_num_endpoints : NULL;
451 :
452 0 : ep = &sc->sc_out_ep[0];
453 0 : for (i=0; i<sc->sc_out_num_endpoints; i++) {
454 0 : epd = usbd_interface2endpoint_descriptor(
455 0 : sc->sc_iface,
456 0 : fp->out_ep[i].ep);
457 0 : if (!epd) {
458 : DPRINTF(("%s: cannot get endpoint descriptor(out:%d)\n",
459 : sc->sc_dev.dv_xname, fp->out_ep[i].ep));
460 : goto error;
461 : }
462 0 : if (UE_GET_XFERTYPE(epd->bmAttributes)!=UE_BULK ||
463 0 : UE_GET_DIR(epd->bEndpointAddress)!=UE_DIR_OUT) {
464 0 : printf("%s: illegal endpoint(out:%d)\n",
465 0 : sc->sc_dev.dv_xname, fp->out_ep[i].ep);
466 0 : goto error;
467 : }
468 0 : ep->sc = sc;
469 0 : ep->packetsize = UGETW(epd->wMaxPacketSize);
470 0 : ep->addr = epd->bEndpointAddress;
471 0 : ep->num_jacks = fp->out_ep[i].num_jacks;
472 0 : sc->sc_out_num_jacks += fp->out_ep[i].num_jacks;
473 0 : ep->num_open = 0;
474 0 : memset(ep->jacks, 0, sizeof(ep->jacks));
475 0 : ep++;
476 : }
477 0 : ep = &sc->sc_in_ep[0];
478 0 : for (i=0; i<sc->sc_in_num_endpoints; i++) {
479 0 : epd = usbd_interface2endpoint_descriptor(
480 0 : sc->sc_iface,
481 0 : fp->in_ep[i].ep);
482 0 : if (!epd) {
483 : DPRINTF(("%s: cannot get endpoint descriptor(in:%d)\n",
484 : sc->sc_dev.dv_xname, fp->in_ep[i].ep));
485 : goto error;
486 : }
487 0 : if (UE_GET_XFERTYPE(epd->bmAttributes)!=UE_BULK ||
488 0 : UE_GET_DIR(epd->bEndpointAddress)!=UE_DIR_IN) {
489 0 : printf("%s: illegal endpoint(in:%d)\n",
490 0 : sc->sc_dev.dv_xname, fp->in_ep[i].ep);
491 0 : goto error;
492 : }
493 0 : ep->sc = sc;
494 0 : ep->addr = epd->bEndpointAddress;
495 0 : ep->packetsize = UGETW(epd->wMaxPacketSize);
496 0 : ep->num_jacks = fp->in_ep[i].num_jacks;
497 0 : sc->sc_in_num_jacks += fp->in_ep[i].num_jacks;
498 0 : ep->num_open = 0;
499 0 : memset(ep->jacks, 0, sizeof(ep->jacks));
500 0 : ep++;
501 : }
502 :
503 0 : return USBD_NORMAL_COMPLETION;
504 : error:
505 0 : free(sc->sc_endpoints, M_USBDEV, 0);
506 0 : sc->sc_endpoints = NULL;
507 0 : return USBD_INVAL;
508 0 : }
509 :
510 : static usbd_status
511 0 : alloc_all_endpoints_yamaha(struct umidi_softc *sc)
512 : {
513 : /* This driver currently supports max 1in/1out bulk endpoints */
514 : usb_descriptor_t *desc;
515 : usb_endpoint_descriptor_t *epd;
516 : int out_addr, in_addr, in_packetsize, i, dir;
517 : size_t remain, descsize;
518 :
519 : out_addr = in_addr = 0;
520 :
521 : /* detect endpoints */
522 0 : desc = TO_D(usbd_get_interface_descriptor(sc->sc_iface));
523 0 : for (i=(int)TO_IFD(desc)->bNumEndpoints-1; i>=0; i--) {
524 0 : epd = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
525 0 : if (UE_GET_XFERTYPE(epd->bmAttributes) == UE_BULK) {
526 0 : dir = UE_GET_DIR(epd->bEndpointAddress);
527 0 : if (dir==UE_DIR_OUT && !out_addr)
528 0 : out_addr = epd->bEndpointAddress;
529 0 : else if (dir==UE_DIR_IN && !in_addr) {
530 : in_addr = epd->bEndpointAddress;
531 0 : in_packetsize = UGETW(epd->wMaxPacketSize);
532 0 : }
533 : }
534 : }
535 0 : desc = NEXT_D(desc);
536 :
537 : /* count jacks */
538 0 : if (!(desc->bDescriptorType==UDESC_CS_INTERFACE &&
539 0 : desc->bDescriptorSubtype==UMIDI_MS_HEADER))
540 0 : return USBD_INVAL;
541 0 : remain = (size_t)UGETW(TO_CSIFD(desc)->wTotalLength) -
542 0 : (size_t)desc->bLength;
543 0 : desc = NEXT_D(desc);
544 :
545 0 : while (remain>=sizeof(usb_descriptor_t)) {
546 0 : descsize = desc->bLength;
547 0 : if (descsize>remain || descsize==0)
548 : break;
549 0 : if (desc->bDescriptorType==UDESC_CS_INTERFACE &&
550 0 : remain>=UMIDI_JACK_DESCRIPTOR_SIZE) {
551 0 : if (desc->bDescriptorSubtype==UMIDI_OUT_JACK)
552 0 : sc->sc_out_num_jacks++;
553 0 : else if (desc->bDescriptorSubtype==UMIDI_IN_JACK)
554 0 : sc->sc_in_num_jacks++;
555 : }
556 0 : desc = NEXT_D(desc);
557 0 : remain-=descsize;
558 : }
559 :
560 : /* validate some parameters */
561 0 : if (sc->sc_out_num_jacks>UMIDI_MAX_EPJACKS)
562 0 : sc->sc_out_num_jacks = UMIDI_MAX_EPJACKS;
563 0 : if (sc->sc_in_num_jacks>UMIDI_MAX_EPJACKS)
564 0 : sc->sc_in_num_jacks = UMIDI_MAX_EPJACKS;
565 0 : if (sc->sc_out_num_jacks && out_addr)
566 0 : sc->sc_out_num_endpoints = 1;
567 : else {
568 0 : sc->sc_out_num_endpoints = 0;
569 0 : sc->sc_out_num_jacks = 0;
570 : }
571 0 : if (sc->sc_in_num_jacks && in_addr)
572 0 : sc->sc_in_num_endpoints = 1;
573 : else {
574 0 : sc->sc_in_num_endpoints = 0;
575 0 : sc->sc_in_num_jacks = 0;
576 : }
577 0 : sc->sc_endpoints = mallocarray(sc->sc_out_num_endpoints +
578 0 : sc->sc_in_num_endpoints, sizeof(struct umidi_endpoint),
579 : M_USBDEV, M_WAITOK | M_CANFAIL);
580 0 : if (!sc->sc_endpoints)
581 0 : return USBD_NOMEM;
582 0 : if (sc->sc_out_num_endpoints) {
583 0 : sc->sc_out_ep = sc->sc_endpoints;
584 0 : sc->sc_out_ep->sc = sc;
585 0 : sc->sc_out_ep->addr = out_addr;
586 0 : sc->sc_out_ep->packetsize = UGETW(epd->wMaxPacketSize);
587 0 : sc->sc_out_ep->num_jacks = sc->sc_out_num_jacks;
588 0 : sc->sc_out_ep->num_open = 0;
589 0 : memset(sc->sc_out_ep->jacks, 0, sizeof(sc->sc_out_ep->jacks));
590 0 : } else
591 0 : sc->sc_out_ep = NULL;
592 :
593 0 : if (sc->sc_in_num_endpoints) {
594 0 : sc->sc_in_ep = sc->sc_endpoints+sc->sc_out_num_endpoints;
595 0 : sc->sc_in_ep->sc = sc;
596 0 : sc->sc_in_ep->addr = in_addr;
597 0 : sc->sc_in_ep->packetsize = in_packetsize;
598 0 : sc->sc_in_ep->num_jacks = sc->sc_in_num_jacks;
599 0 : sc->sc_in_ep->num_open = 0;
600 0 : memset(sc->sc_in_ep->jacks, 0, sizeof(sc->sc_in_ep->jacks));
601 0 : } else
602 0 : sc->sc_in_ep = NULL;
603 :
604 0 : return USBD_NORMAL_COMPLETION;
605 0 : }
606 :
607 : static usbd_status
608 0 : alloc_all_endpoints_genuine(struct umidi_softc *sc)
609 : {
610 : usb_interface_descriptor_t *interface_desc;
611 : usb_config_descriptor_t *config_desc;
612 : usb_descriptor_t *desc;
613 : size_t remain, descsize;
614 0 : struct umidi_endpoint *p, *q, *lowest, *endep, tmpep;
615 : int epaddr, eppacketsize, num_ep;
616 :
617 0 : interface_desc = usbd_get_interface_descriptor(sc->sc_iface);
618 0 : num_ep = interface_desc->bNumEndpoints;
619 0 : sc->sc_endpoints = p = mallocarray(num_ep,
620 : sizeof(struct umidi_endpoint), M_USBDEV, M_WAITOK | M_CANFAIL);
621 0 : if (!p)
622 0 : return USBD_NOMEM;
623 :
624 0 : sc->sc_out_num_endpoints = sc->sc_in_num_endpoints = 0;
625 : epaddr = -1;
626 :
627 : /* get the list of endpoints for midi stream */
628 0 : config_desc = usbd_get_config_descriptor(sc->sc_udev);
629 0 : desc = (usb_descriptor_t *) config_desc;
630 0 : remain = (size_t)UGETW(config_desc->wTotalLength);
631 0 : while (remain>=sizeof(usb_descriptor_t)) {
632 0 : descsize = desc->bLength;
633 0 : if (descsize>remain || descsize==0)
634 : break;
635 0 : if (desc->bDescriptorType==UDESC_ENDPOINT &&
636 0 : remain>=USB_ENDPOINT_DESCRIPTOR_SIZE &&
637 0 : UE_GET_XFERTYPE(TO_EPD(desc)->bmAttributes) == UE_BULK) {
638 0 : epaddr = TO_EPD(desc)->bEndpointAddress;
639 0 : eppacketsize = UGETW(TO_EPD(desc)->wMaxPacketSize);
640 0 : } else if (desc->bDescriptorType==UDESC_CS_ENDPOINT &&
641 0 : remain>=UMIDI_CS_ENDPOINT_DESCRIPTOR_SIZE &&
642 0 : epaddr!=-1) {
643 0 : if (num_ep>0) {
644 0 : num_ep--;
645 0 : p->sc = sc;
646 0 : p->addr = epaddr;
647 0 : p->packetsize = eppacketsize;
648 0 : p->num_jacks = TO_CSEPD(desc)->bNumEmbMIDIJack;
649 0 : if (UE_GET_DIR(epaddr)==UE_DIR_OUT) {
650 0 : sc->sc_out_num_endpoints++;
651 0 : sc->sc_out_num_jacks += p->num_jacks;
652 0 : } else {
653 0 : sc->sc_in_num_endpoints++;
654 0 : sc->sc_in_num_jacks += p->num_jacks;
655 : }
656 0 : p++;
657 0 : }
658 : } else
659 : epaddr = -1;
660 0 : desc = NEXT_D(desc);
661 0 : remain-=descsize;
662 : }
663 :
664 : /* sort endpoints */
665 0 : num_ep = sc->sc_out_num_endpoints + sc->sc_in_num_endpoints;
666 0 : p = sc->sc_endpoints;
667 0 : endep = p + num_ep;
668 0 : while (p<endep) {
669 : lowest = p;
670 0 : for (q=p+1; q<endep; q++) {
671 0 : if ((UE_GET_DIR(lowest->addr)==UE_DIR_IN &&
672 0 : UE_GET_DIR(q->addr)==UE_DIR_OUT) ||
673 0 : ((UE_GET_DIR(lowest->addr)==
674 0 : UE_GET_DIR(q->addr)) &&
675 0 : (UE_GET_ADDR(lowest->addr)>
676 0 : UE_GET_ADDR(q->addr))))
677 0 : lowest = q;
678 : }
679 0 : if (lowest != p) {
680 0 : memcpy((void *)&tmpep, (void *)p, sizeof(tmpep));
681 0 : memcpy((void *)p, (void *)lowest, sizeof(tmpep));
682 0 : memcpy((void *)lowest, (void *)&tmpep, sizeof(tmpep));
683 0 : }
684 0 : p->num_open = 0;
685 0 : p++;
686 : }
687 :
688 0 : sc->sc_out_ep = sc->sc_out_num_endpoints ? sc->sc_endpoints : NULL;
689 0 : sc->sc_in_ep =
690 0 : sc->sc_in_num_endpoints ?
691 0 : sc->sc_endpoints+sc->sc_out_num_endpoints : NULL;
692 :
693 0 : return USBD_NORMAL_COMPLETION;
694 0 : }
695 :
696 :
697 : /*
698 : * jack stuffs
699 : */
700 :
701 : static usbd_status
702 0 : alloc_all_jacks(struct umidi_softc *sc)
703 : {
704 : int i, j;
705 : struct umidi_endpoint *ep;
706 : struct umidi_jack *jack, **rjack;
707 :
708 : /* allocate/initialize structures */
709 0 : sc->sc_jacks = mallocarray(sc->sc_in_num_jacks + sc->sc_out_num_jacks,
710 : sizeof(*sc->sc_out_jacks), M_USBDEV, M_WAITOK | M_CANFAIL);
711 0 : if (!sc->sc_jacks)
712 0 : return USBD_NOMEM;
713 0 : sc->sc_out_jacks =
714 0 : sc->sc_out_num_jacks ? sc->sc_jacks : NULL;
715 0 : sc->sc_in_jacks =
716 0 : sc->sc_in_num_jacks ? sc->sc_jacks+sc->sc_out_num_jacks : NULL;
717 :
718 0 : jack = &sc->sc_out_jacks[0];
719 0 : for (i=0; i<sc->sc_out_num_jacks; i++) {
720 0 : jack->opened = 0;
721 0 : jack->binded = 0;
722 0 : jack->arg = NULL;
723 0 : jack->u.out.intr = NULL;
724 0 : jack->intr = 0;
725 0 : jack->cable_number = i;
726 0 : jack++;
727 : }
728 0 : jack = &sc->sc_in_jacks[0];
729 0 : for (i=0; i<sc->sc_in_num_jacks; i++) {
730 0 : jack->opened = 0;
731 0 : jack->binded = 0;
732 0 : jack->arg = NULL;
733 0 : jack->u.in.intr = NULL;
734 0 : jack->cable_number = i;
735 0 : jack++;
736 : }
737 :
738 : /* assign each jacks to each endpoints */
739 0 : jack = &sc->sc_out_jacks[0];
740 0 : ep = &sc->sc_out_ep[0];
741 0 : for (i=0; i<sc->sc_out_num_endpoints; i++) {
742 0 : rjack = &ep->jacks[0];
743 0 : for (j=0; j<ep->num_jacks; j++) {
744 0 : *rjack = jack;
745 0 : jack->endpoint = ep;
746 0 : jack++;
747 0 : rjack++;
748 : }
749 0 : ep++;
750 : }
751 0 : jack = &sc->sc_in_jacks[0];
752 0 : ep = &sc->sc_in_ep[0];
753 0 : for (i=0; i<sc->sc_in_num_endpoints; i++) {
754 0 : rjack = &ep->jacks[0];
755 0 : for (j=0; j<ep->num_jacks; j++) {
756 0 : *rjack = jack;
757 0 : jack->endpoint = ep;
758 0 : jack++;
759 0 : rjack++;
760 : }
761 0 : ep++;
762 : }
763 :
764 0 : return USBD_NORMAL_COMPLETION;
765 0 : }
766 :
767 : static void
768 0 : free_all_jacks(struct umidi_softc *sc)
769 : {
770 0 : int s, jacks = sc->sc_in_num_jacks + sc->sc_out_num_jacks;
771 :
772 0 : s = splusb();
773 0 : if (sc->sc_out_jacks) {
774 0 : free(sc->sc_jacks, M_USBDEV, jacks * sizeof(*sc->sc_out_jacks));
775 0 : sc->sc_jacks = sc->sc_in_jacks = sc->sc_out_jacks = NULL;
776 0 : sc->sc_out_num_jacks = sc->sc_in_num_jacks = 0;
777 0 : }
778 0 : splx(s);
779 0 : }
780 :
781 : static usbd_status
782 0 : bind_jacks_to_mididev(struct umidi_softc *sc,
783 : struct umidi_jack *out_jack,
784 : struct umidi_jack *in_jack,
785 : struct umidi_mididev *mididev)
786 : {
787 0 : if ((out_jack && out_jack->binded) || (in_jack && in_jack->binded))
788 0 : return USBD_IN_USE;
789 0 : if (mididev->out_jack || mididev->in_jack)
790 0 : return USBD_IN_USE;
791 :
792 0 : if (out_jack)
793 0 : out_jack->binded = 1;
794 0 : if (in_jack)
795 0 : in_jack->binded = 1;
796 0 : mididev->in_jack = in_jack;
797 0 : mididev->out_jack = out_jack;
798 :
799 0 : return USBD_NORMAL_COMPLETION;
800 0 : }
801 :
802 : static void
803 0 : unbind_jacks_from_mididev(struct umidi_mididev *mididev)
804 : {
805 0 : if ((mididev->flags & FWRITE) && mididev->out_jack)
806 0 : close_jack(mididev->out_jack);
807 0 : if ((mididev->flags & FREAD) && mididev->in_jack)
808 0 : close_jack(mididev->in_jack);
809 :
810 0 : if (mididev->out_jack)
811 0 : mididev->out_jack->binded = 0;
812 0 : if (mididev->in_jack)
813 0 : mididev->in_jack->binded = 0;
814 0 : mididev->out_jack = mididev->in_jack = NULL;
815 0 : }
816 :
817 : static void
818 0 : unbind_all_jacks(struct umidi_softc *sc)
819 : {
820 : int i;
821 :
822 0 : if (sc->sc_mididevs)
823 0 : for (i=0; i<sc->sc_num_mididevs; i++) {
824 0 : unbind_jacks_from_mididev(&sc->sc_mididevs[i]);
825 : }
826 0 : }
827 :
828 : static usbd_status
829 0 : assign_all_jacks_automatically(struct umidi_softc *sc)
830 : {
831 : usbd_status err;
832 : int i;
833 : struct umidi_jack *out, *in;
834 :
835 : err =
836 0 : alloc_all_mididevs(sc,
837 0 : max(sc->sc_out_num_jacks, sc->sc_in_num_jacks));
838 0 : if (err!=USBD_NORMAL_COMPLETION)
839 0 : return err;
840 :
841 0 : for (i=0; i<sc->sc_num_mididevs; i++) {
842 0 : out = (i<sc->sc_out_num_jacks) ? &sc->sc_out_jacks[i]:NULL;
843 0 : in = (i<sc->sc_in_num_jacks) ? &sc->sc_in_jacks[i]:NULL;
844 0 : err = bind_jacks_to_mididev(sc, out, in, &sc->sc_mididevs[i]);
845 0 : if (err!=USBD_NORMAL_COMPLETION) {
846 0 : free_all_mididevs(sc);
847 0 : return err;
848 : }
849 : }
850 :
851 0 : return USBD_NORMAL_COMPLETION;
852 0 : }
853 :
854 : static usbd_status
855 0 : open_out_jack(struct umidi_jack *jack, void *arg, void (*intr)(void *))
856 : {
857 0 : if (jack->opened)
858 0 : return USBD_IN_USE;
859 :
860 0 : jack->arg = arg;
861 0 : jack->u.out.intr = intr;
862 0 : init_packet(&jack->packet);
863 0 : jack->opened = 1;
864 0 : jack->endpoint->num_open++;
865 :
866 0 : return USBD_NORMAL_COMPLETION;
867 0 : }
868 :
869 : static usbd_status
870 0 : open_in_jack(struct umidi_jack *jack, void *arg, void (*intr)(void *, int))
871 : {
872 0 : if (jack->opened)
873 0 : return USBD_IN_USE;
874 :
875 0 : jack->arg = arg;
876 0 : jack->u.in.intr = intr;
877 0 : jack->opened = 1;
878 0 : jack->endpoint->num_open++;
879 :
880 0 : return USBD_NORMAL_COMPLETION;
881 0 : }
882 :
883 : static void
884 0 : close_jack(struct umidi_jack *jack)
885 : {
886 0 : if (jack->opened) {
887 0 : jack->opened = 0;
888 0 : jack->endpoint->num_open--;
889 0 : }
890 0 : }
891 :
892 : static usbd_status
893 0 : attach_mididev(struct umidi_softc *sc, struct umidi_mididev *mididev)
894 : {
895 0 : if (mididev->sc)
896 0 : return USBD_IN_USE;
897 :
898 0 : mididev->sc = sc;
899 :
900 0 : mididev->mdev = midi_attach_mi(&umidi_hw_if, mididev, &sc->sc_dev);
901 :
902 0 : return USBD_NORMAL_COMPLETION;
903 0 : }
904 :
905 : static usbd_status
906 0 : detach_mididev(struct umidi_mididev *mididev, int flags)
907 : {
908 0 : if (!mididev->sc)
909 0 : return USBD_NO_ADDR;
910 :
911 0 : if (mididev->opened)
912 0 : umidi_close(mididev);
913 0 : unbind_jacks_from_mididev(mididev);
914 :
915 0 : if (mididev->mdev)
916 0 : config_detach(mididev->mdev, flags);
917 :
918 0 : mididev->sc = NULL;
919 :
920 0 : return USBD_NORMAL_COMPLETION;
921 0 : }
922 :
923 : static usbd_status
924 0 : deactivate_mididev(struct umidi_mididev *mididev)
925 : {
926 0 : if (mididev->out_jack)
927 0 : mididev->out_jack->binded = 0;
928 0 : if (mididev->in_jack)
929 0 : mididev->in_jack->binded = 0;
930 0 : config_deactivate(mididev->mdev);
931 :
932 0 : return USBD_NORMAL_COMPLETION;
933 : }
934 :
935 : static usbd_status
936 0 : alloc_all_mididevs(struct umidi_softc *sc, int nmidi)
937 : {
938 0 : sc->sc_num_mididevs = nmidi;
939 0 : sc->sc_mididevs = mallocarray(nmidi, sizeof(*sc->sc_mididevs),
940 : M_USBDEV, M_WAITOK | M_CANFAIL | M_ZERO);
941 0 : if (!sc->sc_mididevs)
942 0 : return USBD_NOMEM;
943 :
944 0 : return USBD_NORMAL_COMPLETION;
945 0 : }
946 :
947 : static void
948 0 : free_all_mididevs(struct umidi_softc *sc)
949 : {
950 0 : if (sc->sc_mididevs)
951 0 : free(sc->sc_mididevs, M_USBDEV,
952 0 : sc->sc_num_mididevs * sizeof(*sc->sc_mididevs));
953 0 : sc->sc_mididevs = NULL;
954 0 : sc->sc_num_mididevs = 0;
955 0 : }
956 :
957 : static usbd_status
958 0 : attach_all_mididevs(struct umidi_softc *sc)
959 : {
960 : usbd_status err;
961 : int i;
962 :
963 0 : if (sc->sc_mididevs)
964 0 : for (i=0; i<sc->sc_num_mididevs; i++) {
965 0 : err = attach_mididev(sc, &sc->sc_mididevs[i]);
966 0 : if (err!=USBD_NORMAL_COMPLETION)
967 0 : return err;
968 : }
969 :
970 0 : return USBD_NORMAL_COMPLETION;
971 0 : }
972 :
973 : static usbd_status
974 0 : detach_all_mididevs(struct umidi_softc *sc, int flags)
975 : {
976 : usbd_status err;
977 : int i;
978 :
979 0 : if (sc->sc_mididevs)
980 0 : for (i=0; i<sc->sc_num_mididevs; i++) {
981 0 : err = detach_mididev(&sc->sc_mididevs[i], flags);
982 0 : if (err!=USBD_NORMAL_COMPLETION)
983 0 : return err;
984 : }
985 :
986 0 : return USBD_NORMAL_COMPLETION;
987 0 : }
988 :
989 : static usbd_status
990 0 : deactivate_all_mididevs(struct umidi_softc *sc)
991 : {
992 : usbd_status err;
993 : int i;
994 :
995 0 : if (sc->sc_mididevs)
996 0 : for (i=0; i<sc->sc_num_mididevs; i++) {
997 0 : err = deactivate_mididev(&sc->sc_mididevs[i]);
998 0 : if (err!=USBD_NORMAL_COMPLETION)
999 0 : return err;
1000 : }
1001 :
1002 0 : return USBD_NORMAL_COMPLETION;
1003 0 : }
1004 :
1005 : #ifdef UMIDI_DEBUG
1006 : static void
1007 : dump_sc(struct umidi_softc *sc)
1008 : {
1009 : int i;
1010 :
1011 : DPRINTFN(10, ("%s: %s\n", sc->sc_dev.dv_xname, __func__));
1012 : for (i=0; i<sc->sc_out_num_endpoints; i++) {
1013 : DPRINTFN(10, ("\tout_ep(%p):\n", &sc->sc_out_ep[i]));
1014 : dump_ep(&sc->sc_out_ep[i]);
1015 : }
1016 : for (i=0; i<sc->sc_in_num_endpoints; i++) {
1017 : DPRINTFN(10, ("\tin_ep(%p):\n", &sc->sc_in_ep[i]));
1018 : dump_ep(&sc->sc_in_ep[i]);
1019 : }
1020 : }
1021 :
1022 : static void
1023 : dump_ep(struct umidi_endpoint *ep)
1024 : {
1025 : int i;
1026 : for (i=0; i<ep->num_jacks; i++) {
1027 : DPRINTFN(10, ("\t\tjack(%p):\n", ep->jacks[i]));
1028 : dump_jack(ep->jacks[i]);
1029 : }
1030 : }
1031 : static void
1032 : dump_jack(struct umidi_jack *jack)
1033 : {
1034 : DPRINTFN(10, ("\t\t\tep=%p\n",
1035 : jack->endpoint));
1036 : }
1037 :
1038 : #endif /* UMIDI_DEBUG */
1039 :
1040 :
1041 :
1042 : /*
1043 : * MUX MIDI PACKET
1044 : */
1045 :
1046 : static const int packet_length[16] = {
1047 : /*0*/ -1,
1048 : /*1*/ -1,
1049 : /*2*/ 2,
1050 : /*3*/ 3,
1051 : /*4*/ 3,
1052 : /*5*/ 1,
1053 : /*6*/ 2,
1054 : /*7*/ 3,
1055 : /*8*/ 3,
1056 : /*9*/ 3,
1057 : /*A*/ 3,
1058 : /*B*/ 3,
1059 : /*C*/ 2,
1060 : /*D*/ 2,
1061 : /*E*/ 3,
1062 : /*F*/ 1,
1063 : };
1064 :
1065 : #define GET_CN(p) (((unsigned char)(p)>>4)&0x0F)
1066 : #define GET_CIN(p) ((unsigned char)(p)&0x0F)
1067 :
1068 : static void
1069 0 : init_packet(struct umidi_packet *packet)
1070 : {
1071 0 : packet->status = 0;
1072 0 : packet->index = 0;
1073 0 : }
1074 :
1075 : static usbd_status
1076 0 : start_input_transfer(struct umidi_endpoint *ep)
1077 : {
1078 : usbd_status err;
1079 0 : usbd_setup_xfer(ep->xfer, ep->pipe,
1080 0 : (void *)ep,
1081 0 : ep->buffer, ep->packetsize,
1082 : USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, in_intr);
1083 0 : err = usbd_transfer(ep->xfer);
1084 0 : if (err != USBD_NORMAL_COMPLETION && err != USBD_IN_PROGRESS) {
1085 : DPRINTF(("%s: %s: usbd_transfer() failed err=%s\n",
1086 : ep->sc->sc_dev.dv_xname, __func__, usbd_errstr(err)));
1087 0 : return err;
1088 : }
1089 0 : return USBD_NORMAL_COMPLETION;
1090 0 : }
1091 :
1092 : static usbd_status
1093 0 : start_output_transfer(struct umidi_endpoint *ep)
1094 : {
1095 : usbd_status err;
1096 0 : usbd_setup_xfer(ep->xfer, ep->pipe,
1097 0 : (void *)ep,
1098 0 : ep->buffer, ep->used,
1099 : USBD_NO_COPY, USBD_NO_TIMEOUT, out_intr);
1100 0 : err = usbd_transfer(ep->xfer);
1101 0 : if (err != USBD_NORMAL_COMPLETION && err != USBD_IN_PROGRESS) {
1102 : DPRINTF(("%s: %s: usbd_transfer() failed err=%s\n",
1103 : ep->sc->sc_dev.dv_xname, __func__, usbd_errstr(err)));
1104 0 : return err;
1105 : }
1106 0 : ep->used = ep->packetsize;
1107 0 : return USBD_NORMAL_COMPLETION;
1108 0 : }
1109 :
1110 :
1111 : #ifdef UMIDI_DEBUG
1112 : #define DPR_PACKET(dir, sc, p) \
1113 : DPRINTFN(500, \
1114 : ("%s: umidi packet(" #dir "): %02X %02X %02X %02X\n", \
1115 : sc->sc_dev.dv_xname, \
1116 : (unsigned char)(p)->buffer[0], \
1117 : (unsigned char)(p)->buffer[1], \
1118 : (unsigned char)(p)->buffer[2], \
1119 : (unsigned char)(p)->buffer[3]));
1120 : #else
1121 : #define DPR_PACKET(dir, sc, p)
1122 : #endif
1123 :
1124 : static int
1125 0 : out_jack_output(struct umidi_jack *j, int d)
1126 : {
1127 0 : struct umidi_endpoint *ep = j->endpoint;
1128 0 : struct umidi_softc *sc = ep->sc;
1129 : int s;
1130 :
1131 0 : if (usbd_is_dying(sc->sc_udev))
1132 0 : return 1;
1133 0 : if (!j->opened)
1134 0 : return 1;
1135 0 : s = splusb();
1136 0 : if (ep->busy) {
1137 0 : if (!j->intr) {
1138 0 : SIMPLEQ_INSERT_TAIL(&ep->intrq, j, intrq_entry);
1139 0 : ep->pending++;
1140 0 : j->intr = 1;
1141 0 : }
1142 0 : splx(s);
1143 0 : return 0;
1144 : }
1145 0 : if (!out_build_packet(j->cable_number, &j->packet, d,
1146 0 : ep->buffer + ep->used)) {
1147 0 : splx(s);
1148 0 : return 1;
1149 : }
1150 0 : ep->used += UMIDI_PACKET_SIZE;
1151 0 : if (ep->used == ep->packetsize) {
1152 0 : ep->busy = 1;
1153 0 : start_output_transfer(ep);
1154 0 : }
1155 0 : splx(s);
1156 0 : return 1;
1157 0 : }
1158 :
1159 : static void
1160 0 : out_jack_flush(struct umidi_jack *j)
1161 : {
1162 0 : struct umidi_endpoint *ep = j->endpoint;
1163 : int s;
1164 :
1165 0 : if (usbd_is_dying(ep->sc->sc_udev) || !j->opened)
1166 0 : return;
1167 :
1168 0 : s = splusb();
1169 0 : if (ep->used != 0 && !ep->busy) {
1170 0 : ep->busy = 1;
1171 0 : start_output_transfer(ep);
1172 0 : }
1173 0 : splx(s);
1174 0 : }
1175 :
1176 :
1177 : static void
1178 0 : in_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
1179 : {
1180 0 : int cn, evlen, remain, i;
1181 : unsigned char *buf;
1182 0 : struct umidi_endpoint *ep = (struct umidi_endpoint *)priv;
1183 : struct umidi_jack *jack;
1184 :
1185 0 : if (usbd_is_dying(ep->sc->sc_udev))
1186 0 : return;
1187 :
1188 0 : usbd_get_xfer_status(xfer, NULL, NULL, &remain, NULL);
1189 0 : if (status != USBD_NORMAL_COMPLETION) {
1190 : DPRINTF(("%s: abnormal status: %s\n", __func__, usbd_errstr(status)));
1191 0 : return;
1192 : }
1193 0 : buf = ep->buffer;
1194 0 : while (remain >= UMIDI_PACKET_SIZE) {
1195 0 : cn = GET_CN(buf[0]);
1196 0 : if (cn < ep->num_jacks && (jack = ep->jacks[cn]) &&
1197 0 : jack->binded && jack->opened && jack->u.in.intr) {
1198 0 : evlen = packet_length[GET_CIN(buf[0])];
1199 0 : mtx_enter(&audio_lock);
1200 0 : for (i=0; i<evlen; i++)
1201 0 : (*jack->u.in.intr)(jack->arg, buf[i+1]);
1202 0 : mtx_leave(&audio_lock);
1203 0 : }
1204 0 : buf += UMIDI_PACKET_SIZE;
1205 0 : remain -= UMIDI_PACKET_SIZE;
1206 : }
1207 0 : (void)start_input_transfer(ep);
1208 0 : }
1209 :
1210 : static void
1211 0 : out_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
1212 : {
1213 0 : struct umidi_endpoint *ep = (struct umidi_endpoint *)priv;
1214 0 : struct umidi_softc *sc = ep->sc;
1215 : struct umidi_jack *j;
1216 : unsigned pending;
1217 :
1218 0 : if (usbd_is_dying(sc->sc_udev))
1219 0 : return;
1220 :
1221 0 : ep->used = 0;
1222 0 : ep->busy = 0;
1223 0 : for (pending = ep->pending; pending > 0; pending--) {
1224 0 : j = SIMPLEQ_FIRST(&ep->intrq);
1225 : #ifdef DIAGNOSTIC
1226 0 : if (j == NULL) {
1227 0 : printf("umidi: missing intr entry\n");
1228 0 : break;
1229 : }
1230 : #endif
1231 0 : SIMPLEQ_REMOVE_HEAD(&ep->intrq, intrq_entry);
1232 0 : ep->pending--;
1233 0 : j->intr = 0;
1234 0 : mtx_enter(&audio_lock);
1235 0 : if (j->opened && j->u.out.intr)
1236 0 : (*j->u.out.intr)(j->arg);
1237 0 : mtx_leave(&audio_lock);
1238 : }
1239 0 : }
1240 :
1241 : #define UMIDI_VOICELEN(status) (umidi_evlen[((status) >> 4) & 7])
1242 : static const unsigned int umidi_evlen[] = { 4, 4, 4, 4, 3, 3, 4 };
1243 :
1244 : #define EV_SYSEX 0xf0
1245 : #define EV_MTC 0xf1
1246 : #define EV_SPP 0xf2
1247 : #define EV_SONGSEL 0xf3
1248 : #define EV_TUNE_REQ 0xf6
1249 : #define EV_SYSEX_STOP 0xf7
1250 :
1251 : static int
1252 0 : out_build_packet(int cable_number, struct umidi_packet *packet,
1253 : uByte data, u_char *obuf)
1254 : {
1255 0 : if (data >= 0xf8) { /* is it a realtime message ? */
1256 0 : obuf[0] = data >> 4 | cable_number << 4;
1257 0 : obuf[1] = data;
1258 0 : obuf[2] = 0;
1259 0 : obuf[3] = 0;
1260 0 : return 1;
1261 : }
1262 0 : if (data >= 0xf0) { /* is it a common message ? */
1263 0 : switch(data) {
1264 : case EV_SYSEX:
1265 0 : packet->buf[1] = packet->status = data;
1266 0 : packet->index = 2;
1267 0 : break;
1268 : case EV_SYSEX_STOP:
1269 0 : if (packet->status != EV_SYSEX) break;
1270 0 : if (packet->index == 0)
1271 0 : packet->index = 1;
1272 0 : packet->status = data;
1273 0 : packet->buf[packet->index++] = data;
1274 0 : packet->buf[0] = (0x4 - 1 + packet->index) | cable_number << 4;
1275 0 : goto packetready;
1276 : case EV_TUNE_REQ:
1277 0 : packet->status = data;
1278 0 : packet->buf[0] = 0x5 | cable_number << 4;
1279 0 : packet->index = 1;
1280 0 : goto packetready;
1281 : default:
1282 0 : packet->status = data;
1283 0 : break;
1284 : }
1285 0 : return 0;
1286 : }
1287 0 : if (data >= 0x80) { /* is it a voice message ? */
1288 0 : packet->status = data;
1289 0 : packet->index = 0;
1290 0 : return 0;
1291 : }
1292 :
1293 : /* else it is a data byte */
1294 0 : if (packet->status >= 0xf0) {
1295 0 : switch(packet->status) {
1296 : case EV_SYSEX: /* sysex starts or continues */
1297 0 : if (packet->index == 0)
1298 0 : packet->index = 1;
1299 :
1300 0 : packet->buf[packet->index++] = data;
1301 0 : if (packet->index >= UMIDI_PACKET_SIZE) {
1302 0 : packet->buf[0] = 0x4 | cable_number << 4;
1303 0 : goto packetready;
1304 : }
1305 : break;
1306 : case EV_MTC: /* messages with 1 data byte */
1307 : case EV_SONGSEL:
1308 0 : packet->buf[0] = 0x2 | cable_number << 4;
1309 0 : packet->buf[1] = packet->status;
1310 0 : packet->buf[2] = data;
1311 0 : packet->index = 3;
1312 0 : goto packetready;
1313 : case EV_SPP: /* messages with 2 data bytes */
1314 0 : if (packet->index == 0) {
1315 0 : packet->buf[0] = 0x3 | cable_number << 4;
1316 0 : packet->index = 1;
1317 0 : }
1318 0 : packet->buf[packet->index++] = data;
1319 0 : if (packet->index >= UMIDI_PACKET_SIZE) {
1320 0 : packet->buf[1] = packet->status;
1321 0 : goto packetready;
1322 : }
1323 : break;
1324 : default: /* ignore data with unknown status */
1325 : break;
1326 : }
1327 0 : return 0;
1328 : }
1329 0 : if (packet->status >= 0x80) { /* is it a voice message ? */
1330 0 : if (packet->index == 0) {
1331 0 : packet->buf[0] = packet->status >> 4 | cable_number << 4;
1332 0 : packet->buf[1] = packet->status;
1333 0 : packet->index = 2;
1334 0 : }
1335 0 : packet->buf[packet->index++] = data;
1336 0 : if (packet->index >= UMIDI_VOICELEN(packet->status))
1337 : goto packetready;
1338 : }
1339 : /* ignore data with unknown status */
1340 0 : return 0;
1341 :
1342 : packetready:
1343 0 : while (packet->index < UMIDI_PACKET_SIZE)
1344 0 : packet->buf[packet->index++] = 0;
1345 0 : packet->index = 0;
1346 0 : memcpy(obuf, packet->buf, UMIDI_PACKET_SIZE);
1347 0 : return 1;
1348 0 : }
|