midi.c revision 1.21.6.2 1 /* $NetBSD: midi.c,v 1.21.6.2 2001/09/26 15:28:10 fvdl 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(vdev_rdev(devvp)));
405 if (sc == NULL)
406 return (ENXIO);
407 if (sc->dying)
408 return (EIO);
409
410 vdev_setprivdata(devvp, 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;
450 struct midi_hw_if *hw;
451 int s, error;
452
453 sc = vdev_privdata(devvp);
454
455 DPRINTF(("midiclose %p\n", sc));
456
457 midi_start_output(sc, 0);
458 s = splaudio();
459 while (sc->outbuf.used > 0 && !error) {
460 DPRINTFN(2,("midiclose sleep used=%d\n", sc->outbuf.used));
461 error = midi_sleep_timo(&sc->wchan, "mid_dr", 30*hz);
462 }
463 splx(s);
464 sc->isopen = 0;
465
466 hw = sc->hw_if;
467 hw->close(sc->hw_hdl);
468 #if NSEQUENCER > 0
469 sc->seqopen = 0;
470 sc->seq_md = 0;
471 #endif
472 return 0;
473 }
474
475 int
476 midiread(devvp, uio, ioflag)
477 struct vnode *devvp;
478 struct uio *uio;
479 int ioflag;
480 {
481 struct midi_softc *sc;
482 struct midi_buffer *mb;
483 int error;
484 u_char *outp;
485 int used, cc, n, resid;
486 int s;
487
488 sc = vdev_privdata(devvp);
489
490 DPRINTF(("midiread: %p, count=%lu\n", sc,
491 (unsigned long)uio->uio_resid));
492
493 if (sc->dying)
494 return EIO;
495
496 error = 0;
497 resid = uio->uio_resid;
498 mb = &sc->inbuf;
499 while (uio->uio_resid == resid && !error) {
500 s = splaudio();
501 while (mb->used <= 0) {
502 if (ioflag & IO_NDELAY) {
503 splx(s);
504 return EWOULDBLOCK;
505 }
506 error = midi_sleep(&sc->rchan, "mid rd");
507 if (error) {
508 splx(s);
509 return error;
510 }
511 }
512 used = mb->used;
513 outp = mb->outp;
514 splx(s);
515 if (sc->dying)
516 return EIO;
517 cc = used; /* maximum to read */
518 n = mb->end - outp;
519 if (n < cc)
520 cc = n; /* don't read beyond end of buffer */
521 if (uio->uio_resid < cc)
522 cc = uio->uio_resid; /* and no more than we want */
523 DPRINTFN(3, ("midiread: uiomove cc=%d\n", cc));
524 error = uiomove(outp, cc, uio);
525 if (error)
526 break;
527 used -= cc;
528 outp += cc;
529 if (outp >= mb->end)
530 outp = mb->start;
531 s = splaudio();
532 mb->outp = outp;
533 mb->used = used;
534 splx(s);
535 }
536 return error;
537 }
538
539 void
540 midi_timeout(arg)
541 void *arg;
542 {
543 struct midi_softc *sc = arg;
544
545 DPRINTFN(3,("midi_timeout: %p\n", sc));
546 midi_start_output(sc, 1);
547 }
548
549 int
550 midi_start_output(sc, intr)
551 struct midi_softc *sc;
552 int intr;
553 {
554 struct midi_buffer *mb = &sc->outbuf;
555 u_char out;
556 int error;
557 int s;
558 int i;
559
560 error = 0;
561
562 if (sc->dying)
563 return EIO;
564
565 if (sc->pbus && !intr) {
566 DPRINTFN(4, ("midi_start_output: busy\n"));
567 return 0;
568 }
569 sc->pbus = (mb->used > 0)?1:0;
570 for (i = 0; i < MIDI_MAX_WRITE && mb->used > 0 &&
571 (!error || error==EINPROGRESS); i++) {
572 s = splaudio();
573 out = *mb->outp;
574 mb->outp++;
575 if (mb->outp >= mb->end)
576 mb->outp = mb->start;
577 mb->used--;
578 splx(s);
579 #ifdef MIDI_SAVE
580 midisave.buf[midicnt] = out;
581 midicnt = (midicnt + 1) % MIDI_SAVE_SIZE;
582 #endif
583 DPRINTFN(4, ("midi_start_output: %p i=%d, data=0x%02x\n",
584 sc, i, out));
585 error = sc->hw_if->output(sc->hw_hdl, out);
586 if ((sc->props & MIDI_PROP_OUT_INTR) && error!=EINPROGRESS)
587 /* If ointr is enabled, midi_start_output()
588 * normally writes only one byte,
589 * except hw_if->output() returns EINPROGRESS.
590 */
591 break;
592 }
593 midi_wakeup(&sc->wchan);
594 selwakeup(&sc->wsel);
595 if (sc->async)
596 psignal(sc->async, SIGIO);
597 if (!(sc->props & MIDI_PROP_OUT_INTR) || error==EINPROGRESS) {
598 if (mb->used > 0)
599 callout_reset(&sc->sc_callout, midi_wait,
600 midi_timeout, sc);
601 else
602 sc->pbus = 0;
603 }
604 if ((sc->props & MIDI_PROP_OUT_INTR) && error==EINPROGRESS)
605 error = 0;
606
607 return error;
608 }
609
610 int
611 midiwrite(devvp, uio, ioflag)
612 struct vnode *devvp;
613 struct uio *uio;
614 int ioflag;
615 {
616 struct midi_softc *sc;
617 struct midi_buffer *mb;
618 int error;
619 u_char *inp;
620 int used, cc, n;
621 int s;
622
623 sc = vdev_privdata(devvp);
624
625 DPRINTFN(2, ("midiwrite: %p, unit=%d, count=%lu\n", sc, unit,
626 (unsigned long)uio->uio_resid));
627
628 if (sc->dying)
629 return EIO;
630
631 error = 0;
632 mb = &sc->outbuf;
633 while (uio->uio_resid > 0 && !error) {
634 s = splaudio();
635 if (mb->used >= mb->usedhigh) {
636 DPRINTFN(3,("midi_write: sleep used=%d hiwat=%d\n",
637 mb->used, mb->usedhigh));
638 if (ioflag & IO_NDELAY) {
639 splx(s);
640 return EWOULDBLOCK;
641 }
642 error = midi_sleep(&sc->wchan, "mid wr");
643 if (error) {
644 splx(s);
645 return error;
646 }
647 }
648 used = mb->used;
649 inp = mb->inp;
650 splx(s);
651 if (sc->dying)
652 return EIO;
653 cc = mb->usedhigh - used; /* maximum to write */
654 n = mb->end - inp;
655 if (n < cc)
656 cc = n; /* don't write beyond end of buffer */
657 if (uio->uio_resid < cc)
658 cc = uio->uio_resid; /* and no more than we have */
659 error = uiomove(inp, cc, uio);
660 #ifdef MIDI_DEBUG
661 if (error)
662 printf("midi_write:(1) uiomove failed %d; "
663 "cc=%d inp=%p\n",
664 error, cc, inp);
665 #endif
666 if (error)
667 break;
668 inp = mb->inp + cc;
669 if (inp >= mb->end)
670 inp = mb->start;
671 s = splaudio();
672 mb->inp = inp;
673 mb->used += cc;
674 splx(s);
675 error = midi_start_output(sc, 0);
676 }
677 return error;
678 }
679
680 /*
681 * This write routine is only called from sequencer code and expects
682 * a write that is smaller than the MIDI buffer.
683 */
684 int
685 midi_writebytes(unit, buf, cc)
686 int unit;
687 u_char *buf;
688 int cc;
689 {
690 struct midi_softc *sc = midi_cd.cd_devs[unit];
691 struct midi_buffer *mb = &sc->outbuf;
692 int n, s;
693
694 DPRINTFN(2, ("midi_writebytes: %p, unit=%d, cc=%d\n", sc, unit, cc));
695 DPRINTFN(3, ("midi_writebytes: %x %x %x\n",buf[0],buf[1],buf[2]));
696
697 if (sc->dying)
698 return EIO;
699
700 s = splaudio();
701 if (mb->used + cc >= mb->usedhigh) {
702 splx(s);
703 return (EWOULDBLOCK);
704 }
705 n = mb->end - mb->inp;
706 if (cc < n)
707 n = cc;
708 mb->used += cc;
709 memcpy(mb->inp, buf, n);
710 mb->inp += n;
711 if (mb->inp >= mb->end) {
712 mb->inp = mb->start;
713 cc -= n;
714 if (cc > 0) {
715 memcpy(mb->inp, buf + n, cc);
716 mb->inp += cc;
717 }
718 }
719 splx(s);
720 return (midi_start_output(sc, 0));
721 }
722
723 int
724 midiioctl(devvp, cmd, addr, flag, p)
725 struct vnode *devvp;
726 u_long cmd;
727 caddr_t addr;
728 int flag;
729 struct proc *p;
730 {
731 struct midi_softc *sc;
732 struct midi_hw_if *hw;
733 int error;
734
735 sc = vdev_privdata(devvp);
736
737 DPRINTF(("midiioctl: %p cmd=0x%08lx\n", sc, cmd));
738
739 if (sc->dying)
740 return EIO;
741
742 error = 0;
743 switch (cmd) {
744 case FIONBIO:
745 /* All handled in the upper FS layer. */
746 break;
747
748 case FIOASYNC:
749 if (*(int *)addr) {
750 if (sc->async)
751 return EBUSY;
752 sc->async = p;
753 DPRINTF(("midi_ioctl: FIOASYNC %p\n", p));
754 } else
755 sc->async = 0;
756 break;
757
758 #if 0
759 case MIDI_PRETIME:
760 /* XXX OSS
761 * This should set up a read timeout, but that's
762 * why we have poll(), so there's nothing yet. */
763 error = EINVAL;
764 break;
765 #endif
766
767 #ifdef MIDI_SAVE
768 case MIDI_GETSAVE:
769 error = copyout(&midisave, *(void **)addr, sizeof midisave);
770 break;
771 #endif
772
773 default:
774 hw = sc->hw_if;
775 if (hw->ioctl)
776 error = hw->ioctl(sc->hw_hdl, cmd, addr, flag, p);
777 else
778 error = EINVAL;
779 break;
780 }
781 return error;
782 }
783
784 int
785 midipoll(devvp, events, p)
786 struct vnode *devvp;
787 int events;
788 struct proc *p;
789 {
790 struct midi_softc *sc;
791 int revents;
792 int s;
793
794 sc = vdev_privdata(devvp);
795
796 revents = 0;
797 s = splaudio();
798
799 DPRINTF(("midipoll: %p events=0x%x\n", sc, events));
800
801 if (sc->dying)
802 return EIO;
803
804 if (events & (POLLIN | POLLRDNORM))
805 if (sc->inbuf.used > 0)
806 revents |= events & (POLLIN | POLLRDNORM);
807
808 if (events & (POLLOUT | POLLWRNORM))
809 if (sc->outbuf.used < sc->outbuf.usedhigh)
810 revents |= events & (POLLOUT | POLLWRNORM);
811
812 if (revents == 0) {
813 if (events & (POLLIN | POLLRDNORM))
814 selrecord(p, &sc->rsel);
815
816 if (events & (POLLOUT | POLLWRNORM))
817 selrecord(p, &sc->wsel);
818 }
819
820 splx(s);
821 return revents;
822 }
823
824 void
825 midi_getinfo(dev, mi)
826 dev_t dev;
827 struct midi_info *mi;
828 {
829 struct midi_softc *sc;
830
831 sc = device_lookup(&midi_cd, MIDIUNIT(dev));
832 if (sc == NULL)
833 return;
834 if (sc->dying)
835 return;
836
837 sc->hw_if->getinfo(sc->hw_hdl, mi);
838 }
839
840 #endif /* NMIDI > 0 */
841
842 #if NMIDI > 0 || NMIDIBUS > 0
843
844 int audioprint __P((void *, const char *));
845
846 struct device *
847 midi_attach_mi(mhwp, hdlp, dev)
848 struct midi_hw_if *mhwp;
849 void *hdlp;
850 struct device *dev;
851 {
852 struct audio_attach_args arg;
853
854 #ifdef DIAGNOSTIC
855 if (mhwp == NULL) {
856 printf("midi_attach_mi: NULL\n");
857 return (0);
858 }
859 #endif
860 arg.type = AUDIODEV_TYPE_MIDI;
861 arg.hwif = mhwp;
862 arg.hdl = hdlp;
863 return (config_found(dev, &arg, audioprint));
864 }
865
866 #endif /* NMIDI > 0 || NMIDIBUS > 0 */
867