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