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