1 /* $OpenBSD: midi.c,v 1.40 2015/05/22 12:52:00 jsg 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 #include <sys/param.h> 20 #include <sys/fcntl.h> 21 #include <sys/systm.h> 22 #include <sys/ioctl.h> 23 #include <sys/conf.h> 24 #include <sys/poll.h> 25 #include <sys/kernel.h> 26 #include <sys/timeout.h> 27 #include <sys/vnode.h> 28 #include <sys/signalvar.h> 29 #include <sys/malloc.h> 30 #include <sys/device.h> 31 32 #include <dev/midi_if.h> 33 #include <dev/audio_if.h> 34 #include <dev/midivar.h> 35 36 37 int midiopen(dev_t, int, int, struct proc *); 38 int midiclose(dev_t, int, int, struct proc *); 39 int midiread(dev_t, struct uio *, int); 40 int midiwrite(dev_t, struct uio *, int); 41 int midipoll(dev_t, int, struct proc *); 42 int midikqfilter(dev_t, struct knote *); 43 int midiioctl(dev_t, u_long, caddr_t, int, struct proc *); 44 int midiprobe(struct device *, void *, void *); 45 void midiattach(struct device *, struct device *, void *); 46 int mididetach(struct device *, int); 47 int midiprint(void *, const char *); 48 49 void midi_iintr(void *, int); 50 void midi_ointr(void *); 51 void midi_timeout(void *); 52 void midi_out_start(struct midi_softc *); 53 void midi_out_stop(struct midi_softc *); 54 void midi_out_do(struct midi_softc *); 55 void midi_attach(struct midi_softc *, struct device *); 56 57 58 struct cfattach midi_ca = { 59 sizeof(struct midi_softc), midiprobe, midiattach, mididetach 60 }; 61 62 struct cfdriver midi_cd = { 63 NULL, "midi", DV_DULL 64 }; 65 66 67 void filt_midiwdetach(struct knote *); 68 int filt_midiwrite(struct knote *, long); 69 70 struct filterops midiwrite_filtops = { 71 1, NULL, filt_midiwdetach, filt_midiwrite 72 }; 73 74 void filt_midirdetach(struct knote *); 75 int filt_midiread(struct knote *, long); 76 77 struct filterops midiread_filtops = { 78 1, NULL, filt_midirdetach, filt_midiread 79 }; 80 81 void 82 midi_iintr(void *addr, int data) 83 { 84 struct midi_softc *sc = (struct midi_softc *)addr; 85 struct midi_buffer *mb = &sc->inbuf; 86 87 MUTEX_ASSERT_LOCKED(&audio_lock); 88 if (!(sc->dev.dv_flags & DVF_ACTIVE) || !(sc->flags & FREAD)) 89 return; 90 91 if (MIDIBUF_ISFULL(mb)) 92 return; /* discard data */ 93 94 MIDIBUF_WRITE(mb, data); 95 if (mb->used == 1) { 96 if (sc->rchan) { 97 sc->rchan = 0; 98 wakeup(&sc->rchan); 99 } 100 selwakeup(&sc->rsel); 101 if (sc->async) 102 psignal(sc->async, SIGIO); 103 } 104 } 105 106 int 107 midiread(dev_t dev, struct uio *uio, int ioflag) 108 { 109 struct midi_softc *sc; 110 struct midi_buffer *mb; 111 size_t count; 112 int error; 113 114 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)); 115 if (sc == NULL) 116 return ENXIO; 117 if (!(sc->flags & FREAD)) { 118 error = ENXIO; 119 goto done; 120 } 121 mb = &sc->inbuf; 122 123 /* if there is no data then sleep (unless IO_NDELAY flag is set) */ 124 error = 0; 125 mtx_enter(&audio_lock); 126 while (MIDIBUF_ISEMPTY(mb)) { 127 if (ioflag & IO_NDELAY) { 128 mtx_leave(&audio_lock); 129 error = EWOULDBLOCK; 130 goto done; 131 } 132 sc->rchan = 1; 133 error = msleep(&sc->rchan, &audio_lock, PWAIT | PCATCH, "mid_rd", 0); 134 if (!(sc->dev.dv_flags & DVF_ACTIVE)) 135 error = EIO; 136 if (error) { 137 mtx_leave(&audio_lock); 138 goto done; 139 } 140 } 141 142 /* at this stage, there is at least 1 byte */ 143 144 while (uio->uio_resid > 0 && mb->used > 0) { 145 count = MIDIBUF_SIZE - mb->start; 146 if (count > mb->used) 147 count = mb->used; 148 if (count > uio->uio_resid) 149 count = uio->uio_resid; 150 mtx_leave(&audio_lock); 151 error = uiomove(mb->data + mb->start, count, uio); 152 if (error) 153 goto done; 154 mtx_enter(&audio_lock); 155 MIDIBUF_REMOVE(mb, count); 156 } 157 mtx_leave(&audio_lock); 158 done: 159 device_unref(&sc->dev); 160 return error; 161 } 162 163 void 164 midi_ointr(void *addr) 165 { 166 struct midi_softc *sc = (struct midi_softc *)addr; 167 struct midi_buffer *mb; 168 169 MUTEX_ASSERT_LOCKED(&audio_lock); 170 if (!(sc->dev.dv_flags & DVF_ACTIVE) || !(sc->flags & FWRITE)) 171 return; 172 173 mb = &sc->outbuf; 174 if (mb->used > 0) { 175 #ifdef MIDI_DEBUG 176 if (!sc->isbusy) { 177 printf("midi_ointr: output must be busy\n"); 178 } 179 #endif 180 midi_out_do(sc); 181 } else if (sc->isbusy) 182 midi_out_stop(sc); 183 } 184 185 void 186 midi_timeout(void *addr) 187 { 188 mtx_enter(&audio_lock); 189 midi_ointr(addr); 190 mtx_leave(&audio_lock); 191 } 192 193 void 194 midi_out_start(struct midi_softc *sc) 195 { 196 if (!sc->isbusy) { 197 sc->isbusy = 1; 198 midi_out_do(sc); 199 } 200 } 201 202 void 203 midi_out_stop(struct midi_softc *sc) 204 { 205 sc->isbusy = 0; 206 if (sc->wchan) { 207 sc->wchan = 0; 208 wakeup(&sc->wchan); 209 } 210 selwakeup(&sc->wsel); 211 if (sc->async) 212 psignal(sc->async, SIGIO); 213 } 214 215 void 216 midi_out_do(struct midi_softc *sc) 217 { 218 struct midi_buffer *mb = &sc->outbuf; 219 220 while (mb->used > 0) { 221 if (!sc->hw_if->output(sc->hw_hdl, mb->data[mb->start])) 222 break; 223 MIDIBUF_REMOVE(mb, 1); 224 if (MIDIBUF_ISEMPTY(mb)) { 225 if (sc->hw_if->flush != NULL) 226 sc->hw_if->flush(sc->hw_hdl); 227 midi_out_stop(sc); 228 return; 229 } 230 } 231 232 if (!(sc->props & MIDI_PROP_OUT_INTR)) { 233 if (MIDIBUF_ISEMPTY(mb)) 234 midi_out_stop(sc); 235 else 236 timeout_add(&sc->timeo, 1); 237 } 238 } 239 240 int 241 midiwrite(dev_t dev, struct uio *uio, int ioflag) 242 { 243 struct midi_softc *sc; 244 struct midi_buffer *mb; 245 size_t count; 246 int error; 247 248 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)); 249 if (sc == NULL) 250 return ENXIO; 251 if (!(sc->flags & FWRITE)) { 252 error = ENXIO; 253 goto done; 254 } 255 mb = &sc->outbuf; 256 257 /* 258 * If IO_NDELAY flag is set then check if there is enough room 259 * in the buffer to store at least one byte. If not then dont 260 * start the write process. 261 */ 262 error = 0; 263 mtx_enter(&audio_lock); 264 if ((ioflag & IO_NDELAY) && MIDIBUF_ISFULL(mb) && (uio->uio_resid > 0)) { 265 mtx_leave(&audio_lock); 266 error = EWOULDBLOCK; 267 goto done; 268 } 269 270 while (uio->uio_resid > 0) { 271 while (MIDIBUF_ISFULL(mb)) { 272 if (ioflag & IO_NDELAY) { 273 /* 274 * At this stage at least one byte is already 275 * moved so we do not return EWOULDBLOCK 276 */ 277 mtx_leave(&audio_lock); 278 goto done; 279 } 280 sc->wchan = 1; 281 error = msleep(&sc->wchan, &audio_lock, 282 PWAIT | PCATCH, "mid_wr", 0); 283 if (!(sc->dev.dv_flags & DVF_ACTIVE)) 284 error = EIO; 285 if (error) { 286 mtx_leave(&audio_lock); 287 goto done; 288 } 289 } 290 291 count = MIDIBUF_SIZE - MIDIBUF_END(mb); 292 if (count > MIDIBUF_AVAIL(mb)) 293 count = MIDIBUF_AVAIL(mb); 294 if (count > uio->uio_resid) 295 count = uio->uio_resid; 296 mtx_leave(&audio_lock); 297 error = uiomove(mb->data + MIDIBUF_END(mb), count, uio); 298 if (error) 299 goto done; 300 mtx_enter(&audio_lock); 301 mb->used += count; 302 midi_out_start(sc); 303 } 304 mtx_leave(&audio_lock); 305 done: 306 device_unref(&sc->dev); 307 return error; 308 } 309 310 int 311 midipoll(dev_t dev, int events, struct proc *p) 312 { 313 struct midi_softc *sc; 314 int revents; 315 316 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)); 317 if (sc == NULL) 318 return POLLERR; 319 revents = 0; 320 mtx_enter(&audio_lock); 321 if (events & (POLLIN | POLLRDNORM)) { 322 if (!MIDIBUF_ISEMPTY(&sc->inbuf)) 323 revents |= events & (POLLIN | POLLRDNORM); 324 } 325 if (events & (POLLOUT | POLLWRNORM)) { 326 if (!MIDIBUF_ISFULL(&sc->outbuf)) 327 revents |= events & (POLLOUT | POLLWRNORM); 328 } 329 if (revents == 0) { 330 if (events & (POLLIN | POLLRDNORM)) 331 selrecord(p, &sc->rsel); 332 if (events & (POLLOUT | POLLWRNORM)) 333 selrecord(p, &sc->wsel); 334 } 335 mtx_leave(&audio_lock); 336 device_unref(&sc->dev); 337 return (revents); 338 } 339 340 int 341 midikqfilter(dev_t dev, struct knote *kn) 342 { 343 struct midi_softc *sc; 344 struct klist *klist; 345 int error; 346 347 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)); 348 if (sc == NULL) 349 return ENXIO; 350 error = 0; 351 switch (kn->kn_filter) { 352 case EVFILT_READ: 353 klist = &sc->rsel.si_note; 354 kn->kn_fop = &midiread_filtops; 355 break; 356 case EVFILT_WRITE: 357 klist = &sc->wsel.si_note; 358 kn->kn_fop = &midiwrite_filtops; 359 break; 360 default: 361 error = EINVAL; 362 goto done; 363 } 364 kn->kn_hook = (void *)sc; 365 366 mtx_enter(&audio_lock); 367 SLIST_INSERT_HEAD(klist, kn, kn_selnext); 368 mtx_leave(&audio_lock); 369 done: 370 device_unref(&sc->dev); 371 return error; 372 } 373 374 void 375 filt_midirdetach(struct knote *kn) 376 { 377 struct midi_softc *sc = (struct midi_softc *)kn->kn_hook; 378 379 mtx_enter(&audio_lock); 380 SLIST_REMOVE(&sc->rsel.si_note, kn, knote, kn_selnext); 381 mtx_leave(&audio_lock); 382 } 383 384 int 385 filt_midiread(struct knote *kn, long hint) 386 { 387 struct midi_softc *sc = (struct midi_softc *)kn->kn_hook; 388 int retval; 389 390 mtx_enter(&audio_lock); 391 retval = !MIDIBUF_ISEMPTY(&sc->inbuf); 392 mtx_leave(&audio_lock); 393 394 return (retval); 395 } 396 397 void 398 filt_midiwdetach(struct knote *kn) 399 { 400 struct midi_softc *sc = (struct midi_softc *)kn->kn_hook; 401 402 mtx_enter(&audio_lock); 403 SLIST_REMOVE(&sc->wsel.si_note, kn, knote, kn_selnext); 404 mtx_leave(&audio_lock); 405 } 406 407 int 408 filt_midiwrite(struct knote *kn, long hint) 409 { 410 struct midi_softc *sc = (struct midi_softc *)kn->kn_hook; 411 int retval; 412 413 mtx_enter(&audio_lock); 414 retval = !MIDIBUF_ISFULL(&sc->outbuf); 415 mtx_leave(&audio_lock); 416 417 return (retval); 418 } 419 420 int 421 midiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) 422 { 423 struct midi_softc *sc; 424 int error; 425 426 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)); 427 if (sc == NULL) 428 return ENXIO; 429 error = 0; 430 switch(cmd) { 431 case FIONBIO: 432 /* All handled in the upper FS layer */ 433 break; 434 case FIOASYNC: 435 if (*(int *)addr) { 436 if (sc->async) { 437 error = EBUSY; 438 goto done; 439 } 440 sc->async = p; 441 } else 442 sc->async = 0; 443 break; 444 default: 445 error = ENOTTY; 446 } 447 done: 448 device_unref(&sc->dev); 449 return error; 450 } 451 452 int 453 midiopen(dev_t dev, int flags, int mode, struct proc *p) 454 { 455 struct midi_softc *sc; 456 int error; 457 458 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)); 459 if (sc == NULL) 460 return ENXIO; 461 error = 0; 462 if (sc->flags) { 463 error = EBUSY; 464 goto done; 465 } 466 MIDIBUF_INIT(&sc->inbuf); 467 MIDIBUF_INIT(&sc->outbuf); 468 sc->isbusy = 0; 469 sc->rchan = sc->wchan = 0; 470 sc->async = 0; 471 sc->flags = flags; 472 error = sc->hw_if->open(sc->hw_hdl, flags, midi_iintr, midi_ointr, sc); 473 if (error) 474 sc->flags = 0; 475 done: 476 device_unref(&sc->dev); 477 return error; 478 } 479 480 int 481 midiclose(dev_t dev, int fflag, int devtype, struct proc *p) 482 { 483 struct midi_softc *sc; 484 struct midi_buffer *mb; 485 int error; 486 487 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)); 488 if (sc == NULL) 489 return ENXIO; 490 491 /* start draining output buffer */ 492 error = 0; 493 mb = &sc->outbuf; 494 mtx_enter(&audio_lock); 495 if (!MIDIBUF_ISEMPTY(mb)) 496 midi_out_start(sc); 497 while (sc->isbusy) { 498 sc->wchan = 1; 499 error = msleep(&sc->wchan, &audio_lock, 500 PWAIT, "mid_dr", 5 * hz); 501 if (!(sc->dev.dv_flags & DVF_ACTIVE)) 502 error = EIO; 503 if (error) 504 break; 505 } 506 mtx_leave(&audio_lock); 507 508 /* 509 * some hw_if->close() reset immediately the midi uart 510 * which flushes the internal buffer of the uart device, 511 * so we may lose some (important) data. To avoid this, 512 * sleep 20ms (around 64 bytes) to give the time to the 513 * uart to drain its internal buffers. 514 */ 515 tsleep(&sc->wchan, PWAIT, "mid_cl", hz * MIDI_MAXWRITE / MIDI_RATE); 516 sc->hw_if->close(sc->hw_hdl); 517 sc->flags = 0; 518 device_unref(&sc->dev); 519 return 0; 520 } 521 522 int 523 midiprobe(struct device *parent, void *match, void *aux) 524 { 525 struct audio_attach_args *sa = aux; 526 527 return (sa != NULL && (sa->type == AUDIODEV_TYPE_MIDI) ? 1 : 0); 528 } 529 530 void 531 midiattach(struct device *parent, struct device *self, void *aux) 532 { 533 struct midi_info mi; 534 struct midi_softc *sc = (struct midi_softc *)self; 535 struct audio_attach_args *sa = (struct audio_attach_args *)aux; 536 struct midi_hw_if *hwif = sa->hwif; 537 void *hdl = sa->hdl; 538 539 #ifdef DIAGNOSTIC 540 if (hwif == 0 || 541 hwif->open == 0 || 542 hwif->close == 0 || 543 hwif->output == 0 || 544 hwif->getinfo == 0) { 545 printf("midi: missing method\n"); 546 return; 547 } 548 #endif 549 sc->hw_if = hwif; 550 sc->hw_hdl = hdl; 551 sc->hw_if->getinfo(sc->hw_hdl, &mi); 552 sc->props = mi.props; 553 sc->flags = 0; 554 timeout_set(&sc->timeo, midi_timeout, sc); 555 printf(": <%s>\n", mi.name); 556 } 557 558 int 559 mididetach(struct device *self, int flags) 560 { 561 struct midi_softc *sc = (struct midi_softc *)self; 562 int maj, mn; 563 564 /* locate the major number */ 565 for (maj = 0; maj < nchrdev; maj++) { 566 if (cdevsw[maj].d_open == midiopen) { 567 /* Nuke the vnodes for any open instances (calls close). */ 568 mn = self->dv_unit; 569 vdevgone(maj, mn, mn, VCHR); 570 } 571 } 572 573 /* 574 * The close() method did nothing (device_lookup() returns 575 * NULL), so quickly halt transfers (normally parent is already 576 * gone, and code below is no-op), and wake-up user-land blocked 577 * in read/write/ioctl, which return EIO. 578 */ 579 if (sc->flags) { 580 if (sc->flags & FREAD) { 581 sc->rchan = 0; 582 wakeup(&sc->rchan); 583 selwakeup(&sc->rsel); 584 } 585 if (sc->flags & FWRITE) { 586 sc->wchan = 0; 587 wakeup(&sc->wchan); 588 selwakeup(&sc->wsel); 589 } 590 sc->hw_if->close(sc->hw_hdl); 591 sc->flags = 0; 592 } 593 return 0; 594 } 595 596 int 597 midiprint(void *aux, const char *pnp) 598 { 599 if (pnp) 600 printf("midi at %s", pnp); 601 return (UNCONF); 602 } 603 604 struct device * 605 midi_attach_mi(struct midi_hw_if *hwif, void *hdl, struct device *dev) 606 { 607 struct audio_attach_args arg; 608 609 arg.type = AUDIODEV_TYPE_MIDI; 610 arg.hwif = hwif; 611 arg.hdl = hdl; 612 return config_found(dev, &arg, midiprint); 613 } 614