2 * SPDX-License-Identifier: BSD-2-Clause-NetBSD
4 * Copyright (c) 2003 Mathew Kanner
5 * Copyright (c) 1998 The NetBSD Foundation, Inc.
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Lennart Augustsson (augustss@netbsd.org).
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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
39 #include <sys/cdefs.h>
40 __FBSDID("$FreeBSD$");
42 #include <sys/param.h>
43 #include <sys/queue.h>
44 #include <sys/kernel.h>
46 #include <sys/mutex.h>
48 #include <sys/signalvar.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>
57 #include <sys/fcntl.h>
58 #include <sys/types.h>
63 #include <sys/module.h>
65 #ifdef HAVE_KERNEL_OPTION_HEADERS
69 #include <dev/sound/midi/midi.h>
72 #include <dev/sound/midi/midiq.h>
74 MALLOC_DEFINE(M_MIDI, "midi buffers", "Midi data allocation area");
76 #ifndef KOBJMETHOD_END
77 #define KOBJMETHOD_END { NULL, NULL }
80 #define PCMMKMINOR(u, d, c) ((((c) & 0xff) << 16) | (((u) & 0x0f) << 4) | ((d) & 0x0f))
81 #define MIDIMKMINOR(u, d, c) PCMMKMINOR(u, d, c)
83 #define MIDI_DEV_RAW 2
84 #define MIDI_DEV_MIDICTL 12
87 MIDI_IN_START, MIDI_IN_SYSEX, MIDI_IN_DATA
91 * The MPU interface current has init() uninit() inqsize() outqsize()
92 * callback() : fiddle with the tx|rx status.
98 * /dev/rmidi Structure definitions
101 #define MIDI_NAMELEN 16
104 struct mtx lock; /* Protects all but queues */
107 int unit; /* Should only be used in midistat */
108 int channel; /* Should only be used in midistat */
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;
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. */
126 struct synth_midi *synth;
128 TAILQ_ENTRY(snd_midi) link;
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;
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),
160 DEFINE_CLASS(midisynth, midisynth_methods, 0);
163 * Module Exports & Interface
165 * struct midi_chan *midi_init(MPU_CLASS cls, int unit, int chan,
167 * int midi_uninit(struct snd_midi *)
170 * EBUSY or other error
172 * int midi_in(struct snd_midi *, char *buf, int count)
173 * int midi_out(struct snd_midi *, char *buf, int count)
175 * midi_{in,out} return actual size transfered
181 * midi_devs tailq, holder of all rmidi instances protected by midistat_lock
184 TAILQ_HEAD(, snd_midi) midi_devs;
187 * /dev/midistat variables and declarations, protected by midistat_lock
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;
197 * /dev/midistat dev_t declarations
200 static d_open_t midistat_open;
201 static d_close_t midistat_close;
202 static d_read_t midistat_read;
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",
214 * /dev/rmidi dev_t declarations, struct variable access is protected by
215 * locks contained within the structure.
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;
225 static struct cdevsw midi_cdevsw = {
226 .d_version = D_VERSION,
228 .d_close = midi_close,
230 .d_write = midi_write,
231 .d_ioctl = midi_ioctl,
237 * Prototypes of library functions
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);
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");
252 /* XXX: should this be moved into debug.midi? */
253 SYSCTL_INT(_hw_midi, OID_AUTO, debug, CTLFLAG_RW, &midi_debug, 0, "");
256 SYSCTL_INT(_hw_midi, OID_AUTO, dumpraw, CTLFLAG_RW, &midi_dumpraw, 0, "");
259 SYSCTL_INT(_hw_midi, OID_AUTO, instroff, CTLFLAG_RW, &midi_instroff, 0, "");
261 int midistat_verbose;
262 SYSCTL_INT(_hw_midi_stat, OID_AUTO, verbose, CTLFLAG_RW,
263 &midistat_verbose, 0, "");
265 #define MIDI_DEBUG(l,a) if(midi_debug>=l) a
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.
278 * It is an error to call midi_init with an already used unit/channel combo.
280 * Returns NULL on error
284 midi_init(kobj_class_t cls, int unit, int channel, void *cookie)
288 int inqsize, outqsize;
291 MIDI_DEBUG(1, printf("midiinit: unit %d/%d.\n", unit, channel));
292 mtx_lock(&midistat_lock);
294 * Protect against call with existing unit/channel or auto-allocate a
298 TAILQ_FOREACH(m, &midi_devs, link) {
301 if (m->unit == unit && m->channel == channel) {
302 mtx_unlock(&m->lock);
307 * Find a better unit number
312 mtx_unlock(&m->lock);
318 MIDI_DEBUG(1, printf("midiinit #2: unit %d/%d.\n", unit, channel));
319 m = malloc(sizeof(*m), M_MIDI, M_NOWAIT | M_ZERO);
323 m->synth = malloc(sizeof(*m->synth), M_MIDI, M_NOWAIT | M_ZERO);
324 if (m->synth == NULL)
326 kobj_init((kobj_t)m->synth, &midisynth_class);
328 kobj_init((kobj_t)m, cls);
329 inqsize = MPU_INQSIZE(m, cookie);
330 outqsize = MPU_OUTQSIZE(m, cookie);
332 MIDI_DEBUG(1, printf("midiinit queues %d/%d.\n", inqsize, outqsize));
333 if (!inqsize && !outqsize)
336 mtx_init(&m->lock, "raw midi", NULL, 0);
337 mtx_init(&m->qlock, "q raw midi", NULL, 0);
343 buf = malloc(sizeof(MIDI_TYPE) * inqsize, M_MIDI, M_NOWAIT);
347 MIDIQ_INIT(m->inq, buf, inqsize);
350 buf = malloc(sizeof(MIDI_TYPE) * outqsize, M_MIDI, M_NOWAIT);
353 m->hiwat = outqsize / 2;
355 MIDIQ_INIT(m->outq, buf, outqsize);
357 if ((inqsize && !MIDIQ_BUF(m->inq)) ||
358 (outqsize && !MIDIQ_BUF(m->outq)))
365 m->channel = channel;
368 if (MPU_INIT(m, cookie))
371 mtx_unlock(&m->lock);
372 mtx_unlock(&m->qlock);
374 TAILQ_INSERT_TAIL(&midi_devs, m, link);
376 mtx_unlock(&midistat_lock);
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);
385 err3: mtx_destroy(&m->qlock);
386 mtx_destroy(&m->lock);
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"));
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
407 midi_uninit(struct snd_midi *m)
412 mtx_lock(&midistat_lock);
415 if (!(m->rchan || m->wchan))
427 err = midi_destroy(m, 0);
431 err: mtx_unlock(&m->lock);
432 exit: mtx_unlock(&midistat_lock);
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.
444 static int midi_lengths[] = {2, 2, 2, 2, 1, 1, 2, 0};
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)
453 #define MIDI_SYSEX_START 0xF0
454 #define MIDI_SYSEX_END 0xF7
458 midi_in(struct snd_midi *m, MIDI_TYPE *buf, int size)
460 /* int i, sig, enq; */
463 /* MIDI_TYPE data; */
464 MIDI_DEBUG(5, printf("midi_in: m=%p size=%d\n", m, size));
469 if (!(m->flags & M_RX))
477 * Don't bother queuing if not in read mode. Discard everything and
478 * return size so the caller doesn't freak out.
481 if (!(m->flags & M_RX))
484 for (i = sig = 0; i < size; i++) {
488 if (data == MIDI_ACK)
491 switch (m->inq_state) {
493 if (MIDI_IS_STATUS(data)) {
495 case 0xf0: /* Sysex */
496 m->inq_state = MIDI_IN_SYSEX;
498 case 0xf1: /* MTC quarter frame */
499 case 0xf3: /* Song select */
500 m->inq_state = MIDI_IN_DATA;
504 case 0xf2: /* Song position pointer */
505 m->inq_state = MIDI_IN_DATA;
510 if (MIDI_IS_COMMON(data)) {
514 m->inq_state = MIDI_IN_DATA;
516 m->inq_status = data;
517 m->inq_left = MIDI_LENGTH(data);
521 } else if (MIDI_IS_STATUS(m->inq_status)) {
522 m->inq_state = MIDI_IN_DATA;
523 if (!MIDIQ_FULL(m->inq)) {
525 MIDIQ_ENQ(m->inq, &m->inq_status, 1);
528 m->inq_left = MIDI_LENGTH(m->inq_status) - 1;
532 * End of case MIDI_IN_START:
537 if (--m->inq_left <= 0)
538 sig = 1;/* deliver data */
541 if (data == MIDI_SYSEX_END)
542 m->inq_state = MIDI_IN_START;
547 if (!MIDIQ_FULL(m->inq)) {
548 MIDIQ_ENQ(m->inq, &data, 1);
552 * End of the state machines main "for loop"
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) {
562 MIDIQ_ENQ(m->inq, buf, size);
564 MIDI_DEBUG(4, printf("midi_in: Discarding data qu\n"));
565 mtx_unlock(&m->qlock);
575 kern_psignal(m->async, SIGIO);
576 PROC_UNLOCK(m->async);
581 mtx_unlock(&m->qlock);
586 * midi_out: The only clearer of the M_TXEN flag.
589 midi_out(struct snd_midi *m, MIDI_TYPE *buf, int size)
596 if (!(m->flags & M_TXEN))
599 MIDI_DEBUG(2, printf("midi_out: %p\n", m));
601 used = MIN(size, MIDIQ_LEN(m->outq));
602 MIDI_DEBUG(3, printf("midi_out: used %d\n", used));
604 MIDIQ_DEQ(m->outq, buf, used);
605 if (MIDIQ_EMPTY(m->outq)) {
607 MPU_CALLBACKP(m, m->cookie, m->flags);
609 if (used && MIDIQ_AVAIL(m->outq) > m->hiwat) {
617 kern_psignal(m->async, SIGIO);
618 PROC_UNLOCK(m->async);
621 mtx_unlock(&m->qlock);
627 * /dev/rmidi#.# device access functions
630 midi_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
632 struct snd_midi *m = i_dev->si_drv1;
635 MIDI_DEBUG(1, printf("midiopen %p %s %s\n", td,
636 flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : ""));
646 if (MIDIQ_SIZE(m->inq) == 0)
648 else if (m->flags & M_RX)
653 if (flags & FWRITE) {
654 if (MIDIQ_SIZE(m->outq) == 0)
656 else if (m->flags & M_TX)
668 m->flags |= M_RX | M_RXEN;
670 * Only clear the inq, the outq might still have data to drain
671 * from a previous session
679 MPU_CALLBACK(m, m->cookie, m->flags);
681 MIDI_DEBUG(2, printf("midi_open: opened.\n"));
683 err: mtx_unlock(&m->qlock);
684 mtx_unlock(&m->lock);
689 midi_close(struct cdev *i_dev, int flags, int mode, struct thread *td)
691 struct snd_midi *m = i_dev->si_drv1;
695 MIDI_DEBUG(1, printf("midi_close %p %s %s\n", td,
696 flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : ""));
704 if ((flags & FREAD && !(m->flags & M_RX)) ||
705 (flags & FWRITE && !(m->flags & M_TX))) {
714 m->flags &= ~(M_RX | M_RXEN);
718 if ((m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN)))
719 MPU_CALLBACK(m, m->cookie, m->flags);
721 MIDI_DEBUG(1, printf("midi_close: closed, busy = %d.\n", m->busy));
723 mtx_unlock(&m->qlock);
724 mtx_unlock(&m->lock);
730 * TODO: midi_read, per oss programmer's guide pg. 42 should return as soon
731 * as data is available.
734 midi_read(struct cdev *i_dev, struct uio *uio, int ioflag)
736 #define MIDI_RSIZE 32
737 struct snd_midi *m = i_dev->si_drv1;
740 char buf[MIDI_RSIZE];
742 MIDI_DEBUG(5, printf("midiread: count=%lu\n",
743 (unsigned long)uio->uio_resid));
753 if (!(m->flags & M_RX))
756 while (uio->uio_resid > 0) {
757 while (MIDIQ_EMPTY(m->inq)) {
758 retval = EWOULDBLOCK;
759 if (ioflag & O_NONBLOCK)
761 mtx_unlock(&m->lock);
763 retval = msleep(&m->rchan, &m->qlock,
764 PCATCH | PDROP, "midi RX", 0);
766 * We slept, maybe things have changed since last
771 if (m != i_dev->si_drv1)
773 /* if (retval && retval != ERESTART) */
782 MIDI_DEBUG(6, printf("midi_read start\n"));
784 * At this point, it is certain that m->inq has data
787 used = MIN(MIDIQ_LEN(m->inq), uio->uio_resid);
788 used = MIN(used, MIDI_RSIZE);
790 MIDI_DEBUG(6, printf("midiread: uiomove cc=%d\n", used));
791 MIDIQ_DEQ(m->inq, buf, used);
792 retval = uiomove(buf, used, uio);
798 * If we Made it here then transfer is good
801 err1: mtx_unlock(&m->qlock);
802 mtx_unlock(&m->lock);
803 err0: MIDI_DEBUG(4, printf("midi_read: ret %d\n", retval));
808 * midi_write: The only setter of M_TXEN
812 midi_write(struct cdev *i_dev, struct uio *uio, int ioflag)
814 #define MIDI_WSIZE 32
815 struct snd_midi *m = i_dev->si_drv1;
818 char buf[MIDI_WSIZE];
821 MIDI_DEBUG(4, printf("midi_write\n"));
829 if (!(m->flags & M_TX))
832 while (uio->uio_resid > 0) {
833 while (MIDIQ_AVAIL(m->outq) == 0) {
834 retval = EWOULDBLOCK;
835 if (ioflag & O_NONBLOCK)
837 mtx_unlock(&m->lock);
839 MIDI_DEBUG(3, printf("midi_write msleep\n"));
840 retval = msleep(&m->wchan, &m->qlock,
841 PCATCH | PDROP, "midi TX", 0);
843 * We slept, maybe things have changed since last
848 if (m != i_dev->si_drv1)
860 * We are certain than data can be placed on the queue
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)));
870 MIDI_DEBUG(5, printf("midi_write: uiomove cc=%d\n", used));
871 retval = uiomove(buf, used, uio);
874 MIDIQ_ENQ(m->outq, buf, used);
876 * Inform the bottom half that data can be written
878 if (!(m->flags & M_TXEN)) {
880 MPU_CALLBACK(m, m->cookie, m->flags);
884 * If we Made it here then transfer is good
887 err1: mtx_unlock(&m->qlock);
888 mtx_unlock(&m->lock);
893 midi_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
900 midi_poll(struct cdev *i_dev, int events, struct thread *td)
902 struct snd_midi *m = i_dev->si_drv1;
913 if (events & (POLLIN | POLLRDNORM))
914 if (!MIDIQ_EMPTY(m->inq))
915 events |= events & (POLLIN | POLLRDNORM);
917 if (events & (POLLOUT | POLLWRNORM))
918 if (MIDIQ_AVAIL(m->outq) < m->hiwat)
919 events |= events & (POLLOUT | POLLWRNORM);
922 if (events & (POLLIN | POLLRDNORM))
923 selrecord(td, &m->rsel);
925 if (events & (POLLOUT | POLLWRNORM))
926 selrecord(td, &m->wsel);
928 mtx_unlock(&m->lock);
929 mtx_unlock(&m->qlock);
935 * /dev/midistat device functions
939 midistat_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
943 MIDI_DEBUG(1, printf("midistat_open\n"));
944 mtx_lock(&midistat_lock);
946 if (midistat_isopen) {
947 mtx_unlock(&midistat_lock);
951 mtx_unlock(&midistat_lock);
953 if (sbuf_new(&midistat_sbuf, NULL, 4096, SBUF_AUTOEXTEND) == NULL) {
955 mtx_lock(&midistat_lock);
958 mtx_lock(&midistat_lock);
960 error = (midistat_prepare(&midistat_sbuf) > 0) ? 0 : ENOMEM;
964 mtx_unlock(&midistat_lock);
969 midistat_close(struct cdev *i_dev, int flags, int mode, struct thread *td)
971 MIDI_DEBUG(1, printf("midistat_close\n"));
972 mtx_lock(&midistat_lock);
973 if (!midistat_isopen) {
974 mtx_unlock(&midistat_lock);
977 sbuf_delete(&midistat_sbuf);
980 mtx_unlock(&midistat_lock);
985 midistat_read(struct cdev *i_dev, struct uio *buf, int flag)
989 MIDI_DEBUG(4, printf("midistat_read\n"));
990 mtx_lock(&midistat_lock);
991 if (!midistat_isopen) {
992 mtx_unlock(&midistat_lock);
995 l = min(buf->uio_resid, sbuf_len(&midistat_sbuf) - midistat_bufptr);
998 mtx_unlock(&midistat_lock);
999 err = uiomove(sbuf_data(&midistat_sbuf) + midistat_bufptr, l,
1001 mtx_lock(&midistat_lock);
1004 midistat_bufptr += l;
1005 mtx_unlock(&midistat_lock);
1010 * Module library functions
1014 midistat_prepare(struct sbuf *s)
1018 mtx_assert(&midistat_lock, MA_OWNED);
1020 sbuf_printf(s, "FreeBSD Midi Driver (midi2)\n");
1021 if (TAILQ_EMPTY(&midi_devs)) {
1022 sbuf_printf(s, "No devices installed.\n");
1026 sbuf_printf(s, "Installed devices:\n");
1028 TAILQ_FOREACH(m, &midi_devs, link) {
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);
1043 * Convert IOCTL command to string for debugging
1047 midi_cmdname(int cmd)
1052 } *tab, cmdtab_midiioctl[] = {
1053 #define A(x) {x, ## x}
1055 * Once we have some real IOCTLs define, the following will
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),
1073 for (tab = cmdtab_midiioctl; tab->cmd != cmd && tab->cmd != -1; tab++);
1085 midisynth_open(void *n, void *arg, int flags)
1087 struct snd_midi *m = ((struct synth_midi *)n)->m;
1090 MIDI_DEBUG(1, printf("midisynth_open %s %s\n",
1091 flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : ""));
1097 mtx_lock(&m->qlock);
1101 if (flags & FREAD) {
1102 if (MIDIQ_SIZE(m->inq) == 0)
1104 else if (m->flags & M_RX)
1109 if (flags & FWRITE) {
1110 if (MIDIQ_SIZE(m->outq) == 0)
1112 else if (m->flags & M_TX)
1120 * TODO: Consider m->async = 0;
1123 if (flags & FREAD) {
1124 m->flags |= M_RX | M_RXEN;
1126 * Only clear the inq, the outq might still have data to drain
1127 * from a previous session
1129 MIDIQ_CLEAR(m->inq);
1133 if (flags & FWRITE) {
1137 m->synth_flags = flags & (FREAD | FWRITE);
1139 MPU_CALLBACK(m, m->cookie, m->flags);
1142 err: mtx_unlock(&m->qlock);
1143 mtx_unlock(&m->lock);
1144 MIDI_DEBUG(2, printf("midisynth_open: return %d.\n", retval));
1149 midisynth_close(void *n)
1151 struct snd_midi *m = ((struct synth_midi *)n)->m;
1155 MIDI_DEBUG(1, printf("midisynth_close %s %s\n",
1156 m->synth_flags & FREAD ? "M_RX" : "",
1157 m->synth_flags & FWRITE ? "M_TX" : ""));
1163 mtx_lock(&m->qlock);
1165 if ((m->synth_flags & FREAD && !(m->flags & M_RX)) ||
1166 (m->synth_flags & FWRITE && !(m->flags & M_TX))) {
1172 oldflags = m->flags;
1174 if (m->synth_flags & FREAD)
1175 m->flags &= ~(M_RX | M_RXEN);
1176 if (m->synth_flags & FWRITE)
1179 if ((m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN)))
1180 MPU_CALLBACK(m, m->cookie, m->flags);
1182 MIDI_DEBUG(1, printf("midi_close: closed, busy = %d.\n", m->busy));
1184 mtx_unlock(&m->qlock);
1185 mtx_unlock(&m->lock);
1195 midisynth_writeraw(void *n, uint8_t *buf, size_t len)
1197 struct snd_midi *m = ((struct synth_midi *)n)->m;
1202 MIDI_DEBUG(4, printf("midisynth_writeraw\n"));
1210 mtx_lock(&m->qlock);
1212 if (!(m->flags & M_TX))
1216 printf("midi dump: ");
1219 while (MIDIQ_AVAIL(m->outq) == 0) {
1220 if (!(m->flags & M_TXEN)) {
1222 MPU_CALLBACK(m, m->cookie, m->flags);
1224 mtx_unlock(&m->lock);
1226 MIDI_DEBUG(3, printf("midisynth_writeraw msleep\n"));
1227 retval = msleep(&m->wchan, &m->qlock,
1228 PCATCH | PDROP, "midi TX", 0);
1230 * We slept, maybe things have changed since last
1233 if (retval == EINTR)
1239 mtx_lock(&m->qlock);
1246 * We are certain than data can be placed on the queue
1249 used = MIN(MIDIQ_AVAIL(m->outq), len);
1250 used = MIN(used, MIDI_WSIZE);
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)));
1257 for (i = 0; i < used; i++)
1258 printf("%x ", buf[i]);
1260 MIDIQ_ENQ(m->outq, buf, used);
1264 * Inform the bottom half that data can be written
1266 if (!(m->flags & M_TXEN)) {
1268 MPU_CALLBACK(m, m->cookie, m->flags);
1272 * If we Made it here then transfer is good
1278 err1: mtx_unlock(&m->qlock);
1279 mtx_unlock(&m->lock);
1280 err0: return retval;
1284 midisynth_killnote(void *n, uint8_t chn, uint8_t note, uint8_t vel)
1289 if (note > 127 || chn > 15)
1296 c[0] = 0x90 | (chn & 0x0f); /* Note on. */
1297 c[1] = (u_char)note;
1300 c[0] = 0x80 | (chn & 0x0f); /* Note off. */
1301 c[1] = (u_char)note;
1305 return midisynth_writeraw(n, c, 3);
1309 midisynth_setinstr(void *n, uint8_t chn, uint16_t instr)
1313 if (instr > 127 || chn > 15)
1316 c[0] = 0xc0 | (chn & 0x0f); /* Progamme change. */
1317 c[1] = instr + midi_instroff;
1319 return midisynth_writeraw(n, c, 2);
1323 midisynth_startnote(void *n, uint8_t chn, uint8_t note, uint8_t vel)
1327 if (note > 127 || chn > 15)
1333 c[0] = 0x90 | (chn & 0x0f); /* Note on. */
1334 c[1] = (u_char)note;
1337 return midisynth_writeraw(n, c, 3);
1340 midisynth_alloc(void *n, uint8_t chan, uint8_t note)
1346 midisynth_controller(void *n, uint8_t chn, uint8_t ctrlnum, uint16_t val)
1350 if (ctrlnum > 127 || chn > 15)
1353 c[0] = 0xb0 | (chn & 0x0f); /* Control Message. */
1356 return midisynth_writeraw(n, c, 3);
1360 midisynth_bender(void *n, uint8_t chn, uint16_t val)
1365 if (val > 16383 || chn > 15)
1368 c[0] = 0xe0 | (chn & 0x0f); /* Pitch bend. */
1369 c[1] = (u_char)val & 0x7f;
1370 c[2] = (u_char)(val >> 7) & 0x7f;
1372 return midisynth_writeraw(n, c, 3);
1376 * Single point of midi destructions.
1379 midi_destroy(struct snd_midi *m, int midiuninit)
1382 mtx_assert(&midistat_lock, MA_OWNED);
1383 mtx_assert(&m->lock, MA_OWNED);
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);
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);
1402 * Load and unload functions, creates the /dev/midistat device
1408 mtx_init(&midistat_lock, "midistat lock", NULL, 0);
1409 TAILQ_INIT(&midi_devs); /* Initialize the queue. */
1411 midistat_dev = make_dev(&midistat_cdevsw,
1412 MIDIMKMINOR(0, MIDI_DEV_MIDICTL, 0),
1413 UID_ROOT, GID_WHEEL, 0666, "midistat");
1421 struct snd_midi *m, *tmp;
1424 MIDI_DEBUG(1, printf("midi_unload()\n"));
1426 mtx_lock(&midistat_lock);
1427 if (midistat_isopen)
1430 TAILQ_FOREACH_SAFE(m, &midi_devs, link, tmp) {
1435 retval = midi_destroy(m, 1);
1440 mtx_unlock(&midistat_lock); /* XXX */
1442 destroy_dev(midistat_dev);
1444 * Made it here then unload is complete
1446 mtx_destroy(&midistat_lock);
1450 mtx_unlock(&m->lock);
1452 mtx_unlock(&midistat_lock);
1454 MIDI_DEBUG(2, printf("midi_unload: failed\n"));
1458 extern int seq_modevent(module_t mod, int type, void *data);
1461 midi_modevent(module_t mod, int type, void *data)
1469 retval = midi_load();
1471 retval = seq_modevent(mod, type, data);
1475 retval = midi_unload();
1477 retval = seq_modevent(mod, type, data);
1488 midimapper_addseq(void *arg1, int *unit, void **cookie)
1492 return (kobj_t)arg1;
1496 midimapper_open(void *arg1, void **cookie)
1501 mtx_lock(&midistat_lock);
1503 TAILQ_FOREACH(m, &midi_devs, link) {
1507 mtx_unlock(&midistat_lock);
1512 midimapper_close(void *arg1, void *cookie)
1518 midimapper_fetch_synth(void *arg, void *cookie, int unit)
1523 mtx_lock(&midistat_lock);
1525 TAILQ_FOREACH(m, &midi_devs, link) {
1526 if (unit == retval) {
1527 mtx_unlock(&midistat_lock);
1528 return (kobj_t)m->synth;
1533 mtx_unlock(&midistat_lock);
1537 DEV_MODULE(midi, midi_modevent, NULL);
1538 MODULE_VERSION(midi, 1);