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