1 /* $OpenBSD: midi.c,v 1.28 2012/04/17 07:58:47 ratchov Exp $ */ 2 3 /* 4 * Copyright (c) 2003, 2004 Alexandre Ratchov 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* 20 * TODO 21 * - put the sequencer stuff in sequencer.c and sequencervar.h 22 * there is no reason to have it here. The sequencer 23 * driver need only to open the midi hw_if thus it does not 24 * need this driver 25 */ 26 27 #include "sequencer.h" 28 29 #include <sys/param.h> 30 #include <sys/fcntl.h> 31 #include <sys/systm.h> 32 #include <sys/ioctl.h> 33 #include <sys/exec.h> 34 #include <sys/conf.h> 35 #include <sys/lkm.h> 36 #include <sys/proc.h> 37 #include <sys/poll.h> 38 #include <sys/kernel.h> 39 #include <sys/timeout.h> 40 #include <sys/vnode.h> 41 #include <sys/signalvar.h> 42 #include <sys/malloc.h> 43 #include <sys/device.h> 44 45 #include <dev/midi_if.h> 46 #include <dev/audio_if.h> 47 #include <dev/midivar.h> 48 49 50 int midiopen(dev_t, int, int, struct proc *); 51 int midiclose(dev_t, int, int, struct proc *); 52 int midiread(dev_t, struct uio *, int); 53 int midiwrite(dev_t, struct uio *, int); 54 int midipoll(dev_t, int, struct proc *); 55 int midikqfilter(dev_t, struct knote *); 56 int midiioctl(dev_t, u_long, caddr_t, int, struct proc *); 57 int midiprobe(struct device *, void *, void *); 58 void midiattach(struct device *, struct device *, void *); 59 int mididetach(struct device *, int); 60 int midiprint(void *, const char *); 61 62 void midi_iintr(void *, int); 63 void midi_ointr(void *); 64 void midi_out_start(struct midi_softc *); 65 void midi_out_stop(struct midi_softc *); 66 void midi_out_do(struct midi_softc *); 67 void midi_attach(struct midi_softc *, struct device *); 68 69 70 #if NSEQUENCER > 0 71 int midi_unit_count(void); 72 void midi_toevent(struct midi_softc *, int); 73 int midi_writebytes(int, u_char *, int); 74 void midiseq_in(struct midi_dev *, u_char *, int); 75 #endif 76 77 struct cfattach midi_ca = { 78 sizeof(struct midi_softc), midiprobe, midiattach, mididetach 79 }; 80 81 struct cfdriver midi_cd = { 82 NULL, "midi", DV_DULL 83 }; 84 85 86 void filt_midiwdetach(struct knote *); 87 int filt_midiwrite(struct knote *, long); 88 89 struct filterops midiwrite_filtops = { 90 1, NULL, filt_midiwdetach, filt_midiwrite 91 }; 92 93 void filt_midirdetach(struct knote *); 94 int filt_midiread(struct knote *, long); 95 96 struct filterops midiread_filtops = { 97 1, NULL, filt_midirdetach, filt_midiread 98 }; 99 100 101 void 102 midi_iintr(void *addr, int data) 103 { 104 struct midi_softc *sc = (struct midi_softc *)addr; 105 struct midi_buffer *mb = &sc->inbuf; 106 107 if (sc->isdying || !sc->isopen || !(sc->flags & FREAD)) 108 return; 109 110 #if NSEQUENCER > 0 111 if (sc->seqopen) { 112 midi_toevent(sc, data); 113 return; 114 } 115 #endif 116 if (MIDIBUF_ISFULL(mb)) 117 return; /* discard data */ 118 119 MIDIBUF_WRITE(mb, data); 120 if (mb->used == 1) { 121 if (sc->rchan) { 122 sc->rchan = 0; 123 wakeup(&sc->rchan); 124 } 125 selwakeup(&sc->rsel); 126 if (sc->async) 127 psignal(sc->async, SIGIO); 128 } 129 } 130 131 132 int 133 midiread(dev_t dev, struct uio *uio, int ioflag) 134 { 135 struct midi_softc *sc = MIDI_DEV2SC(dev); 136 struct midi_buffer *mb = &sc->inbuf; 137 unsigned count; 138 int s, error; 139 140 if (!(sc->flags & FREAD)) 141 return ENXIO; 142 143 /* if there is no data then sleep (unless IO_NDELAY flag is set) */ 144 145 s = splaudio(); 146 while (MIDIBUF_ISEMPTY(mb)) { 147 if (sc->isdying) { 148 splx(s); 149 return EIO; 150 } 151 if (ioflag & IO_NDELAY) { 152 splx(s); 153 return EWOULDBLOCK; 154 } 155 sc->rchan = 1; 156 error = tsleep(&sc->rchan, PWAIT|PCATCH, "mid_rd", 0); 157 if (error) { 158 splx(s); 159 return error; 160 } 161 } 162 163 /* at this stage, there is at least 1 byte */ 164 165 while (uio->uio_resid > 0 && mb->used > 0) { 166 count = MIDIBUF_SIZE - mb->start; 167 if (count > mb->used) 168 count = mb->used; 169 if (count > uio->uio_resid) 170 count = uio->uio_resid; 171 error = uiomove(mb->data + mb->start, count, uio); 172 if (error) { 173 splx(s); 174 return error; 175 } 176 MIDIBUF_REMOVE(mb, count); 177 } 178 splx(s); 179 return 0; 180 } 181 182 183 void 184 midi_ointr(void *addr) 185 { 186 struct midi_softc *sc = (struct midi_softc *)addr; 187 struct midi_buffer *mb; 188 int s; 189 190 if (sc->isopen && !sc->isdying) { 191 mb = &sc->outbuf; 192 s = splaudio(); 193 if (mb->used > 0) { 194 #ifdef MIDI_DEBUG 195 if (!sc->isbusy) { 196 printf("midi_ointr: output must be busy\n"); 197 } 198 #endif 199 midi_out_do(sc); 200 } else if (sc->isbusy) 201 midi_out_stop(sc); 202 splx(s); 203 } 204 } 205 206 207 void 208 midi_out_start(struct midi_softc *sc) 209 { 210 if (!sc->isbusy) { 211 sc->isbusy = 1; 212 midi_out_do(sc); 213 } 214 } 215 216 217 void 218 midi_out_stop(struct midi_softc *sc) 219 { 220 sc->isbusy = 0; 221 if (sc->wchan) { 222 sc->wchan = 0; 223 wakeup(&sc->wchan); 224 } 225 selwakeup(&sc->wsel); 226 if (sc->async) 227 psignal(sc->async, SIGIO); 228 } 229 230 231 void 232 midi_out_do(struct midi_softc *sc) 233 { 234 struct midi_buffer *mb = &sc->outbuf; 235 236 while (mb->used > 0) { 237 if (!sc->hw_if->output(sc->hw_hdl, mb->data[mb->start])) 238 break; 239 MIDIBUF_REMOVE(mb, 1); 240 if (MIDIBUF_ISEMPTY(mb)) { 241 if (sc->hw_if->flush != NULL) 242 sc->hw_if->flush(sc->hw_hdl); 243 midi_out_stop(sc); 244 return; 245 } 246 } 247 248 if (!(sc->props & MIDI_PROP_OUT_INTR)) { 249 if (MIDIBUF_ISEMPTY(mb)) 250 midi_out_stop(sc); 251 else 252 timeout_add(&sc->timeo, 1); 253 } 254 } 255 256 257 int 258 midiwrite(dev_t dev, struct uio *uio, int ioflag) 259 { 260 struct midi_softc *sc = MIDI_DEV2SC(dev); 261 struct midi_buffer *mb = &sc->outbuf; 262 unsigned count; 263 int s, error; 264 265 if (!(sc->flags & FWRITE)) 266 return ENXIO; 267 if (sc->isdying) 268 return EIO; 269 270 /* 271 * If IO_NDELAY flag is set then check if there is enough room 272 * in the buffer to store at least one byte. If not then dont 273 * start the write process. 274 */ 275 276 if ((ioflag & IO_NDELAY) && MIDIBUF_ISFULL(mb) && (uio->uio_resid > 0)) 277 return EWOULDBLOCK; 278 279 while (uio->uio_resid > 0) { 280 s = splaudio(); 281 while (MIDIBUF_ISFULL(mb)) { 282 if (ioflag & IO_NDELAY) { 283 /* 284 * At this stage at least one byte is already 285 * moved so we do not return EWOULDBLOCK 286 */ 287 splx(s); 288 return 0; 289 } 290 sc->wchan = 1; 291 error = tsleep(&sc->wchan, PWAIT|PCATCH, "mid_wr", 0); 292 if (error) { 293 splx(s); 294 return error; 295 } 296 if (sc->isdying) { 297 splx(s); 298 return EIO; 299 } 300 } 301 302 count = MIDIBUF_SIZE - MIDIBUF_END(mb); 303 if (count > MIDIBUF_AVAIL(mb)) 304 count = MIDIBUF_AVAIL(mb); 305 if (count > uio->uio_resid) 306 count = uio->uio_resid; 307 error = uiomove(mb->data + MIDIBUF_END(mb), count, uio); 308 if (error) { 309 splx(s); 310 return error; 311 } 312 mb->used += count; 313 midi_out_start(sc); 314 splx(s); 315 } 316 return 0; 317 } 318 319 320 int 321 midipoll(dev_t dev, int events, struct proc *p) 322 { 323 struct midi_softc *sc = MIDI_DEV2SC(dev); 324 int s, revents; 325 326 if (sc->isdying) 327 return POLLERR; 328 329 revents = 0; 330 s = splaudio(); 331 if (events & (POLLIN | POLLRDNORM)) { 332 if (!MIDIBUF_ISEMPTY(&sc->inbuf)) 333 revents |= events & (POLLIN | POLLRDNORM); 334 } 335 if (events & (POLLOUT | POLLWRNORM)) { 336 if (!MIDIBUF_ISFULL(&sc->outbuf)) 337 revents |= events & (POLLOUT | POLLWRNORM); 338 } 339 if (revents == 0) { 340 if (events & (POLLIN | POLLRDNORM)) 341 selrecord(p, &sc->rsel); 342 if (events & (POLLOUT | POLLWRNORM)) 343 selrecord(p, &sc->wsel); 344 } 345 splx(s); 346 return (revents); 347 } 348 349 350 int 351 midikqfilter(dev_t dev, struct knote *kn) 352 { 353 struct midi_softc *sc = MIDI_DEV2SC(dev); 354 struct klist *klist; 355 int s; 356 357 switch (kn->kn_filter) { 358 case EVFILT_READ: 359 klist = &sc->rsel.si_note; 360 kn->kn_fop = &midiread_filtops; 361 break; 362 case EVFILT_WRITE: 363 klist = &sc->wsel.si_note; 364 kn->kn_fop = &midiwrite_filtops; 365 break; 366 default: 367 return (EINVAL); 368 } 369 kn->kn_hook = (void *)sc; 370 371 s = splaudio(); 372 SLIST_INSERT_HEAD(klist, kn, kn_selnext); 373 splx(s); 374 375 return (0); 376 } 377 378 379 void 380 filt_midirdetach(struct knote *kn) 381 { 382 struct midi_softc *sc = (struct midi_softc *)kn->kn_hook; 383 int s; 384 385 s = splaudio(); 386 SLIST_REMOVE(&sc->rsel.si_note, kn, knote, kn_selnext); 387 splx(s); 388 } 389 390 391 int 392 filt_midiread(struct knote *kn, long hint) 393 { 394 struct midi_softc *sc = (struct midi_softc *)kn->kn_hook; 395 int s, retval; 396 397 s = splaudio(); 398 retval = !MIDIBUF_ISEMPTY(&sc->inbuf); 399 splx(s); 400 401 return (retval); 402 } 403 404 405 void 406 filt_midiwdetach(struct knote *kn) 407 { 408 struct midi_softc *sc = (struct midi_softc *)kn->kn_hook; 409 int s; 410 411 s = splaudio(); 412 SLIST_REMOVE(&sc->wsel.si_note, kn, knote, kn_selnext); 413 splx(s); 414 } 415 416 417 int 418 filt_midiwrite(struct knote *kn, long hint) 419 { 420 struct midi_softc *sc = (struct midi_softc *)kn->kn_hook; 421 int s, retval; 422 423 s = splaudio(); 424 retval = !MIDIBUF_ISFULL(&sc->outbuf); 425 splx(s); 426 427 return (retval); 428 } 429 430 431 int 432 midiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) 433 { 434 struct midi_softc *sc = MIDI_DEV2SC(dev); 435 436 if (sc->isdying) 437 return EIO; 438 439 switch(cmd) { 440 case FIONBIO: 441 /* All handled in the upper FS layer */ 442 break; 443 case FIOASYNC: 444 if (*(int *)addr) { 445 if (sc->async) 446 return EBUSY; 447 sc->async = p; 448 } else 449 sc->async = 0; 450 break; 451 default: 452 return ENOTTY; 453 } 454 return 0; 455 } 456 457 458 int 459 midiopen(dev_t dev, int flags, int mode, struct proc *p) 460 { 461 struct midi_softc *sc; 462 int err; 463 464 if (MIDI_UNIT(dev) >= midi_cd.cd_ndevs) 465 return ENXIO; 466 sc = MIDI_DEV2SC(dev); 467 if (sc == NULL) /* there may be more units than devices */ 468 return ENXIO; 469 if (sc->isdying) 470 return EIO; 471 if (sc->isopen) 472 return EBUSY; 473 474 MIDIBUF_INIT(&sc->inbuf); 475 MIDIBUF_INIT(&sc->outbuf); 476 sc->isbusy = 0; 477 sc->rchan = sc->wchan = 0; 478 sc->async = 0; 479 sc->flags = flags; 480 481 err = sc->hw_if->open(sc->hw_hdl, flags, midi_iintr, midi_ointr, sc); 482 if (err) 483 return err; 484 sc->isopen = 1; 485 #if NSEQUENCER > 0 486 sc->seq_md = 0; 487 sc->seqopen = 0; 488 sc->evstatus = 0xff; 489 #endif 490 return 0; 491 } 492 493 494 int 495 midiclose(dev_t dev, int fflag, int devtype, struct proc *p) 496 { 497 struct midi_softc *sc = MIDI_DEV2SC(dev); 498 struct midi_buffer *mb; 499 int error; 500 int s; 501 502 mb = &sc->outbuf; 503 if (!sc->isdying) { 504 /* start draining output buffer */ 505 s = splaudio(); 506 if (!MIDIBUF_ISEMPTY(mb)) 507 midi_out_start(sc); 508 while (sc->isbusy) { 509 sc->wchan = 1; 510 error = tsleep(&sc->wchan, PWAIT, "mid_dr", 5 * hz); 511 if (error || sc->isdying) 512 break; 513 } 514 splx(s); 515 } 516 517 /* 518 * some hw_if->close() reset immediately the midi uart 519 * which flushes the internal buffer of the uart device, 520 * so we may lose some (important) data. To avoid this, 521 * sleep 20ms (around 64 bytes) to give the time to the 522 * uart to drain its internal buffers. 523 */ 524 tsleep(&sc->wchan, PWAIT, "mid_cl", hz * MIDI_MAXWRITE / MIDI_RATE); 525 sc->hw_if->close(sc->hw_hdl); 526 sc->isopen = 0; 527 return 0; 528 } 529 530 531 int 532 midiprobe(struct device *parent, void *match, void *aux) 533 { 534 struct audio_attach_args *sa = aux; 535 536 return (sa != NULL && (sa->type == AUDIODEV_TYPE_MIDI) ? 1 : 0); 537 } 538 539 540 void 541 midi_attach(struct midi_softc *sc, struct device *parent) 542 { 543 struct midi_info mi; 544 545 sc->isdying = 0; 546 sc->hw_if->getinfo(sc->hw_hdl, &mi); 547 sc->props = mi.props; 548 sc->isopen = 0; 549 timeout_set(&sc->timeo, midi_ointr, sc); 550 printf(": <%s>\n", mi.name); 551 } 552 553 554 void 555 midiattach(struct device *parent, struct device *self, void *aux) 556 { 557 struct midi_softc *sc = (struct midi_softc *)self; 558 struct audio_attach_args *sa = (struct audio_attach_args *)aux; 559 struct midi_hw_if *hwif = sa->hwif; 560 void *hdl = sa->hdl; 561 562 #ifdef DIAGNOSTIC 563 if (hwif == 0 || 564 hwif->open == 0 || 565 hwif->close == 0 || 566 hwif->output == 0 || 567 hwif->getinfo == 0) { 568 printf("midi: missing method\n"); 569 return; 570 } 571 #endif 572 sc->hw_if = hwif; 573 sc->hw_hdl = hdl; 574 midi_attach(sc, parent); 575 } 576 577 578 int 579 mididetach(struct device *self, int flags) 580 { 581 struct midi_softc *sc = (struct midi_softc *)self; 582 int maj, mn; 583 584 sc->isdying = 1; 585 if (sc->wchan) { 586 sc->wchan = 0; 587 wakeup(&sc->wchan); 588 } 589 if (sc->rchan) { 590 sc->rchan = 0; 591 wakeup(&sc->rchan); 592 } 593 594 /* locate the major number */ 595 for (maj = 0; maj < nchrdev; maj++) { 596 if (cdevsw[maj].d_open == midiopen) { 597 /* Nuke the vnodes for any open instances (calls close). */ 598 mn = self->dv_unit; 599 vdevgone(maj, mn, mn, VCHR); 600 } 601 } 602 return 0; 603 } 604 605 606 int 607 midiprint(void *aux, const char *pnp) 608 { 609 if (pnp) 610 printf("midi at %s", pnp); 611 return (UNCONF); 612 } 613 614 615 void 616 midi_getinfo(dev_t dev, struct midi_info *mi) 617 { 618 struct midi_softc *sc = MIDI_DEV2SC(dev); 619 620 if (MIDI_UNIT(dev) >= midi_cd.cd_ndevs || sc == NULL || sc->isdying) { 621 mi->name = "unconfigured"; 622 mi->props = 0; 623 return; 624 } 625 sc->hw_if->getinfo(sc->hw_hdl, mi); 626 } 627 628 629 struct device * 630 midi_attach_mi(struct midi_hw_if *hwif, void *hdl, struct device *dev) 631 { 632 struct audio_attach_args arg; 633 634 arg.type = AUDIODEV_TYPE_MIDI; 635 arg.hwif = hwif; 636 arg.hdl = hdl; 637 return config_found(dev, &arg, midiprint); 638 } 639 640 641 int 642 midi_unit_count(void) 643 { 644 return midi_cd.cd_ndevs; 645 } 646 647 648 #if NSEQUENCER > 0 649 #define MIDI_EVLEN(status) (midi_evlen[((status) >> 4) & 7]) 650 unsigned midi_evlen[] = { 2, 2, 2, 2, 1, 1, 2 }; 651 652 void 653 midi_toevent(struct midi_softc *sc, int data) 654 { 655 unsigned char mesg[3]; 656 657 if (data >= 0xf8) { /* is it a realtime message ? */ 658 switch(data) { 659 case 0xf8: /* midi timer tic */ 660 case 0xfa: /* midi timer start */ 661 case 0xfb: /* midi timer continue (after stop) */ 662 case 0xfc: /* midi timer stop */ 663 mesg[0] = data; 664 midiseq_in(sc->seq_md, mesg, 1); 665 break; 666 default: 667 break; 668 } 669 } else if (data >= 0x80) { /* is it a common or voice message ? */ 670 sc->evstatus = data; 671 sc->evindex = 0; 672 } else { /* else it is a data byte */ 673 /* strip common messages and bogus data */ 674 if (sc->evstatus >= 0xf0 || sc->evstatus < 0x80) 675 return; 676 677 sc->evdata[sc->evindex++] = data; 678 if (sc->evindex == MIDI_EVLEN(sc->evstatus)) { 679 sc->evindex = 0; 680 mesg[0] = sc->evstatus; 681 mesg[1] = sc->evdata[0]; 682 mesg[2] = sc->evdata[1]; 683 midiseq_in(sc->seq_md, mesg, 1 + MIDI_EVLEN(sc->evstatus)); 684 } 685 } 686 } 687 688 689 int 690 midi_writebytes(int unit, unsigned char *mesg, int mesglen) 691 { 692 struct midi_softc *sc = midi_cd.cd_devs[unit]; 693 struct midi_buffer *mb = &sc->outbuf; 694 unsigned count; 695 int s; 696 697 s = splaudio(); 698 if (mesglen > MIDIBUF_AVAIL(mb)) { 699 splx(s); 700 return EWOULDBLOCK; 701 } 702 703 while (mesglen > 0) { 704 count = MIDIBUF_SIZE - MIDIBUF_END(mb); 705 if (count > MIDIBUF_AVAIL(mb)) count = MIDIBUF_AVAIL(mb); 706 if (count > mesglen) count = mesglen; 707 bcopy(mesg, mb->data + MIDIBUF_END(mb), count); 708 mb->used += count; 709 mesg += count; 710 mesglen -= count; 711 midi_out_start(sc); 712 } 713 splx(s); 714 return 0; 715 } 716 717 #endif /* NSEQUENCER > 0 */ 718