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