1 /*- 2 * Copyright (c) 2003 Mathew Kanner 3 * Copyright (c) 1998 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Lennart Augustsson (augustss@netbsd.org). 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 /* 32 * Parts of this file started out as NetBSD: midi.c 1.31 33 * They are mostly gone. Still the most obvious will be the state 34 * machine midi_in 35 */ 36 37 #include <sys/cdefs.h> 38 __FBSDID("$FreeBSD: head/sys/dev/sound/midi/midi.c 227309 2011-11-07 15:43:11Z ed $"); 39 40 #include <sys/param.h> 41 #include <sys/queue.h> 42 #include <sys/kernel.h> 43 #include <sys/lock.h> 44 #include <sys/mutex.h> 45 #include <sys/proc.h> 46 #include <sys/signalvar.h> 47 #include <sys/conf.h> 48 #include <sys/sysctl.h> 49 #include <sys/types.h> 50 #include <sys/malloc.h> 51 #include <sys/systm.h> 52 #include <sys/fcntl.h> 53 #include <sys/uio.h> 54 #include <sys/poll.h> 55 #include <sys/sbuf.h> 56 #include <sys/kobj.h> 57 #include <sys/module.h> 58 #include <sys/device.h> 59 60 #ifdef HAVE_KERNEL_OPTION_HEADERS 61 #include "opt_snd.h" 62 #endif 63 64 #include <dev/sound/midi/midi.h> 65 #include "mpu_if.h" 66 67 #include <dev/sound/midi/midiq.h> 68 #include "synth_if.h" 69 MALLOC_DEFINE(M_MIDI, "midi buffers", "Midi data allocation area"); 70 71 #ifndef KOBJMETHOD_END 72 #define KOBJMETHOD_END { NULL, NULL } 73 #endif 74 75 #define PCMMKMINOR(u, d, c) ((((c) & 0xff) << 16) | (((u) & 0x0f) << 4) | ((d) & 0x0f)) 76 #define MIDIMKMINOR(u, d, c) PCMMKMINOR(u, d, c) 77 78 #define MIDI_DEV_RAW 2 79 #define MIDI_DEV_MIDICTL 12 80 81 enum midi_states { 82 MIDI_IN_START, MIDI_IN_SYSEX, MIDI_IN_DATA 83 }; 84 85 /* 86 * The MPU interface current has init() uninit() inqsize(( outqsize() 87 * callback() : fiddle with the tx|rx status. 88 */ 89 90 #include "mpu_if.h" 91 92 /* 93 * /dev/rmidi Structure definitions 94 */ 95 96 #define MIDI_NAMELEN 16 97 struct snd_midi { 98 KOBJ_FIELDS; 99 struct lock lock; /* Protects all but queues */ 100 void *cookie; 101 102 int unit; /* Should only be used in midistat */ 103 int channel; /* Should only be used in midistat */ 104 105 int busy; 106 int flags; /* File flags */ 107 char name[MIDI_NAMELEN]; 108 struct lock qlock; /* Protects inq, outq and flags */ 109 MIDIQ_HEAD(, char) inq, outq; 110 int rchan, wchan; 111 struct kqinfo rkq, wkq; 112 int hiwat; /* QLEN(outq)>High-water -> disable 113 * writes from userland */ 114 enum midi_states inq_state; 115 int inq_status, inq_left; /* Variables for the state machine in 116 * Midi_in, this is to provide that 117 * signals only get issued only 118 * complete command packets. */ 119 struct proc *async; 120 struct cdev *dev; 121 struct synth_midi *synth; 122 int synth_flags; 123 TAILQ_ENTRY(snd_midi) link; 124 }; 125 126 struct synth_midi { 127 KOBJ_FIELDS; 128 struct snd_midi *m; 129 }; 130 131 static synth_open_t midisynth_open; 132 static synth_close_t midisynth_close; 133 static synth_writeraw_t midisynth_writeraw; 134 static synth_killnote_t midisynth_killnote; 135 static synth_startnote_t midisynth_startnote; 136 static synth_setinstr_t midisynth_setinstr; 137 static synth_alloc_t midisynth_alloc; 138 static synth_controller_t midisynth_controller; 139 static synth_bender_t midisynth_bender; 140 141 142 static kobj_method_t midisynth_methods[] = { 143 KOBJMETHOD(synth_open, midisynth_open), 144 KOBJMETHOD(synth_close, midisynth_close), 145 KOBJMETHOD(synth_writeraw, midisynth_writeraw), 146 KOBJMETHOD(synth_setinstr, midisynth_setinstr), 147 KOBJMETHOD(synth_startnote, midisynth_startnote), 148 KOBJMETHOD(synth_killnote, midisynth_killnote), 149 KOBJMETHOD(synth_alloc, midisynth_alloc), 150 KOBJMETHOD(synth_controller, midisynth_controller), 151 KOBJMETHOD(synth_bender, midisynth_bender), 152 KOBJMETHOD_END 153 }; 154 155 DEFINE_CLASS(midisynth, midisynth_methods, 0); 156 157 /* 158 * Module Exports & Interface 159 * 160 * struct midi_chan *midi_init(MPU_CLASS cls, int unit, int chan) int 161 * midi_uninit(struct snd_midi *) 0 == no error EBUSY or other error int 162 * Midi_in(struct midi_chan *, char *buf, int count) int Midi_out(struct 163 * midi_chan *, char *buf, int count) 164 * 165 * midi_{in,out} return actual size transfered 166 * 167 */ 168 169 170 /* 171 * midi_devs tailq, holder of all rmidi instances protected by midistat_lock 172 */ 173 174 TAILQ_HEAD(, snd_midi) midi_devs; 175 176 /* 177 * /dev/midistat variables and declarations, protected by midistat_lock 178 */ 179 180 static struct lock midistat_lock; 181 static int midistat_isopen = 0; 182 static struct sbuf midistat_sbuf; 183 static int midistat_bufptr; 184 static struct cdev *midistat_dev; 185 186 /* 187 * /dev/midistat dev_t declarations 188 */ 189 190 static d_open_t midistat_open; 191 static d_close_t midistat_close; 192 static d_read_t midistat_read; 193 194 static void midi_filter_detach(struct knote *); 195 static int midi_filter_read(struct knote *, long); 196 static int midi_filter_write(struct knote *, long); 197 198 static struct dev_ops midistat_ops = { 199 { "midistat", 0, D_MPSAFE }, 200 .d_open = midistat_open, 201 .d_close = midistat_close, 202 .d_read = midistat_read, 203 }; 204 205 static struct filterops midi_read_filterops = 206 { FILTEROP_ISFD, NULL, midi_filter_detach, midi_filter_read }; 207 static struct filterops midi_write_filterops = 208 { FILTEROP_ISFD, NULL, midi_filter_detach, midi_filter_write }; 209 210 /* 211 * /dev/rmidi dev_t declarations, struct variable access is protected by 212 * locks contained within the structure. 213 */ 214 215 static d_open_t midi_open; 216 static d_close_t midi_close; 217 static d_ioctl_t midi_ioctl; 218 static d_read_t midi_read; 219 static d_write_t midi_write; 220 static d_kqfilter_t midi_kqfilter; 221 222 static struct dev_ops midi_ops = { 223 { "rmidi", 0, D_MPSAFE }, 224 .d_open = midi_open, 225 .d_close = midi_close, 226 .d_read = midi_read, 227 .d_write = midi_write, 228 .d_ioctl = midi_ioctl, 229 .d_kqfilter = midi_kqfilter, 230 }; 231 232 /* 233 * Prototypes of library functions 234 */ 235 236 static int midi_destroy(struct snd_midi *, int); 237 static int midistat_prepare(struct sbuf * s); 238 static int midi_load(void); 239 static int midi_unload(void); 240 241 /* 242 * Misc declr. 243 */ 244 SYSCTL_NODE(_hw, OID_AUTO, midi, CTLFLAG_RD, 0, "Midi driver"); 245 static SYSCTL_NODE(_hw_midi, OID_AUTO, stat, CTLFLAG_RD, 0, "Status device"); 246 247 int midi_debug; 248 /* XXX: should this be moved into debug.midi? */ 249 SYSCTL_INT(_hw_midi, OID_AUTO, debug, CTLFLAG_RW, &midi_debug, 0, ""); 250 251 int midi_dumpraw; 252 SYSCTL_INT(_hw_midi, OID_AUTO, dumpraw, CTLFLAG_RW, &midi_dumpraw, 0, ""); 253 254 int midi_instroff; 255 SYSCTL_INT(_hw_midi, OID_AUTO, instroff, CTLFLAG_RW, &midi_instroff, 0, ""); 256 257 int midistat_verbose; 258 SYSCTL_INT(_hw_midi_stat, OID_AUTO, verbose, CTLFLAG_RW, 259 &midistat_verbose, 0, ""); 260 261 #define MIDI_DEBUG(l,a) if(midi_debug>=l) a 262 /* 263 * CODE START 264 */ 265 266 /* 267 * Register a new rmidi device. cls midi_if interface unit == 0 means 268 * auto-assign new unit number unit != 0 already assigned a unit number, eg. 269 * not the first channel provided by this device. channel, sub-unit 270 * cookie is passed back on MPU calls Typical device drivers will call with 271 * unit=0, channel=1..(number of channels) and cookie=soft_c and won't care 272 * what unit number is used. 273 * 274 * It is an error to call midi_init with an already used unit/channel combo. 275 * 276 * Returns NULL on error 277 * 278 */ 279 struct snd_midi * 280 midi_init(kobj_class_t cls, int unit, int channel, void *cookie) 281 { 282 struct snd_midi *m; 283 int i; 284 int inqsize, outqsize; 285 MIDI_TYPE *buf; 286 287 MIDI_DEBUG(1, kprintf("midiinit: unit %d/%d.\n", unit, channel)); 288 lockmgr(&midistat_lock, LK_EXCLUSIVE); 289 /* 290 * Protect against call with existing unit/channel or auto-allocate a 291 * new unit number. 292 */ 293 i = -1; 294 TAILQ_FOREACH(m, &midi_devs, link) { 295 lockmgr(&m->lock, LK_EXCLUSIVE); 296 if (unit != 0) { 297 if (m->unit == unit && m->channel == channel) { 298 lockmgr(&m->lock, LK_RELEASE); 299 goto err0; 300 } 301 } else { 302 /* 303 * Find a better unit number 304 */ 305 if (m->unit > i) 306 i = m->unit; 307 } 308 lockmgr(&m->lock, LK_RELEASE); 309 } 310 311 if (unit == 0) 312 unit = i + 1; 313 314 MIDI_DEBUG(1, kprintf("midiinit #2: unit %d/%d.\n", unit, channel)); 315 m = kmalloc(sizeof(*m), M_MIDI, M_WAITOK | M_ZERO); 316 317 m->synth = kmalloc(sizeof(*m->synth), M_MIDI, M_WAITOK | M_ZERO); 318 kobj_init((kobj_t)m->synth, &midisynth_class); 319 m->synth->m = m; 320 kobj_init((kobj_t)m, cls); 321 inqsize = MPU_INQSIZE(m, cookie); 322 outqsize = MPU_OUTQSIZE(m, cookie); 323 324 MIDI_DEBUG(1, kprintf("midiinit queues %d/%d.\n", inqsize, outqsize)); 325 if (!inqsize && !outqsize) 326 goto err1; 327 328 lockinit(&m->lock, "raw midi", 0, LK_CANRECURSE); 329 lockinit(&m->qlock, "q raw midi", 0, LK_CANRECURSE); 330 331 lockmgr(&m->lock, LK_EXCLUSIVE); 332 lockmgr(&m->qlock, LK_EXCLUSIVE); 333 334 if (inqsize) 335 buf = kmalloc(sizeof(MIDI_TYPE) * inqsize, M_MIDI, M_WAITOK); 336 else 337 buf = NULL; 338 339 MIDIQ_INIT(m->inq, buf, inqsize); 340 341 if (outqsize) 342 buf = kmalloc(sizeof(MIDI_TYPE) * outqsize, M_MIDI, M_WAITOK); 343 else 344 buf = NULL; 345 m->hiwat = outqsize / 2; 346 347 MIDIQ_INIT(m->outq, buf, outqsize); 348 349 if ((inqsize && !MIDIQ_BUF(m->inq)) || 350 (outqsize && !MIDIQ_BUF(m->outq))) 351 goto err2; 352 353 354 m->busy = 0; 355 m->flags = 0; 356 m->unit = unit; 357 m->channel = channel; 358 m->cookie = cookie; 359 360 if (MPU_INIT(m, cookie)) 361 goto err2; 362 363 lockmgr(&m->lock, LK_RELEASE); 364 lockmgr(&m->qlock, LK_RELEASE); 365 366 TAILQ_INSERT_TAIL(&midi_devs, m, link); 367 368 lockmgr(&midistat_lock, LK_RELEASE); 369 370 m->dev = make_dev(&midi_ops, 371 MIDIMKMINOR(unit, MIDI_DEV_RAW, channel), 372 UID_ROOT, GID_WHEEL, 0666, "midi%d.%d", unit, channel); 373 m->dev->si_drv1 = m; 374 375 return m; 376 377 err2: lockuninit(&m->qlock); 378 lockuninit(&m->lock); 379 380 if (MIDIQ_BUF(m->inq)) 381 kfree(MIDIQ_BUF(m->inq), M_MIDI); 382 if (MIDIQ_BUF(m->outq)) 383 kfree(MIDIQ_BUF(m->outq), M_MIDI); 384 err1: kfree(m, M_MIDI); 385 err0: lockmgr(&midistat_lock, LK_RELEASE); 386 MIDI_DEBUG(1, kprintf("midi_init ended in error\n")); 387 return NULL; 388 } 389 390 /* 391 * midi_uninit does not call MIDI_UNINIT, as since this is the implementors 392 * entry point. midi_unint if fact, does not send any methods. A call to 393 * midi_uninit is a defacto promise that you won't manipulate ch anymore 394 * 395 */ 396 397 int 398 midi_uninit(struct snd_midi *m) 399 { 400 int err; 401 402 err = ENXIO; 403 lockmgr(&midistat_lock, LK_EXCLUSIVE); 404 lockmgr(&m->lock, LK_EXCLUSIVE); 405 if (m->busy) { 406 if (!(m->rchan || m->wchan)) 407 goto err; 408 409 if (m->rchan) { 410 wakeup(&m->rchan); 411 m->rchan = 0; 412 } 413 if (m->wchan) { 414 wakeup(&m->wchan); 415 m->wchan = 0; 416 } 417 } 418 err = midi_destroy(m, 0); 419 if (!err) 420 goto exit; 421 422 err: lockmgr(&m->lock, LK_RELEASE); 423 exit: lockmgr(&midistat_lock, LK_RELEASE); 424 return err; 425 } 426 427 /* 428 * midi_in: process all data until the queue is full, then discards the rest. 429 * Since midi_in is a state machine, data discards can cause it to get out of 430 * whack. Process as much as possible. It calls, wakeup, selnotify and 431 * psignal at most once. 432 */ 433 434 #ifdef notdef 435 static int midi_lengths[] = {2, 2, 2, 2, 1, 1, 2, 0}; 436 437 #endif /* notdef */ 438 /* Number of bytes in a MIDI command */ 439 #define MIDI_LENGTH(d) (midi_lengths[((d) >> 4) & 7]) 440 #define MIDI_ACK 0xfe 441 #define MIDI_IS_STATUS(d) ((d) >= 0x80) 442 #define MIDI_IS_COMMON(d) ((d) >= 0xf0) 443 444 #define MIDI_SYSEX_START 0xF0 445 #define MIDI_SYSEX_END 0xF7 446 447 448 int 449 midi_in(struct snd_midi *m, MIDI_TYPE *buf, int size) 450 { 451 /* int i, sig, enq; */ 452 int used; 453 454 /* MIDI_TYPE data; */ 455 MIDI_DEBUG(5, kprintf("midi_in: m=%p size=%d\n", m, size)); 456 457 /* 458 * XXX: locking flub 459 */ 460 if (!(m->flags & M_RX)) 461 return size; 462 463 used = 0; 464 465 lockmgr(&m->qlock, LK_EXCLUSIVE); 466 #if 0 467 /* 468 * Don't bother queuing if not in read mode. Discard everything and 469 * return size so the caller doesn't freak out. 470 */ 471 472 if (!(m->flags & M_RX)) 473 return size; 474 475 for (i = sig = 0; i < size; i++) { 476 477 data = buf[i]; 478 enq = 0; 479 if (data == MIDI_ACK) 480 continue; 481 482 switch (m->inq_state) { 483 case MIDI_IN_START: 484 if (MIDI_IS_STATUS(data)) { 485 switch (data) { 486 case 0xf0: /* Sysex */ 487 m->inq_state = MIDI_IN_SYSEX; 488 break; 489 case 0xf1: /* MTC quarter frame */ 490 case 0xf3: /* Song select */ 491 m->inq_state = MIDI_IN_DATA; 492 enq = 1; 493 m->inq_left = 1; 494 break; 495 case 0xf2: /* Song position pointer */ 496 m->inq_state = MIDI_IN_DATA; 497 enq = 1; 498 m->inq_left = 2; 499 break; 500 default: 501 if (MIDI_IS_COMMON(data)) { 502 enq = 1; 503 sig = 1; 504 } else { 505 m->inq_state = MIDI_IN_DATA; 506 enq = 1; 507 m->inq_status = data; 508 m->inq_left = MIDI_LENGTH(data); 509 } 510 break; 511 } 512 } else if (MIDI_IS_STATUS(m->inq_status)) { 513 m->inq_state = MIDI_IN_DATA; 514 if (!MIDIQ_FULL(m->inq)) { 515 used++; 516 MIDIQ_ENQ(m->inq, &m->inq_status, 1); 517 } 518 enq = 1; 519 m->inq_left = MIDI_LENGTH(m->inq_status) - 1; 520 } 521 break; 522 /* 523 * End of case MIDI_IN_START: 524 */ 525 526 case MIDI_IN_DATA: 527 enq = 1; 528 if (--m->inq_left <= 0) 529 sig = 1;/* deliver data */ 530 break; 531 case MIDI_IN_SYSEX: 532 if (data == MIDI_SYSEX_END) 533 m->inq_state = MIDI_IN_START; 534 break; 535 } 536 537 if (enq) 538 if (!MIDIQ_FULL(m->inq)) { 539 MIDIQ_ENQ(m->inq, &data, 1); 540 used++; 541 } 542 /* 543 * End of the state machines main "for loop" 544 */ 545 } 546 if (sig) { 547 #endif 548 MIDI_DEBUG(6, kprintf("midi_in: len %jd avail %jd\n", 549 (intmax_t)MIDIQ_LEN(m->inq), 550 (intmax_t)MIDIQ_AVAIL(m->inq))); 551 if (MIDIQ_AVAIL(m->inq) > size) { 552 used = size; 553 MIDIQ_ENQ(m->inq, buf, size); 554 } else { 555 MIDI_DEBUG(4, kprintf("midi_in: Discarding data qu\n")); 556 lockmgr(&m->qlock, LK_RELEASE); 557 return 0; 558 } 559 if (m->rchan) { 560 wakeup(&m->rchan); 561 m->rchan = 0; 562 } 563 KNOTE(&m->rkq.ki_note, 0); 564 if (m->async) { 565 PHOLD(m->async); 566 ksignal(m->async, SIGIO); 567 PRELE(m->async); 568 } 569 #if 0 570 } 571 #endif 572 lockmgr(&m->qlock, LK_RELEASE); 573 return used; 574 } 575 576 /* 577 * midi_out: The only clearer of the M_TXEN flag. 578 */ 579 int 580 midi_out(struct snd_midi *m, MIDI_TYPE *buf, int size) 581 { 582 int used; 583 584 /* 585 * XXX: locking flub 586 */ 587 if (!(m->flags & M_TXEN)) 588 return 0; 589 590 MIDI_DEBUG(2, kprintf("midi_out: %p\n", m)); 591 lockmgr(&m->qlock, LK_EXCLUSIVE); 592 used = MIN(size, MIDIQ_LEN(m->outq)); 593 MIDI_DEBUG(3, kprintf("midi_out: used %d\n", used)); 594 if (used) 595 MIDIQ_DEQ(m->outq, buf, used); 596 if (MIDIQ_EMPTY(m->outq)) { 597 m->flags &= ~M_TXEN; 598 MPU_CALLBACKP(m, m->cookie, m->flags); 599 } 600 if (used && MIDIQ_AVAIL(m->outq) > m->hiwat) { 601 if (m->wchan) { 602 wakeup(&m->wchan); 603 m->wchan = 0; 604 } 605 KNOTE(&m->wkq.ki_note, 0); 606 if (m->async) { 607 PHOLD(m->async); 608 ksignal(m->async, SIGIO); 609 PRELE(m->async); 610 } 611 } 612 lockmgr(&m->qlock, LK_RELEASE); 613 return used; 614 } 615 616 617 /* 618 * /dev/rmidi#.# device access functions 619 */ 620 int 621 midi_open(struct dev_open_args *ap) 622 { 623 cdev_t i_dev = ap->a_head.a_dev; 624 int flags = ap->a_oflags; 625 struct snd_midi *m = i_dev->si_drv1; 626 int retval; 627 628 #if 0 /* XXX */ 629 MIDI_DEBUG(1, kprintf("midiopen %p %s %s\n", td, 630 flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : "")); 631 #endif 632 if (m == NULL) 633 return ENXIO; 634 635 lockmgr(&m->lock, LK_EXCLUSIVE); 636 lockmgr(&m->qlock, LK_EXCLUSIVE); 637 638 retval = 0; 639 640 if (flags & FREAD) { 641 if (MIDIQ_SIZE(m->inq) == 0) 642 retval = ENXIO; 643 else if (m->flags & M_RX) 644 retval = EBUSY; 645 if (retval) 646 goto err; 647 } 648 if (flags & FWRITE) { 649 if (MIDIQ_SIZE(m->outq) == 0) 650 retval = ENXIO; 651 else if (m->flags & M_TX) 652 retval = EBUSY; 653 if (retval) 654 goto err; 655 } 656 m->busy++; 657 658 m->rchan = 0; 659 m->wchan = 0; 660 m->async = 0; 661 662 if (flags & FREAD) { 663 m->flags |= M_RX | M_RXEN; 664 /* 665 * Only clear the inq, the outq might still have data to drain 666 * from a previous session 667 */ 668 MIDIQ_CLEAR(m->inq); 669 }; 670 671 if (flags & FWRITE) 672 m->flags |= M_TX; 673 674 MPU_CALLBACK(m, m->cookie, m->flags); 675 676 MIDI_DEBUG(2, kprintf("midi_open: opened.\n")); 677 678 err: lockmgr(&m->qlock, LK_RELEASE); 679 lockmgr(&m->lock, LK_RELEASE); 680 return retval; 681 } 682 683 int 684 midi_close(struct dev_close_args *ap) 685 { 686 cdev_t i_dev = ap->a_head.a_dev; 687 int flags = ap->a_fflag; 688 struct snd_midi *m = i_dev->si_drv1; 689 int retval; 690 int oldflags; 691 692 #if 0 /* XXX */ 693 MIDI_DEBUG(1, kprintf("midi_close %p %s %s\n", td, 694 flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : "")); 695 #endif 696 697 if (m == NULL) 698 return ENXIO; 699 700 lockmgr(&m->lock, LK_EXCLUSIVE); 701 lockmgr(&m->qlock, LK_EXCLUSIVE); 702 703 if ((flags & FREAD && !(m->flags & M_RX)) || 704 (flags & FWRITE && !(m->flags & M_TX))) { 705 retval = ENXIO; 706 goto err; 707 } 708 m->busy--; 709 710 oldflags = m->flags; 711 712 if (flags & FREAD) 713 m->flags &= ~(M_RX | M_RXEN); 714 if (flags & FWRITE) 715 m->flags &= ~M_TX; 716 717 if ((m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN))) 718 MPU_CALLBACK(m, m->cookie, m->flags); 719 720 MIDI_DEBUG(1, kprintf("midi_close: closed, busy = %d.\n", m->busy)); 721 722 lockmgr(&m->qlock, LK_RELEASE); 723 lockmgr(&m->lock, LK_RELEASE); 724 retval = 0; 725 err: return retval; 726 } 727 728 /* 729 * TODO: midi_read, per oss programmer's guide pg. 42 should return as soon 730 * as data is available. 731 */ 732 int 733 midi_read(struct dev_read_args *ap) 734 { 735 cdev_t i_dev = ap->a_head.a_dev; 736 struct uio *uio = ap->a_uio; 737 int ioflag = ap->a_ioflag; 738 #define MIDI_RSIZE 32 739 struct snd_midi *m = i_dev->si_drv1; 740 int retval; 741 int used; 742 char buf[MIDI_RSIZE]; 743 744 MIDI_DEBUG(5, kprintf("midiread: count=%lu\n", 745 (unsigned long)uio->uio_resid)); 746 747 retval = EIO; 748 749 if (m == NULL) 750 goto err0; 751 752 lockmgr(&m->lock, LK_EXCLUSIVE); 753 lockmgr(&m->qlock, LK_EXCLUSIVE); 754 755 if (!(m->flags & M_RX)) 756 goto err1; 757 758 while (uio->uio_resid > 0) { 759 while (MIDIQ_EMPTY(m->inq)) { 760 retval = EWOULDBLOCK; 761 if (ioflag & O_NONBLOCK) 762 goto err1; 763 lockmgr(&m->lock, LK_RELEASE); 764 m->rchan = 1; 765 retval = lksleep(&m->rchan, &m->qlock, 766 PCATCH, "midi RX", 0); 767 /* 768 * We slept, maybe things have changed since last 769 * dying check 770 */ 771 if (retval == EINTR) 772 goto err0; 773 if (m != i_dev->si_drv1) 774 retval = ENXIO; 775 /* if (retval && retval != ERESTART) */ 776 if (retval) 777 goto err0; 778 lockmgr(&m->lock, LK_EXCLUSIVE); 779 lockmgr(&m->qlock, LK_EXCLUSIVE); 780 m->rchan = 0; 781 if (!m->busy) 782 goto err1; 783 } 784 MIDI_DEBUG(6, kprintf("midi_read start\n")); 785 /* 786 * At this point, it is certain that m->inq has data 787 */ 788 789 used = MIN(MIDIQ_LEN(m->inq), uio->uio_resid); 790 used = MIN(used, MIDI_RSIZE); 791 792 MIDI_DEBUG(6, kprintf("midiread: uiomove cc=%d\n", used)); 793 MIDIQ_DEQ(m->inq, buf, used); 794 retval = uiomove(buf, used, uio); 795 if (retval) 796 goto err1; 797 } 798 799 /* 800 * If we Made it here then transfer is good 801 */ 802 retval = 0; 803 err1: lockmgr(&m->qlock, LK_RELEASE); 804 lockmgr(&m->lock, LK_RELEASE); 805 err0: MIDI_DEBUG(4, kprintf("midi_read: ret %d\n", retval)); 806 return retval; 807 } 808 809 /* 810 * midi_write: The only setter of M_TXEN 811 */ 812 813 int 814 midi_write(struct dev_write_args *ap) 815 { 816 cdev_t i_dev = ap->a_head.a_dev; 817 struct uio *uio = ap->a_uio; 818 int ioflag = ap->a_ioflag; 819 #define MIDI_WSIZE 32 820 struct snd_midi *m = i_dev->si_drv1; 821 int retval; 822 int used; 823 char buf[MIDI_WSIZE]; 824 825 826 MIDI_DEBUG(4, kprintf("midi_write\n")); 827 retval = 0; 828 if (m == NULL) 829 goto err0; 830 831 lockmgr(&m->lock, LK_EXCLUSIVE); 832 lockmgr(&m->qlock, LK_EXCLUSIVE); 833 834 if (!(m->flags & M_TX)) 835 goto err1; 836 837 while (uio->uio_resid > 0) { 838 while (MIDIQ_AVAIL(m->outq) == 0) { 839 retval = EWOULDBLOCK; 840 if (ioflag & O_NONBLOCK) 841 goto err1; 842 lockmgr(&m->lock, LK_RELEASE); 843 m->wchan = 1; 844 MIDI_DEBUG(3, kprintf("midi_write lksleep\n")); 845 retval = lksleep(&m->wchan, &m->qlock, 846 PCATCH, "midi TX", 0); 847 /* 848 * We slept, maybe things have changed since last 849 * dying check 850 */ 851 if (retval == EINTR) 852 goto err0; 853 if (m != i_dev->si_drv1) 854 retval = ENXIO; 855 if (retval) 856 goto err0; 857 lockmgr(&m->lock, LK_EXCLUSIVE); 858 lockmgr(&m->qlock, LK_EXCLUSIVE); 859 m->wchan = 0; 860 if (!m->busy) 861 goto err1; 862 } 863 864 /* 865 * We are certain than data can be placed on the queue 866 */ 867 868 used = MIN(MIDIQ_AVAIL(m->outq), uio->uio_resid); 869 used = MIN(used, MIDI_WSIZE); 870 MIDI_DEBUG(5, kprintf("midiout: resid %zd len %jd avail %jd\n", 871 uio->uio_resid, (intmax_t)MIDIQ_LEN(m->outq), 872 (intmax_t)MIDIQ_AVAIL(m->outq))); 873 874 875 MIDI_DEBUG(5, kprintf("midi_write: uiomove cc=%d\n", used)); 876 retval = uiomove(buf, used, uio); 877 if (retval) 878 goto err1; 879 MIDIQ_ENQ(m->outq, buf, used); 880 /* 881 * Inform the bottom half that data can be written 882 */ 883 if (!(m->flags & M_TXEN)) { 884 m->flags |= M_TXEN; 885 MPU_CALLBACK(m, m->cookie, m->flags); 886 } 887 } 888 /* 889 * If we Made it here then transfer is good 890 */ 891 retval = 0; 892 err1: lockmgr(&m->qlock, LK_RELEASE); 893 lockmgr(&m->lock, LK_RELEASE); 894 err0: return retval; 895 } 896 897 int 898 midi_ioctl(struct dev_ioctl_args *ap) 899 { 900 return ENXIO; 901 } 902 903 int 904 midi_kqfilter(struct dev_kqfilter_args *ap) 905 { 906 cdev_t dev = ap->a_head.a_dev; 907 struct knote *kn = ap->a_kn; 908 struct snd_midi *m; 909 struct klist *klist; 910 911 ap->a_result = 0; 912 m = dev->si_drv1; 913 914 switch (kn->kn_filter) { 915 case EVFILT_READ: 916 kn->kn_fop = &midi_read_filterops; 917 kn->kn_hook = (caddr_t)m; 918 klist = &m->rkq.ki_note; 919 break; 920 case EVFILT_WRITE: 921 kn->kn_fop = &midi_write_filterops; 922 kn->kn_hook = (caddr_t)m; 923 klist = &m->wkq.ki_note; 924 break; 925 default: 926 ap->a_result = EOPNOTSUPP; 927 return (0); 928 } 929 930 knote_insert(klist, kn); 931 932 return(0); 933 } 934 935 static void 936 midi_filter_detach(struct knote *kn) 937 { 938 struct snd_midi *m = (struct snd_midi *)kn->kn_hook; 939 struct klist *rklist = &m->rkq.ki_note; 940 struct klist *wklist = &m->wkq.ki_note; 941 942 knote_remove(rklist, kn); 943 knote_remove(wklist, kn); 944 } 945 946 static int 947 midi_filter_read(struct knote *kn, long hint) 948 { 949 struct snd_midi *m = (struct snd_midi *)kn->kn_hook; 950 int ready = 0; 951 952 lockmgr(&m->lock, LK_EXCLUSIVE); 953 lockmgr(&m->qlock, LK_EXCLUSIVE); 954 955 if (!MIDIQ_EMPTY(m->inq)) 956 ready = 1; 957 958 lockmgr(&m->lock, LK_RELEASE); 959 lockmgr(&m->qlock, LK_RELEASE); 960 961 return (ready); 962 } 963 964 static int 965 midi_filter_write(struct knote *kn, long hint) 966 { 967 struct snd_midi *m = (struct snd_midi *)kn->kn_hook; 968 int ready = 0; 969 970 lockmgr(&m->lock, LK_EXCLUSIVE); 971 lockmgr(&m->qlock, LK_EXCLUSIVE); 972 973 if (MIDIQ_AVAIL(m->outq) < m->hiwat) 974 ready = 1; 975 976 lockmgr(&m->lock, LK_RELEASE); 977 lockmgr(&m->qlock, LK_RELEASE); 978 979 return (ready); 980 } 981 982 /* 983 * /dev/midistat device functions 984 * 985 */ 986 static int 987 midistat_open(struct dev_open_args *ap) 988 { 989 int error; 990 991 MIDI_DEBUG(1, kprintf("midistat_open\n")); 992 lockmgr(&midistat_lock, LK_EXCLUSIVE); 993 994 if (midistat_isopen) { 995 lockmgr(&midistat_lock, LK_RELEASE); 996 return EBUSY; 997 } 998 midistat_isopen = 1; 999 lockmgr(&midistat_lock, LK_RELEASE); 1000 1001 if (sbuf_new(&midistat_sbuf, NULL, 4096, SBUF_AUTOEXTEND) == NULL) { 1002 error = ENXIO; 1003 lockmgr(&midistat_lock, LK_EXCLUSIVE); 1004 goto out; 1005 } 1006 lockmgr(&midistat_lock, LK_EXCLUSIVE); 1007 midistat_bufptr = 0; 1008 error = (midistat_prepare(&midistat_sbuf) > 0) ? 0 : ENOMEM; 1009 1010 out: if (error) 1011 midistat_isopen = 0; 1012 lockmgr(&midistat_lock, LK_RELEASE); 1013 return error; 1014 } 1015 1016 static int 1017 midistat_close(struct dev_close_args *ap) 1018 { 1019 MIDI_DEBUG(1, kprintf("midistat_close\n")); 1020 lockmgr(&midistat_lock, LK_EXCLUSIVE); 1021 if (!midistat_isopen) { 1022 lockmgr(&midistat_lock, LK_RELEASE); 1023 return EBADF; 1024 } 1025 sbuf_delete(&midistat_sbuf); 1026 midistat_isopen = 0; 1027 1028 lockmgr(&midistat_lock, LK_RELEASE); 1029 return 0; 1030 } 1031 1032 static int 1033 midistat_read(struct dev_read_args *ap) 1034 { 1035 struct uio *buf = ap->a_uio; 1036 int l, err; 1037 1038 MIDI_DEBUG(4, kprintf("midistat_read\n")); 1039 lockmgr(&midistat_lock, LK_EXCLUSIVE); 1040 if (!midistat_isopen) { 1041 lockmgr(&midistat_lock, LK_RELEASE); 1042 return EBADF; 1043 } 1044 l = min(buf->uio_resid, sbuf_len(&midistat_sbuf) - midistat_bufptr); 1045 err = 0; 1046 if (l > 0) { 1047 lockmgr(&midistat_lock, LK_RELEASE); 1048 err = uiomove(sbuf_data(&midistat_sbuf) + midistat_bufptr, l, 1049 buf); 1050 lockmgr(&midistat_lock, LK_EXCLUSIVE); 1051 } else 1052 l = 0; 1053 midistat_bufptr += l; 1054 lockmgr(&midistat_lock, LK_RELEASE); 1055 return err; 1056 } 1057 1058 /* 1059 * Module library functions 1060 */ 1061 1062 static int 1063 midistat_prepare(struct sbuf *s) 1064 { 1065 struct snd_midi *m; 1066 1067 KKASSERT(lockowned(&midistat_lock)); 1068 1069 sbuf_printf(s, "FreeBSD Midi Driver (midi2)\n"); 1070 if (TAILQ_EMPTY(&midi_devs)) { 1071 sbuf_printf(s, "No devices installed.\n"); 1072 sbuf_finish(s); 1073 return sbuf_len(s); 1074 } 1075 sbuf_printf(s, "Installed devices:\n"); 1076 1077 TAILQ_FOREACH(m, &midi_devs, link) { 1078 lockmgr(&m->lock, LK_EXCLUSIVE); 1079 sbuf_printf(s, "%s [%d/%d:%s]", m->name, m->unit, m->channel, 1080 MPU_PROVIDER(m, m->cookie)); 1081 sbuf_printf(s, "%s", MPU_DESCR(m, m->cookie, midistat_verbose)); 1082 sbuf_printf(s, "\n"); 1083 lockmgr(&m->lock, LK_RELEASE); 1084 } 1085 1086 sbuf_finish(s); 1087 return sbuf_len(s); 1088 } 1089 1090 #ifdef notdef 1091 /* 1092 * Convert IOCTL command to string for debugging 1093 */ 1094 1095 static char * 1096 midi_cmdname(int cmd) 1097 { 1098 static struct { 1099 int cmd; 1100 char *name; 1101 } *tab, cmdtab_midiioctl[] = { 1102 #define A(x) {x, ## x} 1103 /* 1104 * Once we have some real IOCTLs define, the following will 1105 * be relavant. 1106 * 1107 * A(SNDCTL_MIDI_PRETIME), A(SNDCTL_MIDI_MPUMODE), 1108 * A(SNDCTL_MIDI_MPUCMD), A(SNDCTL_SYNTH_INFO), 1109 * A(SNDCTL_MIDI_INFO), A(SNDCTL_SYNTH_MEMAVL), 1110 * A(SNDCTL_FM_LOAD_INSTR), A(SNDCTL_FM_4OP_ENABLE), 1111 * A(MIOSPASSTHRU), A(MIOGPASSTHRU), A(AIONWRITE), 1112 * A(AIOGSIZE), A(AIOSSIZE), A(AIOGFMT), A(AIOSFMT), 1113 * A(AIOGMIX), A(AIOSMIX), A(AIOSTOP), A(AIOSYNC), 1114 * A(AIOGCAP), 1115 */ 1116 #undef A 1117 { 1118 -1, "unknown" 1119 }, 1120 }; 1121 1122 for (tab = cmdtab_midiioctl; tab->cmd != cmd && tab->cmd != -1; tab++); 1123 return tab->name; 1124 } 1125 1126 #endif /* notdef */ 1127 1128 /* 1129 * midisynth 1130 */ 1131 1132 1133 int 1134 midisynth_open(void *n, void *arg, int flags) 1135 { 1136 struct snd_midi *m = ((struct synth_midi *)n)->m; 1137 int retval; 1138 1139 MIDI_DEBUG(1, kprintf("midisynth_open %s %s\n", 1140 flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : "")); 1141 1142 if (m == NULL) 1143 return ENXIO; 1144 1145 lockmgr(&m->lock, LK_EXCLUSIVE); 1146 lockmgr(&m->qlock, LK_EXCLUSIVE); 1147 1148 retval = 0; 1149 1150 if (flags & FREAD) { 1151 if (MIDIQ_SIZE(m->inq) == 0) 1152 retval = ENXIO; 1153 else if (m->flags & M_RX) 1154 retval = EBUSY; 1155 if (retval) 1156 goto err; 1157 } 1158 if (flags & FWRITE) { 1159 if (MIDIQ_SIZE(m->outq) == 0) 1160 retval = ENXIO; 1161 else if (m->flags & M_TX) 1162 retval = EBUSY; 1163 if (retval) 1164 goto err; 1165 } 1166 m->busy++; 1167 1168 /* 1169 * TODO: Consider m->async = 0; 1170 */ 1171 1172 if (flags & FREAD) { 1173 m->flags |= M_RX | M_RXEN; 1174 /* 1175 * Only clear the inq, the outq might still have data to drain 1176 * from a previous session 1177 */ 1178 MIDIQ_CLEAR(m->inq); 1179 m->rchan = 0; 1180 }; 1181 1182 if (flags & FWRITE) { 1183 m->flags |= M_TX; 1184 m->wchan = 0; 1185 } 1186 m->synth_flags = flags & (FREAD | FWRITE); 1187 1188 MPU_CALLBACK(m, m->cookie, m->flags); 1189 1190 1191 err: lockmgr(&m->qlock, LK_RELEASE); 1192 lockmgr(&m->lock, LK_RELEASE); 1193 MIDI_DEBUG(2, kprintf("midisynth_open: return %d.\n", retval)); 1194 return retval; 1195 } 1196 1197 int 1198 midisynth_close(void *n) 1199 { 1200 struct snd_midi *m = ((struct synth_midi *)n)->m; 1201 int retval; 1202 int oldflags; 1203 1204 MIDI_DEBUG(1, kprintf("midisynth_close %s %s\n", 1205 m->synth_flags & FREAD ? "M_RX" : "", 1206 m->synth_flags & FWRITE ? "M_TX" : "")); 1207 1208 if (m == NULL) 1209 return ENXIO; 1210 1211 lockmgr(&m->lock, LK_EXCLUSIVE); 1212 lockmgr(&m->qlock, LK_EXCLUSIVE); 1213 1214 if ((m->synth_flags & FREAD && !(m->flags & M_RX)) || 1215 (m->synth_flags & FWRITE && !(m->flags & M_TX))) { 1216 retval = ENXIO; 1217 goto err; 1218 } 1219 m->busy--; 1220 1221 oldflags = m->flags; 1222 1223 if (m->synth_flags & FREAD) 1224 m->flags &= ~(M_RX | M_RXEN); 1225 if (m->synth_flags & FWRITE) 1226 m->flags &= ~M_TX; 1227 1228 if ((m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN))) 1229 MPU_CALLBACK(m, m->cookie, m->flags); 1230 1231 MIDI_DEBUG(1, kprintf("midi_close: closed, busy = %d.\n", m->busy)); 1232 1233 lockmgr(&m->qlock, LK_RELEASE); 1234 lockmgr(&m->lock, LK_RELEASE); 1235 retval = 0; 1236 err: return retval; 1237 } 1238 1239 /* 1240 * Always blocking. 1241 */ 1242 1243 int 1244 midisynth_writeraw(void *n, uint8_t *buf, size_t len) 1245 { 1246 struct snd_midi *m = ((struct synth_midi *)n)->m; 1247 int retval; 1248 int used; 1249 int i; 1250 1251 MIDI_DEBUG(4, kprintf("midisynth_writeraw\n")); 1252 1253 retval = 0; 1254 1255 if (m == NULL) 1256 return ENXIO; 1257 1258 lockmgr(&m->lock, LK_EXCLUSIVE); 1259 lockmgr(&m->qlock, LK_EXCLUSIVE); 1260 1261 if (!(m->flags & M_TX)) 1262 goto err1; 1263 1264 if (midi_dumpraw) 1265 kprintf("midi dump: "); 1266 1267 while (len > 0) { 1268 while (MIDIQ_AVAIL(m->outq) == 0) { 1269 if (!(m->flags & M_TXEN)) { 1270 m->flags |= M_TXEN; 1271 MPU_CALLBACK(m, m->cookie, m->flags); 1272 } 1273 lockmgr(&m->lock, LK_RELEASE); 1274 m->wchan = 1; 1275 MIDI_DEBUG(3, kprintf("midisynth_writeraw lksleep\n")); 1276 retval = lksleep(&m->wchan, &m->qlock, 1277 PCATCH, "midi TX", 0); 1278 /* 1279 * We slept, maybe things have changed since last 1280 * dying check 1281 */ 1282 if (retval == EINTR) 1283 goto err0; 1284 1285 if (retval) 1286 goto err0; 1287 lockmgr(&m->lock, LK_EXCLUSIVE); 1288 lockmgr(&m->qlock, LK_EXCLUSIVE); 1289 m->wchan = 0; 1290 if (!m->busy) 1291 goto err1; 1292 } 1293 1294 /* 1295 * We are certain than data can be placed on the queue 1296 */ 1297 1298 used = MIN(MIDIQ_AVAIL(m->outq), len); 1299 used = MIN(used, MIDI_WSIZE); 1300 MIDI_DEBUG(5, 1301 kprintf("midi_synth: resid %zu len %jd avail %jd\n", 1302 len, (intmax_t)MIDIQ_LEN(m->outq), 1303 (intmax_t)MIDIQ_AVAIL(m->outq))); 1304 1305 if (midi_dumpraw) 1306 for (i = 0; i < used; i++) 1307 kprintf("%x ", buf[i]); 1308 1309 MIDIQ_ENQ(m->outq, buf, used); 1310 len -= used; 1311 1312 /* 1313 * Inform the bottom half that data can be written 1314 */ 1315 if (!(m->flags & M_TXEN)) { 1316 m->flags |= M_TXEN; 1317 MPU_CALLBACK(m, m->cookie, m->flags); 1318 } 1319 } 1320 /* 1321 * If we Made it here then transfer is good 1322 */ 1323 if (midi_dumpraw) 1324 kprintf("\n"); 1325 1326 retval = 0; 1327 err1: lockmgr(&m->qlock, LK_RELEASE); 1328 lockmgr(&m->lock, LK_RELEASE); 1329 err0: return retval; 1330 } 1331 1332 static int 1333 midisynth_killnote(void *n, uint8_t chn, uint8_t note, uint8_t vel) 1334 { 1335 u_char c[3]; 1336 1337 1338 if (note > 127 || chn > 15) 1339 return (EINVAL); 1340 1341 if (vel > 127) 1342 vel = 127; 1343 1344 if (vel == 64) { 1345 c[0] = 0x90 | (chn & 0x0f); /* Note on. */ 1346 c[1] = (u_char)note; 1347 c[2] = 0; 1348 } else { 1349 c[0] = 0x80 | (chn & 0x0f); /* Note off. */ 1350 c[1] = (u_char)note; 1351 c[2] = (u_char)vel; 1352 } 1353 1354 return midisynth_writeraw(n, c, 3); 1355 } 1356 1357 static int 1358 midisynth_setinstr(void *n, uint8_t chn, uint16_t instr) 1359 { 1360 u_char c[2]; 1361 1362 if (instr > 127 || chn > 15) 1363 return EINVAL; 1364 1365 c[0] = 0xc0 | (chn & 0x0f); /* Progamme change. */ 1366 c[1] = instr + midi_instroff; 1367 1368 return midisynth_writeraw(n, c, 2); 1369 } 1370 1371 static int 1372 midisynth_startnote(void *n, uint8_t chn, uint8_t note, uint8_t vel) 1373 { 1374 u_char c[3]; 1375 1376 if (note > 127 || chn > 15) 1377 return EINVAL; 1378 1379 if (vel > 127) 1380 vel = 127; 1381 1382 c[0] = 0x90 | (chn & 0x0f); /* Note on. */ 1383 c[1] = (u_char)note; 1384 c[2] = (u_char)vel; 1385 1386 return midisynth_writeraw(n, c, 3); 1387 } 1388 static int 1389 midisynth_alloc(void *n, uint8_t chan, uint8_t note) 1390 { 1391 return chan; 1392 } 1393 1394 static int 1395 midisynth_controller(void *n, uint8_t chn, uint8_t ctrlnum, uint16_t val) 1396 { 1397 u_char c[3]; 1398 1399 if (ctrlnum > 127 || chn > 15) 1400 return EINVAL; 1401 1402 c[0] = 0xb0 | (chn & 0x0f); /* Control Message. */ 1403 c[1] = ctrlnum; 1404 c[2] = val; 1405 return midisynth_writeraw(n, c, 3); 1406 } 1407 1408 static int 1409 midisynth_bender(void *n, uint8_t chn, uint16_t val) 1410 { 1411 u_char c[3]; 1412 1413 1414 if (val > 16383 || chn > 15) 1415 return EINVAL; 1416 1417 c[0] = 0xe0 | (chn & 0x0f); /* Pitch bend. */ 1418 c[1] = (u_char)val & 0x7f; 1419 c[2] = (u_char)(val >> 7) & 0x7f; 1420 1421 return midisynth_writeraw(n, c, 3); 1422 } 1423 1424 /* 1425 * Single point of midi destructions. 1426 */ 1427 static int 1428 midi_destroy(struct snd_midi *m, int midiuninit) 1429 { 1430 1431 KKASSERT(lockowned(&midistat_lock)); 1432 KKASSERT(lockowned(&m->lock)); 1433 1434 MIDI_DEBUG(3, kprintf("midi_destroy\n")); 1435 m->dev->si_drv1 = NULL; 1436 lockmgr(&m->lock, LK_RELEASE); /* XXX */ 1437 destroy_dev(m->dev); 1438 TAILQ_REMOVE(&midi_devs, m, link); 1439 if (midiuninit) 1440 MPU_UNINIT(m, m->cookie); 1441 kfree(MIDIQ_BUF(m->inq), M_MIDI); 1442 kfree(MIDIQ_BUF(m->outq), M_MIDI); 1443 lockuninit(&m->qlock); 1444 lockuninit(&m->lock); 1445 kfree(m, M_MIDI); 1446 return 0; 1447 } 1448 1449 /* 1450 * Load and unload functions, creates the /dev/midistat device 1451 */ 1452 1453 static int 1454 midi_load(void) 1455 { 1456 lockinit(&midistat_lock, "midistat lock", 0, LK_CANRECURSE); 1457 TAILQ_INIT(&midi_devs); /* Initialize the queue. */ 1458 1459 midistat_dev = make_dev(&midistat_ops, 1460 MIDIMKMINOR(0, MIDI_DEV_MIDICTL, 0), 1461 UID_ROOT, GID_WHEEL, 0666, "midistat"); 1462 1463 return 0; 1464 } 1465 1466 static int 1467 midi_unload(void) 1468 { 1469 struct snd_midi *m; 1470 int retval; 1471 1472 MIDI_DEBUG(1, kprintf("midi_unload()\n")); 1473 retval = EBUSY; 1474 lockmgr(&midistat_lock, LK_EXCLUSIVE); 1475 if (midistat_isopen) 1476 goto exit0; 1477 1478 TAILQ_FOREACH(m, &midi_devs, link) { 1479 lockmgr(&m->lock, LK_EXCLUSIVE); 1480 if (m->busy) 1481 retval = EBUSY; 1482 else 1483 retval = midi_destroy(m, 1); 1484 if (retval) 1485 goto exit1; 1486 } 1487 1488 lockmgr(&midistat_lock, LK_RELEASE); /* XXX */ 1489 1490 destroy_dev(midistat_dev); 1491 /* 1492 * Made it here then unload is complete 1493 */ 1494 lockuninit(&midistat_lock); 1495 return 0; 1496 1497 exit1: 1498 lockmgr(&m->lock, LK_RELEASE); 1499 exit0: 1500 lockmgr(&midistat_lock, LK_RELEASE); 1501 if (retval) 1502 MIDI_DEBUG(2, kprintf("midi_unload: failed\n")); 1503 return retval; 1504 } 1505 1506 extern int seq_modevent(module_t mod, int type, void *data); 1507 1508 static int 1509 midi_modevent(module_t mod, int type, void *data) 1510 { 1511 int retval; 1512 1513 retval = 0; 1514 1515 switch (type) { 1516 case MOD_LOAD: 1517 retval = midi_load(); 1518 #if 0 1519 if (retval == 0) 1520 retval = seq_modevent(mod, type, data); 1521 #endif 1522 break; 1523 1524 case MOD_UNLOAD: 1525 retval = midi_unload(); 1526 #if 0 1527 if (retval == 0) 1528 retval = seq_modevent(mod, type, data); 1529 #endif 1530 break; 1531 1532 default: 1533 break; 1534 } 1535 1536 return retval; 1537 } 1538 1539 kobj_t 1540 midimapper_addseq(void *arg1, int *unit, void **cookie) 1541 { 1542 unit = 0; 1543 1544 return (kobj_t)arg1; 1545 } 1546 1547 int 1548 midimapper_open(void *arg1, void **cookie) 1549 { 1550 int retval = 0; 1551 struct snd_midi *m; 1552 1553 lockmgr(&midistat_lock, LK_EXCLUSIVE); 1554 1555 TAILQ_FOREACH(m, &midi_devs, link) { 1556 retval++; 1557 } 1558 1559 lockmgr(&midistat_lock, LK_RELEASE); 1560 return retval; 1561 } 1562 1563 int 1564 midimapper_close(void *arg1, void *cookie) 1565 { 1566 return 0; 1567 } 1568 1569 kobj_t 1570 midimapper_fetch_synth(void *arg, void *cookie, int unit) 1571 { 1572 struct snd_midi *m; 1573 int retval = 0; 1574 1575 lockmgr(&midistat_lock, LK_EXCLUSIVE); 1576 1577 TAILQ_FOREACH(m, &midi_devs, link) { 1578 if (unit == retval) { 1579 lockmgr(&midistat_lock, LK_RELEASE); 1580 return (kobj_t)m->synth; 1581 } 1582 retval++; 1583 } 1584 1585 lockmgr(&midistat_lock, LK_RELEASE); 1586 return NULL; 1587 } 1588 1589 DEV_MODULE(midi, midi_modevent, NULL); 1590 MODULE_VERSION(midi, 1); 1591