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