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