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