midi.c revision 1.21.6.1 1 /* $NetBSD: midi.c,v 1.21.6.1 2001/09/07 04:45:23 thorpej 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).
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include "midi.h"
40 #include "sequencer.h"
41
42 #include <sys/param.h>
43 #include <sys/ioctl.h>
44 #include <sys/fcntl.h>
45 #include <sys/vnode.h>
46 #include <sys/select.h>
47 #include <sys/poll.h>
48 #include <sys/malloc.h>
49 #include <sys/proc.h>
50 #include <sys/systm.h>
51 #include <sys/callout.h>
52 #include <sys/syslog.h>
53 #include <sys/kernel.h>
54 #include <sys/signalvar.h>
55 #include <sys/conf.h>
56 #include <sys/audioio.h>
57 #include <sys/midiio.h>
58 #include <sys/device.h>
59 #include <sys/vnode.h>
60
61 #include <miscfs/specfs/specdev.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 #else
74 #define DPRINTF(x)
75 #define DPRINTFN(n,x)
76 #endif
77
78 int midi_wait;
79
80 void midi_in __P((void *, int));
81 void midi_out __P((void *));
82 int midi_start_output __P((struct midi_softc *, int));
83 int midi_sleep_timo __P((int *, char *, int));
84 int midi_sleep __P((int *, char *));
85 void midi_wakeup __P((int *));
86 void midi_initbuf __P((struct midi_buffer *));
87 void midi_timeout __P((void *));
88
89 int midiprobe __P((struct device *, struct cfdata *, void *));
90 void midiattach __P((struct device *, struct device *, void *));
91 int mididetach __P((struct device *, int));
92 int midiactivate __P((struct device *, enum devact));
93
94 struct cfattach midi_ca = {
95 sizeof(struct midi_softc), midiprobe, midiattach,
96 mididetach, midiactivate
97 };
98
99 #ifdef MIDI_SAVE
100 #define MIDI_SAVE_SIZE 100000
101 int midicnt;
102 struct {
103 int cnt;
104 u_char buf[MIDI_SAVE_SIZE];
105 } midisave;
106 #define MIDI_GETSAVE _IOWR('m', 100, int)
107
108 #endif
109
110 extern struct cfdriver midi_cd;
111
112 int
113 midiprobe(parent, match, aux)
114 struct device *parent;
115 struct cfdata *match;
116 void *aux;
117 {
118 struct audio_attach_args *sa = aux;
119
120 DPRINTFN(6,("midiprobe: type=%d sa=%p hw=%p\n",
121 sa->type, sa, sa->hwif));
122 return (sa->type == AUDIODEV_TYPE_MIDI);
123 }
124
125 void
126 midiattach(parent, self, aux)
127 struct device *parent, *self;
128 void *aux;
129 {
130 struct midi_softc *sc = (void *)self;
131 struct audio_attach_args *sa = aux;
132 struct midi_hw_if *hwp = sa->hwif;
133 void *hdlp = sa->hdl;
134
135 DPRINTFN(6, ("MIDI attach\n"));
136
137 #ifdef DIAGNOSTIC
138 if (hwp == 0 ||
139 hwp->open == 0 ||
140 hwp->close == 0 ||
141 hwp->output == 0 ||
142 hwp->getinfo == 0) {
143 printf("midi: missing method\n");
144 return;
145 }
146 #endif
147
148 callout_init(&sc->sc_callout);
149
150 sc->hw_if = hwp;
151 sc->hw_hdl = hdlp;
152 sc->dying = 0;
153 midi_attach(sc, parent);
154 }
155
156 int
157 midiactivate(self, act)
158 struct device *self;
159 enum devact act;
160 {
161 struct midi_softc *sc = (struct midi_softc *)self;
162
163 switch (act) {
164 case DVACT_ACTIVATE:
165 return (EOPNOTSUPP);
166 break;
167
168 case DVACT_DEACTIVATE:
169 sc->dying = 1;
170 break;
171 }
172 return (0);
173 }
174
175 int
176 mididetach(self, flags)
177 struct device *self;
178 int flags;
179 {
180 struct midi_softc *sc = (struct midi_softc *)self;
181 int maj, mn;
182
183 DPRINTF(("midi_detach: sc=%p flags=%d\n", sc, flags));
184
185 sc->dying = 1;
186
187 wakeup(&sc->wchan);
188 wakeup(&sc->rchan);
189
190 /* locate the major number */
191 for (maj = 0; maj < nchrdev; maj++)
192 if (cdevsw[maj].d_open == midiopen)
193 break;
194
195 /* Nuke the vnodes for any open instances (calls close). */
196 mn = self->dv_unit;
197 vdevgone(maj, mn, mn, VCHR);
198
199 return (0);
200 }
201
202 void
203 midi_attach(sc, parent)
204 struct midi_softc *sc;
205 struct device *parent;
206 {
207 struct midi_info mi;
208
209 sc->isopen = 0;
210
211 midi_wait = MIDI_WAIT * hz / 1000000;
212 if (midi_wait == 0)
213 midi_wait = 1;
214
215 sc->sc_dev = parent;
216 sc->hw_if->getinfo(sc->hw_hdl, &mi);
217 sc->props = mi.props;
218 printf(": %s\n", mi.name);
219 }
220
221 int
222 midi_unit_count()
223 {
224 return midi_cd.cd_ndevs;
225 }
226
227 void
228 midi_initbuf(mb)
229 struct midi_buffer *mb;
230 {
231 mb->used = 0;
232 mb->usedhigh = MIDI_BUFSIZE;
233 mb->end = mb->start + mb->usedhigh;
234 mb->inp = mb->outp = mb->start;
235 }
236
237 int
238 midi_sleep_timo(chan, label, timo)
239 int *chan;
240 char *label;
241 int timo;
242 {
243 int st;
244
245 if (!label)
246 label = "midi";
247
248 DPRINTFN(5, ("midi_sleep_timo: %p %s %d\n", chan, label, timo));
249 *chan = 1;
250 st = tsleep(chan, PWAIT | PCATCH, label, timo);
251 *chan = 0;
252 #ifdef MIDI_DEBUG
253 if (st != 0)
254 printf("midi_sleep: %d\n", st);
255 #endif
256 return st;
257 }
258
259 int
260 midi_sleep(chan, label)
261 int *chan;
262 char *label;
263 {
264 return midi_sleep_timo(chan, label, 0);
265 }
266
267 void
268 midi_wakeup(chan)
269 int *chan;
270 {
271 if (*chan) {
272 DPRINTFN(5, ("midi_wakeup: %p\n", chan));
273 wakeup(chan);
274 *chan = 0;
275 }
276 }
277
278 static int midi_lengths[] = { 2,2,2,2,1,1,2,0 };
279 /* Number of bytes in a MIDI command */
280 #define MIDI_LENGTH(d) (midi_lengths[((d) >> 4) & 7])
281
282 void
283 midi_in(addr, data)
284 void *addr;
285 int data;
286 {
287 struct midi_softc *sc = addr;
288 struct midi_buffer *mb = &sc->inbuf;
289 int i;
290
291 if (!sc->isopen)
292 return;
293 if (data == MIDI_ACK)
294 return;
295
296 DPRINTFN(3, ("midi_in: sc=%p data=0x%02x state=%d pos=%d\n",
297 sc, data, sc->in_state, sc->in_pos));
298
299 if (!(sc->flags & FREAD))
300 return; /* discard data if not reading */
301
302 switch(sc->in_state) {
303 case MIDI_IN_START:
304 if (MIDI_IS_STATUS(data)) {
305 switch(data) {
306 case 0xf0: /* Sysex */
307 sc->in_state = MIDI_IN_SYSEX;
308 break;
309 case 0xf1: /* MTC quarter frame */
310 case 0xf3: /* Song select */
311 sc->in_state = MIDI_IN_DATA;
312 sc->in_msg[0] = data;
313 sc->in_pos = 1;
314 sc->in_left = 1;
315 break;
316 case 0xf2: /* Song position pointer */
317 sc->in_state = MIDI_IN_DATA;
318 sc->in_msg[0] = data;
319 sc->in_pos = 1;
320 sc->in_left = 2;
321 break;
322 default:
323 if (MIDI_IS_COMMON(data)) {
324 sc->in_msg[0] = data;
325 sc->in_pos = 1;
326 goto deliver;
327 } else {
328 sc->in_state = MIDI_IN_DATA;
329 sc->in_msg[0] = sc->in_status = data;
330 sc->in_pos = 1;
331 sc->in_left = MIDI_LENGTH(data);
332 }
333 break;
334 }
335 } else {
336 if (MIDI_IS_STATUS(sc->in_status)) {
337 sc->in_state = MIDI_IN_DATA;
338 sc->in_msg[0] = sc->in_status;
339 sc->in_msg[1] = data;
340 sc->in_pos = 2;
341 sc->in_left = MIDI_LENGTH(sc->in_status) - 1;
342 }
343 }
344 return;
345 case MIDI_IN_DATA:
346 sc->in_msg[sc->in_pos++] = data;
347 if (--sc->in_left <= 0)
348 break; /* deliver data */
349 return;
350 case MIDI_IN_SYSEX:
351 if (data == MIDI_SYSEX_END)
352 sc->in_state = MIDI_IN_START;
353 return;
354 }
355 deliver:
356 sc->in_state = MIDI_IN_START;
357 #if NSEQUENCER > 0
358 if (sc->seqopen) {
359 extern void midiseq_in __P((struct midi_dev *,u_char *,int));
360 midiseq_in(sc->seq_md, sc->in_msg, sc->in_pos);
361 return;
362 }
363 #endif
364
365 if (mb->used + sc->in_pos > mb->usedhigh) {
366 DPRINTF(("midi_in: buffer full, discard data=0x%02x\n",
367 sc->in_msg[0]));
368 return;
369 }
370 for (i = 0; i < sc->in_pos; i++) {
371 *mb->inp++ = sc->in_msg[i];
372 if (mb->inp >= mb->end)
373 mb->inp = mb->start;
374 mb->used++;
375 }
376 midi_wakeup(&sc->rchan);
377 selwakeup(&sc->rsel);
378 if (sc->async)
379 psignal(sc->async, SIGIO);
380 }
381
382 void
383 midi_out(addr)
384 void *addr;
385 {
386 struct midi_softc *sc = addr;
387
388 if (!sc->isopen)
389 return;
390 DPRINTFN(3, ("midi_out: %p\n", sc));
391 midi_start_output(sc, 1);
392 }
393
394 int
395 midiopen(devvp, flags, ifmt, p)
396 struct vnode *devvp;
397 int flags, ifmt;
398 struct proc *p;
399 {
400 struct midi_softc *sc;
401 struct midi_hw_if *hw;
402 int error;
403
404 sc = device_lookup(&midi_cd, MIDIUNIT(devvp->v_rdev));
405 if (sc == NULL)
406 return (ENXIO);
407 if (sc->dying)
408 return (EIO);
409
410 devvp->v_devcookie = sc;
411
412 DPRINTF(("midiopen %p\n", sc));
413
414 hw = sc->hw_if;
415 if (!hw)
416 return ENXIO;
417 if (sc->isopen)
418 return EBUSY;
419 sc->in_state = MIDI_IN_START;
420 sc->in_status = 0;
421 error = hw->open(sc->hw_hdl, flags, midi_in, midi_out, sc);
422 if (error)
423 return error;
424 sc->isopen++;
425 midi_initbuf(&sc->outbuf);
426 midi_initbuf(&sc->inbuf);
427 sc->flags = flags;
428 sc->rchan = 0;
429 sc->wchan = 0;
430 sc->pbus = 0;
431 sc->async = 0;
432
433 #ifdef MIDI_SAVE
434 if (midicnt != 0) {
435 midisave.cnt = midicnt;
436 midicnt = 0;
437 }
438 #endif
439
440 return 0;
441 }
442
443 int
444 midiclose(devvp, flags, ifmt, p)
445 struct vnode *devvp;
446 int flags, ifmt;
447 struct proc *p;
448 {
449 struct midi_softc *sc = devvp->v_devcookie;
450 struct midi_hw_if *hw = sc->hw_if;
451 int s, error;
452
453 DPRINTF(("midiclose %p\n", sc));
454
455 midi_start_output(sc, 0);
456 error = 0;
457 s = splaudio();
458 while (sc->outbuf.used > 0 && !error) {
459 DPRINTFN(2,("midiclose sleep used=%d\n", sc->outbuf.used));
460 error = midi_sleep_timo(&sc->wchan, "mid_dr", 30*hz);
461 }
462 splx(s);
463 sc->isopen = 0;
464 hw->close(sc->hw_hdl);
465 #if NSEQUENCER > 0
466 sc->seqopen = 0;
467 sc->seq_md = 0;
468 #endif
469 return 0;
470 }
471
472 int
473 midiread(devvp, uio, ioflag)
474 struct vnode *devvp;
475 struct uio *uio;
476 int ioflag;
477 {
478 struct midi_softc *sc = devvp->v_devcookie;
479 struct midi_buffer *mb = &sc->inbuf;
480 int error;
481 u_char *outp;
482 int used, cc, n, resid;
483 int s;
484
485 DPRINTF(("midiread: %p, count=%lu\n", sc,
486 (unsigned long)uio->uio_resid));
487
488 if (sc->dying)
489 return EIO;
490
491 error = 0;
492 resid = uio->uio_resid;
493 while (uio->uio_resid == resid && !error) {
494 s = splaudio();
495 while (mb->used <= 0) {
496 if (ioflag & IO_NDELAY) {
497 splx(s);
498 return EWOULDBLOCK;
499 }
500 error = midi_sleep(&sc->rchan, "mid rd");
501 if (error) {
502 splx(s);
503 return error;
504 }
505 }
506 used = mb->used;
507 outp = mb->outp;
508 splx(s);
509 if (sc->dying)
510 return EIO;
511 cc = used; /* maximum to read */
512 n = mb->end - outp;
513 if (n < cc)
514 cc = n; /* don't read beyond end of buffer */
515 if (uio->uio_resid < cc)
516 cc = uio->uio_resid; /* and no more than we want */
517 DPRINTFN(3, ("midiread: uiomove cc=%d\n", cc));
518 error = uiomove(outp, cc, uio);
519 if (error)
520 break;
521 used -= cc;
522 outp += cc;
523 if (outp >= mb->end)
524 outp = mb->start;
525 s = splaudio();
526 mb->outp = outp;
527 mb->used = used;
528 splx(s);
529 }
530 return error;
531 }
532
533 void
534 midi_timeout(arg)
535 void *arg;
536 {
537 struct midi_softc *sc = arg;
538
539 DPRINTFN(3,("midi_timeout: %p\n", sc));
540 midi_start_output(sc, 1);
541 }
542
543 int
544 midi_start_output(sc, intr)
545 struct midi_softc *sc;
546 int intr;
547 {
548 struct midi_buffer *mb = &sc->outbuf;
549 u_char out;
550 int error;
551 int s;
552 int i;
553
554 error = 0;
555
556 if (sc->dying)
557 return EIO;
558
559 if (sc->pbus && !intr) {
560 DPRINTFN(4, ("midi_start_output: busy\n"));
561 return 0;
562 }
563 sc->pbus = (mb->used > 0)?1:0;
564 for (i = 0; i < MIDI_MAX_WRITE && mb->used > 0 &&
565 (!error || error==EINPROGRESS); i++) {
566 s = splaudio();
567 out = *mb->outp;
568 mb->outp++;
569 if (mb->outp >= mb->end)
570 mb->outp = mb->start;
571 mb->used--;
572 splx(s);
573 #ifdef MIDI_SAVE
574 midisave.buf[midicnt] = out;
575 midicnt = (midicnt + 1) % MIDI_SAVE_SIZE;
576 #endif
577 DPRINTFN(4, ("midi_start_output: %p i=%d, data=0x%02x\n",
578 sc, i, out));
579 error = sc->hw_if->output(sc->hw_hdl, out);
580 if ((sc->props & MIDI_PROP_OUT_INTR) && error!=EINPROGRESS)
581 /* If ointr is enabled, midi_start_output()
582 * normally writes only one byte,
583 * except hw_if->output() returns EINPROGRESS.
584 */
585 break;
586 }
587 midi_wakeup(&sc->wchan);
588 selwakeup(&sc->wsel);
589 if (sc->async)
590 psignal(sc->async, SIGIO);
591 if (!(sc->props & MIDI_PROP_OUT_INTR) || error==EINPROGRESS) {
592 if (mb->used > 0)
593 callout_reset(&sc->sc_callout, midi_wait,
594 midi_timeout, sc);
595 else
596 sc->pbus = 0;
597 }
598 if ((sc->props & MIDI_PROP_OUT_INTR) && error==EINPROGRESS)
599 error = 0;
600
601 return error;
602 }
603
604 int
605 midiwrite(devvp, uio, ioflag)
606 struct vnode *devvp;
607 struct uio *uio;
608 int ioflag;
609 {
610 struct midi_softc *sc = devvp->v_devcookie;
611 struct midi_buffer *mb = &sc->outbuf;
612 int error;
613 u_char *inp;
614 int used, cc, n;
615 int s;
616
617 DPRINTFN(2, ("midiwrite: %p, unit=%d, count=%lu\n", sc, unit,
618 (unsigned long)uio->uio_resid));
619
620 if (sc->dying)
621 return EIO;
622
623 error = 0;
624 while (uio->uio_resid > 0 && !error) {
625 s = splaudio();
626 if (mb->used >= mb->usedhigh) {
627 DPRINTFN(3,("midi_write: sleep used=%d hiwat=%d\n",
628 mb->used, mb->usedhigh));
629 if (ioflag & IO_NDELAY) {
630 splx(s);
631 return EWOULDBLOCK;
632 }
633 error = midi_sleep(&sc->wchan, "mid wr");
634 if (error) {
635 splx(s);
636 return error;
637 }
638 }
639 used = mb->used;
640 inp = mb->inp;
641 splx(s);
642 if (sc->dying)
643 return EIO;
644 cc = mb->usedhigh - used; /* maximum to write */
645 n = mb->end - inp;
646 if (n < cc)
647 cc = n; /* don't write beyond end of buffer */
648 if (uio->uio_resid < cc)
649 cc = uio->uio_resid; /* and no more than we have */
650 error = uiomove(inp, cc, uio);
651 #ifdef MIDI_DEBUG
652 if (error)
653 printf("midi_write:(1) uiomove failed %d; "
654 "cc=%d inp=%p\n",
655 error, cc, inp);
656 #endif
657 if (error)
658 break;
659 inp = mb->inp + cc;
660 if (inp >= mb->end)
661 inp = mb->start;
662 s = splaudio();
663 mb->inp = inp;
664 mb->used += cc;
665 splx(s);
666 error = midi_start_output(sc, 0);
667 }
668 return error;
669 }
670
671 /*
672 * This write routine is only called from sequencer code and expects
673 * a write that is smaller than the MIDI buffer.
674 */
675 int
676 midi_writebytes(unit, buf, cc)
677 int unit;
678 u_char *buf;
679 int cc;
680 {
681 struct midi_softc *sc = midi_cd.cd_devs[unit];
682 struct midi_buffer *mb = &sc->outbuf;
683 int n, s;
684
685 DPRINTFN(2, ("midi_writebytes: %p, unit=%d, cc=%d\n", sc, unit, cc));
686 DPRINTFN(3, ("midi_writebytes: %x %x %x\n",buf[0],buf[1],buf[2]));
687
688 if (sc->dying)
689 return EIO;
690
691 s = splaudio();
692 if (mb->used + cc >= mb->usedhigh) {
693 splx(s);
694 return (EWOULDBLOCK);
695 }
696 n = mb->end - mb->inp;
697 if (cc < n)
698 n = cc;
699 mb->used += cc;
700 memcpy(mb->inp, buf, n);
701 mb->inp += n;
702 if (mb->inp >= mb->end) {
703 mb->inp = mb->start;
704 cc -= n;
705 if (cc > 0) {
706 memcpy(mb->inp, buf + n, cc);
707 mb->inp += cc;
708 }
709 }
710 splx(s);
711 return (midi_start_output(sc, 0));
712 }
713
714 int
715 midiioctl(devvp, cmd, addr, flag, p)
716 struct vnode *devvp;
717 u_long cmd;
718 caddr_t addr;
719 int flag;
720 struct proc *p;
721 {
722 struct midi_softc *sc = devvp->v_devcookie;
723 struct midi_hw_if *hw = sc->hw_if;
724 int error;
725
726 DPRINTF(("midiioctl: %p cmd=0x%08lx\n", sc, cmd));
727
728 if (sc->dying)
729 return EIO;
730
731 error = 0;
732 switch (cmd) {
733 case FIONBIO:
734 /* All handled in the upper FS layer. */
735 break;
736
737 case FIOASYNC:
738 if (*(int *)addr) {
739 if (sc->async)
740 return EBUSY;
741 sc->async = p;
742 DPRINTF(("midi_ioctl: FIOASYNC %p\n", p));
743 } else
744 sc->async = 0;
745 break;
746
747 #if 0
748 case MIDI_PRETIME:
749 /* XXX OSS
750 * This should set up a read timeout, but that's
751 * why we have poll(), so there's nothing yet. */
752 error = EINVAL;
753 break;
754 #endif
755
756 #ifdef MIDI_SAVE
757 case MIDI_GETSAVE:
758 error = copyout(&midisave, *(void **)addr, sizeof midisave);
759 break;
760 #endif
761
762 default:
763 if (hw->ioctl)
764 error = hw->ioctl(sc->hw_hdl, cmd, addr, flag, p);
765 else
766 error = EINVAL;
767 break;
768 }
769 return error;
770 }
771
772 int
773 midipoll(devvp, events, p)
774 struct vnode *devvp;
775 int events;
776 struct proc *p;
777 {
778 struct midi_softc *sc = devvp->v_devcookie;
779 int revents = 0;
780 int s = splaudio();
781
782 DPRINTF(("midipoll: %p events=0x%x\n", sc, events));
783
784 if (sc->dying)
785 return EIO;
786
787 if (events & (POLLIN | POLLRDNORM))
788 if (sc->inbuf.used > 0)
789 revents |= events & (POLLIN | POLLRDNORM);
790
791 if (events & (POLLOUT | POLLWRNORM))
792 if (sc->outbuf.used < sc->outbuf.usedhigh)
793 revents |= events & (POLLOUT | POLLWRNORM);
794
795 if (revents == 0) {
796 if (events & (POLLIN | POLLRDNORM))
797 selrecord(p, &sc->rsel);
798
799 if (events & (POLLOUT | POLLWRNORM))
800 selrecord(p, &sc->wsel);
801 }
802
803 splx(s);
804 return revents;
805 }
806
807 void
808 midi_getinfo(dev, mi)
809 dev_t dev;
810 struct midi_info *mi;
811 {
812 struct midi_softc *sc;
813
814 sc = device_lookup(&midi_cd, MIDIUNIT(dev));
815 if (sc == NULL)
816 return;
817 if (sc->dying)
818 return;
819
820 sc->hw_if->getinfo(sc->hw_hdl, mi);
821 }
822
823 #endif /* NMIDI > 0 */
824
825 #if NMIDI > 0 || NMIDIBUS > 0
826
827 int audioprint __P((void *, const char *));
828
829 struct device *
830 midi_attach_mi(mhwp, hdlp, dev)
831 struct midi_hw_if *mhwp;
832 void *hdlp;
833 struct device *dev;
834 {
835 struct audio_attach_args arg;
836
837 #ifdef DIAGNOSTIC
838 if (mhwp == NULL) {
839 printf("midi_attach_mi: NULL\n");
840 return (0);
841 }
842 #endif
843 arg.type = AUDIODEV_TYPE_MIDI;
844 arg.hwif = mhwp;
845 arg.hdl = hdlp;
846 return (config_found(dev, &arg, audioprint));
847 }
848
849 #endif /* NMIDI > 0 || NMIDIBUS > 0 */
850