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