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