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