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