2 * Copyright (c) 2003 Mathew Kanner
3 * Copyright (c) 1998 The NetBSD Foundation, Inc.
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Lennart Augustsson (augustss@netbsd.org).
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
32 * Parts of this file started out as NetBSD: midi.c 1.31
33 * They are mostly gone. Still the most obvious will be the state
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD: head/sys/dev/sound/midi/midi.c 227309 2011-11-07 15:43:11Z ed $");
40 #include <sys/param.h>
41 #include <sys/queue.h>
42 #include <sys/kernel.h>
44 #include <sys/mutex.h>
46 #include <sys/signalvar.h>
48 #include <sys/sysctl.h>
49 #include <sys/types.h>
50 #include <sys/malloc.h>
51 #include <sys/param.h>
52 #include <sys/systm.h>
54 #include <sys/fcntl.h>
55 #include <sys/types.h>
60 #include <sys/module.h>
61 #include <sys/device.h>
63 #ifdef HAVE_KERNEL_OPTION_HEADERS
67 #include <dev/sound/midi/midi.h>
70 #include <dev/sound/midi/midiq.h>
72 MALLOC_DEFINE(M_MIDI
, "midi buffers", "Midi data allocation area");
74 #ifndef KOBJMETHOD_END
75 #define KOBJMETHOD_END { NULL, NULL }
78 #define PCMMKMINOR(u, d, c) ((((c) & 0xff) << 16) | (((u) & 0x0f) << 4) | ((d) & 0x0f))
79 #define MIDIMKMINOR(u, d, c) PCMMKMINOR(u, d, c)
81 #define MIDI_DEV_RAW 2
82 #define MIDI_DEV_MIDICTL 12
85 MIDI_IN_START
, MIDI_IN_SYSEX
, MIDI_IN_DATA
89 * The MPU interface current has init() uninit() inqsize(( outqsize()
90 * callback() : fiddle with the tx|rx status.
96 * /dev/rmidi Structure definitions
99 #define MIDI_NAMELEN 16
102 struct lock lock
; /* Protects all but queues */
105 int unit
; /* Should only be used in midistat */
106 int channel
; /* Should only be used in midistat */
109 int flags
; /* File flags */
110 char name
[MIDI_NAMELEN
];
111 struct lock qlock
; /* Protects inq, outq and flags */
112 MIDIQ_HEAD(, char) inq
, outq
;
114 struct kqinfo rkq
, wkq
;
115 int hiwat
; /* QLEN(outq)>High-water -> disable
116 * writes from userland */
117 enum midi_states inq_state
;
118 int inq_status
, inq_left
; /* Variables for the state machine in
119 * Midi_in, this is to provide that
120 * signals only get issued only
121 * complete command packets. */
124 struct synth_midi
*synth
;
126 TAILQ_ENTRY(snd_midi
) link
;
134 static synth_open_t midisynth_open
;
135 static synth_close_t midisynth_close
;
136 static synth_writeraw_t midisynth_writeraw
;
137 static synth_killnote_t midisynth_killnote
;
138 static synth_startnote_t midisynth_startnote
;
139 static synth_setinstr_t midisynth_setinstr
;
140 static synth_alloc_t midisynth_alloc
;
141 static synth_controller_t midisynth_controller
;
142 static synth_bender_t midisynth_bender
;
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
),
158 DEFINE_CLASS(midisynth
, midisynth_methods
, 0);
161 * Module Exports & Interface
163 * struct midi_chan *midi_init(MPU_CLASS cls, int unit, int chan) int
164 * midi_uninit(struct snd_midi *) 0 == no error EBUSY or other error int
165 * Midi_in(struct midi_chan *, char *buf, int count) int Midi_out(struct
166 * midi_chan *, char *buf, int count)
168 * midi_{in,out} return actual size transfered
174 * midi_devs tailq, holder of all rmidi instances protected by midistat_lock
177 TAILQ_HEAD(, snd_midi
) midi_devs
;
180 * /dev/midistat variables and declarations, protected by midistat_lock
183 static struct lock midistat_lock
;
184 static int midistat_isopen
= 0;
185 static struct sbuf midistat_sbuf
;
186 static int midistat_bufptr
;
187 static struct cdev
*midistat_dev
;
190 * /dev/midistat dev_t declarations
193 static d_open_t midistat_open
;
194 static d_close_t midistat_close
;
195 static d_read_t midistat_read
;
197 static void midi_filter_detach(struct knote
*);
198 static int midi_filter_read(struct knote
*, long);
199 static int midi_filter_write(struct knote
*, long);
201 static struct dev_ops midistat_ops
= {
202 { "midistat", 0, D_MPSAFE
},
203 .d_open
= midistat_open
,
204 .d_close
= midistat_close
,
205 .d_read
= midistat_read
,
208 static struct filterops midi_read_filterops
=
209 { FILTEROP_ISFD
, NULL
, midi_filter_detach
, midi_filter_read
};
210 static struct filterops midi_write_filterops
=
211 { FILTEROP_ISFD
, NULL
, midi_filter_detach
, midi_filter_write
};
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_kqfilter_t midi_kqfilter
;
225 static struct dev_ops midi_ops
= {
226 { "rmidi", 0, D_MPSAFE
},
228 .d_close
= midi_close
,
230 .d_write
= midi_write
,
231 .d_ioctl
= midi_ioctl
,
232 .d_kqfilter
= midi_kqfilter
,
236 * Prototypes of library functions
239 static int midi_destroy(struct snd_midi
*, int);
240 static int midistat_prepare(struct sbuf
* s
);
241 static int midi_load(void);
242 static int midi_unload(void);
247 SYSCTL_NODE(_hw
, OID_AUTO
, midi
, CTLFLAG_RD
, 0, "Midi driver");
248 static SYSCTL_NODE(_hw_midi
, OID_AUTO
, stat
, CTLFLAG_RD
, 0, "Status device");
251 /* XXX: should this be moved into debug.midi? */
252 SYSCTL_INT(_hw_midi
, OID_AUTO
, debug
, CTLFLAG_RW
, &midi_debug
, 0, "");
255 SYSCTL_INT(_hw_midi
, OID_AUTO
, dumpraw
, CTLFLAG_RW
, &midi_dumpraw
, 0, "");
258 SYSCTL_INT(_hw_midi
, OID_AUTO
, instroff
, CTLFLAG_RW
, &midi_instroff
, 0, "");
260 int midistat_verbose
;
261 SYSCTL_INT(_hw_midi_stat
, OID_AUTO
, verbose
, CTLFLAG_RW
,
262 &midistat_verbose
, 0, "");
264 #define MIDI_DEBUG(l,a) if(midi_debug>=l) a
270 * Register a new rmidi device. cls midi_if interface unit == 0 means
271 * auto-assign new unit number unit != 0 already assigned a unit number, eg.
272 * not the first channel provided by this device. channel, sub-unit
273 * cookie is passed back on MPU calls Typical device drivers will call with
274 * unit=0, channel=1..(number of channels) and cookie=soft_c and won't care
275 * what unit number is used.
277 * It is an error to call midi_init with an already used unit/channel combo.
279 * Returns NULL on error
283 midi_init(kobj_class_t cls
, int unit
, int channel
, void *cookie
)
287 int inqsize
, outqsize
;
290 MIDI_DEBUG(1, kprintf("midiinit: unit %d/%d.\n", unit
, channel
));
291 lockmgr(&midistat_lock
, LK_EXCLUSIVE
);
293 * Protect against call with existing unit/channel or auto-allocate a
297 TAILQ_FOREACH(m
, &midi_devs
, link
) {
298 lockmgr(&m
->lock
, LK_EXCLUSIVE
);
300 if (m
->unit
== unit
&& m
->channel
== channel
) {
301 lockmgr(&m
->lock
, LK_RELEASE
);
306 * Find a better unit number
311 lockmgr(&m
->lock
, LK_RELEASE
);
317 MIDI_DEBUG(1, kprintf("midiinit #2: unit %d/%d.\n", unit
, channel
));
318 m
= kmalloc(sizeof(*m
), M_MIDI
, M_WAITOK
| M_ZERO
);
320 m
->synth
= kmalloc(sizeof(*m
->synth
), M_MIDI
, M_WAITOK
| M_ZERO
);
321 kobj_init((kobj_t
)m
->synth
, &midisynth_class
);
323 kobj_init((kobj_t
)m
, cls
);
324 inqsize
= MPU_INQSIZE(m
, cookie
);
325 outqsize
= MPU_OUTQSIZE(m
, cookie
);
327 MIDI_DEBUG(1, kprintf("midiinit queues %d/%d.\n", inqsize
, outqsize
));
328 if (!inqsize
&& !outqsize
)
331 lockinit(&m
->lock
, "raw midi", 0, LK_CANRECURSE
);
332 lockinit(&m
->qlock
, "q raw midi", 0, LK_CANRECURSE
);
334 lockmgr(&m
->lock
, LK_EXCLUSIVE
);
335 lockmgr(&m
->qlock
, LK_EXCLUSIVE
);
338 buf
= kmalloc(sizeof(MIDI_TYPE
) * inqsize
, M_MIDI
, M_WAITOK
);
342 MIDIQ_INIT(m
->inq
, buf
, inqsize
);
345 buf
= kmalloc(sizeof(MIDI_TYPE
) * outqsize
, M_MIDI
, M_WAITOK
);
348 m
->hiwat
= outqsize
/ 2;
350 MIDIQ_INIT(m
->outq
, buf
, outqsize
);
352 if ((inqsize
&& !MIDIQ_BUF(m
->inq
)) ||
353 (outqsize
&& !MIDIQ_BUF(m
->outq
)))
360 m
->channel
= channel
;
363 if (MPU_INIT(m
, cookie
))
366 lockmgr(&m
->lock
, LK_RELEASE
);
367 lockmgr(&m
->qlock
, LK_RELEASE
);
369 TAILQ_INSERT_TAIL(&midi_devs
, m
, link
);
371 lockmgr(&midistat_lock
, LK_RELEASE
);
373 m
->dev
= make_dev(&midi_ops
,
374 MIDIMKMINOR(unit
, MIDI_DEV_RAW
, channel
),
375 UID_ROOT
, GID_WHEEL
, 0666, "midi%d.%d", unit
, channel
);
380 err2
: lockuninit(&m
->qlock
);
381 lockuninit(&m
->lock
);
383 if (MIDIQ_BUF(m
->inq
))
384 kfree(MIDIQ_BUF(m
->inq
), M_MIDI
);
385 if (MIDIQ_BUF(m
->outq
))
386 kfree(MIDIQ_BUF(m
->outq
), M_MIDI
);
387 err1
: kfree(m
, M_MIDI
);
388 err0
: lockmgr(&midistat_lock
, LK_RELEASE
);
389 MIDI_DEBUG(1, kprintf("midi_init ended in error\n"));
394 * midi_uninit does not call MIDI_UNINIT, as since this is the implementors
395 * entry point. midi_unint if fact, does not send any methods. A call to
396 * midi_uninit is a defacto promise that you won't manipulate ch anymore
401 midi_uninit(struct snd_midi
*m
)
406 lockmgr(&midistat_lock
, LK_EXCLUSIVE
);
407 lockmgr(&m
->lock
, LK_EXCLUSIVE
);
409 if (!(m
->rchan
|| m
->wchan
))
421 err
= midi_destroy(m
, 0);
425 err
: lockmgr(&m
->lock
, LK_RELEASE
);
426 exit
: lockmgr(&midistat_lock
, LK_RELEASE
);
431 * midi_in: process all data until the queue is full, then discards the rest.
432 * Since midi_in is a state machine, data discards can cause it to get out of
433 * whack. Process as much as possible. It calls, wakeup, selnotify and
434 * psignal at most once.
438 static int midi_lengths
[] = {2, 2, 2, 2, 1, 1, 2, 0};
441 /* Number of bytes in a MIDI command */
442 #define MIDI_LENGTH(d) (midi_lengths[((d) >> 4) & 7])
443 #define MIDI_ACK 0xfe
444 #define MIDI_IS_STATUS(d) ((d) >= 0x80)
445 #define MIDI_IS_COMMON(d) ((d) >= 0xf0)
447 #define MIDI_SYSEX_START 0xF0
448 #define MIDI_SYSEX_END 0xF7
452 midi_in(struct snd_midi
*m
, MIDI_TYPE
*buf
, int size
)
454 /* int i, sig, enq; */
457 /* MIDI_TYPE data; */
458 MIDI_DEBUG(5, kprintf("midi_in: m=%p size=%d\n", m
, size
));
463 if (!(m
->flags
& M_RX
))
468 lockmgr(&m
->qlock
, LK_EXCLUSIVE
);
471 * Don't bother queuing if not in read mode. Discard everything and
472 * return size so the caller doesn't freak out.
475 if (!(m
->flags
& M_RX
))
478 for (i
= sig
= 0; i
< size
; i
++) {
482 if (data
== MIDI_ACK
)
485 switch (m
->inq_state
) {
487 if (MIDI_IS_STATUS(data
)) {
489 case 0xf0: /* Sysex */
490 m
->inq_state
= MIDI_IN_SYSEX
;
492 case 0xf1: /* MTC quarter frame */
493 case 0xf3: /* Song select */
494 m
->inq_state
= MIDI_IN_DATA
;
498 case 0xf2: /* Song position pointer */
499 m
->inq_state
= MIDI_IN_DATA
;
504 if (MIDI_IS_COMMON(data
)) {
508 m
->inq_state
= MIDI_IN_DATA
;
510 m
->inq_status
= data
;
511 m
->inq_left
= MIDI_LENGTH(data
);
515 } else if (MIDI_IS_STATUS(m
->inq_status
)) {
516 m
->inq_state
= MIDI_IN_DATA
;
517 if (!MIDIQ_FULL(m
->inq
)) {
519 MIDIQ_ENQ(m
->inq
, &m
->inq_status
, 1);
522 m
->inq_left
= MIDI_LENGTH(m
->inq_status
) - 1;
526 * End of case MIDI_IN_START:
531 if (--m
->inq_left
<= 0)
532 sig
= 1;/* deliver data */
535 if (data
== MIDI_SYSEX_END
)
536 m
->inq_state
= MIDI_IN_START
;
541 if (!MIDIQ_FULL(m
->inq
)) {
542 MIDIQ_ENQ(m
->inq
, &data
, 1);
546 * End of the state machines main "for loop"
551 MIDI_DEBUG(6, kprintf("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
) {
556 MIDIQ_ENQ(m
->inq
, buf
, size
);
558 MIDI_DEBUG(4, kprintf("midi_in: Discarding data qu\n"));
559 lockmgr(&m
->qlock
, LK_RELEASE
);
566 KNOTE(&m
->rkq
.ki_note
, 0);
569 ksignal(m
->async
, SIGIO
);
575 lockmgr(&m
->qlock
, LK_RELEASE
);
580 * midi_out: The only clearer of the M_TXEN flag.
583 midi_out(struct snd_midi
*m
, MIDI_TYPE
*buf
, int size
)
590 if (!(m
->flags
& M_TXEN
))
593 MIDI_DEBUG(2, kprintf("midi_out: %p\n", m
));
594 lockmgr(&m
->qlock
, LK_EXCLUSIVE
);
595 used
= MIN(size
, MIDIQ_LEN(m
->outq
));
596 MIDI_DEBUG(3, kprintf("midi_out: used %d\n", used
));
598 MIDIQ_DEQ(m
->outq
, buf
, used
);
599 if (MIDIQ_EMPTY(m
->outq
)) {
601 MPU_CALLBACKP(m
, m
->cookie
, m
->flags
);
603 if (used
&& MIDIQ_AVAIL(m
->outq
) > m
->hiwat
) {
608 KNOTE(&m
->wkq
.ki_note
, 0);
611 ksignal(m
->async
, SIGIO
);
615 lockmgr(&m
->qlock
, LK_RELEASE
);
621 * /dev/rmidi#.# device access functions
624 midi_open(struct dev_open_args
*ap
)
626 cdev_t i_dev
= ap
->a_head
.a_dev
;
627 int flags
= ap
->a_oflags
;
628 struct snd_midi
*m
= i_dev
->si_drv1
;
632 MIDI_DEBUG(1, kprintf("midiopen %p %s %s\n", td
,
633 flags
& FREAD
? "M_RX" : "", flags
& FWRITE
? "M_TX" : ""));
638 lockmgr(&m
->lock
, LK_EXCLUSIVE
);
639 lockmgr(&m
->qlock
, LK_EXCLUSIVE
);
644 if (MIDIQ_SIZE(m
->inq
) == 0)
646 else if (m
->flags
& M_RX
)
651 if (flags
& FWRITE
) {
652 if (MIDIQ_SIZE(m
->outq
) == 0)
654 else if (m
->flags
& M_TX
)
666 m
->flags
|= M_RX
| M_RXEN
;
668 * Only clear the inq, the outq might still have data to drain
669 * from a previous session
677 MPU_CALLBACK(m
, m
->cookie
, m
->flags
);
679 MIDI_DEBUG(2, kprintf("midi_open: opened.\n"));
681 err
: lockmgr(&m
->qlock
, LK_RELEASE
);
682 lockmgr(&m
->lock
, LK_RELEASE
);
687 midi_close(struct dev_close_args
*ap
)
689 cdev_t i_dev
= ap
->a_head
.a_dev
;
690 int flags
= ap
->a_fflag
;
691 struct snd_midi
*m
= i_dev
->si_drv1
;
696 MIDI_DEBUG(1, kprintf("midi_close %p %s %s\n", td
,
697 flags
& FREAD
? "M_RX" : "", flags
& FWRITE
? "M_TX" : ""));
703 lockmgr(&m
->lock
, LK_EXCLUSIVE
);
704 lockmgr(&m
->qlock
, LK_EXCLUSIVE
);
706 if ((flags
& FREAD
&& !(m
->flags
& M_RX
)) ||
707 (flags
& FWRITE
&& !(m
->flags
& M_TX
))) {
716 m
->flags
&= ~(M_RX
| M_RXEN
);
720 if ((m
->flags
& (M_TXEN
| M_RXEN
)) != (oldflags
& (M_RXEN
| M_TXEN
)))
721 MPU_CALLBACK(m
, m
->cookie
, m
->flags
);
723 MIDI_DEBUG(1, kprintf("midi_close: closed, busy = %d.\n", m
->busy
));
725 lockmgr(&m
->qlock
, LK_RELEASE
);
726 lockmgr(&m
->lock
, LK_RELEASE
);
732 * TODO: midi_read, per oss programmer's guide pg. 42 should return as soon
733 * as data is available.
736 midi_read(struct dev_read_args
*ap
)
738 cdev_t i_dev
= ap
->a_head
.a_dev
;
739 struct uio
*uio
= ap
->a_uio
;
740 int ioflag
= ap
->a_ioflag
;
741 #define MIDI_RSIZE 32
742 struct snd_midi
*m
= i_dev
->si_drv1
;
745 char buf
[MIDI_RSIZE
];
747 MIDI_DEBUG(5, kprintf("midiread: count=%lu\n",
748 (unsigned long)uio
->uio_resid
));
755 lockmgr(&m
->lock
, LK_EXCLUSIVE
);
756 lockmgr(&m
->qlock
, LK_EXCLUSIVE
);
758 if (!(m
->flags
& M_RX
))
761 while (uio
->uio_resid
> 0) {
762 while (MIDIQ_EMPTY(m
->inq
)) {
763 retval
= EWOULDBLOCK
;
764 if (ioflag
& O_NONBLOCK
)
766 lockmgr(&m
->lock
, LK_RELEASE
);
768 retval
= lksleep(&m
->rchan
, &m
->qlock
,
769 PCATCH
, "midi RX", 0);
771 * We slept, maybe things have changed since last
776 if (m
!= i_dev
->si_drv1
)
778 /* if (retval && retval != ERESTART) */
781 lockmgr(&m
->lock
, LK_EXCLUSIVE
);
782 lockmgr(&m
->qlock
, LK_EXCLUSIVE
);
787 MIDI_DEBUG(6, kprintf("midi_read start\n"));
789 * At this point, it is certain that m->inq has data
792 used
= MIN(MIDIQ_LEN(m
->inq
), uio
->uio_resid
);
793 used
= MIN(used
, MIDI_RSIZE
);
795 MIDI_DEBUG(6, kprintf("midiread: uiomove cc=%d\n", used
));
796 MIDIQ_DEQ(m
->inq
, buf
, used
);
797 retval
= uiomove(buf
, used
, uio
);
803 * If we Made it here then transfer is good
806 err1
: lockmgr(&m
->qlock
, LK_RELEASE
);
807 lockmgr(&m
->lock
, LK_RELEASE
);
808 err0
: MIDI_DEBUG(4, kprintf("midi_read: ret %d\n", retval
));
813 * midi_write: The only setter of M_TXEN
817 midi_write(struct dev_write_args
*ap
)
819 cdev_t i_dev
= ap
->a_head
.a_dev
;
820 struct uio
*uio
= ap
->a_uio
;
821 int ioflag
= ap
->a_ioflag
;
822 #define MIDI_WSIZE 32
823 struct snd_midi
*m
= i_dev
->si_drv1
;
826 char buf
[MIDI_WSIZE
];
829 MIDI_DEBUG(4, kprintf("midi_write\n"));
834 lockmgr(&m
->lock
, LK_EXCLUSIVE
);
835 lockmgr(&m
->qlock
, LK_EXCLUSIVE
);
837 if (!(m
->flags
& M_TX
))
840 while (uio
->uio_resid
> 0) {
841 while (MIDIQ_AVAIL(m
->outq
) == 0) {
842 retval
= EWOULDBLOCK
;
843 if (ioflag
& O_NONBLOCK
)
845 lockmgr(&m
->lock
, LK_RELEASE
);
847 MIDI_DEBUG(3, kprintf("midi_write lksleep\n"));
848 retval
= lksleep(&m
->wchan
, &m
->qlock
,
849 PCATCH
, "midi TX", 0);
851 * We slept, maybe things have changed since last
856 if (m
!= i_dev
->si_drv1
)
860 lockmgr(&m
->lock
, LK_EXCLUSIVE
);
861 lockmgr(&m
->qlock
, LK_EXCLUSIVE
);
868 * We are certain than data can be placed on the queue
871 used
= MIN(MIDIQ_AVAIL(m
->outq
), uio
->uio_resid
);
872 used
= MIN(used
, MIDI_WSIZE
);
873 MIDI_DEBUG(5, kprintf("midiout: resid %zd len %jd avail %jd\n",
874 uio
->uio_resid
, (intmax_t)MIDIQ_LEN(m
->outq
),
875 (intmax_t)MIDIQ_AVAIL(m
->outq
)));
878 MIDI_DEBUG(5, kprintf("midi_write: uiomove cc=%d\n", used
));
879 retval
= uiomove(buf
, used
, uio
);
882 MIDIQ_ENQ(m
->outq
, buf
, used
);
884 * Inform the bottom half that data can be written
886 if (!(m
->flags
& M_TXEN
)) {
888 MPU_CALLBACK(m
, m
->cookie
, m
->flags
);
892 * If we Made it here then transfer is good
895 err1
: lockmgr(&m
->qlock
, LK_RELEASE
);
896 lockmgr(&m
->lock
, LK_RELEASE
);
901 midi_ioctl(struct dev_ioctl_args
*ap
)
907 midi_kqfilter(struct dev_kqfilter_args
*ap
)
909 cdev_t dev
= ap
->a_head
.a_dev
;
910 struct knote
*kn
= ap
->a_kn
;
917 switch (kn
->kn_filter
) {
919 kn
->kn_fop
= &midi_read_filterops
;
920 kn
->kn_hook
= (caddr_t
)m
;
921 klist
= &m
->rkq
.ki_note
;
924 kn
->kn_fop
= &midi_write_filterops
;
925 kn
->kn_hook
= (caddr_t
)m
;
926 klist
= &m
->wkq
.ki_note
;
929 ap
->a_result
= EOPNOTSUPP
;
933 knote_insert(klist
, kn
);
939 midi_filter_detach(struct knote
*kn
)
941 struct snd_midi
*m
= (struct snd_midi
*)kn
->kn_hook
;
942 struct klist
*rklist
= &m
->rkq
.ki_note
;
943 struct klist
*wklist
= &m
->wkq
.ki_note
;
945 knote_remove(rklist
, kn
);
946 knote_remove(wklist
, kn
);
950 midi_filter_read(struct knote
*kn
, long hint
)
952 struct snd_midi
*m
= (struct snd_midi
*)kn
->kn_hook
;
955 lockmgr(&m
->lock
, LK_EXCLUSIVE
);
956 lockmgr(&m
->qlock
, LK_EXCLUSIVE
);
958 if (!MIDIQ_EMPTY(m
->inq
))
961 lockmgr(&m
->lock
, LK_RELEASE
);
962 lockmgr(&m
->qlock
, LK_RELEASE
);
968 midi_filter_write(struct knote
*kn
, long hint
)
970 struct snd_midi
*m
= (struct snd_midi
*)kn
->kn_hook
;
973 lockmgr(&m
->lock
, LK_EXCLUSIVE
);
974 lockmgr(&m
->qlock
, LK_EXCLUSIVE
);
976 if (MIDIQ_AVAIL(m
->outq
) < m
->hiwat
)
979 lockmgr(&m
->lock
, LK_RELEASE
);
980 lockmgr(&m
->qlock
, LK_RELEASE
);
986 * /dev/midistat device functions
990 midistat_open(struct dev_open_args
*ap
)
994 MIDI_DEBUG(1, kprintf("midistat_open\n"));
995 lockmgr(&midistat_lock
, LK_EXCLUSIVE
);
997 if (midistat_isopen
) {
998 lockmgr(&midistat_lock
, LK_RELEASE
);
1001 midistat_isopen
= 1;
1002 lockmgr(&midistat_lock
, LK_RELEASE
);
1004 if (sbuf_new(&midistat_sbuf
, NULL
, 4096, SBUF_AUTOEXTEND
) == NULL
) {
1006 lockmgr(&midistat_lock
, LK_EXCLUSIVE
);
1009 lockmgr(&midistat_lock
, LK_EXCLUSIVE
);
1010 midistat_bufptr
= 0;
1011 error
= (midistat_prepare(&midistat_sbuf
) > 0) ? 0 : ENOMEM
;
1014 midistat_isopen
= 0;
1015 lockmgr(&midistat_lock
, LK_RELEASE
);
1020 midistat_close(struct dev_close_args
*ap
)
1022 MIDI_DEBUG(1, kprintf("midistat_close\n"));
1023 lockmgr(&midistat_lock
, LK_EXCLUSIVE
);
1024 if (!midistat_isopen
) {
1025 lockmgr(&midistat_lock
, LK_RELEASE
);
1028 sbuf_delete(&midistat_sbuf
);
1029 midistat_isopen
= 0;
1031 lockmgr(&midistat_lock
, LK_RELEASE
);
1036 midistat_read(struct dev_read_args
*ap
)
1038 struct uio
*buf
= ap
->a_uio
;
1041 MIDI_DEBUG(4, kprintf("midistat_read\n"));
1042 lockmgr(&midistat_lock
, LK_EXCLUSIVE
);
1043 if (!midistat_isopen
) {
1044 lockmgr(&midistat_lock
, LK_RELEASE
);
1047 l
= min(buf
->uio_resid
, sbuf_len(&midistat_sbuf
) - midistat_bufptr
);
1050 lockmgr(&midistat_lock
, LK_RELEASE
);
1051 err
= uiomove(sbuf_data(&midistat_sbuf
) + midistat_bufptr
, l
,
1053 lockmgr(&midistat_lock
, LK_EXCLUSIVE
);
1056 midistat_bufptr
+= l
;
1057 lockmgr(&midistat_lock
, LK_RELEASE
);
1062 * Module library functions
1066 midistat_prepare(struct sbuf
*s
)
1070 KKASSERT(lockowned(&midistat_lock
));
1072 sbuf_printf(s
, "FreeBSD Midi Driver (midi2)\n");
1073 if (TAILQ_EMPTY(&midi_devs
)) {
1074 sbuf_printf(s
, "No devices installed.\n");
1078 sbuf_printf(s
, "Installed devices:\n");
1080 TAILQ_FOREACH(m
, &midi_devs
, link
) {
1081 lockmgr(&m
->lock
, LK_EXCLUSIVE
);
1082 sbuf_printf(s
, "%s [%d/%d:%s]", m
->name
, m
->unit
, m
->channel
,
1083 MPU_PROVIDER(m
, m
->cookie
));
1084 sbuf_printf(s
, "%s", MPU_DESCR(m
, m
->cookie
, midistat_verbose
));
1085 sbuf_printf(s
, "\n");
1086 lockmgr(&m
->lock
, LK_RELEASE
);
1095 * Convert IOCTL command to string for debugging
1099 midi_cmdname(int cmd
)
1104 } *tab
, cmdtab_midiioctl
[] = {
1105 #define A(x) {x, ## x}
1107 * Once we have some real IOCTLs define, the following will
1110 * A(SNDCTL_MIDI_PRETIME), A(SNDCTL_MIDI_MPUMODE),
1111 * A(SNDCTL_MIDI_MPUCMD), A(SNDCTL_SYNTH_INFO),
1112 * A(SNDCTL_MIDI_INFO), A(SNDCTL_SYNTH_MEMAVL),
1113 * A(SNDCTL_FM_LOAD_INSTR), A(SNDCTL_FM_4OP_ENABLE),
1114 * A(MIOSPASSTHRU), A(MIOGPASSTHRU), A(AIONWRITE),
1115 * A(AIOGSIZE), A(AIOSSIZE), A(AIOGFMT), A(AIOSFMT),
1116 * A(AIOGMIX), A(AIOSMIX), A(AIOSTOP), A(AIOSYNC),
1125 for (tab
= cmdtab_midiioctl
; tab
->cmd
!= cmd
&& tab
->cmd
!= -1; tab
++);
1137 midisynth_open(void *n
, void *arg
, int flags
)
1139 struct snd_midi
*m
= ((struct synth_midi
*)n
)->m
;
1142 MIDI_DEBUG(1, kprintf("midisynth_open %s %s\n",
1143 flags
& FREAD
? "M_RX" : "", flags
& FWRITE
? "M_TX" : ""));
1148 lockmgr(&m
->lock
, LK_EXCLUSIVE
);
1149 lockmgr(&m
->qlock
, LK_EXCLUSIVE
);
1153 if (flags
& FREAD
) {
1154 if (MIDIQ_SIZE(m
->inq
) == 0)
1156 else if (m
->flags
& M_RX
)
1161 if (flags
& FWRITE
) {
1162 if (MIDIQ_SIZE(m
->outq
) == 0)
1164 else if (m
->flags
& M_TX
)
1172 * TODO: Consider m->async = 0;
1175 if (flags
& FREAD
) {
1176 m
->flags
|= M_RX
| M_RXEN
;
1178 * Only clear the inq, the outq might still have data to drain
1179 * from a previous session
1181 MIDIQ_CLEAR(m
->inq
);
1185 if (flags
& FWRITE
) {
1189 m
->synth_flags
= flags
& (FREAD
| FWRITE
);
1191 MPU_CALLBACK(m
, m
->cookie
, m
->flags
);
1194 err
: lockmgr(&m
->qlock
, LK_RELEASE
);
1195 lockmgr(&m
->lock
, LK_RELEASE
);
1196 MIDI_DEBUG(2, kprintf("midisynth_open: return %d.\n", retval
));
1201 midisynth_close(void *n
)
1203 struct snd_midi
*m
= ((struct synth_midi
*)n
)->m
;
1207 MIDI_DEBUG(1, kprintf("midisynth_close %s %s\n",
1208 m
->synth_flags
& FREAD
? "M_RX" : "",
1209 m
->synth_flags
& FWRITE
? "M_TX" : ""));
1214 lockmgr(&m
->lock
, LK_EXCLUSIVE
);
1215 lockmgr(&m
->qlock
, LK_EXCLUSIVE
);
1217 if ((m
->synth_flags
& FREAD
&& !(m
->flags
& M_RX
)) ||
1218 (m
->synth_flags
& FWRITE
&& !(m
->flags
& M_TX
))) {
1224 oldflags
= m
->flags
;
1226 if (m
->synth_flags
& FREAD
)
1227 m
->flags
&= ~(M_RX
| M_RXEN
);
1228 if (m
->synth_flags
& FWRITE
)
1231 if ((m
->flags
& (M_TXEN
| M_RXEN
)) != (oldflags
& (M_RXEN
| M_TXEN
)))
1232 MPU_CALLBACK(m
, m
->cookie
, m
->flags
);
1234 MIDI_DEBUG(1, kprintf("midi_close: closed, busy = %d.\n", m
->busy
));
1236 lockmgr(&m
->qlock
, LK_RELEASE
);
1237 lockmgr(&m
->lock
, LK_RELEASE
);
1247 midisynth_writeraw(void *n
, uint8_t *buf
, size_t len
)
1249 struct snd_midi
*m
= ((struct synth_midi
*)n
)->m
;
1254 MIDI_DEBUG(4, kprintf("midisynth_writeraw\n"));
1261 lockmgr(&m
->lock
, LK_EXCLUSIVE
);
1262 lockmgr(&m
->qlock
, LK_EXCLUSIVE
);
1264 if (!(m
->flags
& M_TX
))
1268 kprintf("midi dump: ");
1271 while (MIDIQ_AVAIL(m
->outq
) == 0) {
1272 if (!(m
->flags
& M_TXEN
)) {
1274 MPU_CALLBACK(m
, m
->cookie
, m
->flags
);
1276 lockmgr(&m
->lock
, LK_RELEASE
);
1278 MIDI_DEBUG(3, kprintf("midisynth_writeraw lksleep\n"));
1279 retval
= lksleep(&m
->wchan
, &m
->qlock
,
1280 PCATCH
, "midi TX", 0);
1282 * We slept, maybe things have changed since last
1285 if (retval
== EINTR
)
1290 lockmgr(&m
->lock
, LK_EXCLUSIVE
);
1291 lockmgr(&m
->qlock
, LK_EXCLUSIVE
);
1298 * We are certain than data can be placed on the queue
1301 used
= MIN(MIDIQ_AVAIL(m
->outq
), len
);
1302 used
= MIN(used
, MIDI_WSIZE
);
1304 kprintf("midi_synth: resid %zu len %jd avail %jd\n",
1305 len
, (intmax_t)MIDIQ_LEN(m
->outq
),
1306 (intmax_t)MIDIQ_AVAIL(m
->outq
)));
1309 for (i
= 0; i
< used
; i
++)
1310 kprintf("%x ", buf
[i
]);
1312 MIDIQ_ENQ(m
->outq
, buf
, used
);
1316 * Inform the bottom half that data can be written
1318 if (!(m
->flags
& M_TXEN
)) {
1320 MPU_CALLBACK(m
, m
->cookie
, m
->flags
);
1324 * If we Made it here then transfer is good
1330 err1
: lockmgr(&m
->qlock
, LK_RELEASE
);
1331 lockmgr(&m
->lock
, LK_RELEASE
);
1332 err0
: return retval
;
1336 midisynth_killnote(void *n
, uint8_t chn
, uint8_t note
, uint8_t vel
)
1341 if (note
> 127 || chn
> 15)
1348 c
[0] = 0x90 | (chn
& 0x0f); /* Note on. */
1349 c
[1] = (u_char
)note
;
1352 c
[0] = 0x80 | (chn
& 0x0f); /* Note off. */
1353 c
[1] = (u_char
)note
;
1357 return midisynth_writeraw(n
, c
, 3);
1361 midisynth_setinstr(void *n
, uint8_t chn
, uint16_t instr
)
1365 if (instr
> 127 || chn
> 15)
1368 c
[0] = 0xc0 | (chn
& 0x0f); /* Progamme change. */
1369 c
[1] = instr
+ midi_instroff
;
1371 return midisynth_writeraw(n
, c
, 2);
1375 midisynth_startnote(void *n
, uint8_t chn
, uint8_t note
, uint8_t vel
)
1379 if (note
> 127 || chn
> 15)
1385 c
[0] = 0x90 | (chn
& 0x0f); /* Note on. */
1386 c
[1] = (u_char
)note
;
1389 return midisynth_writeraw(n
, c
, 3);
1392 midisynth_alloc(void *n
, uint8_t chan
, uint8_t note
)
1398 midisynth_controller(void *n
, uint8_t chn
, uint8_t ctrlnum
, uint16_t val
)
1402 if (ctrlnum
> 127 || chn
> 15)
1405 c
[0] = 0xb0 | (chn
& 0x0f); /* Control Message. */
1408 return midisynth_writeraw(n
, c
, 3);
1412 midisynth_bender(void *n
, uint8_t chn
, uint16_t val
)
1417 if (val
> 16383 || chn
> 15)
1420 c
[0] = 0xe0 | (chn
& 0x0f); /* Pitch bend. */
1421 c
[1] = (u_char
)val
& 0x7f;
1422 c
[2] = (u_char
)(val
>> 7) & 0x7f;
1424 return midisynth_writeraw(n
, c
, 3);
1428 * Single point of midi destructions.
1431 midi_destroy(struct snd_midi
*m
, int midiuninit
)
1434 KKASSERT(lockowned(&midistat_lock
));
1435 KKASSERT(lockowned(&m
->lock
));
1437 MIDI_DEBUG(3, kprintf("midi_destroy\n"));
1438 m
->dev
->si_drv1
= NULL
;
1439 lockmgr(&m
->lock
, LK_RELEASE
); /* XXX */
1440 destroy_dev(m
->dev
);
1441 TAILQ_REMOVE(&midi_devs
, m
, link
);
1443 MPU_UNINIT(m
, m
->cookie
);
1444 kfree(MIDIQ_BUF(m
->inq
), M_MIDI
);
1445 kfree(MIDIQ_BUF(m
->outq
), M_MIDI
);
1446 lockuninit(&m
->qlock
);
1447 lockuninit(&m
->lock
);
1453 * Load and unload functions, creates the /dev/midistat device
1459 lockinit(&midistat_lock
, "midistat lock", 0, LK_CANRECURSE
);
1460 TAILQ_INIT(&midi_devs
); /* Initialize the queue. */
1462 midistat_dev
= make_dev(&midistat_ops
,
1463 MIDIMKMINOR(0, MIDI_DEV_MIDICTL
, 0),
1464 UID_ROOT
, GID_WHEEL
, 0666, "midistat");
1475 MIDI_DEBUG(1, kprintf("midi_unload()\n"));
1477 lockmgr(&midistat_lock
, LK_EXCLUSIVE
);
1478 if (midistat_isopen
)
1481 TAILQ_FOREACH(m
, &midi_devs
, link
) {
1482 lockmgr(&m
->lock
, LK_EXCLUSIVE
);
1486 retval
= midi_destroy(m
, 1);
1491 lockmgr(&midistat_lock
, LK_RELEASE
); /* XXX */
1493 destroy_dev(midistat_dev
);
1495 * Made it here then unload is complete
1497 lockuninit(&midistat_lock
);
1501 lockmgr(&m
->lock
, LK_RELEASE
);
1503 lockmgr(&midistat_lock
, LK_RELEASE
);
1505 MIDI_DEBUG(2, kprintf("midi_unload: failed\n"));
1509 extern int seq_modevent(module_t mod
, int type
, void *data
);
1512 midi_modevent(module_t mod
, int type
, void *data
)
1520 retval
= midi_load();
1523 retval
= seq_modevent(mod
, type
, data
);
1528 retval
= midi_unload();
1531 retval
= seq_modevent(mod
, type
, data
);
1543 midimapper_addseq(void *arg1
, int *unit
, void **cookie
)
1547 return (kobj_t
)arg1
;
1551 midimapper_open(void *arg1
, void **cookie
)
1556 lockmgr(&midistat_lock
, LK_EXCLUSIVE
);
1558 TAILQ_FOREACH(m
, &midi_devs
, link
) {
1562 lockmgr(&midistat_lock
, LK_RELEASE
);
1567 midimapper_close(void *arg1
, void *cookie
)
1573 midimapper_fetch_synth(void *arg
, void *cookie
, int unit
)
1578 lockmgr(&midistat_lock
, LK_EXCLUSIVE
);
1580 TAILQ_FOREACH(m
, &midi_devs
, link
) {
1581 if (unit
== retval
) {
1582 lockmgr(&midistat_lock
, LK_RELEASE
);
1583 return (kobj_t
)m
->synth
;
1588 lockmgr(&midistat_lock
, LK_RELEASE
);
1592 DEV_MODULE(midi
, midi_modevent
, NULL
);
1593 MODULE_VERSION(midi
, 1);