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