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