The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sound/midi/midi.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-NetBSD
    3  *
    4  * Copyright (c) 2003 Mathew Kanner
    5  * Copyright (c) 1998 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Lennart Augustsson (augustss@netbsd.org).
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   30  * POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33  /*
   34   * Parts of this file started out as NetBSD: midi.c 1.31
   35   * They are mostly gone.  Still the most obvious will be the state
   36   * machine midi_in
   37   */
   38 
   39 #include <sys/cdefs.h>
   40 __FBSDID("$FreeBSD$");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/queue.h>
   45 #include <sys/kernel.h>
   46 #include <sys/lock.h>
   47 #include <sys/mutex.h>
   48 #include <sys/proc.h>
   49 #include <sys/signalvar.h>
   50 #include <sys/conf.h>
   51 #include <sys/selinfo.h>
   52 #include <sys/sysctl.h>
   53 #include <sys/malloc.h>
   54 #include <sys/sx.h>
   55 #include <sys/proc.h>
   56 #include <sys/fcntl.h>
   57 #include <sys/types.h>
   58 #include <sys/uio.h>
   59 #include <sys/poll.h>
   60 #include <sys/sbuf.h>
   61 #include <sys/kobj.h>
   62 #include <sys/module.h>
   63 
   64 #ifdef HAVE_KERNEL_OPTION_HEADERS
   65 #include "opt_snd.h"
   66 #endif
   67 
   68 #include <dev/sound/midi/midi.h>
   69 #include "mpu_if.h"
   70 
   71 #include <dev/sound/midi/midiq.h>
   72 #include "synth_if.h"
   73 MALLOC_DEFINE(M_MIDI, "midi buffers", "Midi data allocation area");
   74 
   75 #ifndef KOBJMETHOD_END
   76 #define KOBJMETHOD_END  { NULL, NULL }
   77 #endif
   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 
   85 enum 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
  101 struct 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
  117                                          * writes from userland */
  118         enum midi_states inq_state;
  119         int     inq_status, inq_left;   /* Variables for the state machine in
  120                                          * Midi_in, this is to provide that
  121                                          * signals 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 
  130 struct synth_midi {
  131         KOBJ_FIELDS;
  132         struct snd_midi *m;
  133 };
  134 
  135 static synth_open_t midisynth_open;
  136 static synth_close_t midisynth_close;
  137 static synth_writeraw_t midisynth_writeraw;
  138 static synth_killnote_t midisynth_killnote;
  139 static synth_startnote_t midisynth_startnote;
  140 static synth_setinstr_t midisynth_setinstr;
  141 static synth_alloc_t midisynth_alloc;
  142 static synth_controller_t midisynth_controller;
  143 static synth_bender_t midisynth_bender;
  144 
  145 static kobj_method_t midisynth_methods[] = {
  146         KOBJMETHOD(synth_open, midisynth_open),
  147         KOBJMETHOD(synth_close, midisynth_close),
  148         KOBJMETHOD(synth_writeraw, midisynth_writeraw),
  149         KOBJMETHOD(synth_setinstr, midisynth_setinstr),
  150         KOBJMETHOD(synth_startnote, midisynth_startnote),
  151         KOBJMETHOD(synth_killnote, midisynth_killnote),
  152         KOBJMETHOD(synth_alloc, midisynth_alloc),
  153         KOBJMETHOD(synth_controller, midisynth_controller),
  154         KOBJMETHOD(synth_bender, midisynth_bender),
  155         KOBJMETHOD_END
  156 };
  157 
  158 DEFINE_CLASS(midisynth, midisynth_methods, 0);
  159 
  160 /*
  161  * Module Exports & Interface
  162  *
  163  * struct midi_chan *midi_init(MPU_CLASS cls, int unit, int chan,
  164  *     void *cookie)
  165  * int midi_uninit(struct snd_midi *)
  166  *
  167  * 0 == no error
  168  * EBUSY or other error
  169  *
  170  * int midi_in(struct snd_midi *, char *buf, int count)
  171  * int midi_out(struct snd_midi *, char *buf, int count)
  172  *
  173  * midi_{in,out} return actual size transfered
  174  *
  175  */
  176 
  177 /*
  178  * midi_devs tailq, holder of all rmidi instances protected by midistat_lock
  179  */
  180 
  181 TAILQ_HEAD(, snd_midi) midi_devs;
  182 
  183 /*
  184  * /dev/midistat variables and declarations, protected by midistat_lock
  185  */
  186 
  187 static struct sx midistat_lock;
  188 static int      midistat_isopen = 0;
  189 static struct sbuf midistat_sbuf;
  190 static struct cdev *midistat_dev;
  191 
  192 /*
  193  * /dev/midistat        dev_t declarations
  194  */
  195 
  196 static d_open_t midistat_open;
  197 static d_close_t midistat_close;
  198 static d_read_t midistat_read;
  199 
  200 static struct cdevsw midistat_cdevsw = {
  201         .d_version = D_VERSION,
  202         .d_open = midistat_open,
  203         .d_close = midistat_close,
  204         .d_read = midistat_read,
  205         .d_name = "midistat",
  206 };
  207 
  208 /*
  209  * /dev/rmidi dev_t declarations, struct variable access is protected by
  210  * locks contained within the structure.
  211  */
  212 
  213 static d_open_t midi_open;
  214 static d_close_t midi_close;
  215 static d_ioctl_t midi_ioctl;
  216 static d_read_t midi_read;
  217 static d_write_t midi_write;
  218 static d_poll_t midi_poll;
  219 
  220 static 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 
  235 static int      midi_destroy(struct snd_midi *, int);
  236 static int      midistat_prepare(struct sbuf * s);
  237 static int      midi_load(void);
  238 static int      midi_unload(void);
  239 
  240 /*
  241  * Misc declr.
  242  */
  243 SYSCTL_NODE(_hw, OID_AUTO, midi, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
  244     "Midi driver");
  245 static SYSCTL_NODE(_hw_midi, OID_AUTO, stat, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
  246     "Status device");
  247 
  248 int             midi_debug;
  249 /* XXX: should this be moved into debug.midi? */
  250 SYSCTL_INT(_hw_midi, OID_AUTO, debug, CTLFLAG_RW, &midi_debug, 0, "");
  251 
  252 int             midi_dumpraw;
  253 SYSCTL_INT(_hw_midi, OID_AUTO, dumpraw, CTLFLAG_RW, &midi_dumpraw, 0, "");
  254 
  255 int             midi_instroff;
  256 SYSCTL_INT(_hw_midi, OID_AUTO, instroff, CTLFLAG_RW, &midi_instroff, 0, "");
  257 
  258 int             midistat_verbose;
  259 SYSCTL_INT(_hw_midi_stat, OID_AUTO, verbose, CTLFLAG_RW, 
  260         &midistat_verbose, 0, "");
  261 
  262 #define MIDI_DEBUG(l,a) if(midi_debug>=l) a
  263 /*
  264  * CODE START
  265  */
  266 
  267 /*
  268  * Register a new rmidi device. cls midi_if interface unit == 0 means
  269  * auto-assign new unit number unit != 0 already assigned a unit number, eg.
  270  * not the first channel provided by this device. channel,      sub-unit
  271  * cookie is passed back on MPU calls Typical device drivers will call with
  272  * unit=0, channel=1..(number of channels) and cookie=soft_c and won't care
  273  * what unit number is used.
  274  *
  275  * It is an error to call midi_init with an already used unit/channel combo.
  276  *
  277  * Returns NULL on error
  278  *
  279  */
  280 struct snd_midi *
  281 midi_init(kobj_class_t cls, int unit, int channel, void *cookie)
  282 {
  283         struct snd_midi *m;
  284         int i;
  285         int inqsize, outqsize;
  286         MIDI_TYPE *buf;
  287 
  288         MIDI_DEBUG(1, printf("midiinit: unit %d/%d.\n", unit, channel));
  289         sx_xlock(&midistat_lock);
  290         /*
  291          * Protect against call with existing unit/channel or auto-allocate a
  292          * new unit number.
  293          */
  294         i = -1;
  295         TAILQ_FOREACH(m, &midi_devs, link) {
  296                 mtx_lock(&m->lock);
  297                 if (unit != 0) {
  298                         if (m->unit == unit && m->channel == channel) {
  299                                 mtx_unlock(&m->lock);
  300                                 goto err0;
  301                         }
  302                 } else {
  303                         /*
  304                          * Find a better unit number
  305                          */
  306                         if (m->unit > i)
  307                                 i = m->unit;
  308                 }
  309                 mtx_unlock(&m->lock);
  310         }
  311 
  312         if (unit == 0)
  313                 unit = i + 1;
  314 
  315         MIDI_DEBUG(1, printf("midiinit #2: unit %d/%d.\n", unit, channel));
  316         m = malloc(sizeof(*m), M_MIDI, M_WAITOK | M_ZERO);
  317         m->synth = malloc(sizeof(*m->synth), M_MIDI, M_WAITOK | M_ZERO);
  318         kobj_init((kobj_t)m->synth, &midisynth_class);
  319         m->synth->m = m;
  320         kobj_init((kobj_t)m, cls);
  321         inqsize = MPU_INQSIZE(m, cookie);
  322         outqsize = MPU_OUTQSIZE(m, cookie);
  323 
  324         MIDI_DEBUG(1, printf("midiinit queues %d/%d.\n", inqsize, outqsize));
  325         if (!inqsize && !outqsize)
  326                 goto err1;
  327 
  328         mtx_init(&m->lock, "raw midi", NULL, 0);
  329         mtx_init(&m->qlock, "q raw midi", NULL, 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         m->busy = 0;
  354         m->flags = 0;
  355         m->unit = unit;
  356         m->channel = channel;
  357         m->cookie = cookie;
  358 
  359         if (MPU_INIT(m, cookie))
  360                 goto err2;
  361 
  362         mtx_unlock(&m->lock);
  363         mtx_unlock(&m->qlock);
  364 
  365         TAILQ_INSERT_TAIL(&midi_devs, m, link);
  366 
  367         sx_xunlock(&midistat_lock);
  368 
  369         m->dev = make_dev(&midi_cdevsw,
  370             MIDIMKMINOR(unit, MIDI_DEV_RAW, channel),
  371             UID_ROOT, GID_WHEEL, 0666, "midi%d.%d", unit, channel);
  372         m->dev->si_drv1 = m;
  373 
  374         return m;
  375 
  376 err2:
  377         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);
  384 err1:
  385         free(m->synth, M_MIDI);
  386         free(m, M_MIDI);
  387 err0:
  388         sx_xunlock(&midistat_lock);
  389         MIDI_DEBUG(1, printf("midi_init ended in error\n"));
  390         return NULL;
  391 }
  392 
  393 /*
  394  * midi_uninit does not call MIDI_UNINIT, as since this is the implementors
  395  * entry point. midi_uninit if fact, does not send any methods. A call to
  396  * midi_uninit is a defacto promise that you won't manipulate ch anymore
  397  *
  398  */
  399 
  400 int
  401 midi_uninit(struct snd_midi *m)
  402 {
  403         int err;
  404 
  405         err = EBUSY;
  406         sx_xlock(&midistat_lock);
  407         mtx_lock(&m->lock);
  408         if (m->busy) {
  409                 if (!(m->rchan || m->wchan))
  410                         goto err;
  411 
  412                 if (m->rchan) {
  413                         wakeup(&m->rchan);
  414                         m->rchan = 0;
  415                 }
  416                 if (m->wchan) {
  417                         wakeup(&m->wchan);
  418                         m->wchan = 0;
  419                 }
  420         }
  421         err = midi_destroy(m, 0);
  422         if (!err)
  423                 goto exit;
  424 
  425 err:
  426         mtx_unlock(&m->lock);
  427 exit:
  428         sx_xunlock(&midistat_lock);
  429         return err;
  430 }
  431 
  432 /*
  433  * midi_in: process all data until the queue is full, then discards the rest.
  434  * Since midi_in is a state machine, data discards can cause it to get out of
  435  * whack.  Process as much as possible.  It calls, wakeup, selnotify and
  436  * psignal at most once.
  437  */
  438 
  439 #ifdef notdef
  440 static int midi_lengths[] = {2, 2, 2, 2, 1, 1, 2, 0};
  441 
  442 #endif                                  /* notdef */
  443 /* Number of bytes in a MIDI command */
  444 #define MIDI_LENGTH(d) (midi_lengths[((d) >> 4) & 7])
  445 #define MIDI_ACK        0xfe
  446 #define MIDI_IS_STATUS(d) ((d) >= 0x80)
  447 #define MIDI_IS_COMMON(d) ((d) >= 0xf0)
  448 
  449 #define MIDI_SYSEX_START        0xF0
  450 #define MIDI_SYSEX_END      0xF7
  451 
  452 int
  453 midi_in(struct snd_midi *m, MIDI_TYPE *buf, int size)
  454 {
  455         /* int             i, sig, enq; */
  456         int used;
  457 
  458         /* MIDI_TYPE       data; */
  459         MIDI_DEBUG(5, printf("midi_in: m=%p size=%d\n", m, size));
  460 
  461 /*
  462  * XXX: locking flub
  463  */
  464         if (!(m->flags & M_RX))
  465                 return size;
  466 
  467         used = 0;
  468 
  469         mtx_lock(&m->qlock);
  470 #if 0
  471         /*
  472          * Don't bother queuing if not in read mode.  Discard everything and
  473          * return size so the caller doesn't freak out.
  474          */
  475 
  476         if (!(m->flags & M_RX))
  477                 return size;
  478 
  479         for (i = sig = 0; i < size; i++) {
  480                 data = buf[i];
  481                 enq = 0;
  482                 if (data == MIDI_ACK)
  483                         continue;
  484 
  485                 switch (m->inq_state) {
  486                 case MIDI_IN_START:
  487                         if (MIDI_IS_STATUS(data)) {
  488                                 switch (data) {
  489                                 case 0xf0:      /* Sysex */
  490                                         m->inq_state = MIDI_IN_SYSEX;
  491                                         break;
  492                                 case 0xf1:      /* MTC quarter frame */
  493                                 case 0xf3:      /* Song select */
  494                                         m->inq_state = MIDI_IN_DATA;
  495                                         enq = 1;
  496                                         m->inq_left = 1;
  497                                         break;
  498                                 case 0xf2:      /* Song position pointer */
  499                                         m->inq_state = MIDI_IN_DATA;
  500                                         enq = 1;
  501                                         m->inq_left = 2;
  502                                         break;
  503                                 default:
  504                                         if (MIDI_IS_COMMON(data)) {
  505                                                 enq = 1;
  506                                                 sig = 1;
  507                                         } else {
  508                                                 m->inq_state = MIDI_IN_DATA;
  509                                                 enq = 1;
  510                                                 m->inq_status = data;
  511                                                 m->inq_left = MIDI_LENGTH(data);
  512                                         }
  513                                         break;
  514                                 }
  515                         } else if (MIDI_IS_STATUS(m->inq_status)) {
  516                                 m->inq_state = MIDI_IN_DATA;
  517                                 if (!MIDIQ_FULL(m->inq)) {
  518                                         used++;
  519                                         MIDIQ_ENQ(m->inq, &m->inq_status, 1);
  520                                 }
  521                                 enq = 1;
  522                                 m->inq_left = MIDI_LENGTH(m->inq_status) - 1;
  523                         }
  524                         break;
  525                         /*
  526                          * End of case MIDI_IN_START:
  527                          */
  528 
  529                 case MIDI_IN_DATA:
  530                         enq = 1;
  531                         if (--m->inq_left <= 0)
  532                                 sig = 1;/* deliver data */
  533                         break;
  534                 case MIDI_IN_SYSEX:
  535                         if (data == MIDI_SYSEX_END)
  536                                 m->inq_state = MIDI_IN_START;
  537                         break;
  538                 }
  539 
  540                 if (enq)
  541                         if (!MIDIQ_FULL(m->inq)) {
  542                                 MIDIQ_ENQ(m->inq, &data, 1);
  543                                 used++;
  544                         }
  545                 /*
  546                  * End of the state machines main "for loop"
  547                  */
  548         }
  549         if (sig) {
  550 #endif
  551                 MIDI_DEBUG(6, printf("midi_in: len %jd avail %jd\n",
  552                     (intmax_t)MIDIQ_LEN(m->inq),
  553                     (intmax_t)MIDIQ_AVAIL(m->inq)));
  554                 if (MIDIQ_AVAIL(m->inq) > size) {
  555                         used = size;
  556                         MIDIQ_ENQ(m->inq, buf, size);
  557                 } else {
  558                         MIDI_DEBUG(4, printf("midi_in: Discarding data qu\n"));
  559                         mtx_unlock(&m->qlock);
  560                         return 0;
  561                 }
  562                 if (m->rchan) {
  563                         wakeup(&m->rchan);
  564                         m->rchan = 0;
  565                 }
  566                 selwakeup(&m->rsel);
  567                 if (m->async) {
  568                         PROC_LOCK(m->async);
  569                         kern_psignal(m->async, SIGIO);
  570                         PROC_UNLOCK(m->async);
  571                 }
  572 #if 0
  573         }
  574 #endif
  575         mtx_unlock(&m->qlock);
  576         return used;
  577 }
  578 
  579 /*
  580  * midi_out: The only clearer of the M_TXEN flag.
  581  */
  582 int
  583 midi_out(struct snd_midi *m, MIDI_TYPE *buf, int size)
  584 {
  585         int used;
  586 
  587 /*
  588  * XXX: locking flub
  589  */
  590         if (!(m->flags & M_TXEN))
  591                 return 0;
  592 
  593         MIDI_DEBUG(2, printf("midi_out: %p\n", m));
  594         mtx_lock(&m->qlock);
  595         used = MIN(size, MIDIQ_LEN(m->outq));
  596         MIDI_DEBUG(3, printf("midi_out: used %d\n", used));
  597         if (used)
  598                 MIDIQ_DEQ(m->outq, buf, used);
  599         if (MIDIQ_EMPTY(m->outq)) {
  600                 m->flags &= ~M_TXEN;
  601                 MPU_CALLBACKP(m, m->cookie, m->flags);
  602         }
  603         if (used && MIDIQ_AVAIL(m->outq) > m->hiwat) {
  604                 if (m->wchan) {
  605                         wakeup(&m->wchan);
  606                         m->wchan = 0;
  607                 }
  608                 selwakeup(&m->wsel);
  609                 if (m->async) {
  610                         PROC_LOCK(m->async);
  611                         kern_psignal(m->async, SIGIO);
  612                         PROC_UNLOCK(m->async);
  613                 }
  614         }
  615         mtx_unlock(&m->qlock);
  616         return used;
  617 }
  618 
  619 /*
  620  * /dev/rmidi#.#        device access functions
  621  */
  622 int
  623 midi_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
  624 {
  625         struct snd_midi *m = i_dev->si_drv1;
  626         int retval;
  627 
  628         MIDI_DEBUG(1, printf("midiopen %p %s %s\n", td,
  629             flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : ""));
  630         if (m == NULL)
  631                 return ENXIO;
  632 
  633         mtx_lock(&m->lock);
  634         mtx_lock(&m->qlock);
  635 
  636         retval = 0;
  637 
  638         if (flags & FREAD) {
  639                 if (MIDIQ_SIZE(m->inq) == 0)
  640                         retval = ENXIO;
  641                 else if (m->flags & M_RX)
  642                         retval = EBUSY;
  643                 if (retval)
  644                         goto err;
  645         }
  646         if (flags & FWRITE) {
  647                 if (MIDIQ_SIZE(m->outq) == 0)
  648                         retval = ENXIO;
  649                 else if (m->flags & M_TX)
  650                         retval = EBUSY;
  651                 if (retval)
  652                         goto err;
  653         }
  654         m->busy++;
  655 
  656         m->rchan = 0;
  657         m->wchan = 0;
  658         m->async = 0;
  659 
  660         if (flags & FREAD) {
  661                 m->flags |= M_RX | M_RXEN;
  662                 /*
  663                  * Only clear the inq, the outq might still have data to drain
  664                  * from a previous session
  665                  */
  666                 MIDIQ_CLEAR(m->inq);
  667         }
  668 
  669         if (flags & FWRITE)
  670                 m->flags |= M_TX;
  671 
  672         MPU_CALLBACK(m, m->cookie, m->flags);
  673 
  674         MIDI_DEBUG(2, printf("midi_open: opened.\n"));
  675 
  676 err:    mtx_unlock(&m->qlock);
  677         mtx_unlock(&m->lock);
  678         return retval;
  679 }
  680 
  681 int
  682 midi_close(struct cdev *i_dev, int flags, int mode, struct thread *td)
  683 {
  684         struct snd_midi *m = i_dev->si_drv1;
  685         int retval;
  686         int oldflags;
  687 
  688         MIDI_DEBUG(1, printf("midi_close %p %s %s\n", td,
  689             flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : ""));
  690 
  691         if (m == NULL)
  692                 return ENXIO;
  693 
  694         mtx_lock(&m->lock);
  695         mtx_lock(&m->qlock);
  696 
  697         if ((flags & FREAD && !(m->flags & M_RX)) ||
  698             (flags & FWRITE && !(m->flags & M_TX))) {
  699                 retval = ENXIO;
  700                 goto err;
  701         }
  702         m->busy--;
  703 
  704         oldflags = m->flags;
  705 
  706         if (flags & FREAD)
  707                 m->flags &= ~(M_RX | M_RXEN);
  708         if (flags & FWRITE)
  709                 m->flags &= ~M_TX;
  710 
  711         if ((m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN)))
  712                 MPU_CALLBACK(m, m->cookie, m->flags);
  713 
  714         MIDI_DEBUG(1, printf("midi_close: closed, busy = %d.\n", m->busy));
  715 
  716         mtx_unlock(&m->qlock);
  717         mtx_unlock(&m->lock);
  718         retval = 0;
  719 err:    return retval;
  720 }
  721 
  722 /*
  723  * TODO: midi_read, per oss programmer's guide pg. 42 should return as soon
  724  * as data is available.
  725  */
  726 int
  727 midi_read(struct cdev *i_dev, struct uio *uio, int ioflag)
  728 {
  729 #define MIDI_RSIZE 32
  730         struct snd_midi *m = i_dev->si_drv1;
  731         int retval;
  732         int used;
  733         char buf[MIDI_RSIZE];
  734 
  735         MIDI_DEBUG(5, printf("midiread: count=%lu\n",
  736             (unsigned long)uio->uio_resid));
  737 
  738         retval = EIO;
  739 
  740         if (m == NULL)
  741                 goto err0;
  742 
  743         mtx_lock(&m->lock);
  744         mtx_lock(&m->qlock);
  745 
  746         if (!(m->flags & M_RX))
  747                 goto err1;
  748 
  749         while (uio->uio_resid > 0) {
  750                 while (MIDIQ_EMPTY(m->inq)) {
  751                         retval = EWOULDBLOCK;
  752                         if (ioflag & O_NONBLOCK)
  753                                 goto err1;
  754                         mtx_unlock(&m->lock);
  755                         m->rchan = 1;
  756                         retval = msleep(&m->rchan, &m->qlock,
  757                             PCATCH | PDROP, "midi RX", 0);
  758                         /*
  759                          * We slept, maybe things have changed since last
  760                          * dying check
  761                          */
  762                         if (retval == EINTR)
  763                                 goto err0;
  764                         if (m != i_dev->si_drv1)
  765                                 retval = ENXIO;
  766                         /* if (retval && retval != ERESTART) */
  767                         if (retval)
  768                                 goto err0;
  769                         mtx_lock(&m->lock);
  770                         mtx_lock(&m->qlock);
  771                         m->rchan = 0;
  772                         if (!m->busy)
  773                                 goto err1;
  774                 }
  775                 MIDI_DEBUG(6, printf("midi_read start\n"));
  776                 /*
  777                  * At this point, it is certain that m->inq has data
  778                  */
  779 
  780                 used = MIN(MIDIQ_LEN(m->inq), uio->uio_resid);
  781                 used = MIN(used, MIDI_RSIZE);
  782 
  783                 MIDI_DEBUG(6, printf("midiread: uiomove cc=%d\n", used));
  784                 MIDIQ_DEQ(m->inq, buf, used);
  785                 retval = uiomove(buf, used, uio);
  786                 if (retval)
  787                         goto err1;
  788         }
  789 
  790         /*
  791          * If we Made it here then transfer is good
  792          */
  793         retval = 0;
  794 err1:   mtx_unlock(&m->qlock);
  795         mtx_unlock(&m->lock);
  796 err0:   MIDI_DEBUG(4, printf("midi_read: ret %d\n", retval));
  797         return retval;
  798 }
  799 
  800 /*
  801  * midi_write: The only setter of M_TXEN
  802  */
  803 
  804 int
  805 midi_write(struct cdev *i_dev, struct uio *uio, int ioflag)
  806 {
  807 #define MIDI_WSIZE 32
  808         struct snd_midi *m = i_dev->si_drv1;
  809         int retval;
  810         int used;
  811         char buf[MIDI_WSIZE];
  812 
  813         MIDI_DEBUG(4, printf("midi_write\n"));
  814         retval = 0;
  815         if (m == NULL)
  816                 goto err0;
  817 
  818         mtx_lock(&m->lock);
  819         mtx_lock(&m->qlock);
  820 
  821         if (!(m->flags & M_TX))
  822                 goto err1;
  823 
  824         while (uio->uio_resid > 0) {
  825                 while (MIDIQ_AVAIL(m->outq) == 0) {
  826                         retval = EWOULDBLOCK;
  827                         if (ioflag & O_NONBLOCK)
  828                                 goto err1;
  829                         mtx_unlock(&m->lock);
  830                         m->wchan = 1;
  831                         MIDI_DEBUG(3, printf("midi_write msleep\n"));
  832                         retval = msleep(&m->wchan, &m->qlock,
  833                             PCATCH | PDROP, "midi TX", 0);
  834                         /*
  835                          * We slept, maybe things have changed since last
  836                          * dying check
  837                          */
  838                         if (retval == EINTR)
  839                                 goto err0;
  840                         if (m != i_dev->si_drv1)
  841                                 retval = ENXIO;
  842                         if (retval)
  843                                 goto err0;
  844                         mtx_lock(&m->lock);
  845                         mtx_lock(&m->qlock);
  846                         m->wchan = 0;
  847                         if (!m->busy)
  848                                 goto err1;
  849                 }
  850 
  851                 /*
  852                  * We are certain than data can be placed on the queue
  853                  */
  854 
  855                 used = MIN(MIDIQ_AVAIL(m->outq), uio->uio_resid);
  856                 used = MIN(used, MIDI_WSIZE);
  857                 MIDI_DEBUG(5, printf("midiout: resid %zd len %jd avail %jd\n",
  858                     uio->uio_resid, (intmax_t)MIDIQ_LEN(m->outq),
  859                     (intmax_t)MIDIQ_AVAIL(m->outq)));
  860 
  861                 MIDI_DEBUG(5, printf("midi_write: uiomove cc=%d\n", used));
  862                 retval = uiomove(buf, used, uio);
  863                 if (retval)
  864                         goto err1;
  865                 MIDIQ_ENQ(m->outq, buf, used);
  866                 /*
  867                  * Inform the bottom half that data can be written
  868                  */
  869                 if (!(m->flags & M_TXEN)) {
  870                         m->flags |= M_TXEN;
  871                         MPU_CALLBACK(m, m->cookie, m->flags);
  872                 }
  873         }
  874         /*
  875          * If we Made it here then transfer is good
  876          */
  877         retval = 0;
  878 err1:   mtx_unlock(&m->qlock);
  879         mtx_unlock(&m->lock);
  880 err0:   return retval;
  881 }
  882 
  883 int
  884 midi_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
  885     struct thread *td)
  886 {
  887         return ENXIO;
  888 }
  889 
  890 int
  891 midi_poll(struct cdev *i_dev, int events, struct thread *td)
  892 {
  893         struct snd_midi *m = i_dev->si_drv1;
  894         int revents;
  895 
  896         if (m == NULL)
  897                 return 0;
  898 
  899         revents = 0;
  900 
  901         mtx_lock(&m->lock);
  902         mtx_lock(&m->qlock);
  903 
  904         if (events & (POLLIN | POLLRDNORM))
  905                 if (!MIDIQ_EMPTY(m->inq))
  906                         events |= events & (POLLIN | POLLRDNORM);
  907 
  908         if (events & (POLLOUT | POLLWRNORM))
  909                 if (MIDIQ_AVAIL(m->outq) < m->hiwat)
  910                         events |= events & (POLLOUT | POLLWRNORM);
  911 
  912         if (revents == 0) {
  913                 if (events & (POLLIN | POLLRDNORM))
  914                         selrecord(td, &m->rsel);
  915 
  916                 if (events & (POLLOUT | POLLWRNORM))
  917                         selrecord(td, &m->wsel);
  918         }
  919         mtx_unlock(&m->lock);
  920         mtx_unlock(&m->qlock);
  921 
  922         return (revents);
  923 }
  924 
  925 /*
  926  * /dev/midistat device functions
  927  *
  928  */
  929 static int
  930 midistat_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
  931 {
  932         int error;
  933 
  934         MIDI_DEBUG(1, printf("midistat_open\n"));
  935 
  936         sx_xlock(&midistat_lock);
  937         if (midistat_isopen) {
  938                 sx_xunlock(&midistat_lock);
  939                 return EBUSY;
  940         }
  941         midistat_isopen = 1;
  942         if (sbuf_new(&midistat_sbuf, NULL, 4096, SBUF_AUTOEXTEND) == NULL) {
  943                 error = ENXIO;
  944                 goto out;
  945         }
  946         error = (midistat_prepare(&midistat_sbuf) > 0) ? 0 : ENOMEM;
  947 out:
  948         if (error)
  949                 midistat_isopen = 0;
  950         sx_xunlock(&midistat_lock);
  951         return error;
  952 }
  953 
  954 static int
  955 midistat_close(struct cdev *i_dev, int flags, int mode, struct thread *td)
  956 {
  957         MIDI_DEBUG(1, printf("midistat_close\n"));
  958         sx_xlock(&midistat_lock);
  959         if (!midistat_isopen) {
  960                 sx_xunlock(&midistat_lock);
  961                 return EBADF;
  962         }
  963         sbuf_delete(&midistat_sbuf);
  964         midistat_isopen = 0;
  965         sx_xunlock(&midistat_lock);
  966         return 0;
  967 }
  968 
  969 static int
  970 midistat_read(struct cdev *i_dev, struct uio *uio, int flag)
  971 {
  972         long l;
  973         int err;
  974 
  975         MIDI_DEBUG(4, printf("midistat_read\n"));
  976         sx_xlock(&midistat_lock);
  977         if (!midistat_isopen) {
  978                 sx_xunlock(&midistat_lock);
  979                 return EBADF;
  980         }
  981         if (uio->uio_offset < 0 || uio->uio_offset > sbuf_len(&midistat_sbuf)) {
  982                 sx_xunlock(&midistat_lock);
  983                 return EINVAL;
  984         }
  985         err = 0;
  986         l = lmin(uio->uio_resid, sbuf_len(&midistat_sbuf) - uio->uio_offset);
  987         if (l > 0) {
  988                 err = uiomove(sbuf_data(&midistat_sbuf) + uio->uio_offset, l,
  989                     uio);
  990         }
  991         sx_xunlock(&midistat_lock);
  992         return err;
  993 }
  994 
  995 /*
  996  * Module library functions
  997  */
  998 
  999 static int
 1000 midistat_prepare(struct sbuf *s)
 1001 {
 1002         struct snd_midi *m;
 1003 
 1004         sx_assert(&midistat_lock, SA_XLOCKED);
 1005 
 1006         sbuf_printf(s, "FreeBSD Midi Driver (midi2)\n");
 1007         if (TAILQ_EMPTY(&midi_devs)) {
 1008                 sbuf_printf(s, "No devices installed.\n");
 1009                 sbuf_finish(s);
 1010                 return sbuf_len(s);
 1011         }
 1012         sbuf_printf(s, "Installed devices:\n");
 1013 
 1014         TAILQ_FOREACH(m, &midi_devs, link) {
 1015                 mtx_lock(&m->lock);
 1016                 sbuf_printf(s, "%s [%d/%d:%s]", m->name, m->unit, m->channel,
 1017                     MPU_PROVIDER(m, m->cookie));
 1018                 sbuf_printf(s, "%s", MPU_DESCR(m, m->cookie, midistat_verbose));
 1019                 sbuf_printf(s, "\n");
 1020                 mtx_unlock(&m->lock);
 1021         }
 1022 
 1023         sbuf_finish(s);
 1024         return sbuf_len(s);
 1025 }
 1026 
 1027 #ifdef notdef
 1028 /*
 1029  * Convert IOCTL command to string for debugging
 1030  */
 1031 
 1032 static char *
 1033 midi_cmdname(int cmd)
 1034 {
 1035         static struct {
 1036                 int     cmd;
 1037                 char   *name;
 1038         }     *tab, cmdtab_midiioctl[] = {
 1039 #define A(x)    {x, ## x}
 1040                 /*
 1041                  * Once we have some real IOCTLs define, the following will
 1042                  * be relavant.
 1043                  *
 1044                  * A(SNDCTL_MIDI_PRETIME), A(SNDCTL_MIDI_MPUMODE),
 1045                  * A(SNDCTL_MIDI_MPUCMD), A(SNDCTL_SYNTH_INFO),
 1046                  * A(SNDCTL_MIDI_INFO), A(SNDCTL_SYNTH_MEMAVL),
 1047                  * A(SNDCTL_FM_LOAD_INSTR), A(SNDCTL_FM_4OP_ENABLE),
 1048                  * A(MIOSPASSTHRU), A(MIOGPASSTHRU), A(AIONWRITE),
 1049                  * A(AIOGSIZE), A(AIOSSIZE), A(AIOGFMT), A(AIOSFMT),
 1050                  * A(AIOGMIX), A(AIOSMIX), A(AIOSTOP), A(AIOSYNC),
 1051                  * A(AIOGCAP),
 1052                  */
 1053 #undef A
 1054                 {
 1055                         -1, "unknown"
 1056                 },
 1057         };
 1058 
 1059         for (tab = cmdtab_midiioctl; tab->cmd != cmd && tab->cmd != -1; tab++);
 1060         return tab->name;
 1061 }
 1062 
 1063 #endif                                  /* notdef */
 1064 
 1065 /*
 1066  * midisynth
 1067  */
 1068 
 1069 int
 1070 midisynth_open(void *n, void *arg, int flags)
 1071 {
 1072         struct snd_midi *m = ((struct synth_midi *)n)->m;
 1073         int retval;
 1074 
 1075         MIDI_DEBUG(1, printf("midisynth_open %s %s\n",
 1076             flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : ""));
 1077 
 1078         if (m == NULL)
 1079                 return ENXIO;
 1080 
 1081         mtx_lock(&m->lock);
 1082         mtx_lock(&m->qlock);
 1083 
 1084         retval = 0;
 1085 
 1086         if (flags & FREAD) {
 1087                 if (MIDIQ_SIZE(m->inq) == 0)
 1088                         retval = ENXIO;
 1089                 else if (m->flags & M_RX)
 1090                         retval = EBUSY;
 1091                 if (retval)
 1092                         goto err;
 1093         }
 1094         if (flags & FWRITE) {
 1095                 if (MIDIQ_SIZE(m->outq) == 0)
 1096                         retval = ENXIO;
 1097                 else if (m->flags & M_TX)
 1098                         retval = EBUSY;
 1099                 if (retval)
 1100                         goto err;
 1101         }
 1102         m->busy++;
 1103 
 1104         /*
 1105          * TODO: Consider m->async = 0;
 1106          */
 1107 
 1108         if (flags & FREAD) {
 1109                 m->flags |= M_RX | M_RXEN;
 1110                 /*
 1111                  * Only clear the inq, the outq might still have data to drain
 1112                  * from a previous session
 1113                  */
 1114                 MIDIQ_CLEAR(m->inq);
 1115                 m->rchan = 0;
 1116         }
 1117 
 1118         if (flags & FWRITE) {
 1119                 m->flags |= M_TX;
 1120                 m->wchan = 0;
 1121         }
 1122         m->synth_flags = flags & (FREAD | FWRITE);
 1123 
 1124         MPU_CALLBACK(m, m->cookie, m->flags);
 1125 
 1126 err:    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 
 1132 int
 1133 midisynth_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         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;
 1171 err:    return retval;
 1172 }
 1173 
 1174 /*
 1175  * Always blocking.
 1176  */
 1177 
 1178 int
 1179 midisynth_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,
 1236                     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++)
 1242                                 printf("%x ", buf[i]);
 1243 
 1244                 MIDIQ_ENQ(m->outq, buf, used);
 1245                 len -= used;
 1246 
 1247                 /*
 1248                  * Inform the bottom half that data can be written
 1249                  */
 1250                 if (!(m->flags & M_TXEN)) {
 1251                         m->flags |= M_TXEN;
 1252                         MPU_CALLBACK(m, m->cookie, m->flags);
 1253                 }
 1254         }
 1255         /*
 1256          * If we Made it here then transfer is good
 1257          */
 1258         if (midi_dumpraw)
 1259                 printf("\n");
 1260 
 1261         retval = 0;
 1262 err1:   mtx_unlock(&m->qlock);
 1263         mtx_unlock(&m->lock);
 1264 err0:   return retval;
 1265 }
 1266 
 1267 static int
 1268 midisynth_killnote(void *n, uint8_t chn, uint8_t note, uint8_t vel)
 1269 {
 1270         u_char c[3];
 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 
 1291 static int
 1292 midisynth_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 
 1305 static int
 1306 midisynth_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 }
 1322 static int
 1323 midisynth_alloc(void *n, uint8_t chan, uint8_t note)
 1324 {
 1325         return chan;
 1326 }
 1327 
 1328 static int
 1329 midisynth_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 
 1342 static int
 1343 midisynth_bender(void *n, uint8_t chn, uint16_t val)
 1344 {
 1345         u_char c[3];
 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  */
 1360 static int
 1361 midi_destroy(struct snd_midi *m, int midiuninit)
 1362 {
 1363         sx_assert(&midistat_lock, SA_XLOCKED);
 1364         mtx_assert(&m->lock, MA_OWNED);
 1365 
 1366         MIDI_DEBUG(3, printf("midi_destroy\n"));
 1367         m->dev->si_drv1 = NULL;
 1368         mtx_unlock(&m->lock);   /* XXX */
 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->synth, M_MIDI);
 1378         free(m, M_MIDI);
 1379         return 0;
 1380 }
 1381 
 1382 /*
 1383  * Load and unload functions, creates the /dev/midistat device
 1384  */
 1385 
 1386 static int
 1387 midi_load(void)
 1388 {
 1389         sx_init(&midistat_lock, "midistat lock");
 1390         TAILQ_INIT(&midi_devs);
 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 
 1399 static int
 1400 midi_unload(void)
 1401 {
 1402         struct snd_midi *m, *tmp;
 1403         int retval;
 1404 
 1405         MIDI_DEBUG(1, printf("midi_unload()\n"));
 1406         retval = EBUSY;
 1407         sx_xlock(&midistat_lock);
 1408         if (midistat_isopen)
 1409                 goto exit0;
 1410 
 1411         TAILQ_FOREACH_SAFE(m, &midi_devs, link, tmp) {
 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         sx_xunlock(&midistat_lock);
 1421         destroy_dev(midistat_dev);
 1422 
 1423         /*
 1424          * Made it here then unload is complete
 1425          */
 1426         sx_destroy(&midistat_lock);
 1427         return 0;
 1428 
 1429 exit1:
 1430         mtx_unlock(&m->lock);
 1431 exit0:
 1432         sx_xunlock(&midistat_lock);
 1433         if (retval)
 1434                 MIDI_DEBUG(2, printf("midi_unload: failed\n"));
 1435         return retval;
 1436 }
 1437 
 1438 extern int seq_modevent(module_t mod, int type, void *data);
 1439 
 1440 static int
 1441 midi_modevent(module_t mod, int type, void *data)
 1442 {
 1443         int retval;
 1444 
 1445         retval = 0;
 1446 
 1447         switch (type) {
 1448         case MOD_LOAD:
 1449                 retval = midi_load();
 1450                 if (retval == 0)
 1451                         retval = seq_modevent(mod, type, data);
 1452                 break;
 1453 
 1454         case MOD_UNLOAD:
 1455                 retval = midi_unload();
 1456                 if (retval == 0)
 1457                         retval = seq_modevent(mod, type, data);
 1458                 break;
 1459 
 1460         default:
 1461                 break;
 1462         }
 1463 
 1464         return retval;
 1465 }
 1466 
 1467 kobj_t
 1468 midimapper_addseq(void *arg1, int *unit, void **cookie)
 1469 {
 1470         unit = NULL;
 1471 
 1472         return (kobj_t)arg1;
 1473 }
 1474 
 1475 int
 1476 midimapper_open(void *arg1, void **cookie)
 1477 {
 1478         int retval = 0;
 1479         struct snd_midi *m;
 1480 
 1481         sx_xlock(&midistat_lock);
 1482         TAILQ_FOREACH(m, &midi_devs, link) {
 1483                 retval++;
 1484         }
 1485         sx_xunlock(&midistat_lock);
 1486         return retval;
 1487 }
 1488 
 1489 int
 1490 midimapper_close(void *arg1, void *cookie)
 1491 {
 1492         return 0;
 1493 }
 1494 
 1495 kobj_t
 1496 midimapper_fetch_synth(void *arg, void *cookie, int unit)
 1497 {
 1498         struct snd_midi *m;
 1499         int retval = 0;
 1500 
 1501         sx_xlock(&midistat_lock);
 1502         TAILQ_FOREACH(m, &midi_devs, link) {
 1503                 if (unit == retval) {
 1504                         sx_xunlock(&midistat_lock);
 1505                         return (kobj_t)m->synth;
 1506                 }
 1507                 retval++;
 1508         }
 1509         sx_xunlock(&midistat_lock);
 1510         return NULL;
 1511 }
 1512 
 1513 DEV_MODULE(midi, midi_modevent, NULL);
 1514 MODULE_VERSION(midi, 1);

Cache object: 32d224076af82cc1d6f3352891f460e7


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.