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