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

Cache object: 39d53ad17a9cec16d4caddb3c22e49a0


[ 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.