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