midi.c revision 1.43.2.19 1 /* $NetBSD: midi.c,v 1.43.2.19 2006/05/31 03:17:06 chap Exp $ */
2
3 /*
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (augustss (at) NetBSD.org) and (MIDI FST and Active
9 * Sense handling) Chapman Flack (chap (at) NetBSD.org).
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: midi.c,v 1.43.2.19 2006/05/31 03:17:06 chap Exp $");
42
43 #include "midi.h"
44 #include "sequencer.h"
45
46 #include <sys/param.h>
47 #include <sys/ioctl.h>
48 #include <sys/fcntl.h>
49 #include <sys/vnode.h>
50 #include <sys/select.h>
51 #include <sys/poll.h>
52 #include <sys/malloc.h>
53 #include <sys/proc.h>
54 #include <sys/systm.h>
55 #include <sys/callout.h>
56 #include <sys/syslog.h>
57 #include <sys/kernel.h>
58 #include <sys/signalvar.h>
59 #include <sys/conf.h>
60 #include <sys/audioio.h>
61 #include <sys/midiio.h>
62
63 #include <dev/audio_if.h>
64 #include <dev/midi_if.h>
65 #include <dev/midivar.h>
66
67 #if NMIDI > 0
68
69 #ifdef AUDIO_DEBUG
70 #define DPRINTF(x) if (mididebug) printf x
71 #define DPRINTFN(n,x) if (mididebug >= (n)) printf x
72 int mididebug = 0;
73 /*
74 * 1: detected protocol errors and buffer overflows
75 * 2: probe, attach, detach
76 * 3: open, close
77 * 4: data received except realtime
78 * 5: ioctl
79 * 6: read, write, poll
80 * 7: data transmitted
81 * 8: uiomoves, synchronization
82 * 9: realtime data received
83 */
84 #else
85 #define DPRINTF(x)
86 #define DPRINTFN(n,x)
87 #endif
88
89 static struct simplelock hwif_register_lock = SIMPLELOCK_INITIALIZER;
90 static struct midi_softc *hwif_softc = NULL;
91
92 void midi_in(void *, int);
93 void midi_out(void *);
94 int midi_poll_out(struct midi_softc *);
95 int midi_intr_out(struct midi_softc *);
96 int midi_msg_out(struct midi_softc *,
97 u_char **, u_char **, u_char **, u_char **);
98 int midi_start_output(struct midi_softc *);
99 int midi_sleep_timo(int *, const char *, int, struct simplelock *);
100 int midi_sleep(int *, const char *, struct simplelock *);
101 void midi_wakeup(int *);
102 void midi_initbuf(struct midi_buffer *);
103 void midi_xmt_asense(void *);
104 void midi_rcv_asense(void *);
105
106 int midiprobe(struct device *, struct cfdata *, void *);
107 void midiattach(struct device *, struct device *, void *);
108 int mididetach(struct device *, int);
109 int midiactivate(struct device *, enum devact);
110
111 dev_type_open(midiopen);
112 dev_type_close(midiclose);
113 dev_type_read(midiread);
114 dev_type_write(midiwrite);
115 dev_type_ioctl(midiioctl);
116 dev_type_poll(midipoll);
117 dev_type_kqfilter(midikqfilter);
118
119 const struct cdevsw midi_cdevsw = {
120 midiopen, midiclose, midiread, midiwrite, midiioctl,
121 nostop, notty, midipoll, nommap, midikqfilter,
122 };
123
124 CFATTACH_DECL(midi, sizeof(struct midi_softc),
125 midiprobe, midiattach, mididetach, midiactivate);
126
127 #define MIDI_XMT_ASENSE_PERIOD mstohz(275)
128 #define MIDI_RCV_ASENSE_PERIOD mstohz(300)
129
130 extern struct cfdriver midi_cd;
131
132 int
133 midiprobe(struct device *parent, struct cfdata *match, void *aux)
134 {
135 struct audio_attach_args *sa = aux;
136
137 DPRINTFN(2,("midiprobe: type=%d sa=%p hw=%p\n",
138 sa->type, sa, sa->hwif));
139 return (sa->type == AUDIODEV_TYPE_MIDI);
140 }
141
142 void
143 midiattach(struct device *parent, struct device *self, void *aux)
144 {
145 struct midi_softc *sc = (void *)self;
146 struct audio_attach_args *sa = aux;
147 const struct midi_hw_if *hwp = sa->hwif;
148 void *hdlp = sa->hdl;
149
150 DPRINTFN(2, ("MIDI attach\n"));
151
152 #ifdef DIAGNOSTIC
153 if (hwp == 0 ||
154 hwp->open == 0 ||
155 hwp->close == 0 ||
156 hwp->output == 0 ||
157 hwp->getinfo == 0) {
158 printf("midi: missing method\n");
159 return;
160 }
161 #endif
162
163 sc->hw_if = hwp;
164 sc->hw_hdl = hdlp;
165 midi_attach(sc, parent);
166 }
167
168 int
169 midiactivate(struct device *self, enum devact act)
170 {
171 struct midi_softc *sc = (struct midi_softc *)self;
172
173 switch (act) {
174 case DVACT_ACTIVATE:
175 return (EOPNOTSUPP);
176
177 case DVACT_DEACTIVATE:
178 sc->dying = 1;
179 break;
180 }
181 return (0);
182 }
183
184 int
185 mididetach(struct device *self, int flags)
186 {
187 struct midi_softc *sc = (struct midi_softc *)self;
188 int maj, mn;
189
190 DPRINTFN(2,("midi_detach: sc=%p flags=%d\n", sc, flags));
191
192 sc->dying = 1;
193
194 wakeup(&sc->wchan);
195 wakeup(&sc->rchan);
196
197 /* locate the major number */
198 maj = cdevsw_lookup_major(&midi_cdevsw);
199
200 /* Nuke the vnodes for any open instances (calls close). */
201 mn = device_unit(self);
202 vdevgone(maj, mn, mn, VCHR);
203
204 evcnt_detach(&sc->xmt.bytesDiscarded);
205 evcnt_detach(&sc->xmt.incompleteMessages);
206 if ( sc->props & MIDI_PROP_CAN_INPUT ) {
207 evcnt_detach(&sc->rcv.bytesDiscarded);
208 evcnt_detach(&sc->rcv.incompleteMessages);
209 }
210
211 return (0);
212 }
213
214 void
215 midi_attach(struct midi_softc *sc, struct device *parent)
216 {
217 struct midi_info mi;
218 int s;
219
220 callout_init(&sc->xmt_asense_co);
221 callout_init(&sc->rcv_asense_co);
222 callout_setfunc(&sc->xmt_asense_co, midi_xmt_asense, sc);
223 callout_setfunc(&sc->rcv_asense_co, midi_rcv_asense, sc);
224 simple_lock_init(&sc->out_lock);
225 simple_lock_init(&sc->in_lock);
226 sc->dying = 0;
227 sc->isopen = 0;
228
229 sc->sc_dev = parent;
230
231 s = splaudio();
232 simple_lock(&hwif_register_lock);
233 hwif_softc = sc;
234 sc->hw_if->getinfo(sc->hw_hdl, &mi);
235 hwif_softc = NULL;
236 simple_unlock(&hwif_register_lock);
237 splx(s);
238
239 sc->props = mi.props;
240
241 evcnt_attach_dynamic(&sc->xmt.bytesDiscarded,
242 EVCNT_TYPE_MISC, NULL,
243 sc->dev.dv_xname, "xmt bytes discarded");
244 evcnt_attach_dynamic(&sc->xmt.incompleteMessages,
245 EVCNT_TYPE_MISC, NULL,
246 sc->dev.dv_xname, "xmt incomplete msgs");
247 if ( sc->props & MIDI_PROP_CAN_INPUT ) {
248 evcnt_attach_dynamic(&sc->rcv.bytesDiscarded,
249 EVCNT_TYPE_MISC, NULL,
250 sc->dev.dv_xname, "rcv bytes discarded");
251 evcnt_attach_dynamic(&sc->rcv.incompleteMessages,
252 EVCNT_TYPE_MISC, NULL,
253 sc->dev.dv_xname, "rcv incomplete msgs");
254 }
255
256 printf(": %s%s\n", mi.name,
257 (sc->props & (MIDI_PROP_OUT_INTR|MIDI_PROP_NO_OUTPUT)) ?
258 "" : " (cpu-intensive output)");
259 }
260
261 void midi_register_hw_if_ext(struct midi_hw_if_ext *exthw) {
262 if ( hwif_softc != NULL ) /* ignore calls resulting from non-init */
263 hwif_softc->hw_if_ext = exthw; /* uses of getinfo */
264 }
265
266 int
267 midi_unit_count(void)
268 {
269 int i;
270 for ( i = 0; i < midi_cd.cd_ndevs; ++i )
271 if ( NULL == midi_cd.cd_devs[i] )
272 break;
273 return i;
274 }
275
276 void
277 midi_initbuf(struct midi_buffer *mb)
278 {
279 mb->idx_producerp = mb->idx_consumerp = mb->idx;
280 mb->buf_producerp = mb->buf_consumerp = mb->buf;
281 }
282 #define PACK_MB_IDX(cat,len) (((cat)<<4)|(len))
283 #define MB_IDX_CAT(idx) ((idx)>>4)
284 #define MB_IDX_LEN(idx) ((idx)&0xf)
285
286 int
287 midi_sleep_timo(int *chan, const char *label, int timo, struct simplelock *lk)
288 {
289 int st;
290
291 if (!label)
292 label = "midi";
293
294 DPRINTFN(8, ("midi_sleep_timo: %p %s %d\n", chan, label, timo));
295 *chan = 1;
296 st = ltsleep(chan, PWAIT | PCATCH, label, timo, lk);
297 *chan = 0;
298 #ifdef MIDI_DEBUG
299 if (st != 0)
300 printf("midi_sleep: %d\n", st);
301 #endif
302 return st;
303 }
304
305 int
306 midi_sleep(int *chan, const char *label, struct simplelock *lk)
307 {
308 return midi_sleep_timo(chan, label, 0, lk);
309 }
310
311 void
312 midi_wakeup(int *chan)
313 {
314 if (*chan) {
315 DPRINTFN(8, ("midi_wakeup: %p\n", chan));
316 wakeup(chan);
317 *chan = 0;
318 }
319 }
320
321 /* in midivar.h:
322 #define MIDI_CAT_DATA 0
323 #define MIDI_CAT_STATUS1 1
324 #define MIDI_CAT_STATUS2 2
325 #define MIDI_CAT_COMMON 3
326 */
327 static char const midi_cats[] = "\0\0\0\0\0\0\0\0\2\2\2\2\1\1\2\3";
328 #define MIDI_CAT(d) (midi_cats[((d)>>4)&15])
329 #define FST_RETURN(offp,endp,ret) \
330 return (s->pos=s->msg+(offp)), (s->end=s->msg+(endp)), (ret)
331
332 enum fst_ret { FST_CHN, FST_CHV, FST_COM, FST_SYX, FST_RT, FST_MORE, FST_ERR,
333 FST_HUH, FST_SXP };
334 enum fst_form { FST_CANON, FST_COMPR, FST_VCOMP };
335 static struct {
336 int off;
337 enum fst_ret tag;
338 } const midi_forms[] = {
339 [FST_CANON] = { .off=0, .tag=FST_CHN },
340 [FST_COMPR] = { .off=1, .tag=FST_CHN },
341 [FST_VCOMP] = { .off=0, .tag=FST_CHV }
342 };
343 #define FST_CRETURN(endp) \
344 FST_RETURN(midi_forms[form].off,endp,midi_forms[form].tag)
345
346 /*
347 * A MIDI finite state transducer suitable for receiving or transmitting. It
348 * will accept correct MIDI input that uses, doesn't use, or sometimes uses the
349 * 'running status' compression technique, and transduce it to fully expanded
350 * (form=FST_CANON) or fully compressed (form=FST_COMPR or FST_VCOMP) form.
351 *
352 * Returns FST_MORE if a complete message has not been parsed yet (SysEx
353 * messages are the exception), FST_ERR or FST_HUH if the input does not
354 * conform to the protocol, or FST_CHN (channel messages), FST_COM (System
355 * Common messages), FST_RT (System Real-Time messages), or FST_SYX (System
356 * Exclusive) to broadly categorize the message parsed. s->pos and s->end
357 * locate the parsed message; while (s->pos<s->end) putchar(*(s->pos++));
358 * would output it.
359 *
360 * FST_HUH means the character c wasn't valid in the original state, but the
361 * state has now been reset to START and the caller should try again passing
362 * the same c. FST_ERR means c isn't valid in the start state; the caller
363 * should kiss it goodbye and continue to try successive characters from the
364 * input until something other than FST_ERR or FST_HUH is returned, at which
365 * point things are resynchronized.
366 *
367 * A FST_SYX return means that between pos and end are from 1 to 3
368 * bytes of a system exclusive message. A SysEx message will be delivered in
369 * one or more chunks of that form, where the first begins with 0xf0 and the
370 * last (which is the only one that might have length < 3) ends with 0xf7.
371 *
372 * Messages corrupted by a protocol error are discarded and won't be seen at
373 * all; again SysEx is the exception, as one or more chunks of it may already
374 * have been parsed.
375 *
376 * For FST_CHN messages, s->msg[0] always contains the status byte even if
377 * FST_COMPR form was requested (pos then points to msg[1]). That way, the
378 * caller can always identify the exact message if there is a need to do so.
379 * For all other message types except FST_SYX, the status byte is at *pos
380 * (which may not necessarily be msg[0]!). There is only one SysEx status
381 * byte, so the return value FST_SYX is sufficient to identify it.
382 *
383 * To simplify some use cases, compression can also be requested with
384 * form=FST_VCOMP. In this form a compressible channel message is indicated
385 * by returning a classification of FST_CHV instead of FST_CHN, and pos points
386 * to the status byte rather than being advanced past it. If the caller in this
387 * case saves the bytes from pos to end, it will have saved the entire message,
388 * and can act on the FST_CHV tag to drop the first byte later. In this form,
389 * unlike FST_CANON, hidden note-off (i.e. note-on with velocity 0) may occur.
390 *
391 * Two obscure points in the MIDI protocol complicate things further, both to
392 * do with the EndSysEx code, 0xf7. First, this code is permitted (and
393 * meaningless) outside of a System Exclusive message, anywhere a status byte
394 * could appear. Second, it is allowed to be absent at the end of a System
395 * Exclusive message (!) - any status byte at all (non-realtime) is allowed to
396 * terminate the message. Both require accomodation in the interface to
397 * midi_fst's caller. A stray 0xf7 should be ignored BUT should count as a
398 * message received for purposes of Active Sense timeout; the case is
399 * represented by a return of FST_COM with a length of zero (pos == end). A
400 * status byte other than 0xf7 during a system exclusive message will cause an
401 * FST_SXP (sysex plus) return; the bytes from pos to end are the end of the
402 * system exclusive message, and after handling those the caller should call
403 * midi_fst again with the same input byte.
404 *
405 * midi(4) will never produce either such form of rubbish.
406 */
407 static enum fst_ret
408 midi_fst(struct midi_state *s, u_char c, enum fst_form form)
409 {
410 int syxpos = 0;
411
412 if ( c >= 0xf8 ) { /* All realtime messages bypass state machine */
413 if ( c == 0xf9 || c == 0xfd ) {
414 DPRINTF( ("midi_fst: s=%p c=0x%02x undefined\n",
415 s, c));
416 s->bytesDiscarded.ev_count++;
417 return FST_ERR;
418 }
419 DPRINTFN(9, ("midi_fst: s=%p System Real-Time data=0x%02x\n",
420 s, c));
421 s->msg[2] = c;
422 FST_RETURN(2,3,FST_RT);
423 }
424
425 DPRINTFN(4, ("midi_fst: s=%p data=0x%02x state=%d\n",
426 s, c, s->state));
427
428 switch ( s->state | MIDI_CAT(c) ) { /* break ==> return FST_MORE */
429
430 case MIDI_IN_START | MIDI_CAT_COMMON:
431 case MIDI_IN_RUN1_1 | MIDI_CAT_COMMON:
432 case MIDI_IN_RUN2_2 | MIDI_CAT_COMMON:
433 case MIDI_IN_RXX2_2 | MIDI_CAT_COMMON:
434 s->msg[0] = c;
435 switch ( c ) {
436 case 0xf0: s->state = MIDI_IN_SYX1_3; break;
437 case 0xf1: s->state = MIDI_IN_COM0_1; break;
438 case 0xf2: s->state = MIDI_IN_COM0_2; break;
439 case 0xf3: s->state = MIDI_IN_COM0_1; break;
440 case 0xf6: s->state = MIDI_IN_START; FST_RETURN(0,1,FST_COM);
441 case 0xf7: s->state = MIDI_IN_START; FST_RETURN(0,0,FST_COM);
442 default: goto protocol_violation;
443 }
444 break;
445
446 case MIDI_IN_RUN1_1 | MIDI_CAT_STATUS1:
447 if ( c == s->msg[0] ) {
448 s->state = MIDI_IN_RNX0_1;
449 break;
450 }
451 /* FALLTHROUGH */
452 case MIDI_IN_RUN2_2 | MIDI_CAT_STATUS1:
453 case MIDI_IN_RXX2_2 | MIDI_CAT_STATUS1:
454 case MIDI_IN_START | MIDI_CAT_STATUS1:
455 s->state = MIDI_IN_RUN0_1;
456 s->msg[0] = c;
457 break;
458
459 case MIDI_IN_RUN2_2 | MIDI_CAT_STATUS2:
460 case MIDI_IN_RXX2_2 | MIDI_CAT_STATUS2:
461 if ( c == s->msg[0] ) {
462 s->state = MIDI_IN_RNX0_2;
463 break;
464 }
465 if ( (c ^ s->msg[0]) == 0x10 && (c & 0xe0) == 0x80 ) {
466 s->state = MIDI_IN_RXX0_2;
467 s->msg[0] = c;
468 break;
469 }
470 /* FALLTHROUGH */
471 case MIDI_IN_RUN1_1 | MIDI_CAT_STATUS2:
472 case MIDI_IN_START | MIDI_CAT_STATUS2:
473 s->state = MIDI_IN_RUN0_2;
474 s->msg[0] = c;
475 break;
476
477 case MIDI_IN_COM0_1 | MIDI_CAT_DATA:
478 s->state = MIDI_IN_START;
479 s->msg[1] = c;
480 FST_RETURN(0,2,FST_COM);
481
482 case MIDI_IN_COM0_2 | MIDI_CAT_DATA:
483 s->state = MIDI_IN_COM1_2;
484 s->msg[1] = c;
485 break;
486
487 case MIDI_IN_COM1_2 | MIDI_CAT_DATA:
488 s->state = MIDI_IN_START;
489 s->msg[2] = c;
490 FST_RETURN(0,3,FST_COM);
491
492 case MIDI_IN_RUN0_1 | MIDI_CAT_DATA:
493 s->state = MIDI_IN_RUN1_1;
494 s->msg[1] = c;
495 FST_RETURN(0,2,FST_CHN);
496
497 case MIDI_IN_RUN1_1 | MIDI_CAT_DATA:
498 case MIDI_IN_RNX0_1 | MIDI_CAT_DATA:
499 s->state = MIDI_IN_RUN1_1;
500 s->msg[1] = c;
501 FST_CRETURN(2);
502
503 case MIDI_IN_RUN0_2 | MIDI_CAT_DATA:
504 s->state = MIDI_IN_RUN1_2;
505 s->msg[1] = c;
506 break;
507
508 case MIDI_IN_RUN1_2 | MIDI_CAT_DATA:
509 if ( FST_CANON == form && 0 == c && (s->msg[0]&0xf0) == 0x90 ) {
510 s->state = MIDI_IN_RXX2_2;
511 s->msg[0] ^= 0x10;
512 s->msg[2] = 64;
513 } else {
514 s->state = MIDI_IN_RUN2_2;
515 s->msg[2] = c;
516 }
517 FST_RETURN(0,3,FST_CHN);
518
519 case MIDI_IN_RUN2_2 | MIDI_CAT_DATA:
520 s->state = MIDI_IN_RNX1_2;
521 s->msg[1] = c;
522 break;
523
524 case MIDI_IN_RXX2_2 | MIDI_CAT_DATA:
525 s->state = MIDI_IN_RXX1_2;
526 s->msg[0] ^= 0x10;
527 s->msg[1] = c;
528 break;
529
530 case MIDI_IN_RNX0_2 | MIDI_CAT_DATA:
531 s->state = MIDI_IN_RNY1_2;
532 s->msg[1] = c;
533 break;
534
535 case MIDI_IN_RXX0_2 | MIDI_CAT_DATA:
536 s->state = MIDI_IN_RXY1_2;
537 s->msg[1] = c;
538 break;
539
540 case MIDI_IN_RNX1_2 | MIDI_CAT_DATA:
541 case MIDI_IN_RNY1_2 | MIDI_CAT_DATA:
542 if ( FST_CANON == form && 0 == c && (s->msg[0]&0xf0) == 0x90 ) {
543 s->state = MIDI_IN_RXX2_2;
544 s->msg[0] ^= 0x10;
545 s->msg[2] = 64;
546 FST_RETURN(0,3,FST_CHN);
547 }
548 s->state = MIDI_IN_RUN2_2;
549 s->msg[2] = c;
550 FST_CRETURN(3);
551
552 case MIDI_IN_RXX1_2 | MIDI_CAT_DATA:
553 case MIDI_IN_RXY1_2 | MIDI_CAT_DATA:
554 if ( ( 0 == c && (s->msg[0]&0xf0) == 0x90)
555 || (64 == c && (s->msg[0]&0xf0) == 0x80
556 && FST_CANON != form) ) {
557 s->state = MIDI_IN_RXX2_2;
558 s->msg[0] ^= 0x10;
559 s->msg[2] = 64 - c;
560 FST_CRETURN(3);
561 }
562 s->state = MIDI_IN_RUN2_2;
563 s->msg[2] = c;
564 FST_RETURN(0,3,FST_CHN);
565
566 case MIDI_IN_SYX1_3 | MIDI_CAT_DATA:
567 s->state = MIDI_IN_SYX2_3;
568 s->msg[1] = c;
569 break;
570
571 case MIDI_IN_SYX2_3 | MIDI_CAT_DATA:
572 s->state = MIDI_IN_SYX0_3;
573 s->msg[2] = c;
574 FST_RETURN(0,3,FST_SYX);
575
576 case MIDI_IN_SYX0_3 | MIDI_CAT_DATA:
577 s->state = MIDI_IN_SYX1_3;
578 s->msg[0] = c;
579 break;
580
581 case MIDI_IN_SYX2_3 | MIDI_CAT_COMMON:
582 case MIDI_IN_SYX2_3 | MIDI_CAT_STATUS1:
583 case MIDI_IN_SYX2_3 | MIDI_CAT_STATUS2:
584 ++ syxpos;
585 /* FALLTHROUGH */
586 case MIDI_IN_SYX1_3 | MIDI_CAT_COMMON:
587 case MIDI_IN_SYX1_3 | MIDI_CAT_STATUS1:
588 case MIDI_IN_SYX1_3 | MIDI_CAT_STATUS2:
589 ++ syxpos;
590 /* FALLTHROUGH */
591 case MIDI_IN_SYX0_3 | MIDI_CAT_COMMON:
592 case MIDI_IN_SYX0_3 | MIDI_CAT_STATUS1:
593 case MIDI_IN_SYX0_3 | MIDI_CAT_STATUS2:
594 s->state = MIDI_IN_START;
595 if ( c == 0xf7 ) {
596 s->msg[syxpos] = c;
597 FST_RETURN(0,1+syxpos,FST_SYX);
598 }
599 s->msg[syxpos] = 0xf7;
600 FST_RETURN(0,1+syxpos,FST_SXP);
601
602 default:
603 protocol_violation:
604 DPRINTF(("midi_fst: unexpected %#02x in state %u\n",
605 c, s->state));
606 switch ( s->state ) {
607 case MIDI_IN_RUN1_1: /* can only get here by seeing an */
608 case MIDI_IN_RUN2_2: /* INVALID System Common message */
609 case MIDI_IN_RXX2_2:
610 s->state = MIDI_IN_START;
611 /* FALLTHROUGH */
612 case MIDI_IN_START:
613 s->bytesDiscarded.ev_count++;
614 return FST_ERR;
615 case MIDI_IN_COM1_2:
616 case MIDI_IN_RUN1_2:
617 case MIDI_IN_RNY1_2:
618 case MIDI_IN_RXY1_2:
619 s->bytesDiscarded.ev_count++;
620 /* FALLTHROUGH */
621 case MIDI_IN_COM0_1:
622 case MIDI_IN_RUN0_1:
623 case MIDI_IN_RNX0_1:
624 case MIDI_IN_COM0_2:
625 case MIDI_IN_RUN0_2:
626 case MIDI_IN_RNX0_2:
627 case MIDI_IN_RXX0_2:
628 case MIDI_IN_RNX1_2:
629 case MIDI_IN_RXX1_2:
630 s->bytesDiscarded.ev_count++;
631 s->incompleteMessages.ev_count++;
632 break;
633 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
634 default:
635 printf("midi_fst: mishandled %#02x(%u) in state %u?!\n",
636 c, MIDI_CAT(c), s->state);
637 #endif
638 }
639 s->state = MIDI_IN_START;
640 return FST_HUH;
641 }
642 return FST_MORE;
643 }
644
645 void
646 midi_in(void *addr, int data)
647 {
648 struct midi_softc *sc = addr;
649 struct midi_buffer *mb = &sc->inbuf;
650 int i;
651 int count;
652 enum fst_ret got;
653 int s; /* hw may have various spls so impose our own */
654 MIDI_BUF_DECLARE(idx);
655 MIDI_BUF_DECLARE(buf);
656
657 if (!sc->isopen)
658 return;
659
660 if (!(sc->flags & FREAD))
661 return; /* discard data if not reading */
662
663 sxp_again:
664 do
665 got = midi_fst(&sc->rcv, data, FST_CANON);
666 while ( got == FST_HUH );
667
668 switch ( got ) {
669 case FST_MORE:
670 case FST_ERR:
671 return;
672 case FST_CHN:
673 case FST_COM:
674 case FST_RT:
675 #if NSEQUENCER > 0
676 if (sc->seqopen) {
677 extern void midiseq_in(struct midi_dev *,u_char *,int);
678 count = sc->rcv.end - sc->rcv.pos;
679 midiseq_in(sc->seq_md, sc->rcv.pos, count);
680 return;
681 }
682 #endif
683 /*
684 * Pass Active Sense to the sequencer if it's open, but not to
685 * a raw reader. (Really should do something intelligent with
686 * it then, though....)
687 */
688 if ( got == FST_RT && MIDI_ACK == sc->rcv.pos[0] ) {
689 if ( !sc->rcv_expect_asense ) {
690 sc->rcv_expect_asense = 1;
691 callout_schedule(&sc->rcv_asense_co,
692 MIDI_RCV_ASENSE_PERIOD);
693 }
694 sc->rcv_quiescent = 0;
695 sc->rcv_eof = 0;
696 return;
697 }
698 /* FALLTHROUGH */
699 /*
700 * Ultimately SysEx msgs should be offered to the sequencer also; the
701 * sequencer API addresses them - but maybe our sequencer can't handle
702 * them yet, so offer only to raw reader. (Which means, ultimately,
703 * discard them if the sequencer's open, as it's not doing reads!)
704 * -> When SysEx support is added to the sequencer, be sure to handle
705 * FST_SXP there too.
706 */
707 case FST_SYX:
708 case FST_SXP:
709 count = sc->rcv.end - sc->rcv.pos;
710 MIDI_IN_LOCK(sc,s);
711 sc->rcv_quiescent = 0;
712 sc->rcv_eof = 0;
713 if ( 0 == count ) {
714 MIDI_IN_UNLOCK(sc,s);
715 break;
716 }
717 MIDI_BUF_PRODUCER_INIT(mb,idx);
718 MIDI_BUF_PRODUCER_INIT(mb,buf);
719 if (count > buf_lim - buf_cur
720 || 1 > idx_lim - idx_cur) {
721 sc->rcv.bytesDiscarded.ev_count += count;
722 MIDI_IN_UNLOCK(sc,s);
723 DPRINTF(("midi_in: buffer full, discard data=0x%02x\n",
724 sc->rcv.pos[0]));
725 return;
726 }
727 for (i = 0; i < count; i++) {
728 *buf_cur++ = sc->rcv.pos[i];
729 MIDI_BUF_WRAP(buf);
730 }
731 *idx_cur++ = PACK_MB_IDX(got,count);
732 MIDI_BUF_WRAP(idx);
733 MIDI_BUF_PRODUCER_WBACK(mb,buf);
734 MIDI_BUF_PRODUCER_WBACK(mb,idx);
735 midi_wakeup(&sc->rchan);
736 if (sc->async)
737 psignal(sc->async, SIGIO);
738 MIDI_IN_UNLOCK(sc,s);
739 selnotify(&sc->rsel, 0); /* filter will spin if locked */
740 break;
741 default: /* don't #ifdef this away, gcc will say FST_HUH not handled */
742 printf("midi_in: midi_fst returned %d?!\n", got);
743 }
744 if ( FST_SXP == got )
745 goto sxp_again;
746 }
747
748 void
749 midi_out(void *addr)
750 {
751 struct midi_softc *sc = addr;
752
753 if (!sc->isopen)
754 return;
755 DPRINTFN(8, ("midi_out: %p\n", sc));
756 midi_intr_out(sc);
757 }
758
759 int
760 midiopen(dev_t dev, int flags, int ifmt, struct lwp *l)
761 {
762 struct midi_softc *sc;
763 const struct midi_hw_if *hw;
764 int error;
765
766 sc = device_lookup(&midi_cd, MIDIUNIT(dev));
767 if (sc == NULL)
768 return (ENXIO);
769 if (sc->dying)
770 return (EIO);
771
772 DPRINTFN(3,("midiopen %p\n", sc));
773
774 hw = sc->hw_if;
775 if (!hw)
776 return ENXIO;
777 if (sc->isopen)
778 return EBUSY;
779
780 /* put both state machines into known states */
781 sc->rcv.state = MIDI_IN_START;
782 sc->rcv.pos = sc->rcv.msg;
783 sc->rcv.end = sc->rcv.msg;
784 sc->xmt.state = MIDI_IN_START;
785 sc->xmt.pos = sc->xmt.msg;
786 sc->xmt.end = sc->xmt.msg;
787
788 /* and the buffers */
789 midi_initbuf(&sc->outbuf);
790 midi_initbuf(&sc->inbuf);
791
792 /* and the receive flags */
793 sc->rcv_expect_asense = 0;
794 sc->rcv_quiescent = 0;
795 sc->rcv_eof = 0;
796
797 error = hw->open(sc->hw_hdl, flags, midi_in, midi_out, sc);
798 if (error)
799 return error;
800 sc->isopen++;
801 sc->flags = flags;
802 sc->rchan = 0;
803 sc->wchan = 0;
804 sc->pbus = 0;
805 sc->async = 0;
806
807 #ifdef MIDI_SAVE
808 if (midicnt != 0) {
809 midisave.cnt = midicnt;
810 midicnt = 0;
811 }
812 #endif
813
814 return 0;
815 }
816
817 int
818 midiclose(dev_t dev, int flags, int ifmt, struct lwp *l)
819 {
820 int unit = MIDIUNIT(dev);
821 struct midi_softc *sc = midi_cd.cd_devs[unit];
822 const struct midi_hw_if *hw = sc->hw_if;
823 int s, error;
824
825 DPRINTFN(3,("midiclose %p\n", sc));
826
827 /* midi_start_output(sc); anything buffered => pbus already set! */
828 error = 0;
829 MIDI_OUT_LOCK(sc,s);
830 while (sc->pbus) {
831 DPRINTFN(8,("midiclose sleep ...\n"));
832 error =
833 midi_sleep_timo(&sc->wchan, "mid_dr", 30*hz, &sc->out_lock);
834 }
835 sc->isopen = 0;
836 MIDI_OUT_UNLOCK(sc,s);
837 callout_stop(&sc->xmt_asense_co); /* xxx fix this - sleep? */
838 callout_stop(&sc->rcv_asense_co);
839 hw->close(sc->hw_hdl);
840 #if NSEQUENCER > 0
841 sc->seqopen = 0;
842 sc->seq_md = 0;
843 #endif
844 return 0;
845 }
846
847 int
848 midiread(dev_t dev, struct uio *uio, int ioflag)
849 {
850 int unit = MIDIUNIT(dev);
851 struct midi_softc *sc = midi_cd.cd_devs[unit];
852 struct midi_buffer *mb = &sc->inbuf;
853 int error;
854 int s;
855 MIDI_BUF_DECLARE(idx);
856 MIDI_BUF_DECLARE(buf);
857 int appetite;
858 int first = 1;
859
860 DPRINTFN(6,("midiread: %p, count=%lu\n", sc,
861 (unsigned long)uio->uio_resid));
862
863 if (sc->dying)
864 return EIO;
865 if ( !(sc->props & MIDI_PROP_CAN_INPUT) )
866 return ENXIO;
867
868 MIDI_IN_LOCK(sc,s);
869 MIDI_BUF_CONSUMER_INIT(mb,idx);
870 MIDI_BUF_CONSUMER_INIT(mb,buf);
871 MIDI_IN_UNLOCK(sc,s);
872
873 error = 0;
874 for ( ;; ) {
875 /*
876 * If the used portion of idx wraps around the end, just take
877 * the first part on this iteration, and we'll get the rest on
878 * the next.
879 */
880 if ( idx_lim > idx_end )
881 idx_lim = idx_end;
882 /*
883 * Count bytes through the last complete message that will
884 * fit in the requested read.
885 */
886 for (appetite = uio->uio_resid; idx_cur < idx_lim; ++idx_cur) {
887 if ( appetite < MB_IDX_LEN(*idx_cur) )
888 break;
889 appetite -= MB_IDX_LEN(*idx_cur);
890 }
891 appetite = uio->uio_resid - appetite;
892 /*
893 * Only if the read is too small to hold even the first
894 * complete message will we return a partial one (updating idx
895 * to reflect the remaining length of the message).
896 */
897 if ( appetite == 0 && idx_cur < idx_lim ) {
898 if ( !first )
899 goto unlocked_exit; /* idx_cur not advanced */
900 appetite = uio->uio_resid;
901 *idx_cur = PACK_MB_IDX(MB_IDX_CAT(*idx_cur),
902 MB_IDX_LEN(*idx_cur) - appetite);
903 }
904 KASSERT(buf_cur + appetite <= buf_lim);
905
906 /* move the bytes */
907 if ( appetite > 0 ) {
908 first = 0; /* we know we won't return empty-handed */
909 /* do two uiomoves if data wrap around end of buf */
910 if ( buf_cur + appetite > buf_end ) {
911 DPRINTFN(8,
912 ("midiread: uiomove cc=%d (prewrap)\n",
913 buf_end - buf_cur));
914 error = uiomove(buf_cur, buf_end-buf_cur, uio);
915 if ( error )
916 goto unlocked_exit;
917 appetite -= buf_end - buf_cur;
918 buf_cur = mb->buf;
919 }
920 DPRINTFN(8, ("midiread: uiomove cc=%d\n", appetite));
921 error = uiomove(buf_cur, appetite, uio);
922 if ( error )
923 goto unlocked_exit;
924 buf_cur += appetite;
925 }
926
927 MIDI_BUF_WRAP(idx);
928 MIDI_BUF_WRAP(buf);
929
930 MIDI_IN_LOCK(sc,s);
931 MIDI_BUF_CONSUMER_WBACK(mb,idx);
932 MIDI_BUF_CONSUMER_WBACK(mb,buf);
933 if ( 0 == uio->uio_resid ) /* if read satisfied, we're done */
934 break;
935 MIDI_BUF_CONSUMER_REFRESH(mb,idx);
936 if ( idx_cur == idx_lim ) { /* need to wait for data? */
937 if ( !first || sc->rcv_eof ) /* never block reader if */
938 break; /* any data already in hand */
939 if (ioflag & IO_NDELAY) {
940 error = EWOULDBLOCK;
941 break;
942 }
943 error = midi_sleep(&sc->rchan, "mid rd", &sc->in_lock);
944 if ( error )
945 break;
946 MIDI_BUF_CONSUMER_REFRESH(mb,idx); /* what'd we get? */
947 }
948 MIDI_BUF_CONSUMER_REFRESH(mb,buf);
949 MIDI_IN_UNLOCK(sc,s);
950 if ( sc->dying )
951 return EIO;
952 }
953 MIDI_IN_UNLOCK(sc,s);
954
955 unlocked_exit:
956 return error;
957 }
958
959 void
960 midi_rcv_asense(void *arg)
961 {
962 struct midi_softc *sc = arg;
963 int s;
964
965 if ( sc->dying || !sc->isopen )
966 return;
967
968 if ( sc->rcv_quiescent ) {
969 MIDI_IN_LOCK(sc,s);
970 sc->rcv_eof = 1;
971 sc->rcv_quiescent = 0;
972 sc->rcv_expect_asense = 0;
973 midi_wakeup(&sc->rchan);
974 if (sc->async)
975 psignal(sc->async, SIGIO);
976 MIDI_IN_UNLOCK(sc,s);
977 selnotify(&sc->rsel, 0); /* filter will spin if locked */
978 return;
979 }
980
981 sc->rcv_quiescent = 1;
982 callout_schedule(&sc->rcv_asense_co, MIDI_RCV_ASENSE_PERIOD);
983 }
984
985 void
986 midi_xmt_asense(void *arg)
987 {
988 struct midi_softc *sc = arg;
989 int s;
990 int error;
991 int armed;
992
993 if ( sc->dying || !sc->isopen )
994 return;
995
996 MIDI_OUT_LOCK(sc,s);
997 if ( sc->pbus || sc->dying || !sc->isopen ) {
998 MIDI_OUT_UNLOCK(sc,s);
999 return;
1000 }
1001 sc->pbus = 1;
1002 DPRINTFN(8,("midi_xmt_asense: %p\n", sc));
1003
1004 if ( sc->props & MIDI_PROP_OUT_INTR ) {
1005 error = sc->hw_if->output(sc->hw_hdl, MIDI_ACK);
1006 armed = (error == 0);
1007 } else { /* polled output, do with interrupts unmasked */
1008 MIDI_OUT_UNLOCK(sc,s);
1009 /* running from softclock, so top half won't sneak in here */
1010 error = sc->hw_if->output(sc->hw_hdl, MIDI_ACK);
1011 MIDI_OUT_LOCK(sc,s);
1012 armed = 0;
1013 }
1014
1015 if ( !armed ) {
1016 sc->pbus = 0;
1017 callout_schedule(&sc->xmt_asense_co, MIDI_XMT_ASENSE_PERIOD);
1018 }
1019
1020 MIDI_OUT_UNLOCK(sc,s);
1021 }
1022
1023 /*
1024 * The way this function was hacked up to plug into poll_out and intr_out
1025 * after they were written won't win it any beauty contests, but it'll work
1026 * (code in haste, refactor at leisure). This may be called with the lock
1027 * (by intr_out) or without the lock (by poll_out) so it only does what could
1028 * be safe either way.
1029 */
1030 int midi_msg_out(struct midi_softc *sc,
1031 u_char **idx, u_char **idxl, u_char **buf, u_char **bufl) {
1032 MIDI_BUF_DECLARE(idx);
1033 MIDI_BUF_DECLARE(buf);
1034 MIDI_BUF_EXTENT_INIT(&sc->outbuf,idx);
1035 MIDI_BUF_EXTENT_INIT(&sc->outbuf,buf);
1036 int length;
1037 int error;
1038 u_char contig[3];
1039 u_char *cp;
1040 u_char *ep;
1041
1042 idx_cur = *idx;
1043 idx_lim = *idxl;
1044 buf_cur = *buf;
1045 buf_lim = *bufl;
1046
1047 length = MB_IDX_LEN(*idx_cur);
1048
1049 for ( cp = contig, ep = cp + length; cp < ep; ) {
1050 *cp++ = *buf_cur++;
1051 MIDI_BUF_WRAP(buf);
1052 }
1053 cp = contig;
1054
1055 switch ( MB_IDX_CAT(*idx_cur) ) {
1056 case FST_CHV: /* chnmsg to be compressed (for device that wants it) */
1057 ++ cp;
1058 -- length;
1059 /* FALLTHROUGH */
1060 case FST_CHN:
1061 error = sc->hw_if_ext->channel(sc->hw_hdl,
1062 MIDI_GET_STATUS(contig[0]),
1063 MIDI_GET_CHAN(contig[0]),
1064 cp, length);
1065 break;
1066 case FST_COM:
1067 error = sc->hw_if_ext->common(sc->hw_hdl,
1068 MIDI_GET_STATUS(contig[0]),
1069 cp, length);
1070 break;
1071 case FST_SYX:
1072 case FST_SXP:
1073 error = sc->hw_if_ext->sysex(sc->hw_hdl,
1074 cp, length);
1075 break;
1076 case FST_RT:
1077 error = sc->hw_if->output(sc->hw_hdl, *cp);
1078 break;
1079 default:
1080 error = EIO;
1081 }
1082
1083 if ( !error ) {
1084 ++ idx_cur;
1085 MIDI_BUF_WRAP(idx);
1086 *idx = idx_cur;
1087 *idxl = idx_lim;
1088 *buf = buf_cur;
1089 *bufl = buf_lim;
1090 }
1091
1092 return error;
1093 }
1094
1095 /*
1096 * midi_poll_out is intended for the midi hw (the vast majority of MIDI UARTs
1097 * on sound cards, apparently) that _do not have transmit-ready interrupts_.
1098 * Every call to hw_if->output for one of these may busy-wait to output the
1099 * byte; at the standard midi data rate that'll be 320us per byte. The
1100 * technique of writing only MIDI_MAX_WRITE bytes in a row and then waiting
1101 * for MIDI_WAIT does not reduce the total time spent busy-waiting, and it
1102 * adds arbitrary delays in transmission (and, since MIDI_WAIT is roughly the
1103 * same as the time to send MIDI_MAX_WRITE bytes, it effectively halves the
1104 * data rate). Here, a somewhat bolder approach is taken. Since midi traffic
1105 * is bursty but time-sensitive--most of the time there will be none at all,
1106 * but when there is it should go out ASAP--the strategy is to just get it
1107 * over with, and empty the buffer in one go. The effect this can have on
1108 * the rest of the system will be limited by the size of the buffer and the
1109 * sparseness of the traffic. But some precautions are in order. Interrupts
1110 * should all be unmasked when this is called, and midiwrite should not fill
1111 * the buffer more than once (when MIDI_PROP_CAN_INTR is false) without a
1112 * yield() so some other process can get scheduled. If the write is nonblocking,
1113 * midiwrite should return a short count rather than yield.
1114 *
1115 * Someday when there is fine-grained MP support, this should be reworked to
1116 * run in a callout so the writing process really could proceed concurrently.
1117 * But obviously where performance is a concern, interrupt-driven hardware
1118 * such as USB midi or (apparently) clcs will always be preferable. And it
1119 * seems (kern/32651) that many of the devices currently working in poll mode
1120 * may really have tx interrupt capability and want only implementation; that
1121 * ought to happen.
1122 */
1123 int
1124 midi_poll_out(struct midi_softc *sc)
1125 {
1126 struct midi_buffer *mb = &sc->outbuf;
1127 int error;
1128 int msglen;
1129 int s;
1130 MIDI_BUF_DECLARE(idx);
1131 MIDI_BUF_DECLARE(buf);
1132
1133 error = 0;
1134
1135 MIDI_OUT_LOCK(sc,s);
1136 MIDI_BUF_CONSUMER_INIT(mb,idx);
1137 MIDI_BUF_CONSUMER_INIT(mb,buf);
1138 MIDI_OUT_UNLOCK(sc,s);
1139
1140 for ( ;; ) {
1141 while ( idx_cur != idx_lim ) {
1142 if ( sc->hw_if_ext ) {
1143 error = midi_msg_out(sc, &idx_cur, &idx_lim,
1144 &buf_cur, &buf_lim);
1145 if ( error )
1146 goto ioerror;
1147 continue;
1148 }
1149 /* or, lacking hw_if_ext ... */
1150 msglen = MB_IDX_LEN(*idx_cur);
1151 DPRINTFN(7,("midi_poll_out: %p <- %#02x\n",
1152 sc->hw_hdl, *buf_cur));
1153 error = sc->hw_if->output(sc->hw_hdl, *buf_cur);
1154 if ( error )
1155 goto ioerror;
1156 ++ buf_cur;
1157 MIDI_BUF_WRAP(buf);
1158 -- msglen;
1159 if ( msglen )
1160 *idx_cur = PACK_MB_IDX(MB_IDX_CAT(*idx_cur),
1161 msglen);
1162 else {
1163 ++ idx_cur;
1164 MIDI_BUF_WRAP(idx);
1165 }
1166 }
1167 KASSERT(buf_cur == buf_lim);
1168 MIDI_OUT_LOCK(sc,s);
1169 MIDI_BUF_CONSUMER_WBACK(mb,idx);
1170 MIDI_BUF_CONSUMER_WBACK(mb,buf);
1171 MIDI_BUF_CONSUMER_REFRESH(mb,idx); /* any more to transmit? */
1172 MIDI_BUF_CONSUMER_REFRESH(mb,buf);
1173 if ( idx_lim == idx_cur )
1174 break; /* still holding lock */
1175 MIDI_OUT_UNLOCK(sc,s);
1176 }
1177 goto disarm; /* lock held */
1178
1179 ioerror:
1180 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
1181 printf("%s: midi_poll_output error %d\n",
1182 sc->dev.dv_xname, error);
1183 #endif
1184 MIDI_OUT_LOCK(sc,s);
1185 MIDI_BUF_CONSUMER_WBACK(mb,idx);
1186 MIDI_BUF_CONSUMER_WBACK(mb,buf);
1187
1188 disarm:
1189 sc->pbus = 0;
1190 callout_schedule(&sc->xmt_asense_co, MIDI_XMT_ASENSE_PERIOD);
1191 MIDI_OUT_UNLOCK(sc,s);
1192 return error;
1193 }
1194
1195 /*
1196 * The interrupt flavor acquires spl and lock once and releases at the end,
1197 * as it expects to write only one byte or message. The interface convention
1198 * is that if hw_if->output returns 0, it has initiated transmission and the
1199 * completion interrupt WILL be forthcoming; if it has not returned 0, NO
1200 * interrupt will be forthcoming, and if it returns EINPROGRESS it wants
1201 * another byte right away.
1202 */
1203 int
1204 midi_intr_out(struct midi_softc *sc)
1205 {
1206 struct midi_buffer *mb = &sc->outbuf;
1207 int error;
1208 int msglen;
1209 int s;
1210 MIDI_BUF_DECLARE(idx);
1211 MIDI_BUF_DECLARE(buf);
1212 int armed = 0;
1213
1214 error = 0;
1215
1216 MIDI_OUT_LOCK(sc,s);
1217 MIDI_BUF_CONSUMER_INIT(mb,idx);
1218 MIDI_BUF_CONSUMER_INIT(mb,buf);
1219
1220 while ( idx_cur != idx_lim ) {
1221 if ( sc->hw_if_ext ) {
1222 error = midi_msg_out(sc, &idx_cur, &idx_lim,
1223 &buf_cur, &buf_lim);
1224 if ( !error ) /* no EINPROGRESS from extended hw_if */
1225 armed = 1;
1226 break;
1227 }
1228 /* or, lacking hw_if_ext ... */
1229 msglen = MB_IDX_LEN(*idx_cur);
1230 error = sc->hw_if->output(sc->hw_hdl, *buf_cur);
1231 if ( error && error != EINPROGRESS )
1232 break;
1233 ++ buf_cur;
1234 MIDI_BUF_WRAP(buf);
1235 -- msglen;
1236 if ( msglen )
1237 *idx_cur = PACK_MB_IDX(MB_IDX_CAT(*idx_cur),msglen);
1238 else {
1239 ++ idx_cur;
1240 MIDI_BUF_WRAP(idx);
1241 }
1242 if ( !error ) {
1243 armed = 1;
1244 break;
1245 }
1246 }
1247 MIDI_BUF_CONSUMER_WBACK(mb,idx);
1248 MIDI_BUF_CONSUMER_WBACK(mb,buf);
1249 if ( !armed ) {
1250 sc->pbus = 0;
1251 callout_schedule(&sc->xmt_asense_co, MIDI_XMT_ASENSE_PERIOD);
1252 }
1253 midi_wakeup(&sc->wchan);
1254 if ( sc->async )
1255 psignal(sc->async, SIGIO);
1256 MIDI_OUT_UNLOCK(sc,s);
1257 selnotify(&sc->wsel, 0); /* filter will spin if locked */
1258
1259 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
1260 if ( error )
1261 printf("%s: midi_intr_output error %d\n",
1262 sc->dev.dv_xname, error);
1263 #endif
1264 return error;
1265 }
1266
1267 int
1268 midi_start_output(struct midi_softc *sc)
1269 {
1270 if (sc->dying)
1271 return EIO;
1272
1273 if ( sc->props & MIDI_PROP_OUT_INTR )
1274 return midi_intr_out(sc);
1275 return midi_poll_out(sc);
1276 }
1277
1278 static int
1279 real_writebytes(struct midi_softc *sc, u_char *ibuf, int cc)
1280 {
1281 u_char *iend = ibuf + cc;
1282 struct midi_buffer *mb = &sc->outbuf;
1283 int arming = 0;
1284 int count;
1285 int s;
1286 int got;
1287 enum fst_form form;
1288 MIDI_BUF_DECLARE(idx);
1289 MIDI_BUF_DECLARE(buf);
1290
1291 /*
1292 * If the hardware uses the extended hw_if, pass it canonicalized
1293 * messages (or compressed ones if it specifically requests, using
1294 * VCOMP form so the bottom half can still pass the op and chan along);
1295 * if it does not, send it compressed messages (using COMPR form as
1296 * there is no need to preserve the status for the bottom half).
1297 */
1298 if ( NULL == sc->hw_if_ext )
1299 form = FST_COMPR;
1300 else if ( sc->hw_if_ext->compress )
1301 form = FST_VCOMP;
1302 else
1303 form = FST_CANON;
1304
1305 MIDI_OUT_LOCK(sc,s);
1306 MIDI_BUF_PRODUCER_INIT(mb,idx);
1307 MIDI_BUF_PRODUCER_INIT(mb,buf);
1308 MIDI_OUT_UNLOCK(sc,s);
1309
1310 if (sc->dying)
1311 return EIO;
1312
1313 while ( ibuf < iend ) {
1314 do {
1315 got = midi_fst(&sc->xmt, *ibuf, form);
1316 } while ( got == FST_HUH );
1317 ++ ibuf;
1318 switch ( got ) {
1319 case FST_MORE:
1320 continue;
1321 case FST_ERR:
1322 #if defined(EPROTO) /* most appropriate SUSv3 errno, but not in errno.h yet */
1323 return EPROTO;
1324 #else
1325 return EIO;
1326 #endif
1327 case FST_CHN:
1328 case FST_CHV: /* only occurs in VCOMP form */
1329 case FST_COM:
1330 case FST_RT:
1331 case FST_SYX:
1332 case FST_SXP:
1333 break; /* go add to buffer */
1334 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
1335 default:
1336 printf("midi_wr: midi_fst returned %d?!\n", got);
1337 #endif
1338 }
1339 count = sc->xmt.end - sc->xmt.pos;
1340 if ( 0 == count ) /* can happen with stray 0xf7; see midi_fst */
1341 continue;
1342 /*
1343 * return EWOULDBLOCK if the data passed will not fit in
1344 * the buffer; the caller should have taken steps to avoid that.
1345 * If got==FST_SXP we lose the new status byte, but we're losing
1346 * anyway, so c'est la vie.
1347 */
1348 if ( idx_cur == idx_lim || count > buf_lim - buf_cur ) {
1349 MIDI_OUT_LOCK(sc,s);
1350 MIDI_BUF_PRODUCER_REFRESH(mb,idx); /* get the most */
1351 MIDI_BUF_PRODUCER_REFRESH(mb,buf); /* current facts */
1352 MIDI_OUT_UNLOCK(sc,s);
1353 if ( idx_cur == idx_lim || count > buf_lim - buf_cur )
1354 return EWOULDBLOCK; /* caller's problem */
1355 }
1356 *idx_cur++ = PACK_MB_IDX(got,count);
1357 MIDI_BUF_WRAP(idx);
1358 while ( count ) {
1359 *buf_cur++ = *(sc->xmt.pos)++;
1360 MIDI_BUF_WRAP(buf);
1361 -- count;
1362 }
1363 if ( FST_SXP == got )
1364 -- ibuf; /* again with same status byte */
1365 }
1366 MIDI_OUT_LOCK(sc,s);
1367 MIDI_BUF_PRODUCER_WBACK(mb,buf);
1368 MIDI_BUF_PRODUCER_WBACK(mb,idx);
1369 /*
1370 * If the output transfer is not already busy, and there is a message
1371 * buffered, mark it busy, stop the Active Sense callout (what if we're
1372 * too late and it's expired already? No big deal, an extra Active Sense
1373 * never hurt anybody) and start the output transfer once we're out of
1374 * the critical section (pbus==1 will stop anyone else doing the same).
1375 */
1376 MIDI_BUF_CONSUMER_INIT(mb,idx); /* check what consumer's got to read */
1377 if ( !sc->pbus && idx_cur < idx_lim ) {
1378 sc->pbus = 1;
1379 callout_stop(&sc->xmt_asense_co);
1380 arming = 1;
1381 }
1382 MIDI_OUT_UNLOCK(sc,s);
1383 return arming ? midi_start_output(sc) : 0;
1384 }
1385
1386 int
1387 midiwrite(dev_t dev, struct uio *uio, int ioflag)
1388 {
1389 int unit = MIDIUNIT(dev);
1390 struct midi_softc *sc = midi_cd.cd_devs[unit];
1391 struct midi_buffer *mb = &sc->outbuf;
1392 int error;
1393 u_char inp[256];
1394 int s;
1395 MIDI_BUF_DECLARE(idx);
1396 MIDI_BUF_DECLARE(buf);
1397 size_t idxspace;
1398 size_t bufspace;
1399 size_t xfrcount;
1400 int pollout = 0;
1401
1402 DPRINTFN(6, ("midiwrite: %p, unit=%d, count=%lu\n", sc, unit,
1403 (unsigned long)uio->uio_resid));
1404
1405 if (sc->dying)
1406 return EIO;
1407
1408 error = 0;
1409 while (uio->uio_resid > 0 && !error) {
1410
1411 /*
1412 * block if necessary for the minimum buffer space to guarantee
1413 * we can write something.
1414 */
1415 MIDI_OUT_LOCK(sc,s);
1416 MIDI_BUF_PRODUCER_INIT(mb,idx); /* init can't go above loop; */
1417 MIDI_BUF_PRODUCER_INIT(mb,buf); /* real_writebytes moves cur */
1418 for ( ;; ) {
1419 idxspace = MIDI_BUF_PRODUCER_REFRESH(mb,idx) - idx_cur;
1420 bufspace = MIDI_BUF_PRODUCER_REFRESH(mb,buf) - buf_cur;
1421 if ( idxspace >= 1 && bufspace >= 3 && !pollout )
1422 break;
1423 DPRINTFN(8,("midi_write: sleep idx=%d buf=%d\n",
1424 idxspace, bufspace));
1425 if (ioflag & IO_NDELAY) {
1426 error = EWOULDBLOCK;
1427 /*
1428 * If some amount has already been transferred,
1429 * the common syscall code will automagically
1430 * convert this to success with a short count.
1431 */
1432 goto locked_exit;
1433 }
1434 if ( pollout ) {
1435 preempt(0); /* see midi_poll_output */
1436 pollout = 0;
1437 } else
1438 error = midi_sleep(&sc->wchan, "mid wr",
1439 &sc->out_lock);
1440 if (error)
1441 /*
1442 * Similarly, the common code will handle
1443 * EINTR and ERESTART properly here, changing to
1444 * a short count if something transferred.
1445 */
1446 goto locked_exit;
1447 }
1448 MIDI_OUT_UNLOCK(sc,s);
1449
1450 /*
1451 * The number of bytes we can safely extract from the uio
1452 * depends on the available idx and buf space. Worst case,
1453 * every byte is a message so 1 idx is required per byte.
1454 * Worst case, the first byte completes a 3-byte msg in prior
1455 * state, and every subsequent byte is a Program Change or
1456 * Channel Pressure msg with running status and expands to 2
1457 * bytes, so the buf space reqd is 3+2(n-1) or 2n+1. So limit
1458 * the transfer to the min of idxspace and (bufspace-1)>>1.
1459 */
1460 xfrcount = (bufspace - 1) >> 1;
1461 if ( xfrcount > idxspace )
1462 xfrcount = idxspace;
1463 if ( xfrcount > sizeof inp )
1464 xfrcount = sizeof inp;
1465 if ( xfrcount > uio->uio_resid )
1466 xfrcount = uio->uio_resid;
1467
1468 error = uiomove(inp, xfrcount, uio);
1469 #ifdef MIDI_DEBUG
1470 if (error)
1471 printf("midi_write:(1) uiomove failed %d; "
1472 "xfrcount=%d inp=%p\n",
1473 error, xfrcount, inp);
1474 #endif
1475 if ( error )
1476 break;
1477
1478 /*
1479 * The number of bytes we extracted being calculated to
1480 * definitely fit in the buffer even with canonicalization,
1481 * there is no excuse for real_writebytes to return EWOULDBLOCK.
1482 */
1483 error = real_writebytes(sc, inp, xfrcount);
1484 KASSERT(error != EWOULDBLOCK);
1485
1486 if ( error )
1487 break;
1488 /*
1489 * If this is a polling device and we just sent a buffer, let's
1490 * not send another without giving some other process a chance.
1491 */
1492 if ( ! (sc->props & MIDI_PROP_OUT_INTR) )
1493 pollout = 1;
1494 DPRINTFN(8,("midiwrite: uio_resid now %u, props=%d\n",
1495 uio->uio_resid, sc->props));
1496 }
1497 return error;
1498
1499 locked_exit:
1500 MIDI_OUT_UNLOCK(sc,s);
1501 return error;
1502 }
1503
1504 /*
1505 * This write routine is only called from sequencer code and expects
1506 * a write that is smaller than the MIDI buffer.
1507 */
1508 int
1509 midi_writebytes(int unit, u_char *bf, int cc)
1510 {
1511 struct midi_softc *sc = midi_cd.cd_devs[unit];
1512
1513 DPRINTFN(7, ("midi_writebytes: %p, unit=%d, cc=%d %#02x %#02x %#02x\n",
1514 sc, unit, cc, bf[0], bf[1], bf[2]));
1515 return real_writebytes(sc, bf, cc);
1516 }
1517
1518 int
1519 midiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct lwp *l)
1520 {
1521 int unit = MIDIUNIT(dev);
1522 struct midi_softc *sc = midi_cd.cd_devs[unit];
1523 const struct midi_hw_if *hw = sc->hw_if;
1524 int error;
1525 int s;
1526 MIDI_BUF_DECLARE(buf);
1527
1528 DPRINTFN(5,("midiioctl: %p cmd=0x%08lx\n", sc, cmd));
1529
1530 if (sc->dying)
1531 return EIO;
1532
1533 error = 0;
1534 switch (cmd) {
1535 case FIONBIO:
1536 /* All handled in the upper FS layer. */
1537 break;
1538
1539 case FIONREAD:
1540 /*
1541 * This code relies on the current implementation of midi_in
1542 * always updating buf and idx together in a critical section,
1543 * so buf always ends at a message boundary. Document this
1544 * ioctl as always returning a value such that the last message
1545 * included is complete (SysEx the only exception), and then
1546 * make sure the implementation doesn't regress. NB that
1547 * means if this ioctl returns n and the proc then issues a
1548 * read of n, n bytes will be read, but if the proc issues a
1549 * read of m < n, fewer than m bytes may be read to ensure the
1550 * read ends at a message boundary.
1551 */
1552 MIDI_IN_LOCK(sc,s);
1553 MIDI_BUF_CONSUMER_INIT(&sc->inbuf,buf);
1554 MIDI_IN_UNLOCK(sc,s);
1555 *(int *)addr = buf_lim - buf_cur;
1556 break;
1557
1558 case FIOASYNC:
1559 if (*(int *)addr) {
1560 if (sc->async)
1561 return EBUSY;
1562 sc->async = l->l_proc;
1563 DPRINTFN(5,("midi_ioctl: FIOASYNC %p\n", l->l_proc));
1564 } else
1565 sc->async = 0;
1566 break;
1567
1568 #if 0
1569 case MIDI_PRETIME:
1570 /* XXX OSS
1571 * This should set up a read timeout, but that's
1572 * why we have poll(), so there's nothing yet. */
1573 error = EINVAL;
1574 break;
1575 #endif
1576
1577 #ifdef MIDI_SAVE
1578 case MIDI_GETSAVE:
1579 error = copyout(&midisave, *(void **)addr, sizeof midisave);
1580 break;
1581 #endif
1582
1583 default:
1584 if (hw->ioctl)
1585 error = hw->ioctl(sc->hw_hdl, cmd, addr, flag, l);
1586 else
1587 error = EINVAL;
1588 break;
1589 }
1590 return error;
1591 }
1592
1593 int
1594 midipoll(dev_t dev, int events, struct lwp *l)
1595 {
1596 int unit = MIDIUNIT(dev);
1597 struct midi_softc *sc = midi_cd.cd_devs[unit];
1598 int revents = 0;
1599 int s;
1600 MIDI_BUF_DECLARE(idx);
1601 MIDI_BUF_DECLARE(buf);
1602
1603 DPRINTFN(6,("midipoll: %p events=0x%x\n", sc, events));
1604
1605 if (sc->dying)
1606 return POLLHUP;
1607
1608 s = splaudio();
1609
1610 if ((sc->flags&FREAD) && (events & (POLLIN | POLLRDNORM))) {
1611 simple_lock(&sc->in_lock);
1612 MIDI_BUF_CONSUMER_INIT(&sc->inbuf,idx);
1613 if (idx_cur < idx_lim)
1614 revents |= events & (POLLIN | POLLRDNORM);
1615 else
1616 selrecord(l, &sc->rsel);
1617 simple_unlock(&sc->in_lock);
1618 }
1619
1620 if ((sc->flags&FWRITE) && (events & (POLLOUT | POLLWRNORM))) {
1621 simple_lock(&sc->out_lock);
1622 MIDI_BUF_PRODUCER_INIT(&sc->outbuf,idx);
1623 MIDI_BUF_PRODUCER_INIT(&sc->outbuf,buf);
1624 if ( idx_lim - idx_cur >= 1 && buf_lim - buf_cur >= 3 )
1625 revents |= events & (POLLOUT | POLLWRNORM);
1626 else
1627 selrecord(l, &sc->wsel);
1628 simple_unlock(&sc->out_lock);
1629 }
1630
1631 splx(s);
1632 return revents;
1633 }
1634
1635 static void
1636 filt_midirdetach(struct knote *kn)
1637 {
1638 struct midi_softc *sc = kn->kn_hook;
1639 int s;
1640
1641 s = splaudio();
1642 SLIST_REMOVE(&sc->rsel.sel_klist, kn, knote, kn_selnext);
1643 splx(s);
1644 }
1645
1646 static int
1647 filt_midiread(struct knote *kn, long hint)
1648 {
1649 struct midi_softc *sc = kn->kn_hook;
1650 int s;
1651 MIDI_BUF_DECLARE(buf);
1652
1653 /* XXXLUKEM (thorpej): please make sure this is correct. */
1654
1655 MIDI_IN_LOCK(sc,s);
1656 MIDI_BUF_CONSUMER_INIT(&sc->inbuf,buf);
1657 kn->kn_data = buf_lim - buf_cur;
1658 MIDI_IN_UNLOCK(sc,s);
1659 return (kn->kn_data > 0);
1660 }
1661
1662 static const struct filterops midiread_filtops =
1663 { 1, NULL, filt_midirdetach, filt_midiread };
1664
1665 static void
1666 filt_midiwdetach(struct knote *kn)
1667 {
1668 struct midi_softc *sc = kn->kn_hook;
1669 int s;
1670
1671 s = splaudio();
1672 SLIST_REMOVE(&sc->wsel.sel_klist, kn, knote, kn_selnext);
1673 splx(s);
1674 }
1675
1676 static int
1677 filt_midiwrite(struct knote *kn, long hint)
1678 {
1679 struct midi_softc *sc = kn->kn_hook;
1680 int s;
1681 MIDI_BUF_DECLARE(idx);
1682 MIDI_BUF_DECLARE(buf);
1683
1684 /* XXXLUKEM (thorpej): please make sure this is correct. */
1685
1686 MIDI_OUT_LOCK(sc,s);
1687 MIDI_BUF_PRODUCER_INIT(&sc->outbuf,idx);
1688 MIDI_BUF_PRODUCER_INIT(&sc->outbuf,buf);
1689 kn->kn_data = ((buf_lim - buf_cur)-1)>>1;
1690 if ( kn->kn_data > idx_lim - idx_cur )
1691 kn->kn_data = idx_lim - idx_cur;
1692 MIDI_OUT_UNLOCK(sc,s);
1693 return (kn->kn_data > 0);
1694 }
1695
1696 static const struct filterops midiwrite_filtops =
1697 { 1, NULL, filt_midiwdetach, filt_midiwrite };
1698
1699 int
1700 midikqfilter(dev_t dev, struct knote *kn)
1701 {
1702 int unit = MIDIUNIT(dev);
1703 struct midi_softc *sc = midi_cd.cd_devs[unit];
1704 struct klist *klist;
1705 int s;
1706
1707 switch (kn->kn_filter) {
1708 case EVFILT_READ:
1709 klist = &sc->rsel.sel_klist;
1710 kn->kn_fop = &midiread_filtops;
1711 break;
1712
1713 case EVFILT_WRITE:
1714 klist = &sc->wsel.sel_klist;
1715 kn->kn_fop = &midiwrite_filtops;
1716 break;
1717
1718 default:
1719 return (1);
1720 }
1721
1722 kn->kn_hook = sc;
1723
1724 s = splaudio();
1725 SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1726 splx(s);
1727
1728 return (0);
1729 }
1730
1731 void
1732 midi_getinfo(dev_t dev, struct midi_info *mi)
1733 {
1734 struct midi_softc *sc;
1735
1736 sc = device_lookup(&midi_cd, MIDIUNIT(dev));
1737 if (sc == NULL)
1738 return;
1739 if (sc->dying)
1740 return;
1741
1742 sc->hw_if->getinfo(sc->hw_hdl, mi);
1743 }
1744
1745 #endif /* NMIDI > 0 */
1746
1747 #if NMIDI > 0 || NMIDIBUS > 0
1748
1749 int audioprint(void *, const char *);
1750
1751 struct device *
1752 midi_attach_mi(const struct midi_hw_if *mhwp, void *hdlp, struct device *dev)
1753 {
1754 struct audio_attach_args arg;
1755
1756 #ifdef DIAGNOSTIC
1757 if (mhwp == NULL) {
1758 aprint_error("midi_attach_mi: NULL\n");
1759 return (0);
1760 }
1761 #endif
1762 arg.type = AUDIODEV_TYPE_MIDI;
1763 arg.hwif = mhwp;
1764 arg.hdl = hdlp;
1765 return (config_found(dev, &arg, audioprint));
1766 }
1767
1768 #endif /* NMIDI > 0 || NMIDIBUS > 0 */
1769