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