1 /* $NetBSD: midi.c,v 1.70 2009/08/23 15:56:07 jmcneill Exp $ */
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (augustss@NetBSD.org) and (MIDI FST and Active
9 * Sense handling) Chapman Flack (chap@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.
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: midi.c,v 1.70 2009/08/23 15:56:07 jmcneill Exp $");
37 #include "sequencer.h"
39 #include <sys/param.h>
40 #include <sys/ioctl.h>
41 #include <sys/fcntl.h>
42 #include <sys/vnode.h>
43 #include <sys/select.h>
45 #include <sys/malloc.h>
47 #include <sys/systm.h>
48 #include <sys/callout.h>
49 #include <sys/syslog.h>
50 #include <sys/kernel.h>
51 #include <sys/signalvar.h>
53 #include <sys/audioio.h>
54 #include <sys/midiio.h>
55 #include <sys/device.h>
58 #include <dev/audio_if.h>
59 #include <dev/midi_if.h>
60 #include <dev/midivar.h>
65 #define DPRINTF(x) if (mididebug) printf x
66 #define DPRINTFN(n,x) if (mididebug >= (n)) printf x
69 * 1: detected protocol errors and buffer overflows
70 * 2: probe, attach, detach
72 * 4: data received except realtime
74 * 6: read, write, poll
76 * 8: uiomoves, synchronization
77 * 9: realtime data received
84 static struct simplelock hwif_register_lock
= SIMPLELOCK_INITIALIZER
;
85 static struct midi_softc
*hwif_softc
= NULL
;
87 void midi_in(void *, int);
88 void midi_out(void *);
89 int midi_poll_out(struct midi_softc
*);
90 int midi_intr_out(struct midi_softc
*);
91 int midi_msg_out(struct midi_softc
*,
92 u_char
**, u_char
**, u_char
**, u_char
**);
93 int midi_start_output(struct midi_softc
*);
94 int midi_sleep_timo(int *, const char *, int, struct simplelock
*);
95 int midi_sleep(int *, const char *, struct simplelock
*);
96 void midi_wakeup(int *);
97 void midi_initbuf(struct midi_buffer
*);
98 void midi_xmt_asense(void *);
99 void midi_rcv_asense(void *);
100 void midi_softintr_rd(void *);
101 void midi_softintr_wr(void *);
103 int midiprobe(device_t
, cfdata_t
, void *);
104 void midiattach(device_t
, device_t
, void *);
105 int mididetach(device_t
, int);
106 int midiactivate(device_t
, enum devact
);
108 dev_type_open(midiopen
);
109 dev_type_close(midiclose
);
110 dev_type_read(midiread
);
111 dev_type_write(midiwrite
);
112 dev_type_ioctl(midiioctl
);
113 dev_type_poll(midipoll
);
114 dev_type_kqfilter(midikqfilter
);
116 const struct cdevsw midi_cdevsw
= {
117 midiopen
, midiclose
, midiread
, midiwrite
, midiioctl
,
118 nostop
, notty
, midipoll
, nommap
, midikqfilter
, D_OTHER
,
121 CFATTACH_DECL_NEW(midi
, sizeof(struct midi_softc
),
122 midiprobe
, midiattach
, mididetach
, midiactivate
);
124 #define MIDI_XMT_ASENSE_PERIOD mstohz(275)
125 #define MIDI_RCV_ASENSE_PERIOD mstohz(300)
127 extern struct cfdriver midi_cd
;
130 midiprobe(device_t parent
, cfdata_t match
, void *aux
)
132 struct audio_attach_args
*sa
= aux
;
134 DPRINTFN(2,("midiprobe: type=%d sa=%p hw=%p\n",
135 sa
->type
, sa
, sa
->hwif
));
136 return (sa
->type
== AUDIODEV_TYPE_MIDI
);
140 midiattach(device_t parent
, device_t self
, void *aux
)
142 struct midi_softc
*sc
= device_private(self
);
143 struct audio_attach_args
*sa
= aux
;
144 const struct midi_hw_if
*hwp
= sa
->hwif
;
145 void *hdlp
= sa
->hdl
;
149 DPRINTFN(2, ("MIDI attach\n"));
157 printf("midi: missing method\n");
165 midi_attach(sc
, parent
);
166 if (!device_pmf_is_registered(self
))
167 if (!pmf_device_register(self
, NULL
, NULL
))
168 aprint_error_dev(self
,
169 "couldn't establish power handler\n");
173 midiactivate(device_t self
, enum devact act
)
175 struct midi_softc
*sc
= device_private(self
);
178 case DVACT_DEACTIVATE
:
187 mididetach(device_t self
, int flags
)
189 struct midi_softc
*sc
= device_private(self
);
192 DPRINTFN(2,("%s: sc=%p flags=%d\n", __func__
, sc
, flags
));
194 pmf_device_deregister(self
);
201 /* locate the major number */
202 maj
= cdevsw_lookup_major(&midi_cdevsw
);
204 /* Nuke the vnodes for any open instances (calls close). */
205 mn
= device_unit(self
);
206 vdevgone(maj
, mn
, mn
, VCHR
);
208 if ( !(sc
->props
& MIDI_PROP_NO_OUTPUT
) ) {
209 evcnt_detach(&sc
->xmt
.bytesDiscarded
);
210 evcnt_detach(&sc
->xmt
.incompleteMessages
);
212 if ( sc
->props
& MIDI_PROP_CAN_INPUT
) {
213 evcnt_detach(&sc
->rcv
.bytesDiscarded
);
214 evcnt_detach(&sc
->rcv
.incompleteMessages
);
217 if (sc
->sih_rd
!= NULL
) {
218 softint_disestablish(sc
->sih_rd
);
221 if (sc
->sih_wr
!= NULL
) {
222 softint_disestablish(sc
->sih_wr
);
230 midi_attach(struct midi_softc
*sc
, device_t parent
)
235 callout_init(&sc
->xmt_asense_co
, 0);
236 callout_init(&sc
->rcv_asense_co
, 0);
237 callout_setfunc(&sc
->xmt_asense_co
, midi_xmt_asense
, sc
);
238 callout_setfunc(&sc
->rcv_asense_co
, midi_rcv_asense
, sc
);
239 simple_lock_init(&sc
->out_lock
);
240 simple_lock_init(&sc
->in_lock
);
246 sc
->sih_rd
= softint_establish(SOFTINT_SERIAL
, midi_softintr_rd
, sc
);
247 sc
->sih_wr
= softint_establish(SOFTINT_SERIAL
, midi_softintr_wr
, sc
);
250 simple_lock(&hwif_register_lock
);
252 sc
->hw_if
->getinfo(sc
->hw_hdl
, &mi
);
254 simple_unlock(&hwif_register_lock
);
257 sc
->props
= mi
.props
;
259 if ( !(sc
->props
& MIDI_PROP_NO_OUTPUT
) ) {
260 evcnt_attach_dynamic(&sc
->xmt
.bytesDiscarded
,
261 EVCNT_TYPE_MISC
, NULL
,
262 device_xname(sc
->dev
), "xmt bytes discarded");
263 evcnt_attach_dynamic(&sc
->xmt
.incompleteMessages
,
264 EVCNT_TYPE_MISC
, NULL
,
265 device_xname(sc
->dev
), "xmt incomplete msgs");
267 if ( sc
->props
& MIDI_PROP_CAN_INPUT
) {
268 evcnt_attach_dynamic(&sc
->rcv
.bytesDiscarded
,
269 EVCNT_TYPE_MISC
, NULL
,
270 device_xname(sc
->dev
), "rcv bytes discarded");
271 evcnt_attach_dynamic(&sc
->rcv
.incompleteMessages
,
272 EVCNT_TYPE_MISC
, NULL
,
273 device_xname(sc
->dev
), "rcv incomplete msgs");
276 aprint_normal(": %s\n", mi
.name
);
279 void midi_register_hw_if_ext(struct midi_hw_if_ext
*exthw
) {
280 if ( hwif_softc
!= NULL
) /* ignore calls resulting from non-init */
281 hwif_softc
->hw_if_ext
= exthw
; /* uses of getinfo */
285 midi_unit_count(void)
288 for ( i
= 0; i
< midi_cd
.cd_ndevs
; ++i
)
289 if ( NULL
== device_lookup(&midi_cd
, i
) )
295 midi_initbuf(struct midi_buffer
*mb
)
297 mb
->idx_producerp
= mb
->idx_consumerp
= mb
->idx
;
298 mb
->buf_producerp
= mb
->buf_consumerp
= mb
->buf
;
300 #define PACK_MB_IDX(cat,len) (((cat)<<4)|(len))
301 #define MB_IDX_CAT(idx) ((idx)>>4)
302 #define MB_IDX_LEN(idx) ((idx)&0xf)
305 midi_sleep_timo(int *chan
, const char *label
, int timo
, struct simplelock
*lk
)
312 DPRINTFN(8, ("midi_sleep_timo: %p %s %d\n", chan
, label
, timo
));
314 st
= ltsleep(chan
, PWAIT
| PCATCH
, label
, timo
, lk
);
318 printf("midi_sleep: %d\n", st
);
324 midi_sleep(int *chan
, const char *label
, struct simplelock
*lk
)
326 return midi_sleep_timo(chan
, label
, 0, lk
);
330 midi_wakeup(int *chan
)
333 DPRINTFN(8, ("midi_wakeup: %p\n", chan
));
340 #define MIDI_CAT_DATA 0
341 #define MIDI_CAT_STATUS1 1
342 #define MIDI_CAT_STATUS2 2
343 #define MIDI_CAT_COMMON 3
345 static char const midi_cats
[] = "\0\0\0\0\0\0\0\0\2\2\2\2\1\1\2\3";
346 #define MIDI_CAT(d) (midi_cats[((d)>>4)&15])
347 #define FST_RETURN(offp,endp,ret) \
348 return (s->pos=s->msg+(offp)), (s->end=s->msg+(endp)), (ret)
350 enum fst_ret
{ FST_CHN
, FST_CHV
, FST_COM
, FST_SYX
, FST_RT
, FST_MORE
, FST_ERR
,
352 enum fst_form
{ FST_CANON
, FST_COMPR
, FST_VCOMP
};
356 } const midi_forms
[] = {
357 [FST_CANON
] = { .off
=0, .tag
=FST_CHN
},
358 [FST_COMPR
] = { .off
=1, .tag
=FST_CHN
},
359 [FST_VCOMP
] = { .off
=0, .tag
=FST_CHV
}
361 #define FST_CRETURN(endp) \
362 FST_RETURN(midi_forms[form].off,endp,midi_forms[form].tag)
365 * A MIDI finite state transducer suitable for receiving or transmitting. It
366 * will accept correct MIDI input that uses, doesn't use, or sometimes uses the
367 * 'running status' compression technique, and transduce it to fully expanded
368 * (form=FST_CANON) or fully compressed (form=FST_COMPR or FST_VCOMP) form.
370 * Returns FST_MORE if a complete message has not been parsed yet (SysEx
371 * messages are the exception), FST_ERR or FST_HUH if the input does not
372 * conform to the protocol, or FST_CHN (channel messages), FST_COM (System
373 * Common messages), FST_RT (System Real-Time messages), or FST_SYX (System
374 * Exclusive) to broadly categorize the message parsed. s->pos and s->end
375 * locate the parsed message; while (s->pos<s->end) putchar(*(s->pos++));
378 * FST_HUH means the character c wasn't valid in the original state, but the
379 * state has now been reset to START and the caller should try again passing
380 * the same c. FST_ERR means c isn't valid in the start state; the caller
381 * should kiss it goodbye and continue to try successive characters from the
382 * input until something other than FST_ERR or FST_HUH is returned, at which
383 * point things are resynchronized.
385 * A FST_SYX return means that between pos and end are from 1 to 3
386 * bytes of a system exclusive message. A SysEx message will be delivered in
387 * one or more chunks of that form, where the first begins with 0xf0 and the
388 * last (which is the only one that might have length < 3) ends with 0xf7.
390 * Messages corrupted by a protocol error are discarded and won't be seen at
391 * all; again SysEx is the exception, as one or more chunks of it may already
394 * For FST_CHN messages, s->msg[0] always contains the status byte even if
395 * FST_COMPR form was requested (pos then points to msg[1]). That way, the
396 * caller can always identify the exact message if there is a need to do so.
397 * For all other message types except FST_SYX, the status byte is at *pos
398 * (which may not necessarily be msg[0]!). There is only one SysEx status
399 * byte, so the return value FST_SYX is sufficient to identify it.
401 * To simplify some use cases, compression can also be requested with
402 * form=FST_VCOMP. In this form a compressible channel message is indicated
403 * by returning a classification of FST_CHV instead of FST_CHN, and pos points
404 * to the status byte rather than being advanced past it. If the caller in this
405 * case saves the bytes from pos to end, it will have saved the entire message,
406 * and can act on the FST_CHV tag to drop the first byte later. In this form,
407 * unlike FST_CANON, hidden note-off (i.e. note-on with velocity 0) may occur.
409 * Two obscure points in the MIDI protocol complicate things further, both to
410 * do with the EndSysEx code, 0xf7. First, this code is permitted (and
411 * meaningless) outside of a System Exclusive message, anywhere a status byte
412 * could appear. Second, it is allowed to be absent at the end of a System
413 * Exclusive message (!) - any status byte at all (non-realtime) is allowed to
414 * terminate the message. Both require accomodation in the interface to
415 * midi_fst's caller. A stray 0xf7 should be ignored BUT should count as a
416 * message received for purposes of Active Sense timeout; the case is
417 * represented by a return of FST_COM with a length of zero (pos == end). A
418 * status byte other than 0xf7 during a system exclusive message will cause an
419 * FST_SXP (sysex plus) return; the bytes from pos to end are the end of the
420 * system exclusive message, and after handling those the caller should call
421 * midi_fst again with the same input byte.
423 * midi(4) will never produce either such form of rubbish.
426 midi_fst(struct midi_state
*s
, u_char c
, enum fst_form form
)
430 if ( c
>= 0xf8 ) { /* All realtime messages bypass state machine */
431 if ( c
== 0xf9 || c
== 0xfd ) {
432 DPRINTF( ("midi_fst: s=%p c=0x%02x undefined\n",
434 s
->bytesDiscarded
.ev_count
++;
437 DPRINTFN(9, ("midi_fst: s=%p System Real-Time data=0x%02x\n",
440 FST_RETURN(2,3,FST_RT
);
443 DPRINTFN(4, ("midi_fst: s=%p data=0x%02x state=%d\n",
446 switch ( s
->state
| MIDI_CAT(c
) ) { /* break ==> return FST_MORE */
448 case MIDI_IN_START
| MIDI_CAT_COMMON
:
449 case MIDI_IN_RUN1_1
| MIDI_CAT_COMMON
:
450 case MIDI_IN_RUN2_2
| MIDI_CAT_COMMON
:
451 case MIDI_IN_RXX2_2
| MIDI_CAT_COMMON
:
454 case 0xf0: s
->state
= MIDI_IN_SYX1_3
; break;
455 case 0xf1: s
->state
= MIDI_IN_COM0_1
; break;
456 case 0xf2: s
->state
= MIDI_IN_COM0_2
; break;
457 case 0xf3: s
->state
= MIDI_IN_COM0_1
; break;
458 case 0xf6: s
->state
= MIDI_IN_START
; FST_RETURN(0,1,FST_COM
);
459 case 0xf7: s
->state
= MIDI_IN_START
; FST_RETURN(0,0,FST_COM
);
460 default: goto protocol_violation
;
464 case MIDI_IN_RUN1_1
| MIDI_CAT_STATUS1
:
465 if ( c
== s
->msg
[0] ) {
466 s
->state
= MIDI_IN_RNX0_1
;
470 case MIDI_IN_RUN2_2
| MIDI_CAT_STATUS1
:
471 case MIDI_IN_RXX2_2
| MIDI_CAT_STATUS1
:
472 case MIDI_IN_START
| MIDI_CAT_STATUS1
:
473 s
->state
= MIDI_IN_RUN0_1
;
477 case MIDI_IN_RUN2_2
| MIDI_CAT_STATUS2
:
478 case MIDI_IN_RXX2_2
| MIDI_CAT_STATUS2
:
479 if ( c
== s
->msg
[0] ) {
480 s
->state
= MIDI_IN_RNX0_2
;
483 if ( (c
^ s
->msg
[0]) == 0x10 && (c
& 0xe0) == 0x80 ) {
484 s
->state
= MIDI_IN_RXX0_2
;
489 case MIDI_IN_RUN1_1
| MIDI_CAT_STATUS2
:
490 case MIDI_IN_START
| MIDI_CAT_STATUS2
:
491 s
->state
= MIDI_IN_RUN0_2
;
495 case MIDI_IN_COM0_1
| MIDI_CAT_DATA
:
496 s
->state
= MIDI_IN_START
;
498 FST_RETURN(0,2,FST_COM
);
500 case MIDI_IN_COM0_2
| MIDI_CAT_DATA
:
501 s
->state
= MIDI_IN_COM1_2
;
505 case MIDI_IN_COM1_2
| MIDI_CAT_DATA
:
506 s
->state
= MIDI_IN_START
;
508 FST_RETURN(0,3,FST_COM
);
510 case MIDI_IN_RUN0_1
| MIDI_CAT_DATA
:
511 s
->state
= MIDI_IN_RUN1_1
;
513 FST_RETURN(0,2,FST_CHN
);
515 case MIDI_IN_RUN1_1
| MIDI_CAT_DATA
:
516 case MIDI_IN_RNX0_1
| MIDI_CAT_DATA
:
517 s
->state
= MIDI_IN_RUN1_1
;
521 case MIDI_IN_RUN0_2
| MIDI_CAT_DATA
:
522 s
->state
= MIDI_IN_RUN1_2
;
526 case MIDI_IN_RUN1_2
| MIDI_CAT_DATA
:
527 if ( FST_CANON
== form
&& 0 == c
&& (s
->msg
[0]&0xf0) == 0x90 ) {
528 s
->state
= MIDI_IN_RXX2_2
;
532 s
->state
= MIDI_IN_RUN2_2
;
535 FST_RETURN(0,3,FST_CHN
);
537 case MIDI_IN_RUN2_2
| MIDI_CAT_DATA
:
538 s
->state
= MIDI_IN_RNX1_2
;
542 case MIDI_IN_RXX2_2
| MIDI_CAT_DATA
:
543 s
->state
= MIDI_IN_RXX1_2
;
548 case MIDI_IN_RNX0_2
| MIDI_CAT_DATA
:
549 s
->state
= MIDI_IN_RNY1_2
;
553 case MIDI_IN_RXX0_2
| MIDI_CAT_DATA
:
554 s
->state
= MIDI_IN_RXY1_2
;
558 case MIDI_IN_RNX1_2
| MIDI_CAT_DATA
:
559 case MIDI_IN_RNY1_2
| MIDI_CAT_DATA
:
560 if ( FST_CANON
== form
&& 0 == c
&& (s
->msg
[0]&0xf0) == 0x90 ) {
561 s
->state
= MIDI_IN_RXX2_2
;
564 FST_RETURN(0,3,FST_CHN
);
566 s
->state
= MIDI_IN_RUN2_2
;
570 case MIDI_IN_RXX1_2
| MIDI_CAT_DATA
:
571 case MIDI_IN_RXY1_2
| MIDI_CAT_DATA
:
572 if ( ( 0 == c
&& (s
->msg
[0]&0xf0) == 0x90)
573 || (64 == c
&& (s
->msg
[0]&0xf0) == 0x80
574 && FST_CANON
!= form
) ) {
575 s
->state
= MIDI_IN_RXX2_2
;
580 s
->state
= MIDI_IN_RUN2_2
;
582 FST_RETURN(0,3,FST_CHN
);
584 case MIDI_IN_SYX1_3
| MIDI_CAT_DATA
:
585 s
->state
= MIDI_IN_SYX2_3
;
589 case MIDI_IN_SYX2_3
| MIDI_CAT_DATA
:
590 s
->state
= MIDI_IN_SYX0_3
;
592 FST_RETURN(0,3,FST_SYX
);
594 case MIDI_IN_SYX0_3
| MIDI_CAT_DATA
:
595 s
->state
= MIDI_IN_SYX1_3
;
599 case MIDI_IN_SYX2_3
| MIDI_CAT_COMMON
:
600 case MIDI_IN_SYX2_3
| MIDI_CAT_STATUS1
:
601 case MIDI_IN_SYX2_3
| MIDI_CAT_STATUS2
:
604 case MIDI_IN_SYX1_3
| MIDI_CAT_COMMON
:
605 case MIDI_IN_SYX1_3
| MIDI_CAT_STATUS1
:
606 case MIDI_IN_SYX1_3
| MIDI_CAT_STATUS2
:
609 case MIDI_IN_SYX0_3
| MIDI_CAT_COMMON
:
610 case MIDI_IN_SYX0_3
| MIDI_CAT_STATUS1
:
611 case MIDI_IN_SYX0_3
| MIDI_CAT_STATUS2
:
612 s
->state
= MIDI_IN_START
;
615 FST_RETURN(0,1+syxpos
,FST_SYX
);
617 s
->msg
[syxpos
] = 0xf7;
618 FST_RETURN(0,1+syxpos
,FST_SXP
);
622 DPRINTF(("midi_fst: unexpected %#02x in state %u\n",
624 switch ( s
->state
) {
625 case MIDI_IN_RUN1_1
: /* can only get here by seeing an */
626 case MIDI_IN_RUN2_2
: /* INVALID System Common message */
628 s
->state
= MIDI_IN_START
;
631 s
->bytesDiscarded
.ev_count
++;
637 s
->bytesDiscarded
.ev_count
++;
648 s
->bytesDiscarded
.ev_count
++;
649 s
->incompleteMessages
.ev_count
++;
651 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
653 printf("midi_fst: mishandled %#02x(%u) in state %u?!\n",
654 c
, MIDI_CAT(c
), s
->state
);
657 s
->state
= MIDI_IN_START
;
664 midi_softintr_rd(void *cookie
)
666 struct midi_softc
*sc
= cookie
;
669 if (sc
->async
!= NULL
) {
670 mutex_enter(proc_lock
);
671 if ((p
= sc
->async
) != NULL
)
673 mutex_exit(proc_lock
);
675 midi_wakeup(&sc
->rchan
);
676 selnotify(&sc
->rsel
, 0, 0); /* filter will spin if locked */
680 midi_softintr_wr(void *cookie
)
682 struct midi_softc
*sc
= cookie
;
685 if (sc
->async
!= NULL
) {
686 mutex_enter(proc_lock
);
687 if ((p
= sc
->async
) != NULL
)
689 mutex_exit(proc_lock
);
691 midi_wakeup(&sc
->wchan
);
692 selnotify(&sc
->wsel
, 0, 0); /* filter will spin if locked */
696 midi_in(void *addr
, int data
)
698 struct midi_softc
*sc
= addr
;
699 struct midi_buffer
*mb
= &sc
->inbuf
;
703 int s
; /* hw may have various spls so impose our own */
704 MIDI_BUF_DECLARE(idx
);
705 MIDI_BUF_DECLARE(buf
);
710 if (!(sc
->flags
& FREAD
))
711 return; /* discard data if not reading */
715 got
= midi_fst(&sc
->rcv
, data
, FST_CANON
);
716 while ( got
== FST_HUH
);
727 extern void midiseq_in(struct midi_dev
*,u_char
*,int);
728 count
= sc
->rcv
.end
- sc
->rcv
.pos
;
729 midiseq_in(sc
->seq_md
, sc
->rcv
.pos
, count
);
734 * Pass Active Sense to the sequencer if it's open, but not to
735 * a raw reader. (Really should do something intelligent with
736 * it then, though....)
738 if ( got
== FST_RT
&& MIDI_ACK
== sc
->rcv
.pos
[0] ) {
739 if ( !sc
->rcv_expect_asense
) {
740 sc
->rcv_expect_asense
= 1;
741 callout_schedule(&sc
->rcv_asense_co
,
742 MIDI_RCV_ASENSE_PERIOD
);
744 sc
->rcv_quiescent
= 0;
750 * Ultimately SysEx msgs should be offered to the sequencer also; the
751 * sequencer API addresses them - but maybe our sequencer can't handle
752 * them yet, so offer only to raw reader. (Which means, ultimately,
753 * discard them if the sequencer's open, as it's not doing reads!)
754 * -> When SysEx support is added to the sequencer, be sure to handle
759 count
= sc
->rcv
.end
- sc
->rcv
.pos
;
761 sc
->rcv_quiescent
= 0;
764 MIDI_IN_UNLOCK(sc
,s
);
767 MIDI_BUF_PRODUCER_INIT(mb
,idx
);
768 MIDI_BUF_PRODUCER_INIT(mb
,buf
);
769 if (count
> buf_lim
- buf_cur
770 || 1 > idx_lim
- idx_cur
) {
771 sc
->rcv
.bytesDiscarded
.ev_count
+= count
;
772 MIDI_IN_UNLOCK(sc
,s
);
773 DPRINTF(("midi_in: buffer full, discard data=0x%02x\n",
777 for (i
= 0; i
< count
; i
++) {
778 *buf_cur
++ = sc
->rcv
.pos
[i
];
781 *idx_cur
++ = PACK_MB_IDX(got
,count
);
783 MIDI_BUF_PRODUCER_WBACK(mb
,buf
);
784 MIDI_BUF_PRODUCER_WBACK(mb
,idx
);
785 MIDI_IN_UNLOCK(sc
,s
);
786 softint_schedule(sc
->sih_rd
);
788 default: /* don't #ifdef this away, gcc will say FST_HUH not handled */
789 printf("midi_in: midi_fst returned %d?!\n", got
);
791 if ( FST_SXP
== got
)
798 struct midi_softc
*sc
= addr
;
802 DPRINTFN(8, ("midi_out: %p\n", sc
));
807 midiopen(dev_t dev
, int flags
, int ifmt
, struct lwp
*l
)
809 struct midi_softc
*sc
;
810 const struct midi_hw_if
*hw
;
813 sc
= device_lookup_private(&midi_cd
, MIDIUNIT(dev
));
819 DPRINTFN(3,("midiopen %p\n", sc
));
827 /* put both state machines into known states */
828 sc
->rcv
.state
= MIDI_IN_START
;
829 sc
->rcv
.pos
= sc
->rcv
.msg
;
830 sc
->rcv
.end
= sc
->rcv
.msg
;
831 sc
->xmt
.state
= MIDI_IN_START
;
832 sc
->xmt
.pos
= sc
->xmt
.msg
;
833 sc
->xmt
.end
= sc
->xmt
.msg
;
835 /* copy error counters so an ioctl (TBA) can give since-open stats */
836 sc
->rcv
.atOpen
.bytesDiscarded
= sc
->rcv
.bytesDiscarded
.ev_count
;
837 sc
->rcv
.atQuery
.bytesDiscarded
= sc
->rcv
.bytesDiscarded
.ev_count
;
839 sc
->xmt
.atOpen
.bytesDiscarded
= sc
->xmt
.bytesDiscarded
.ev_count
;
840 sc
->xmt
.atQuery
.bytesDiscarded
= sc
->xmt
.bytesDiscarded
.ev_count
;
842 /* and the buffers */
843 midi_initbuf(&sc
->outbuf
);
844 midi_initbuf(&sc
->inbuf
);
846 /* and the receive flags */
847 sc
->rcv_expect_asense
= 0;
848 sc
->rcv_quiescent
= 0;
851 error
= hw
->open(sc
->hw_hdl
, flags
, midi_in
, midi_out
, sc
);
863 midisave
.cnt
= midicnt
;
872 midiclose(dev_t dev
, int flags
, int ifmt
,
875 struct midi_softc
*sc
=
876 device_lookup_private(&midi_cd
, MIDIUNIT(dev
));
877 const struct midi_hw_if
*hw
= sc
->hw_if
;
880 DPRINTFN(3,("midiclose %p\n", sc
));
882 /* midi_start_output(sc); anything buffered => pbus already set! */
886 DPRINTFN(8,("midiclose sleep ...\n"));
888 midi_sleep_timo(&sc
->wchan
, "mid_dr", 30*hz
, &sc
->out_lock
);
891 MIDI_OUT_UNLOCK(sc
,s
);
892 callout_stop(&sc
->xmt_asense_co
); /* xxx fix this - sleep? */
893 callout_stop(&sc
->rcv_asense_co
);
894 hw
->close(sc
->hw_hdl
);
903 midiread(dev_t dev
, struct uio
*uio
, int ioflag
)
905 struct midi_softc
*sc
=
906 device_lookup_private(&midi_cd
, MIDIUNIT(dev
));
907 struct midi_buffer
*mb
= &sc
->inbuf
;
910 MIDI_BUF_DECLARE(idx
);
911 MIDI_BUF_DECLARE(buf
);
915 DPRINTFN(6,("midiread: %p, count=%lu\n", sc
,
916 (unsigned long)uio
->uio_resid
));
920 if ( !(sc
->props
& MIDI_PROP_CAN_INPUT
) )
924 MIDI_BUF_CONSUMER_INIT(mb
,idx
);
925 MIDI_BUF_CONSUMER_INIT(mb
,buf
);
926 MIDI_IN_UNLOCK(sc
,s
);
931 * If the used portion of idx wraps around the end, just take
932 * the first part on this iteration, and we'll get the rest on
935 if ( idx_lim
> idx_end
)
938 * Count bytes through the last complete message that will
939 * fit in the requested read.
941 for (appetite
= uio
->uio_resid
; idx_cur
< idx_lim
; ++idx_cur
) {
942 if ( appetite
< MB_IDX_LEN(*idx_cur
) )
944 appetite
-= MB_IDX_LEN(*idx_cur
);
946 appetite
= uio
->uio_resid
- appetite
;
948 * Only if the read is too small to hold even the first
949 * complete message will we return a partial one (updating idx
950 * to reflect the remaining length of the message).
952 if ( appetite
== 0 && idx_cur
< idx_lim
) {
954 goto unlocked_exit
; /* idx_cur not advanced */
955 appetite
= uio
->uio_resid
;
956 *idx_cur
= PACK_MB_IDX(MB_IDX_CAT(*idx_cur
),
957 MB_IDX_LEN(*idx_cur
) - appetite
);
959 KASSERT(buf_cur
+ appetite
<= buf_lim
);
962 if ( appetite
> 0 ) {
963 first
= 0; /* we know we won't return empty-handed */
964 /* do two uiomoves if data wrap around end of buf */
965 if ( buf_cur
+ appetite
> buf_end
) {
967 ("midiread: uiomove cc=%td (prewrap)\n",
969 error
= uiomove(buf_cur
, buf_end
-buf_cur
, uio
);
972 appetite
-= buf_end
- buf_cur
;
975 DPRINTFN(8, ("midiread: uiomove cc=%d\n", appetite
));
976 error
= uiomove(buf_cur
, appetite
, uio
);
986 MIDI_BUF_CONSUMER_WBACK(mb
,idx
);
987 MIDI_BUF_CONSUMER_WBACK(mb
,buf
);
988 if ( 0 == uio
->uio_resid
) /* if read satisfied, we're done */
990 MIDI_BUF_CONSUMER_REFRESH(mb
,idx
);
991 if ( idx_cur
== idx_lim
) { /* need to wait for data? */
992 if ( !first
|| sc
->rcv_eof
) /* never block reader if */
993 break; /* any data already in hand */
994 if (ioflag
& IO_NDELAY
) {
998 error
= midi_sleep(&sc
->rchan
, "mid rd", &sc
->in_lock
);
1001 MIDI_BUF_CONSUMER_REFRESH(mb
,idx
); /* what'd we get? */
1003 MIDI_BUF_CONSUMER_REFRESH(mb
,buf
);
1004 MIDI_IN_UNLOCK(sc
,s
);
1008 MIDI_IN_UNLOCK(sc
,s
);
1015 midi_rcv_asense(void *arg
)
1017 struct midi_softc
*sc
= arg
;
1020 if ( sc
->dying
|| !sc
->isopen
)
1023 if ( sc
->rcv_quiescent
) {
1026 sc
->rcv_quiescent
= 0;
1027 sc
->rcv_expect_asense
= 0;
1028 MIDI_IN_UNLOCK(sc
,s
);
1029 softint_schedule(sc
->sih_rd
);
1033 sc
->rcv_quiescent
= 1;
1034 callout_schedule(&sc
->rcv_asense_co
, MIDI_RCV_ASENSE_PERIOD
);
1038 midi_xmt_asense(void *arg
)
1040 struct midi_softc
*sc
= arg
;
1045 if ( sc
->dying
|| !sc
->isopen
)
1048 MIDI_OUT_LOCK(sc
,s
);
1049 if ( sc
->pbus
|| sc
->dying
|| !sc
->isopen
) {
1050 MIDI_OUT_UNLOCK(sc
,s
);
1054 DPRINTFN(8,("midi_xmt_asense: %p\n", sc
));
1056 if ( sc
->props
& MIDI_PROP_OUT_INTR
) {
1057 error
= sc
->hw_if
->output(sc
->hw_hdl
, MIDI_ACK
);
1058 armed
= (error
== 0);
1059 } else { /* polled output, do with interrupts unmasked */
1060 MIDI_OUT_UNLOCK(sc
,s
);
1061 /* running from softclock, so top half won't sneak in here */
1062 error
= sc
->hw_if
->output(sc
->hw_hdl
, MIDI_ACK
);
1063 MIDI_OUT_LOCK(sc
,s
);
1069 callout_schedule(&sc
->xmt_asense_co
, MIDI_XMT_ASENSE_PERIOD
);
1072 MIDI_OUT_UNLOCK(sc
,s
);
1076 * The way this function was hacked up to plug into poll_out and intr_out
1077 * after they were written won't win it any beauty contests, but it'll work
1078 * (code in haste, refactor at leisure). This may be called with the lock
1079 * (by intr_out) or without the lock (by poll_out) so it only does what could
1080 * be safe either way.
1082 int midi_msg_out(struct midi_softc
*sc
,
1083 u_char
**idx
, u_char
**idxl
, u_char
**buf
, u_char
**bufl
) {
1084 MIDI_BUF_DECLARE(idx
);
1085 MIDI_BUF_DECLARE(buf
);
1086 MIDI_BUF_EXTENT_INIT(&sc
->outbuf
,idx
);
1087 MIDI_BUF_EXTENT_INIT(&sc
->outbuf
,buf
);
1099 length
= MB_IDX_LEN(*idx_cur
);
1101 for ( cp
= contig
, ep
= cp
+ length
; cp
< ep
; ) {
1107 switch ( MB_IDX_CAT(*idx_cur
) ) {
1108 case FST_CHV
: /* chnmsg to be compressed (for device that wants it) */
1113 error
= sc
->hw_if_ext
->channel(sc
->hw_hdl
,
1114 MIDI_GET_STATUS(contig
[0]),
1115 MIDI_GET_CHAN(contig
[0]),
1119 error
= sc
->hw_if_ext
->common(sc
->hw_hdl
,
1120 MIDI_GET_STATUS(contig
[0]),
1125 error
= sc
->hw_if_ext
->sysex(sc
->hw_hdl
,
1129 error
= sc
->hw_if
->output(sc
->hw_hdl
, *cp
);
1148 * midi_poll_out is intended for the midi hw (the vast majority of MIDI UARTs
1149 * on sound cards, apparently) that _do not have transmit-ready interrupts_.
1150 * Every call to hw_if->output for one of these may busy-wait to output the
1151 * byte; at the standard midi data rate that'll be 320us per byte. The
1152 * technique of writing only MIDI_MAX_WRITE bytes in a row and then waiting
1153 * for MIDI_WAIT does not reduce the total time spent busy-waiting, and it
1154 * adds arbitrary delays in transmission (and, since MIDI_WAIT is roughly the
1155 * same as the time to send MIDI_MAX_WRITE bytes, it effectively halves the
1156 * data rate). Here, a somewhat bolder approach is taken. Since midi traffic
1157 * is bursty but time-sensitive--most of the time there will be none at all,
1158 * but when there is it should go out ASAP--the strategy is to just get it
1159 * over with, and empty the buffer in one go. The effect this can have on
1160 * the rest of the system will be limited by the size of the buffer and the
1161 * sparseness of the traffic. But some precautions are in order. Interrupts
1162 * should all be unmasked when this is called, and midiwrite should not fill
1163 * the buffer more than once (when MIDI_PROP_CAN_INTR is false) without a
1164 * yield() so some other process can get scheduled. If the write is nonblocking,
1165 * midiwrite should return a short count rather than yield.
1167 * Someday when there is fine-grained MP support, this should be reworked to
1168 * run in a callout so the writing process really could proceed concurrently.
1169 * But obviously where performance is a concern, interrupt-driven hardware
1170 * such as USB midi or (apparently) clcs will always be preferable. And it
1171 * seems (kern/32651) that many of the devices currently working in poll mode
1172 * may really have tx interrupt capability and want only implementation; that
1176 midi_poll_out(struct midi_softc
*sc
)
1178 struct midi_buffer
*mb
= &sc
->outbuf
;
1182 MIDI_BUF_DECLARE(idx
);
1183 MIDI_BUF_DECLARE(buf
);
1187 MIDI_OUT_LOCK(sc
,s
);
1188 MIDI_BUF_CONSUMER_INIT(mb
,idx
);
1189 MIDI_BUF_CONSUMER_INIT(mb
,buf
);
1190 MIDI_OUT_UNLOCK(sc
,s
);
1193 while ( idx_cur
!= idx_lim
) {
1194 if ( sc
->hw_if_ext
) {
1195 error
= midi_msg_out(sc
, &idx_cur
, &idx_lim
,
1196 &buf_cur
, &buf_lim
);
1201 /* or, lacking hw_if_ext ... */
1202 msglen
= MB_IDX_LEN(*idx_cur
);
1203 DPRINTFN(7,("midi_poll_out: %p <- %#02x\n",
1204 sc
->hw_hdl
, *buf_cur
));
1205 error
= sc
->hw_if
->output(sc
->hw_hdl
, *buf_cur
);
1212 *idx_cur
= PACK_MB_IDX(MB_IDX_CAT(*idx_cur
),
1219 KASSERT(buf_cur
== buf_lim
);
1220 MIDI_OUT_LOCK(sc
,s
);
1221 MIDI_BUF_CONSUMER_WBACK(mb
,idx
);
1222 MIDI_BUF_CONSUMER_WBACK(mb
,buf
);
1223 MIDI_BUF_CONSUMER_REFRESH(mb
,idx
); /* any more to transmit? */
1224 MIDI_BUF_CONSUMER_REFRESH(mb
,buf
);
1225 if ( idx_lim
== idx_cur
)
1226 break; /* still holding lock */
1227 MIDI_OUT_UNLOCK(sc
,s
);
1229 goto disarm
; /* lock held */
1232 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
1233 aprint_error_dev(sc
->dev
, "midi_poll_output error %d\n", error
);
1235 MIDI_OUT_LOCK(sc
,s
);
1236 MIDI_BUF_CONSUMER_WBACK(mb
,idx
);
1237 MIDI_BUF_CONSUMER_WBACK(mb
,buf
);
1241 callout_schedule(&sc
->xmt_asense_co
, MIDI_XMT_ASENSE_PERIOD
);
1242 MIDI_OUT_UNLOCK(sc
,s
);
1247 * The interrupt flavor acquires spl and lock once and releases at the end,
1248 * as it expects to write only one byte or message. The interface convention
1249 * is that if hw_if->output returns 0, it has initiated transmission and the
1250 * completion interrupt WILL be forthcoming; if it has not returned 0, NO
1251 * interrupt will be forthcoming, and if it returns EINPROGRESS it wants
1252 * another byte right away.
1255 midi_intr_out(struct midi_softc
*sc
)
1257 struct midi_buffer
*mb
= &sc
->outbuf
;
1261 MIDI_BUF_DECLARE(idx
);
1262 MIDI_BUF_DECLARE(buf
);
1267 MIDI_OUT_LOCK(sc
,s
);
1268 MIDI_BUF_CONSUMER_INIT(mb
,idx
);
1269 MIDI_BUF_CONSUMER_INIT(mb
,buf
);
1271 while ( idx_cur
!= idx_lim
) {
1272 if ( sc
->hw_if_ext
) {
1273 error
= midi_msg_out(sc
, &idx_cur
, &idx_lim
,
1274 &buf_cur
, &buf_lim
);
1275 if ( !error
) /* no EINPROGRESS from extended hw_if */
1279 /* or, lacking hw_if_ext ... */
1280 msglen
= MB_IDX_LEN(*idx_cur
);
1281 error
= sc
->hw_if
->output(sc
->hw_hdl
, *buf_cur
);
1282 if ( error
&& error
!= EINPROGRESS
)
1288 *idx_cur
= PACK_MB_IDX(MB_IDX_CAT(*idx_cur
),msglen
);
1298 MIDI_BUF_CONSUMER_WBACK(mb
,idx
);
1299 MIDI_BUF_CONSUMER_WBACK(mb
,buf
);
1302 callout_schedule(&sc
->xmt_asense_co
, MIDI_XMT_ASENSE_PERIOD
);
1304 MIDI_OUT_UNLOCK(sc
,s
);
1305 softint_schedule(sc
->sih_wr
);
1307 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
1309 aprint_error_dev(sc
->dev
, "midi_intr_output error %d\n",
1316 midi_start_output(struct midi_softc
*sc
)
1321 if ( sc
->props
& MIDI_PROP_OUT_INTR
)
1322 return midi_intr_out(sc
);
1323 return midi_poll_out(sc
);
1327 real_writebytes(struct midi_softc
*sc
, u_char
*ibuf
, int cc
)
1329 u_char
*iend
= ibuf
+ cc
;
1330 struct midi_buffer
*mb
= &sc
->outbuf
;
1336 MIDI_BUF_DECLARE(idx
);
1337 MIDI_BUF_DECLARE(buf
);
1340 * If the hardware uses the extended hw_if, pass it canonicalized
1341 * messages (or compressed ones if it specifically requests, using
1342 * VCOMP form so the bottom half can still pass the op and chan along);
1343 * if it does not, send it compressed messages (using COMPR form as
1344 * there is no need to preserve the status for the bottom half).
1346 if ( NULL
== sc
->hw_if_ext
)
1348 else if ( sc
->hw_if_ext
->compress
)
1353 MIDI_OUT_LOCK(sc
,s
);
1354 MIDI_BUF_PRODUCER_INIT(mb
,idx
);
1355 MIDI_BUF_PRODUCER_INIT(mb
,buf
);
1356 MIDI_OUT_UNLOCK(sc
,s
);
1361 while ( ibuf
< iend
) {
1362 got
= midi_fst(&sc
->xmt
, *ibuf
, form
);
1371 case FST_CHV
: /* only occurs in VCOMP form */
1376 break; /* go add to buffer */
1377 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
1379 printf("midi_wr: midi_fst returned %d?!\n", got
);
1382 count
= sc
->xmt
.end
- sc
->xmt
.pos
;
1383 if ( 0 == count
) /* can happen with stray 0xf7; see midi_fst */
1386 * return EWOULDBLOCK if the data passed will not fit in
1387 * the buffer; the caller should have taken steps to avoid that.
1388 * If got==FST_SXP we lose the new status byte, but we're losing
1389 * anyway, so c'est la vie.
1391 if ( idx_cur
== idx_lim
|| count
> buf_lim
- buf_cur
) {
1392 MIDI_OUT_LOCK(sc
,s
);
1393 MIDI_BUF_PRODUCER_REFRESH(mb
,idx
); /* get the most */
1394 MIDI_BUF_PRODUCER_REFRESH(mb
,buf
); /* current facts */
1395 MIDI_OUT_UNLOCK(sc
,s
);
1396 if ( idx_cur
== idx_lim
|| count
> buf_lim
- buf_cur
)
1397 return EWOULDBLOCK
; /* caller's problem */
1399 *idx_cur
++ = PACK_MB_IDX(got
,count
);
1402 *buf_cur
++ = *(sc
->xmt
.pos
)++;
1406 if ( FST_SXP
== got
)
1407 -- ibuf
; /* again with same status byte */
1409 MIDI_OUT_LOCK(sc
,s
);
1410 MIDI_BUF_PRODUCER_WBACK(mb
,buf
);
1411 MIDI_BUF_PRODUCER_WBACK(mb
,idx
);
1413 * If the output transfer is not already busy, and there is a message
1414 * buffered, mark it busy, stop the Active Sense callout (what if we're
1415 * too late and it's expired already? No big deal, an extra Active Sense
1416 * never hurt anybody) and start the output transfer once we're out of
1417 * the critical section (pbus==1 will stop anyone else doing the same).
1419 MIDI_BUF_CONSUMER_INIT(mb
,idx
); /* check what consumer's got to read */
1420 if ( !sc
->pbus
&& idx_cur
< idx_lim
) {
1422 callout_stop(&sc
->xmt_asense_co
);
1425 MIDI_OUT_UNLOCK(sc
,s
);
1426 return arming
? midi_start_output(sc
) : 0;
1430 midiwrite(dev_t dev
, struct uio
*uio
, int ioflag
)
1432 struct midi_softc
*sc
=
1433 device_lookup_private(&midi_cd
, MIDIUNIT(dev
));
1434 struct midi_buffer
*mb
= &sc
->outbuf
;
1438 MIDI_BUF_DECLARE(idx
);
1439 MIDI_BUF_DECLARE(buf
);
1445 DPRINTFN(6, ("midiwrite: %p, unit=%d, count=%lu\n", sc
, (int)minor(dev
),
1446 (unsigned long)uio
->uio_resid
));
1452 while (uio
->uio_resid
> 0 && !error
) {
1455 * block if necessary for the minimum buffer space to guarantee
1456 * we can write something.
1458 MIDI_OUT_LOCK(sc
,s
);
1459 MIDI_BUF_PRODUCER_INIT(mb
,idx
); /* init can't go above loop; */
1460 MIDI_BUF_PRODUCER_INIT(mb
,buf
); /* real_writebytes moves cur */
1462 idxspace
= MIDI_BUF_PRODUCER_REFRESH(mb
,idx
) - idx_cur
;
1463 bufspace
= MIDI_BUF_PRODUCER_REFRESH(mb
,buf
) - buf_cur
;
1464 if ( idxspace
>= 1 && bufspace
>= 3 && !pollout
)
1466 DPRINTFN(8,("midi_write: sleep idx=%zd buf=%zd\n",
1467 idxspace
, bufspace
));
1468 if (ioflag
& IO_NDELAY
) {
1469 error
= EWOULDBLOCK
;
1471 * If some amount has already been transferred,
1472 * the common syscall code will automagically
1473 * convert this to success with a short count.
1478 preempt(); /* see midi_poll_output */
1481 error
= midi_sleep(&sc
->wchan
, "mid wr",
1485 * Similarly, the common code will handle
1486 * EINTR and ERESTART properly here, changing to
1487 * a short count if something transferred.
1491 MIDI_OUT_UNLOCK(sc
,s
);
1494 * The number of bytes we can safely extract from the uio
1495 * depends on the available idx and buf space. Worst case,
1496 * every byte is a message so 1 idx is required per byte.
1497 * Worst case, the first byte completes a 3-byte msg in prior
1498 * state, and every subsequent byte is a Program Change or
1499 * Channel Pressure msg with running status and expands to 2
1500 * bytes, so the buf space reqd is 3+2(n-1) or 2n+1. So limit
1501 * the transfer to the min of idxspace and (bufspace-1)>>1.
1503 xfrcount
= (bufspace
- 1) >> 1;
1504 if ( xfrcount
> idxspace
)
1505 xfrcount
= idxspace
;
1506 if ( xfrcount
> sizeof inp
)
1507 xfrcount
= sizeof inp
;
1508 if ( xfrcount
> uio
->uio_resid
)
1509 xfrcount
= uio
->uio_resid
;
1511 error
= uiomove(inp
, xfrcount
, uio
);
1514 printf("midi_write:(1) uiomove failed %d; "
1515 "xfrcount=%d inp=%p\n",
1516 error
, xfrcount
, inp
);
1522 * The number of bytes we extracted being calculated to
1523 * definitely fit in the buffer even with canonicalization,
1524 * there is no excuse for real_writebytes to return EWOULDBLOCK.
1526 error
= real_writebytes(sc
, inp
, xfrcount
);
1527 KASSERT(error
!= EWOULDBLOCK
);
1532 * If this is a polling device and we just sent a buffer, let's
1533 * not send another without giving some other process a chance.
1535 if ( ! (sc
->props
& MIDI_PROP_OUT_INTR
) )
1537 DPRINTFN(8,("midiwrite: uio_resid now %zu, props=%d\n",
1538 uio
->uio_resid
, sc
->props
));
1543 MIDI_OUT_UNLOCK(sc
,s
);
1548 * This write routine is only called from sequencer code and expects
1549 * a write that is smaller than the MIDI buffer.
1552 midi_writebytes(int unit
, u_char
*bf
, int cc
)
1554 struct midi_softc
*sc
=
1555 device_lookup_private(&midi_cd
, unit
);
1557 DPRINTFN(7, ("midi_writebytes: %p, unit=%d, cc=%d %#02x %#02x %#02x\n",
1558 sc
, unit
, cc
, bf
[0], bf
[1], bf
[2]));
1559 return real_writebytes(sc
, bf
, cc
);
1563 midiioctl(dev_t dev
, u_long cmd
, void *addr
, int flag
, struct lwp
*l
)
1565 struct midi_softc
*sc
=
1566 device_lookup_private(&midi_cd
, MIDIUNIT(dev
));
1567 const struct midi_hw_if
*hw
= sc
->hw_if
;
1570 MIDI_BUF_DECLARE(buf
);
1572 DPRINTFN(5,("midiioctl: %p cmd=0x%08lx\n", sc
, cmd
));
1580 /* All handled in the upper FS layer. */
1585 * This code relies on the current implementation of midi_in
1586 * always updating buf and idx together in a critical section,
1587 * so buf always ends at a message boundary. Document this
1588 * ioctl as always returning a value such that the last message
1589 * included is complete (SysEx the only exception), and then
1590 * make sure the implementation doesn't regress. NB that
1591 * means if this ioctl returns n and the proc then issues a
1592 * read of n, n bytes will be read, but if the proc issues a
1593 * read of m < n, fewer than m bytes may be read to ensure the
1594 * read ends at a message boundary.
1597 MIDI_BUF_CONSUMER_INIT(&sc
->inbuf
,buf
);
1598 MIDI_IN_UNLOCK(sc
,s
);
1599 *(int *)addr
= buf_lim
- buf_cur
;
1606 sc
->async
= l
->l_proc
;
1607 DPRINTFN(5,("midi_ioctl: FIOASYNC %p\n", l
->l_proc
));
1615 * This should set up a read timeout, but that's
1616 * why we have poll(), so there's nothing yet. */
1623 error
= copyout(&midisave
, *(void **)addr
, sizeof midisave
);
1629 error
= hw
->ioctl(sc
->hw_hdl
, cmd
, addr
, flag
, l
);
1638 midipoll(dev_t dev
, int events
, struct lwp
*l
)
1640 struct midi_softc
*sc
=
1641 device_lookup_private(&midi_cd
, MIDIUNIT(dev
));
1644 MIDI_BUF_DECLARE(idx
);
1645 MIDI_BUF_DECLARE(buf
);
1647 DPRINTFN(6,("midipoll: %p events=0x%x\n", sc
, events
));
1654 if ((sc
->flags
&FREAD
) && (events
& (POLLIN
| POLLRDNORM
))) {
1655 simple_lock(&sc
->in_lock
);
1656 MIDI_BUF_CONSUMER_INIT(&sc
->inbuf
,idx
);
1657 if (idx_cur
< idx_lim
)
1658 revents
|= events
& (POLLIN
| POLLRDNORM
);
1660 selrecord(l
, &sc
->rsel
);
1661 simple_unlock(&sc
->in_lock
);
1664 if ((sc
->flags
&FWRITE
) && (events
& (POLLOUT
| POLLWRNORM
))) {
1665 simple_lock(&sc
->out_lock
);
1666 MIDI_BUF_PRODUCER_INIT(&sc
->outbuf
,idx
);
1667 MIDI_BUF_PRODUCER_INIT(&sc
->outbuf
,buf
);
1668 if ( idx_lim
- idx_cur
>= 1 && buf_lim
- buf_cur
>= 3 )
1669 revents
|= events
& (POLLOUT
| POLLWRNORM
);
1671 selrecord(l
, &sc
->wsel
);
1672 simple_unlock(&sc
->out_lock
);
1680 filt_midirdetach(struct knote
*kn
)
1682 struct midi_softc
*sc
= kn
->kn_hook
;
1686 SLIST_REMOVE(&sc
->rsel
.sel_klist
, kn
, knote
, kn_selnext
);
1691 filt_midiread(struct knote
*kn
, long hint
)
1693 struct midi_softc
*sc
= kn
->kn_hook
;
1695 MIDI_BUF_DECLARE(buf
);
1697 /* XXXLUKEM (thorpej): please make sure this is correct. */
1700 MIDI_BUF_CONSUMER_INIT(&sc
->inbuf
,buf
);
1701 kn
->kn_data
= buf_lim
- buf_cur
;
1702 MIDI_IN_UNLOCK(sc
,s
);
1703 return (kn
->kn_data
> 0);
1706 static const struct filterops midiread_filtops
=
1707 { 1, NULL
, filt_midirdetach
, filt_midiread
};
1710 filt_midiwdetach(struct knote
*kn
)
1712 struct midi_softc
*sc
= kn
->kn_hook
;
1716 SLIST_REMOVE(&sc
->wsel
.sel_klist
, kn
, knote
, kn_selnext
);
1721 filt_midiwrite(struct knote
*kn
, long hint
)
1723 struct midi_softc
*sc
= kn
->kn_hook
;
1725 MIDI_BUF_DECLARE(idx
);
1726 MIDI_BUF_DECLARE(buf
);
1728 /* XXXLUKEM (thorpej): please make sure this is correct. */
1730 MIDI_OUT_LOCK(sc
,s
);
1731 MIDI_BUF_PRODUCER_INIT(&sc
->outbuf
,idx
);
1732 MIDI_BUF_PRODUCER_INIT(&sc
->outbuf
,buf
);
1733 kn
->kn_data
= ((buf_lim
- buf_cur
)-1)>>1;
1734 if ( kn
->kn_data
> idx_lim
- idx_cur
)
1735 kn
->kn_data
= idx_lim
- idx_cur
;
1736 MIDI_OUT_UNLOCK(sc
,s
);
1737 return (kn
->kn_data
> 0);
1740 static const struct filterops midiwrite_filtops
=
1741 { 1, NULL
, filt_midiwdetach
, filt_midiwrite
};
1744 midikqfilter(dev_t dev
, struct knote
*kn
)
1746 struct midi_softc
*sc
=
1747 device_lookup_private(&midi_cd
, MIDIUNIT(dev
));
1748 struct klist
*klist
;
1751 switch (kn
->kn_filter
) {
1753 klist
= &sc
->rsel
.sel_klist
;
1754 kn
->kn_fop
= &midiread_filtops
;
1758 klist
= &sc
->wsel
.sel_klist
;
1759 kn
->kn_fop
= &midiwrite_filtops
;
1769 SLIST_INSERT_HEAD(klist
, kn
, kn_selnext
);
1776 midi_getinfo(dev_t dev
, struct midi_info
*mi
)
1778 struct midi_softc
*sc
;
1780 sc
= device_lookup_private(&midi_cd
, MIDIUNIT(dev
));
1786 sc
->hw_if
->getinfo(sc
->hw_hdl
, mi
);
1789 #elif NMIDIBUS > 0 /* but NMIDI == 0 */
1791 void midi_register_hw_if_ext(struct midi_hw_if_ext
*exthw
) { /* stub */
1794 #endif /* NMIDI > 0 */
1796 #if NMIDI > 0 || NMIDIBUS > 0
1798 int audioprint(void *, const char *);
1801 midi_attach_mi(const struct midi_hw_if
*mhwp
, void *hdlp
, device_t dev
)
1803 struct audio_attach_args arg
;
1807 aprint_error("midi_attach_mi: NULL\n");
1811 arg
.type
= AUDIODEV_TYPE_MIDI
;
1814 return (config_found(dev
, &arg
, audioprint
));
1817 #endif /* NMIDI > 0 || NMIDIBUS > 0 */