1 /* $NetBSD: midi.c,v 1.38 2004/10/29 12:57:16 yamt 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.38 2004/10/29 12:57:16 yamt 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 const 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 sc->in_msg[0] = data; 297 sc->in_pos = 1; 298 sc->in_left = 0; 299 goto deliver_raw; 300 case 0xf1: /* MTC quarter frame */ 301 case 0xf3: /* Song select */ 302 sc->in_state = MIDI_IN_DATA; 303 sc->in_msg[0] = data; 304 sc->in_pos = 1; 305 sc->in_left = 1; 306 break; 307 case 0xf2: /* Song position pointer */ 308 sc->in_state = MIDI_IN_DATA; 309 sc->in_msg[0] = data; 310 sc->in_pos = 1; 311 sc->in_left = 2; 312 break; 313 default: 314 if (MIDI_IS_COMMON(data)) { 315 sc->in_msg[0] = data; 316 sc->in_pos = 1; 317 goto deliver; 318 } else { 319 sc->in_state = MIDI_IN_DATA; 320 sc->in_msg[0] = sc->in_status = data; 321 sc->in_pos = 1; 322 sc->in_left = MIDI_LENGTH(data); 323 } 324 break; 325 } 326 } else { 327 if (MIDI_IS_STATUS(sc->in_status)) { 328 sc->in_state = MIDI_IN_DATA; 329 sc->in_msg[0] = sc->in_status; 330 sc->in_msg[1] = data; 331 sc->in_pos = 2; 332 sc->in_left = MIDI_LENGTH(sc->in_status) - 1; 333 if (sc->in_left == 0) 334 goto deliver; 335 } 336 } 337 return; 338 case MIDI_IN_DATA: 339 KASSERT(sc->in_left >= 1); 340 KASSERT(sc->in_pos < 3); 341 sc->in_msg[sc->in_pos++] = data; 342 if (--sc->in_left == 0) 343 break; /* deliver data */ 344 return; 345 case MIDI_IN_SYSEX: 346 sc->in_msg[0] = data; 347 sc->in_pos = 1; 348 sc->in_left = 0; 349 if (data == MIDI_SYSEX_END) 350 sc->in_state = MIDI_IN_START; 351 goto deliver_raw; 352 } 353 deliver: 354 sc->in_state = MIDI_IN_START; 355 #if NSEQUENCER > 0 356 if (sc->seqopen) { 357 extern void midiseq_in(struct midi_dev *,u_char *,int); 358 midiseq_in(sc->seq_md, sc->in_msg, sc->in_pos); 359 return; 360 } 361 #endif 362 deliver_raw: 363 if (mb->used + sc->in_pos > mb->usedhigh) { 364 DPRINTF(("midi_in: buffer full, discard data=0x%02x\n", 365 sc->in_msg[0])); 366 return; 367 } 368 for (i = 0; i < sc->in_pos; i++) { 369 *mb->inp++ = sc->in_msg[i]; 370 if (mb->inp >= mb->end) 371 mb->inp = mb->start; 372 mb->used++; 373 } 374 midi_wakeup(&sc->rchan); 375 selnotify(&sc->rsel, 0); 376 if (sc->async) 377 psignal(sc->async, SIGIO); 378 } 379 380 void 381 midi_out(void *addr) 382 { 383 struct midi_softc *sc = addr; 384 385 if (!sc->isopen) 386 return; 387 DPRINTFN(3, ("midi_out: %p\n", sc)); 388 midi_start_output(sc, 1); 389 } 390 391 int 392 midiopen(dev_t dev, int flags, int ifmt, struct proc *p) 393 { 394 struct midi_softc *sc; 395 const struct midi_hw_if *hw; 396 int error; 397 398 sc = device_lookup(&midi_cd, MIDIUNIT(dev)); 399 if (sc == NULL) 400 return (ENXIO); 401 if (sc->dying) 402 return (EIO); 403 404 DPRINTF(("midiopen %p\n", sc)); 405 406 hw = sc->hw_if; 407 if (!hw) 408 return ENXIO; 409 if (sc->isopen) 410 return EBUSY; 411 sc->in_state = MIDI_IN_START; 412 sc->in_status = 0; 413 error = hw->open(sc->hw_hdl, flags, midi_in, midi_out, sc); 414 if (error) 415 return error; 416 sc->isopen++; 417 midi_initbuf(&sc->outbuf); 418 midi_initbuf(&sc->inbuf); 419 sc->flags = flags; 420 sc->rchan = 0; 421 sc->wchan = 0; 422 sc->pbus = 0; 423 sc->async = 0; 424 425 #ifdef MIDI_SAVE 426 if (midicnt != 0) { 427 midisave.cnt = midicnt; 428 midicnt = 0; 429 } 430 #endif 431 432 return 0; 433 } 434 435 int 436 midiclose(dev_t dev, int flags, int ifmt, struct proc *p) 437 { 438 int unit = MIDIUNIT(dev); 439 struct midi_softc *sc = midi_cd.cd_devs[unit]; 440 const struct midi_hw_if *hw = sc->hw_if; 441 int s, error; 442 443 DPRINTF(("midiclose %p\n", sc)); 444 445 midi_start_output(sc, 0); 446 error = 0; 447 s = splaudio(); 448 while (sc->outbuf.used > 0 && !error) { 449 DPRINTFN(2,("midiclose sleep used=%d\n", sc->outbuf.used)); 450 error = midi_sleep_timo(&sc->wchan, "mid_dr", 30*hz); 451 } 452 splx(s); 453 sc->isopen = 0; 454 hw->close(sc->hw_hdl); 455 #if NSEQUENCER > 0 456 sc->seqopen = 0; 457 sc->seq_md = 0; 458 #endif 459 return 0; 460 } 461 462 int 463 midiread(dev_t dev, struct uio *uio, int ioflag) 464 { 465 int unit = MIDIUNIT(dev); 466 struct midi_softc *sc = midi_cd.cd_devs[unit]; 467 struct midi_buffer *mb = &sc->inbuf; 468 int error; 469 u_char *outp; 470 int used, cc, n, resid; 471 int s; 472 473 DPRINTF(("midiread: %p, count=%lu\n", sc, 474 (unsigned long)uio->uio_resid)); 475 476 if (sc->dying) 477 return EIO; 478 479 error = 0; 480 resid = uio->uio_resid; 481 while (uio->uio_resid == resid && !error) { 482 s = splaudio(); 483 while (mb->used <= 0) { 484 if (ioflag & IO_NDELAY) { 485 splx(s); 486 return EWOULDBLOCK; 487 } 488 error = midi_sleep(&sc->rchan, "mid rd"); 489 if (error) { 490 splx(s); 491 return error; 492 } 493 } 494 used = mb->used; 495 outp = mb->outp; 496 splx(s); 497 if (sc->dying) 498 return EIO; 499 cc = used; /* maximum to read */ 500 n = mb->end - outp; 501 if (n < cc) 502 cc = n; /* don't read beyond end of buffer */ 503 if (uio->uio_resid < cc) 504 cc = uio->uio_resid; /* and no more than we want */ 505 DPRINTFN(3, ("midiread: uiomove cc=%d\n", cc)); 506 error = uiomove(outp, cc, uio); 507 if (error) 508 break; 509 used -= cc; 510 outp += cc; 511 if (outp >= mb->end) 512 outp = mb->start; 513 s = splaudio(); 514 mb->outp = outp; 515 mb->used = used; 516 splx(s); 517 } 518 return error; 519 } 520 521 void 522 midi_timeout(void *arg) 523 { 524 struct midi_softc *sc = arg; 525 526 DPRINTFN(3,("midi_timeout: %p\n", sc)); 527 midi_start_output(sc, 1); 528 } 529 530 int 531 midi_start_output(struct midi_softc *sc, int intr) 532 { 533 struct midi_buffer *mb = &sc->outbuf; 534 u_char out; 535 int error; 536 int s; 537 int i; 538 539 error = 0; 540 541 if (sc->dying) 542 return EIO; 543 544 if (sc->pbus && !intr) { 545 DPRINTFN(4, ("midi_start_output: busy\n")); 546 return 0; 547 } 548 sc->pbus = (mb->used > 0)?1:0; 549 for (i = 0; i < MIDI_MAX_WRITE && mb->used > 0 && 550 (!error || error==EINPROGRESS); i++) { 551 s = splaudio(); 552 out = *mb->outp; 553 mb->outp++; 554 if (mb->outp >= mb->end) 555 mb->outp = mb->start; 556 mb->used--; 557 splx(s); 558 #ifdef MIDI_SAVE 559 midisave.buf[midicnt] = out; 560 midicnt = (midicnt + 1) % MIDI_SAVE_SIZE; 561 #endif 562 DPRINTFN(4, ("midi_start_output: %p i=%d, data=0x%02x\n", 563 sc, i, out)); 564 error = sc->hw_if->output(sc->hw_hdl, out); 565 if ((sc->props & MIDI_PROP_OUT_INTR) && error!=EINPROGRESS) 566 /* If ointr is enabled, midi_start_output() 567 * normally writes only one byte, 568 * except hw_if->output() returns EINPROGRESS. 569 */ 570 break; 571 } 572 midi_wakeup(&sc->wchan); 573 selnotify(&sc->wsel, 0); 574 if (sc->async) 575 psignal(sc->async, SIGIO); 576 if (!(sc->props & MIDI_PROP_OUT_INTR) || error==EINPROGRESS) { 577 if (mb->used > 0) 578 callout_reset(&sc->sc_callout, midi_wait, 579 midi_timeout, sc); 580 else 581 sc->pbus = 0; 582 } 583 if ((sc->props & MIDI_PROP_OUT_INTR) && error==EINPROGRESS) 584 error = 0; 585 586 return error; 587 } 588 589 int 590 midiwrite(dev_t dev, struct uio *uio, int ioflag) 591 { 592 int unit = MIDIUNIT(dev); 593 struct midi_softc *sc = midi_cd.cd_devs[unit]; 594 struct midi_buffer *mb = &sc->outbuf; 595 int error; 596 u_char *inp; 597 int used, cc, n; 598 int s; 599 600 DPRINTFN(2, ("midiwrite: %p, unit=%d, count=%lu\n", sc, unit, 601 (unsigned long)uio->uio_resid)); 602 603 if (sc->dying) 604 return EIO; 605 606 error = 0; 607 while (uio->uio_resid > 0 && !error) { 608 s = splaudio(); 609 if (mb->used >= mb->usedhigh) { 610 DPRINTFN(3,("midi_write: sleep used=%d hiwat=%d\n", 611 mb->used, mb->usedhigh)); 612 if (ioflag & IO_NDELAY) { 613 splx(s); 614 return EWOULDBLOCK; 615 } 616 error = midi_sleep(&sc->wchan, "mid wr"); 617 if (error) { 618 splx(s); 619 return error; 620 } 621 } 622 used = mb->used; 623 inp = mb->inp; 624 splx(s); 625 if (sc->dying) 626 return EIO; 627 cc = mb->usedhigh - used; /* maximum to write */ 628 n = mb->end - inp; 629 if (n < cc) 630 cc = n; /* don't write beyond end of buffer */ 631 if (uio->uio_resid < cc) 632 cc = uio->uio_resid; /* and no more than we have */ 633 error = uiomove(inp, cc, uio); 634 #ifdef MIDI_DEBUG 635 if (error) 636 printf("midi_write:(1) uiomove failed %d; " 637 "cc=%d inp=%p\n", 638 error, cc, inp); 639 #endif 640 if (error) 641 break; 642 inp = mb->inp + cc; 643 if (inp >= mb->end) 644 inp = mb->start; 645 s = splaudio(); 646 mb->inp = inp; 647 mb->used += cc; 648 splx(s); 649 error = midi_start_output(sc, 0); 650 } 651 return error; 652 } 653 654 /* 655 * This write routine is only called from sequencer code and expects 656 * a write that is smaller than the MIDI buffer. 657 */ 658 int 659 midi_writebytes(int unit, u_char *buf, int cc) 660 { 661 struct midi_softc *sc = midi_cd.cd_devs[unit]; 662 struct midi_buffer *mb = &sc->outbuf; 663 int n, s; 664 665 DPRINTFN(2, ("midi_writebytes: %p, unit=%d, cc=%d\n", sc, unit, cc)); 666 DPRINTFN(3, ("midi_writebytes: %x %x %x\n",buf[0],buf[1],buf[2])); 667 668 if (sc->dying) 669 return EIO; 670 671 s = splaudio(); 672 if (mb->used + cc >= mb->usedhigh) { 673 splx(s); 674 return (EWOULDBLOCK); 675 } 676 n = mb->end - mb->inp; 677 if (cc < n) 678 n = cc; 679 mb->used += cc; 680 memcpy(mb->inp, buf, n); 681 mb->inp += n; 682 if (mb->inp >= mb->end) { 683 mb->inp = mb->start; 684 cc -= n; 685 if (cc > 0) { 686 memcpy(mb->inp, buf + n, cc); 687 mb->inp += cc; 688 } 689 } 690 splx(s); 691 return (midi_start_output(sc, 0)); 692 } 693 694 int 695 midiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) 696 { 697 int unit = MIDIUNIT(dev); 698 struct midi_softc *sc = midi_cd.cd_devs[unit]; 699 const struct midi_hw_if *hw = sc->hw_if; 700 int error; 701 702 DPRINTF(("midiioctl: %p cmd=0x%08lx\n", sc, cmd)); 703 704 if (sc->dying) 705 return EIO; 706 707 error = 0; 708 switch (cmd) { 709 case FIONBIO: 710 /* All handled in the upper FS layer. */ 711 break; 712 713 case FIOASYNC: 714 if (*(int *)addr) { 715 if (sc->async) 716 return EBUSY; 717 sc->async = p; 718 DPRINTF(("midi_ioctl: FIOASYNC %p\n", p)); 719 } else 720 sc->async = 0; 721 break; 722 723 #if 0 724 case MIDI_PRETIME: 725 /* XXX OSS 726 * This should set up a read timeout, but that's 727 * why we have poll(), so there's nothing yet. */ 728 error = EINVAL; 729 break; 730 #endif 731 732 #ifdef MIDI_SAVE 733 case MIDI_GETSAVE: 734 error = copyout(&midisave, *(void **)addr, sizeof midisave); 735 break; 736 #endif 737 738 default: 739 if (hw->ioctl) 740 error = hw->ioctl(sc->hw_hdl, cmd, addr, flag, p); 741 else 742 error = EINVAL; 743 break; 744 } 745 return error; 746 } 747 748 int 749 midipoll(dev_t dev, int events, struct proc *p) 750 { 751 int unit = MIDIUNIT(dev); 752 struct midi_softc *sc = midi_cd.cd_devs[unit]; 753 int revents = 0; 754 int s; 755 756 DPRINTF(("midipoll: %p events=0x%x\n", sc, events)); 757 758 if (sc->dying) 759 return EIO; 760 761 s = splaudio(); 762 763 if (events & (POLLIN | POLLRDNORM)) 764 if (sc->inbuf.used > 0) 765 revents |= events & (POLLIN | POLLRDNORM); 766 767 if (events & (POLLOUT | POLLWRNORM)) 768 if (sc->outbuf.used < sc->outbuf.usedhigh) 769 revents |= events & (POLLOUT | POLLWRNORM); 770 771 if (revents == 0) { 772 if (events & (POLLIN | POLLRDNORM)) 773 selrecord(p, &sc->rsel); 774 775 if (events & (POLLOUT | POLLWRNORM)) 776 selrecord(p, &sc->wsel); 777 } 778 779 splx(s); 780 return revents; 781 } 782 783 static void 784 filt_midirdetach(struct knote *kn) 785 { 786 struct midi_softc *sc = kn->kn_hook; 787 int s; 788 789 s = splaudio(); 790 SLIST_REMOVE(&sc->rsel.sel_klist, kn, knote, kn_selnext); 791 splx(s); 792 } 793 794 static int 795 filt_midiread(struct knote *kn, long hint) 796 { 797 struct midi_softc *sc = kn->kn_hook; 798 799 /* XXXLUKEM (thorpej): please make sure this is correct. */ 800 801 kn->kn_data = sc->inbuf.used; 802 return (kn->kn_data > 0); 803 } 804 805 static const struct filterops midiread_filtops = 806 { 1, NULL, filt_midirdetach, filt_midiread }; 807 808 static void 809 filt_midiwdetach(struct knote *kn) 810 { 811 struct midi_softc *sc = kn->kn_hook; 812 int s; 813 814 s = splaudio(); 815 SLIST_REMOVE(&sc->wsel.sel_klist, kn, knote, kn_selnext); 816 splx(s); 817 } 818 819 static int 820 filt_midiwrite(struct knote *kn, long hint) 821 { 822 struct midi_softc *sc = kn->kn_hook; 823 824 /* XXXLUKEM (thorpej): please make sure this is correct. */ 825 826 kn->kn_data = sc->outbuf.usedhigh - sc->outbuf.used; 827 return (kn->kn_data > 0); 828 } 829 830 static const struct filterops midiwrite_filtops = 831 { 1, NULL, filt_midiwdetach, filt_midiwrite }; 832 833 int 834 midikqfilter(dev_t dev, struct knote *kn) 835 { 836 int unit = MIDIUNIT(dev); 837 struct midi_softc *sc = midi_cd.cd_devs[unit]; 838 struct klist *klist; 839 int s; 840 841 switch (kn->kn_filter) { 842 case EVFILT_READ: 843 klist = &sc->rsel.sel_klist; 844 kn->kn_fop = &midiread_filtops; 845 break; 846 847 case EVFILT_WRITE: 848 klist = &sc->wsel.sel_klist; 849 kn->kn_fop = &midiwrite_filtops; 850 break; 851 852 default: 853 return (1); 854 } 855 856 kn->kn_hook = sc; 857 858 s = splaudio(); 859 SLIST_INSERT_HEAD(klist, kn, kn_selnext); 860 splx(s); 861 862 return (0); 863 } 864 865 void 866 midi_getinfo(dev_t dev, struct midi_info *mi) 867 { 868 struct midi_softc *sc; 869 870 sc = device_lookup(&midi_cd, MIDIUNIT(dev)); 871 if (sc == NULL) 872 return; 873 if (sc->dying) 874 return; 875 876 sc->hw_if->getinfo(sc->hw_hdl, mi); 877 } 878 879 #endif /* NMIDI > 0 */ 880 881 #if NMIDI > 0 || NMIDIBUS > 0 882 883 int audioprint(void *, const char *); 884 885 struct device * 886 midi_attach_mi(const struct midi_hw_if *mhwp, void *hdlp, struct device *dev) 887 { 888 struct audio_attach_args arg; 889 890 #ifdef DIAGNOSTIC 891 if (mhwp == NULL) { 892 aprint_error("midi_attach_mi: NULL\n"); 893 return (0); 894 } 895 #endif 896 arg.type = AUDIODEV_TYPE_MIDI; 897 arg.hwif = mhwp; 898 arg.hdl = hdlp; 899 return (config_found(dev, &arg, audioprint)); 900 } 901 902 #endif /* NMIDI > 0 || NMIDIBUS > 0 */ 903