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@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