midi.c revision 1.43.2.10 1 /* $NetBSD: midi.c,v 1.43.2.10 2006/05/20 03:24:33 chap Exp $ */
2
3 /*
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (augustss (at) NetBSD.org) and (MIDI FST and Active
9 * Sense handling) Chapman Flack (nblists (at) anastigmatix.net).
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: midi.c,v 1.43.2.10 2006/05/20 03:24:33 chap Exp $");
42
43 #include "midi.h"
44 #include "sequencer.h"
45
46 #include <sys/param.h>
47 #include <sys/ioctl.h>
48 #include <sys/fcntl.h>
49 #include <sys/vnode.h>
50 #include <sys/select.h>
51 #include <sys/poll.h>
52 #include <sys/malloc.h>
53 #include <sys/proc.h>
54 #include <sys/systm.h>
55 #include <sys/callout.h>
56 #include <sys/syslog.h>
57 #include <sys/kernel.h>
58 #include <sys/signalvar.h>
59 #include <sys/conf.h>
60 #include <sys/audioio.h>
61 #include <sys/midiio.h>
62
63 #include <dev/audio_if.h>
64 #include <dev/midi_if.h>
65 #include <dev/midivar.h>
66
67 #if NMIDI > 0
68
69 #ifdef AUDIO_DEBUG
70 #define DPRINTF(x) if (mididebug) printf x
71 #define DPRINTFN(n,x) if (mididebug >= (n)) printf x
72 int mididebug = 0;
73 /*
74 * 1: detected protocol errors and buffer overflows
75 * 2: probe, attach, detach
76 * 3: open, close
77 * 4: data received except realtime
78 * 5: ioctl
79 * 6: read, write, poll
80 * 7: data transmitted
81 * 8: uiomoves, synchronization
82 * 9: realtime data received
83 */
84 #else
85 #define DPRINTF(x)
86 #define DPRINTFN(n,x)
87 #endif
88
89 static struct simplelock hwif_register_lock = SIMPLELOCK_INITIALIZER;
90 static struct midi_softc *hwif_softc = NULL;
91
92 void midi_in(void *, int);
93 void midi_out(void *);
94 int midi_poll_out(struct midi_softc *);
95 int midi_intr_out(struct midi_softc *);
96 int midi_msg_out(struct midi_softc *,
97 u_char **, u_char **, u_char **, u_char **);
98 int midi_start_output(struct midi_softc *);
99 int midi_sleep_timo(int *, char *, int, struct simplelock *);
100 int midi_sleep(int *, char *, struct simplelock *);
101 void midi_wakeup(int *);
102 void midi_initbuf(struct midi_buffer *);
103 void midi_timeout(void *);
104
105 int midiprobe(struct device *, struct cfdata *, void *);
106 void midiattach(struct device *, struct device *, void *);
107 int mididetach(struct device *, int);
108 int midiactivate(struct device *, enum devact);
109
110 dev_type_open(midiopen);
111 dev_type_close(midiclose);
112 dev_type_read(midiread);
113 dev_type_write(midiwrite);
114 dev_type_ioctl(midiioctl);
115 dev_type_poll(midipoll);
116 dev_type_kqfilter(midikqfilter);
117
118 const struct cdevsw midi_cdevsw = {
119 midiopen, midiclose, midiread, midiwrite, midiioctl,
120 nostop, notty, midipoll, nommap, midikqfilter,
121 };
122
123 CFATTACH_DECL(midi, sizeof(struct midi_softc),
124 midiprobe, midiattach, mididetach, midiactivate);
125
126 #ifdef MIDI_SAVE
127 #define MIDI_SAVE_SIZE 100000
128 int midicnt;
129 struct {
130 int cnt;
131 u_char buf[MIDI_SAVE_SIZE];
132 } midisave;
133 #define MIDI_GETSAVE _IOWR('m', 100, int)
134
135 #endif
136
137 extern struct cfdriver midi_cd;
138
139 int
140 midiprobe(struct device *parent, struct cfdata *match, void *aux)
141 {
142 struct audio_attach_args *sa = aux;
143
144 DPRINTFN(2,("midiprobe: type=%d sa=%p hw=%p\n",
145 sa->type, sa, sa->hwif));
146 return (sa->type == AUDIODEV_TYPE_MIDI);
147 }
148
149 void
150 midiattach(struct device *parent, struct device *self, void *aux)
151 {
152 struct midi_softc *sc = (void *)self;
153 struct audio_attach_args *sa = aux;
154 struct midi_hw_if *hwp = sa->hwif;
155 void *hdlp = sa->hdl;
156
157 DPRINTFN(2, ("MIDI attach\n"));
158
159 #ifdef DIAGNOSTIC
160 if (hwp == 0 ||
161 hwp->open == 0 ||
162 hwp->close == 0 ||
163 hwp->output == 0 ||
164 hwp->getinfo == 0) {
165 printf("midi: missing method\n");
166 return;
167 }
168 #endif
169
170 sc->hw_if = hwp;
171 sc->hw_hdl = hdlp;
172 midi_attach(sc, parent);
173 }
174
175 int
176 midiactivate(struct device *self, enum devact act)
177 {
178 struct midi_softc *sc = (struct midi_softc *)self;
179
180 switch (act) {
181 case DVACT_ACTIVATE:
182 return (EOPNOTSUPP);
183
184 case DVACT_DEACTIVATE:
185 sc->dying = 1;
186 break;
187 }
188 return (0);
189 }
190
191 int
192 mididetach(struct device *self, int flags)
193 {
194 struct midi_softc *sc = (struct midi_softc *)self;
195 int maj, mn;
196
197 DPRINTFN(2,("midi_detach: sc=%p flags=%d\n", sc, flags));
198
199 sc->dying = 1;
200
201 wakeup(&sc->wchan);
202 wakeup(&sc->rchan);
203
204 /* locate the major number */
205 maj = cdevsw_lookup_major(&midi_cdevsw);
206
207 /* Nuke the vnodes for any open instances (calls close). */
208 mn = self->dv_unit;
209 vdevgone(maj, mn, mn, VCHR);
210
211 evcnt_detach(&sc->xmt.bytesDiscarded);
212 evcnt_detach(&sc->xmt.incompleteMessages);
213 if ( sc->props & MIDI_PROP_CAN_INPUT ) {
214 evcnt_detach(&sc->rcv.bytesDiscarded);
215 evcnt_detach(&sc->rcv.incompleteMessages);
216 }
217
218 return (0);
219 }
220
221 void
222 midi_attach(struct midi_softc *sc, struct device *parent)
223 {
224 struct midi_info mi;
225 int s;
226
227 callout_init(&sc->sc_callout);
228 callout_setfunc(&sc->sc_callout, midi_timeout, sc);
229 simple_lock_init(&sc->out_lock);
230 simple_lock_init(&sc->in_lock);
231 sc->dying = 0;
232 sc->isopen = 0;
233
234 sc->sc_dev = parent;
235
236 s = splaudio();
237 simple_lock(&hwif_register_lock);
238 hwif_softc = sc;
239 sc->hw_if->getinfo(sc->hw_hdl, &mi);
240 hwif_softc = NULL;
241 simple_unlock(&hwif_register_lock);
242 splx(s);
243
244 sc->props = mi.props;
245
246 evcnt_attach_dynamic(&sc->xmt.bytesDiscarded,
247 EVCNT_TYPE_MISC, NULL,
248 sc->dev.dv_xname, "xmt bytes discarded");
249 evcnt_attach_dynamic(&sc->xmt.incompleteMessages,
250 EVCNT_TYPE_MISC, NULL,
251 sc->dev.dv_xname, "xmt incomplete msgs");
252 if ( sc->props & MIDI_PROP_CAN_INPUT ) {
253 evcnt_attach_dynamic(&sc->rcv.bytesDiscarded,
254 EVCNT_TYPE_MISC, NULL,
255 sc->dev.dv_xname, "rcv bytes discarded");
256 evcnt_attach_dynamic(&sc->rcv.incompleteMessages,
257 EVCNT_TYPE_MISC, NULL,
258 sc->dev.dv_xname, "rcv incomplete msgs");
259 }
260
261 printf(": %s\n", mi.name);
262 }
263
264 void midi_register_hw_if_ext(struct midi_hw_if_ext *exthw) {
265 if ( hwif_softc != NULL )
266 hwif_softc->hw_if_ext = exthw;
267 }
268
269 int
270 midi_unit_count(void)
271 {
272 int i;
273 for ( i = 0; i < midi_cd.cd_ndevs; ++i )
274 if ( NULL == midi_cd.cd_devs[i] )
275 break;
276 return i;
277 }
278
279 void
280 midi_initbuf(struct midi_buffer *mb)
281 {
282 mb->idx_producerp = mb->idx_consumerp = mb->idx;
283 mb->buf_producerp = mb->buf_consumerp = mb->buf;
284 }
285 #define PACK_MB_IDX(cat,len) (((cat)<<4)|(len))
286 #define MB_IDX_CAT(idx) ((idx)>>4)
287 #define MB_IDX_LEN(idx) ((idx)&0xf)
288
289 int
290 midi_sleep_timo(int *chan, char *label, int timo, struct simplelock *lk)
291 {
292 int st;
293
294 if (!label)
295 label = "midi";
296
297 DPRINTFN(8, ("midi_sleep_timo: %p %s %d\n", chan, label, timo));
298 *chan = 1;
299 st = ltsleep(chan, PWAIT | PCATCH, label, timo, lk);
300 *chan = 0;
301 #ifdef MIDI_DEBUG
302 if (st != 0)
303 printf("midi_sleep: %d\n", st);
304 #endif
305 return st;
306 }
307
308 int
309 midi_sleep(int *chan, char *label, struct simplelock *lk)
310 {
311 return midi_sleep_timo(chan, label, 0, lk);
312 }
313
314 void
315 midi_wakeup(int *chan)
316 {
317 if (*chan) {
318 DPRINTFN(8, ("midi_wakeup: %p\n", chan));
319 wakeup(chan);
320 *chan = 0;
321 }
322 }
323
324 /* in midivar.h:
325 #define MIDI_CAT_DATA 0
326 #define MIDI_CAT_STATUS1 1
327 #define MIDI_CAT_STATUS2 2
328 #define MIDI_CAT_COMMON 3
329 */
330 static char const midi_cats[] = "\0\0\0\0\0\0\0\0\2\2\2\2\1\1\2\3";
331 #define MIDI_CAT(d) (midi_cats[((d)>>4)&15])
332 #define FST_RETURN(offp,endp,ret) \
333 return (s->pos=s->msg+(offp)), (s->end=s->msg+(endp)), (ret)
334
335 enum fst_ret { FST_CHN, FST_COM, FST_SYX, FST_RT, FST_MORE, FST_ERR, FST_HUH };
336
337 /*
338 * A MIDI finite state transducer suitable for receiving or transmitting. It
339 * will accept correct MIDI input that uses, doesn't use, or sometimes uses the
340 * 'running status' compression technique, and transduce it to fully expanded
341 * (compress==0) or fully compressed (compress==1) form.
342 *
343 * Returns FST_MORE if a complete message has not been parsed yet (SysEx
344 * messages are the exception), FST_ERR or FST_HUH if the input does not
345 * conform to the protocol, or FST_CHN (channel messages), FST_COM (System
346 * Common messages), FST_RT (System Real-Time messages), or FST_SYX (System
347 * Exclusive) to broadly categorize the message parsed. s->pos and s->end
348 * locate the parsed message; while (s->pos<s->end) putchar(*(s->pos++));
349 * would output it.
350 *
351 * FST_HUH means the character c wasn't valid in the original state, but the
352 * state has now been reset to START and the caller should try again passing
353 * the same c. FST_ERR means c isn't valid in the start state; the caller
354 * should kiss it goodbye and continue to try successive characters from the
355 * input until something other than FST_ERR or FST_HUH is returned, at which
356 * point things are resynchronized.
357 *
358 * A FST_SYX return means that between pos and end are from 1 to 3
359 * bytes of a system exclusive message. A SysEx message will be delivered in
360 * one or more chunks of that form, where the first begins with 0xf0 and the
361 * last (which is the only one that might have length < 3) ends with 0xf7.
362 *
363 * Messages corrupted by a protocol error are discarded and won't be seen at
364 * all; again SysEx is the exception, as one or more chunks of it may already
365 * have been parsed.
366 *
367 * For FST_CHN messages, s->msg[0] always contains the status byte even if
368 * compression was requested (pos then points to msg[1]). That way, the
369 * caller can always identify the exact message if there is a need to do so.
370 * For all other message types except FST_SYX, the status byte is at *pos
371 * (which may not necessarily be msg[0]!). There is only one SysEx status
372 * byte, so the return value FST_SYX is sufficient to identify it.
373 */
374 static enum fst_ret
375 midi_fst(struct midi_state *s, u_char c, int compress)
376 {
377 int syxpos = 0;
378 compress = compress ? 1 : 0;
379
380 if ( c >= 0xf8 ) { /* All realtime messages bypass state machine */
381 if ( c == 0xf9 || c == 0xfd ) {
382 DPRINTF( ("midi_fst: s=%p c=0x%02x undefined\n",
383 s, c));
384 s->bytesDiscarded.ev_count++;
385 return FST_ERR;
386 }
387 DPRINTFN(9, ("midi_fst: s=%p System Real-Time data=0x%02x\n",
388 s, c));
389 s->msg[2] = c;
390 FST_RETURN(2,3,FST_RT);
391 }
392
393 DPRINTFN(4, ("midi_fst: s=%p data=0x%02x state=%d\n",
394 s, c, s->state));
395
396 switch ( s->state | MIDI_CAT(c) ) { /* break ==> return FST_MORE */
397
398 case MIDI_IN_START | MIDI_CAT_COMMON:
399 case MIDI_IN_RUN1_1 | MIDI_CAT_COMMON:
400 case MIDI_IN_RUN2_2 | MIDI_CAT_COMMON:
401 case MIDI_IN_RXX2_2 | MIDI_CAT_COMMON:
402 s->msg[0] = c;
403 switch ( c ) {
404 case 0xf0: s->state = MIDI_IN_SYX1_3; break;
405 case 0xf1: s->state = MIDI_IN_COM0_1; break;
406 case 0xf2: s->state = MIDI_IN_COM0_2; break;
407 case 0xf3: s->state = MIDI_IN_COM0_1; break;
408 case 0xf6: s->state = MIDI_IN_START; FST_RETURN(0,1,FST_COM);
409 default: goto protocol_violation;
410 }
411 break;
412
413 case MIDI_IN_RUN1_1 | MIDI_CAT_STATUS1:
414 if ( c == s->msg[0] ) {
415 s->state = MIDI_IN_RNX0_1;
416 break;
417 }
418 /* FALLTHROUGH */
419 case MIDI_IN_RUN2_2 | MIDI_CAT_STATUS1:
420 case MIDI_IN_RXX2_2 | MIDI_CAT_STATUS1:
421 case MIDI_IN_START | MIDI_CAT_STATUS1:
422 s->state = MIDI_IN_RUN0_1;
423 s->msg[0] = c;
424 break;
425
426 case MIDI_IN_RUN2_2 | MIDI_CAT_STATUS2:
427 case MIDI_IN_RXX2_2 | MIDI_CAT_STATUS2:
428 if ( c == s->msg[0] ) {
429 s->state = MIDI_IN_RNX0_2;
430 break;
431 }
432 if ( (c ^ s->msg[0]) == 0x10 && (c & 0xe0) == 0x80 ) {
433 s->state = MIDI_IN_RXX0_2;
434 s->msg[0] = c;
435 break;
436 }
437 /* FALLTHROUGH */
438 case MIDI_IN_RUN1_1 | MIDI_CAT_STATUS2:
439 case MIDI_IN_START | MIDI_CAT_STATUS2:
440 s->state = MIDI_IN_RUN0_2;
441 s->msg[0] = c;
442 break;
443
444 case MIDI_IN_COM0_1 | MIDI_CAT_DATA:
445 s->state = MIDI_IN_START;
446 s->msg[1] = c;
447 FST_RETURN(0,2,FST_COM);
448
449 case MIDI_IN_COM0_2 | MIDI_CAT_DATA:
450 s->state = MIDI_IN_COM1_2;
451 s->msg[1] = c;
452 break;
453
454 case MIDI_IN_COM1_2 | MIDI_CAT_DATA:
455 s->state = MIDI_IN_START;
456 s->msg[2] = c;
457 FST_RETURN(0,3,FST_COM);
458
459 case MIDI_IN_RUN0_1 | MIDI_CAT_DATA:
460 s->state = MIDI_IN_RUN1_1;
461 s->msg[1] = c;
462 FST_RETURN(0,2,FST_CHN);
463
464 case MIDI_IN_RUN1_1 | MIDI_CAT_DATA:
465 case MIDI_IN_RNX0_1 | MIDI_CAT_DATA:
466 s->state = MIDI_IN_RUN1_1;
467 s->msg[1] = c;
468 FST_RETURN(compress,2,FST_CHN);
469
470 case MIDI_IN_RUN0_2 | MIDI_CAT_DATA:
471 s->state = MIDI_IN_RUN1_2;
472 s->msg[1] = c;
473 break;
474
475 case MIDI_IN_RUN1_2 | MIDI_CAT_DATA:
476 if ( !compress && c == 0 && (s->msg[0] & 0xf0) == 0x90 ) {
477 s->state = MIDI_IN_RXX2_2;
478 s->msg[0] ^= 0x10;
479 s->msg[2] = 64;
480 } else {
481 s->state = MIDI_IN_RUN2_2;
482 s->msg[2] = c;
483 }
484 FST_RETURN(0,3,FST_CHN);
485
486 case MIDI_IN_RUN2_2 | MIDI_CAT_DATA:
487 s->state = MIDI_IN_RNX1_2;
488 s->msg[1] = c;
489 break;
490
491 case MIDI_IN_RXX2_2 | MIDI_CAT_DATA:
492 s->state = MIDI_IN_RXX1_2;
493 s->msg[0] ^= 0x10;
494 s->msg[1] = c;
495 break;
496
497 case MIDI_IN_RNX0_2 | MIDI_CAT_DATA:
498 s->state = MIDI_IN_RNY1_2;
499 s->msg[1] = c;
500 break;
501
502 case MIDI_IN_RXX0_2 | MIDI_CAT_DATA:
503 s->state = MIDI_IN_RXY1_2;
504 s->msg[1] = c;
505 break;
506
507 case MIDI_IN_RNX1_2 | MIDI_CAT_DATA:
508 case MIDI_IN_RNY1_2 | MIDI_CAT_DATA:
509 if ( !compress && c == 0 && (s->msg[0]&0xf0) == 0x90 ) {
510 s->state = MIDI_IN_RXX2_2;
511 s->msg[0] ^= 0x10;
512 s->msg[2] = 64;
513 FST_RETURN(0,3,FST_CHN);
514 }
515 s->state = MIDI_IN_RUN2_2;
516 s->msg[2] = c;
517 FST_RETURN(compress,3,FST_CHN);
518
519 case MIDI_IN_RXX1_2 | MIDI_CAT_DATA:
520 case MIDI_IN_RXY1_2 | MIDI_CAT_DATA:
521 if ( (c == 0 && (s->msg[0]&0xf0) == 0x90)
522 || (c == 64 && (s->msg[0]&0xf0) == 0x80 && compress) ) {
523 s->state = MIDI_IN_RXX2_2;
524 s->msg[0] ^= 0x10;
525 s->msg[2] = 64 - c;
526 FST_RETURN(compress,3,FST_CHN);
527 }
528 s->state = MIDI_IN_RUN2_2;
529 s->msg[2] = c;
530 FST_RETURN(0,3,FST_CHN);
531
532 case MIDI_IN_SYX1_3 | MIDI_CAT_DATA:
533 s->state = MIDI_IN_SYX2_3;
534 s->msg[1] = c;
535 break;
536
537 case MIDI_IN_SYX2_3 | MIDI_CAT_DATA:
538 s->state = MIDI_IN_SYX0_3;
539 s->msg[2] = c;
540 FST_RETURN(0,3,FST_SYX);
541
542 case MIDI_IN_SYX0_3 | MIDI_CAT_DATA:
543 s->state = MIDI_IN_SYX1_3;
544 s->msg[0] = c;
545 break;
546
547 case MIDI_IN_SYX2_3 | MIDI_CAT_COMMON:
548 ++ syxpos;
549 /* FALLTHROUGH */
550 case MIDI_IN_SYX1_3 | MIDI_CAT_COMMON:
551 ++ syxpos;
552 /* FALLTHROUGH */
553 case MIDI_IN_SYX0_3 | MIDI_CAT_COMMON:
554 if ( c == 0xf7 ) {
555 s->state = MIDI_IN_START;
556 s->msg[syxpos] = c;
557 FST_RETURN(0,1+syxpos,FST_SYX);
558 }
559 /* FALLTHROUGH */
560
561 default:
562 protocol_violation:
563 DPRINTF(("midi_fst: unexpected %#02x in state %u\n",
564 c, s->state));
565 switch ( s->state ) {
566 case MIDI_IN_RUN1_1: /* can only get here by seeing an */
567 case MIDI_IN_RUN2_2: /* INVALID System Common message */
568 case MIDI_IN_RXX2_2:
569 s->state = MIDI_IN_START;
570 /* FALLTHROUGH */
571 case MIDI_IN_START:
572 s->bytesDiscarded.ev_count++;
573 return FST_ERR;
574 case MIDI_IN_COM1_2:
575 case MIDI_IN_RUN1_2:
576 case MIDI_IN_SYX2_3:
577 case MIDI_IN_RNY1_2:
578 case MIDI_IN_RXY1_2:
579 s->bytesDiscarded.ev_count++;
580 /* FALLTHROUGH */
581 case MIDI_IN_COM0_1:
582 case MIDI_IN_RUN0_1:
583 case MIDI_IN_RNX0_1:
584 case MIDI_IN_COM0_2:
585 case MIDI_IN_RUN0_2:
586 case MIDI_IN_RNX0_2:
587 case MIDI_IN_RXX0_2:
588 case MIDI_IN_RNX1_2:
589 case MIDI_IN_RXX1_2:
590 case MIDI_IN_SYX1_3:
591 s->bytesDiscarded.ev_count++;
592 /* FALLTHROUGH */
593 case MIDI_IN_SYX0_3:
594 s->incompleteMessages.ev_count++;
595 break;
596 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
597 default:
598 printf("midi_fst: mishandled %#02x(%u) in state %u?!\n",
599 c, MIDI_CAT(c), s->state);
600 #endif
601 }
602 s->state = MIDI_IN_START;
603 return FST_HUH;
604 }
605 return FST_MORE;
606 }
607
608 void
609 midi_in(void *addr, int data)
610 {
611 struct midi_softc *sc = addr;
612 struct midi_buffer *mb = &sc->inbuf;
613 int i;
614 int count;
615 enum fst_ret got;
616 int s; /* hw may have various spls so impose our own */
617 MIDI_BUF_DECLARE(idx);
618 MIDI_BUF_DECLARE(buf);
619
620 if (!sc->isopen)
621 return;
622
623 if (!(sc->flags & FREAD))
624 return; /* discard data if not reading */
625
626 do
627 got = midi_fst(&sc->rcv, data, 0);
628 while ( got == FST_HUH );
629
630 switch ( got ) {
631 case FST_MORE:
632 case FST_ERR:
633 return;
634 case FST_CHN:
635 case FST_COM:
636 case FST_RT:
637 #if NSEQUENCER > 0
638 if (sc->seqopen) {
639 extern void midiseq_in(struct midi_dev *,u_char *,int);
640 count = sc->rcv.end - sc->rcv.pos;
641 midiseq_in(sc->seq_md, sc->rcv.pos, count);
642 return;
643 }
644 #endif
645 /*
646 * Pass Active Sense to the sequencer if it's open, but not to
647 * a raw reader. (Really should do something intelligent with
648 * it then, though....)
649 */
650 if ( got == FST_RT && MIDI_ACK == sc->rcv.pos[0] )
651 return;
652 /* FALLTHROUGH */
653 /*
654 * Ultimately SysEx msgs should be offered to the sequencer also; the
655 * sequencer API addresses them - but maybe our sequencer can't handle
656 * them yet, so offer only to raw reader. (Which means, ultimately,
657 * discard them if the sequencer's open, as it's not doing reads!)
658 */
659 case FST_SYX:
660 count = sc->rcv.end - sc->rcv.pos;
661 MIDI_IN_LOCK(sc,s);
662 MIDI_BUF_PRODUCER_INIT(mb,idx);
663 MIDI_BUF_PRODUCER_INIT(mb,buf);
664 if (count > buf_lim - buf_cur
665 || 1 > idx_lim - idx_cur) {
666 sc->rcv.bytesDiscarded.ev_count += count;
667 MIDI_IN_UNLOCK(sc,s);
668 DPRINTF(("midi_in: buffer full, discard data=0x%02x\n",
669 sc->rcv.pos[0]));
670 return;
671 }
672 for (i = 0; i < count; i++) {
673 *buf_cur++ = sc->rcv.pos[i];
674 MIDI_BUF_WRAP(buf);
675 }
676 *idx_cur++ = PACK_MB_IDX(got,count);
677 MIDI_BUF_WRAP(idx);
678 MIDI_BUF_PRODUCER_WBACK(mb,buf);
679 MIDI_BUF_PRODUCER_WBACK(mb,idx);
680 midi_wakeup(&sc->rchan);
681 selnotify(&sc->rsel, 0);
682 if (sc->async)
683 psignal(sc->async, SIGIO);
684 MIDI_IN_UNLOCK(sc,s);
685 break;
686 default: /* don't #ifdef this away, gcc will say FST_HUH not handled */
687 printf("midi_in: midi_fst returned %d?!\n", got);
688 }
689 }
690
691 void
692 midi_out(void *addr)
693 {
694 struct midi_softc *sc = addr;
695
696 if (!sc->isopen)
697 return;
698 DPRINTFN(8, ("midi_out: %p\n", sc));
699 midi_intr_out(sc);
700 }
701
702 int
703 midiopen(dev_t dev, int flags, int ifmt, struct proc *p)
704 {
705 struct midi_softc *sc;
706 struct midi_hw_if *hw;
707 int error;
708
709 sc = device_lookup(&midi_cd, MIDIUNIT(dev));
710 if (sc == NULL)
711 return (ENXIO);
712 if (sc->dying)
713 return (EIO);
714
715 DPRINTFN(3,("midiopen %p\n", sc));
716
717 hw = sc->hw_if;
718 if (!hw)
719 return ENXIO;
720 if (sc->isopen)
721 return EBUSY;
722
723 /* put both state machines into known states */
724 sc->rcv.state = MIDI_IN_START;
725 sc->rcv.pos = sc->rcv.msg;
726 sc->rcv.end = sc->rcv.msg;
727 sc->xmt.state = MIDI_IN_START;
728 sc->xmt.pos = sc->xmt.msg;
729 sc->xmt.end = sc->xmt.msg;
730
731 /* and the buffers */
732 midi_initbuf(&sc->outbuf);
733 midi_initbuf(&sc->inbuf);
734
735 error = hw->open(sc->hw_hdl, flags, midi_in, midi_out, sc);
736 if (error)
737 return error;
738 sc->isopen++;
739 sc->flags = flags;
740 sc->rchan = 0;
741 sc->wchan = 0;
742 sc->pbus = 0;
743 sc->async = 0;
744
745 #ifdef MIDI_SAVE
746 if (midicnt != 0) {
747 midisave.cnt = midicnt;
748 midicnt = 0;
749 }
750 #endif
751
752 return 0;
753 }
754
755 int
756 midiclose(dev_t dev, int flags, int ifmt, struct proc *p)
757 {
758 int unit = MIDIUNIT(dev);
759 struct midi_softc *sc = midi_cd.cd_devs[unit];
760 struct midi_hw_if *hw = sc->hw_if;
761 int s, error;
762
763 DPRINTFN(3,("midiclose %p\n", sc));
764
765 /* midi_start_output(sc); anything buffered => pbus already set! */
766 error = 0;
767 MIDI_OUT_LOCK(sc,s);
768 while (sc->pbus) {
769 DPRINTFN(8,("midiclose sleep ...\n"));
770 error =
771 midi_sleep_timo(&sc->wchan, "mid_dr", 30*hz, &sc->out_lock);
772 }
773 MIDI_OUT_UNLOCK(sc,s);
774 callout_stop(&sc->sc_callout); /* xxx fix this - sleep? */
775 sc->isopen = 0;
776 hw->close(sc->hw_hdl);
777 #if NSEQUENCER > 0
778 sc->seqopen = 0;
779 sc->seq_md = 0;
780 #endif
781 return 0;
782 }
783
784 int
785 midiread(dev_t dev, struct uio *uio, int ioflag)
786 {
787 int unit = MIDIUNIT(dev);
788 struct midi_softc *sc = midi_cd.cd_devs[unit];
789 struct midi_buffer *mb = &sc->inbuf;
790 int error;
791 int s;
792 MIDI_BUF_DECLARE(idx);
793 MIDI_BUF_DECLARE(buf);
794 int appetite;
795 int first = 1;
796
797 DPRINTFN(6,("midiread: %p, count=%lu\n", sc,
798 (unsigned long)uio->uio_resid));
799
800 if (sc->dying)
801 return EIO;
802 if ( !(sc->props & MIDI_PROP_CAN_INPUT) )
803 return ENXIO;
804
805 MIDI_IN_LOCK(sc,s);
806 MIDI_BUF_CONSUMER_INIT(mb,idx);
807 MIDI_BUF_CONSUMER_INIT(mb,buf);
808 MIDI_IN_UNLOCK(sc,s);
809
810 error = 0;
811 for ( ;; ) {
812 /*
813 * If the used portion of idx wraps around the end, just take
814 * the first part on this iteration, and we'll get the rest on
815 * the next.
816 */
817 if ( idx_lim > idx_end )
818 idx_lim = idx_end;
819 /*
820 * Count bytes through the last complete message that will
821 * fit in the requested read.
822 */
823 for (appetite = uio->uio_resid; idx_cur < idx_lim; ++idx_cur) {
824 if ( appetite < MB_IDX_LEN(*idx_cur) )
825 break;
826 appetite -= MB_IDX_LEN(*idx_cur);
827 }
828 appetite = uio->uio_resid - appetite;
829 /*
830 * Only if the read is too small to hold even the first
831 * complete message will we return a partial one (updating idx
832 * to reflect the remaining length of the message).
833 */
834 if ( appetite == 0 && idx_cur < idx_lim ) {
835 if ( !first )
836 goto unlocked_exit; /* idx_cur not advanced */
837 appetite = uio->uio_resid;
838 *idx_cur = PACK_MB_IDX(MB_IDX_CAT(*idx_cur),
839 MB_IDX_LEN(*idx_cur) - appetite);
840 }
841 KASSERT(buf_cur + appetite <= buf_lim);
842
843 /* move the bytes */
844 if ( appetite > 0 ) {
845 first = 0; /* we know we won't return empty-handed */
846 /* do two uiomoves if data wrap around end of buf */
847 if ( buf_cur + appetite > buf_end ) {
848 DPRINTFN(8,
849 ("midiread: uiomove cc=%d (prewrap)\n",
850 buf_end - buf_cur));
851 error = uiomove(buf_cur, buf_end-buf_cur, uio);
852 if ( error )
853 goto unlocked_exit;
854 appetite -= buf_end - buf_cur;
855 buf_cur = mb->buf;
856 }
857 DPRINTFN(8, ("midiread: uiomove cc=%d\n", appetite));
858 error = uiomove(buf_cur, appetite, uio);
859 if ( error )
860 goto unlocked_exit;
861 buf_cur += appetite;
862 }
863
864 MIDI_BUF_WRAP(idx);
865 MIDI_BUF_WRAP(buf);
866
867 MIDI_IN_LOCK(sc,s);
868 MIDI_BUF_CONSUMER_WBACK(mb,idx);
869 MIDI_BUF_CONSUMER_WBACK(mb,buf);
870 if ( 0 == uio->uio_resid ) /* if read satisfied, we're done */
871 break;
872 MIDI_BUF_CONSUMER_REFRESH(mb,idx);
873 if ( idx_cur == idx_lim ) { /* need to wait for data? */
874 if ( !first ) /* never block reader if */
875 break; /* any data already in hand */
876 if (ioflag & IO_NDELAY) {
877 error = EWOULDBLOCK;
878 break;
879 }
880 error = midi_sleep(&sc->rchan, "mid rd", &sc->in_lock);
881 if ( error )
882 break;
883 MIDI_BUF_CONSUMER_REFRESH(mb,idx); /* what'd we get? */
884 }
885 MIDI_BUF_CONSUMER_REFRESH(mb,buf);
886 MIDI_IN_UNLOCK(sc,s);
887 if ( sc->dying )
888 return EIO;
889 }
890 MIDI_IN_UNLOCK(sc,s);
891
892 unlocked_exit:
893 return error;
894 }
895
896 void
897 midi_timeout(void *arg)
898 {
899 struct midi_softc *sc = arg;
900 int s;
901 int error;
902 int armed;
903
904 MIDI_OUT_LOCK(sc,s);
905 if ( sc->pbus ) {
906 MIDI_OUT_UNLOCK(sc,s);
907 return;
908 }
909 sc->pbus = 1;
910 DPRINTFN(8,("midi_timeout: %p\n", sc));
911
912 if ( sc->props & MIDI_PROP_OUT_INTR ) {
913 error = sc->hw_if->output(sc->hw_hdl, MIDI_ACK);
914 armed = (error == 0);
915 } else { /* polled output, do with interrupts unmasked */
916 MIDI_OUT_UNLOCK(sc,s);
917 error = sc->hw_if->output(sc->hw_hdl, MIDI_ACK);
918 MIDI_OUT_LOCK(sc,s);
919 armed = 0;
920 }
921
922 if ( !armed ) {
923 sc->pbus = 0;
924 callout_schedule(&sc->sc_callout, mstohz(275));
925 }
926
927 MIDI_OUT_UNLOCK(sc,s);
928 }
929
930 /*
931 * The way this function was hacked up to plug into poll_out and intr_out
932 * after they were written won't win it any beauty contests, but it'll work
933 * (code in haste, refactor at leisure). This may be called with the lock
934 * (by intr_out) or without the lock (by poll_out) so it only does what could
935 * be safe either way.
936 */
937 int midi_msg_out(struct midi_softc *sc,
938 u_char **idx, u_char **idxl, u_char **buf, u_char **bufl) {
939 MIDI_BUF_DECLARE(idx);
940 MIDI_BUF_DECLARE(buf);
941 MIDI_BUF_EXTENT_INIT(&sc->outbuf,idx);
942 MIDI_BUF_EXTENT_INIT(&sc->outbuf,buf);
943 int length;
944 int error;
945 u_char contig[3];
946 u_char *cp = contig;
947
948 idx_cur = *idx;
949 idx_lim = *idxl;
950 buf_cur = *buf;
951 buf_lim = *bufl;
952
953 length = MB_IDX_LEN(*idx_cur);
954
955 while ( length --> 0 ) {
956 *cp++ = *buf_cur++;
957 MIDI_BUF_WRAP(buf);
958 }
959
960 switch ( MB_IDX_CAT(*idx_cur) ) {
961 case FST_CHN:
962 error = sc->hw_if_ext->channel(sc->hw_hdl,
963 MIDI_GET_STATUS(contig[0]),
964 MIDI_GET_CHAN(contig[0]),
965 contig, cp - contig);
966 break;
967 case FST_COM:
968 error = sc->hw_if_ext->common(sc->hw_hdl,
969 MIDI_GET_STATUS(contig[0]),
970 contig, cp - contig);
971 break;
972 case FST_SYX:
973 error = sc->hw_if_ext->sysex(sc->hw_hdl,
974 contig, cp - contig);
975 break;
976 case FST_RT:
977 error = sc->hw_if->output(sc->hw_hdl, **buf);
978 break;
979 default:
980 error = EIO;
981 }
982
983 if ( !error ) {
984 ++ idx_cur;
985 MIDI_BUF_WRAP(idx);
986 *idx = idx_cur;
987 *idxl = idx_lim;
988 *buf = buf_cur;
989 *bufl = buf_lim;
990 }
991
992 return error;
993 }
994
995 /*
996 * midi_poll_out is intended for the midi hw (the vast majority of MIDI UARTs
997 * on sound cards, apparently) that _do not have transmit-ready interrupts_.
998 * Every call to hw_if->output for one of these may busy-wait to output the
999 * byte; at the standard midi data rate that'll be 320us per byte. The
1000 * technique of writing only MIDI_MAX_WRITE bytes in a row and then waiting
1001 * for MIDI_WAIT does not reduce the total time spent busy-waiting, and it
1002 * adds arbitrary delays in transmission (and, since MIDI_WAIT is roughly the
1003 * same as the time to send MIDI_MAX_WRITE bytes, it effectively halves the
1004 * data rate). Here, a somewhat bolder approach is taken. Since midi traffic
1005 * is bursty but time-sensitive--most of the time there will be none at all,
1006 * but when there is it should go out ASAP--the strategy is to just get it
1007 * over with, and empty the buffer in one go. The effect this can have on
1008 * the rest of the system will be limited by the size of the buffer and the
1009 * sparseness of the traffic. But some precautions are in order. Interrupts
1010 * should all be unmasked when this is called, and midiwrite should not fill
1011 * the buffer more than once (when MIDI_PROP_CAN_INTR is false) without a
1012 * yield() so some other process can get scheduled. If the write is nonblocking,
1013 * midiwrite should return a short count rather than yield.
1014 *
1015 * Someday when there is fine-grained MP support, this should be reworked to
1016 * run in a callout so the writing process really could proceed concurrently.
1017 * But obviously where performance is a concern, interrupt-driven hardware
1018 * such as USB midi or (apparently) clcs will always be preferable.
1019 */
1020 int
1021 midi_poll_out(struct midi_softc *sc)
1022 {
1023 struct midi_buffer *mb = &sc->outbuf;
1024 int error;
1025 int msglen;
1026 int s;
1027 MIDI_BUF_DECLARE(idx);
1028 MIDI_BUF_DECLARE(buf);
1029
1030 error = 0;
1031
1032 MIDI_OUT_LOCK(sc,s);
1033 MIDI_BUF_CONSUMER_INIT(mb,idx);
1034 MIDI_BUF_CONSUMER_INIT(mb,buf);
1035 MIDI_OUT_UNLOCK(sc,s);
1036
1037 for ( ;; ) {
1038 while ( idx_cur != idx_lim ) {
1039 if ( sc->hw_if_ext ) {
1040 error = midi_msg_out(sc, &idx_cur, &idx_lim,
1041 &buf_cur, &buf_lim);
1042 if ( error )
1043 goto ioerror;
1044 continue;
1045 }
1046 /* or, lacking hw_if_ext ... */
1047 msglen = MB_IDX_LEN(*idx_cur);
1048 DPRINTFN(7,("midi_poll_out: %p <- %#02x\n",
1049 sc->hw_hdl, *buf_cur));
1050 error = sc->hw_if->output(sc->hw_hdl, *buf_cur);
1051 if ( error )
1052 goto ioerror;
1053 ++ buf_cur;
1054 MIDI_BUF_WRAP(buf);
1055 -- msglen;
1056 if ( msglen )
1057 *idx_cur = PACK_MB_IDX(MB_IDX_CAT(*idx_cur),
1058 msglen);
1059 else {
1060 ++ idx_cur;
1061 MIDI_BUF_WRAP(idx);
1062 }
1063 }
1064 KASSERT(buf_cur == buf_lim);
1065 MIDI_OUT_LOCK(sc,s);
1066 MIDI_BUF_CONSUMER_WBACK(mb,idx);
1067 MIDI_BUF_CONSUMER_WBACK(mb,buf);
1068 MIDI_BUF_CONSUMER_REFRESH(mb,idx); /* any more to transmit? */
1069 MIDI_BUF_CONSUMER_REFRESH(mb,buf);
1070 if ( idx_lim == idx_cur )
1071 break; /* still holding lock */
1072 MIDI_OUT_UNLOCK(sc,s);
1073 }
1074 goto disarm; /* lock held */
1075
1076 ioerror:
1077 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
1078 printf("%s: midi_poll_output error %d\n",
1079 sc->dev.dv_xname, error);
1080 #endif
1081 MIDI_OUT_LOCK(sc,s);
1082 MIDI_BUF_CONSUMER_WBACK(mb,idx);
1083 MIDI_BUF_CONSUMER_WBACK(mb,buf);
1084
1085 disarm:
1086 sc->pbus = 0;
1087 callout_schedule(&sc->sc_callout, mstohz(275));
1088 MIDI_OUT_UNLOCK(sc,s);
1089 return error;
1090 }
1091
1092 /*
1093 * The interrupt flavor acquires spl and lock once and releases at the end,
1094 * as it expects to write only one byte or message. The interface convention
1095 * is that if hw_if->output returns 0, it has initiated transmission and the
1096 * completion interrupt WILL be forthcoming; if it has not returned 0, NO
1097 * interrupt will be forthcoming, and if it returns EINPROGRESS it wants
1098 * another byte right away.
1099 */
1100 int
1101 midi_intr_out(struct midi_softc *sc)
1102 {
1103 struct midi_buffer *mb = &sc->outbuf;
1104 int error;
1105 int msglen;
1106 int s;
1107 MIDI_BUF_DECLARE(idx);
1108 MIDI_BUF_DECLARE(buf);
1109 int armed = 0;
1110
1111 error = 0;
1112
1113 MIDI_OUT_LOCK(sc,s);
1114 MIDI_BUF_CONSUMER_INIT(mb,idx);
1115 MIDI_BUF_CONSUMER_INIT(mb,buf);
1116
1117 while ( idx_cur != idx_lim ) {
1118 if ( sc->hw_if_ext ) {
1119 error = midi_msg_out(sc, &idx_cur, &idx_lim,
1120 &buf_cur, &buf_lim);
1121 if ( !error ) /* no EINPROGRESS from extended hw_if */
1122 armed = 1;
1123 break;
1124 }
1125 /* or, lacking hw_if_ext ... */
1126 msglen = MB_IDX_LEN(*idx_cur);
1127 error = sc->hw_if->output(sc->hw_hdl, *buf_cur);
1128 if ( error && error != EINPROGRESS )
1129 break;
1130 ++ buf_cur;
1131 MIDI_BUF_WRAP(buf);
1132 -- msglen;
1133 if ( msglen )
1134 *idx_cur = PACK_MB_IDX(MB_IDX_CAT(*idx_cur),msglen);
1135 else {
1136 ++ idx_cur;
1137 MIDI_BUF_WRAP(idx);
1138 }
1139 if ( !error ) {
1140 armed = 1;
1141 break;
1142 }
1143 }
1144 MIDI_BUF_CONSUMER_WBACK(mb,idx);
1145 MIDI_BUF_CONSUMER_WBACK(mb,buf);
1146 if ( !armed ) {
1147 sc->pbus = 0;
1148 callout_schedule(&sc->sc_callout, mstohz(275));
1149 }
1150 midi_wakeup(&sc->wchan);
1151 selnotify(&sc->wsel, 0);
1152 if ( sc->async )
1153 psignal(sc->async, SIGIO);
1154 MIDI_OUT_UNLOCK(sc,s);
1155
1156 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
1157 if ( error )
1158 printf("%s: midi_intr_output error %d\n",
1159 sc->dev.dv_xname, error);
1160 #endif
1161 return error;
1162 }
1163
1164 int
1165 midi_start_output(struct midi_softc *sc)
1166 {
1167 if (sc->dying)
1168 return EIO;
1169
1170 if ( sc->props & MIDI_PROP_OUT_INTR )
1171 return midi_intr_out(sc);
1172 return midi_poll_out(sc);
1173 }
1174
1175 static int
1176 real_writebytes(struct midi_softc *sc, u_char *buf, int cc)
1177 {
1178 u_char *bufe = buf + cc;
1179 struct midi_buffer *mb = &sc->outbuf;
1180 int arming = 0;
1181 int count;
1182 int s;
1183 int got;
1184 MIDI_BUF_DECLARE(idx);
1185 MIDI_BUF_DECLARE(buf);
1186
1187 MIDI_OUT_LOCK(sc,s);
1188 MIDI_BUF_PRODUCER_INIT(mb,idx);
1189 MIDI_BUF_PRODUCER_INIT(mb,buf);
1190 MIDI_OUT_UNLOCK(sc,s);
1191
1192 if (sc->dying)
1193 return EIO;
1194
1195 while ( buf < bufe ) {
1196 do {
1197 /*
1198 * If the hardware uses the extended hw_if, pass it
1199 * canonicalized messages, else pass it compressed ones.
1200 */
1201 got = midi_fst(&sc->xmt, *buf, !sc->hw_if_ext);
1202 } while ( got == FST_HUH );
1203 ++ buf;
1204 switch ( got ) {
1205 case FST_MORE:
1206 continue;
1207 case FST_ERR:
1208 #if defined(EPROTO) /* most appropriate SUSv3 errno, but not in errno.h yet */
1209 return EPROTO;
1210 #else
1211 return EIO;
1212 #endif
1213 case FST_CHN:
1214 case FST_COM:
1215 case FST_RT:
1216 case FST_SYX:
1217 break; /* go add to buffer */
1218 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
1219 default:
1220 printf("midi_wr: midi_fst returned %d?!\n", got);
1221 #endif
1222 }
1223 count = sc->xmt.end - sc->xmt.pos;
1224 /*
1225 * return EWOULDBLOCK if the data passed will not fit in
1226 * the buffer; the caller should have taken steps to avoid that.
1227 */
1228 if ( idx_cur == idx_lim || count > buf_lim - buf_cur ) {
1229 MIDI_OUT_LOCK(sc,s);
1230 MIDI_BUF_PRODUCER_REFRESH(mb,idx); /* get the most */
1231 MIDI_BUF_PRODUCER_REFRESH(mb,buf); /* current facts */
1232 MIDI_OUT_UNLOCK(sc,s);
1233 if ( idx_cur == idx_lim || count > buf_lim - buf_cur )
1234 return EWOULDBLOCK; /* caller's problem */
1235 }
1236 *idx_cur++ = PACK_MB_IDX(got,count);
1237 MIDI_BUF_WRAP(idx);
1238 while ( count ) {
1239 *buf_cur++ = *(sc->xmt.pos)++;
1240 MIDI_BUF_WRAP(buf);
1241 -- count;
1242 }
1243 }
1244 MIDI_OUT_LOCK(sc,s);
1245 MIDI_BUF_PRODUCER_WBACK(mb,buf);
1246 MIDI_BUF_PRODUCER_WBACK(mb,idx);
1247 /*
1248 * If the output transfer is not already busy, and there is a message
1249 * buffered, mark it busy, stop the Active Sense callout (what if we're
1250 * too late and it's expired already? No big deal, an extra Active Sense
1251 * never hurt anybody) and start the output transfer once we're out of
1252 * the critical section (pbus==1 will stop anyone else doing the same).
1253 */
1254 if ( !sc->pbus && idx_cur < MIDI_BUF_PRODUCER_REFRESH(mb,idx) ) {
1255 sc->pbus = 1;
1256 callout_stop(&sc->sc_callout);
1257 arming = 1;
1258 }
1259 MIDI_OUT_UNLOCK(sc,s);
1260 return arming ? midi_start_output(sc) : 0;
1261 }
1262
1263 int
1264 midiwrite(dev_t dev, struct uio *uio, int ioflag)
1265 {
1266 int unit = MIDIUNIT(dev);
1267 struct midi_softc *sc = midi_cd.cd_devs[unit];
1268 struct midi_buffer *mb = &sc->outbuf;
1269 int error;
1270 u_char inp[256];
1271 int s;
1272 MIDI_BUF_DECLARE(idx);
1273 MIDI_BUF_DECLARE(buf);
1274 size_t idxspace;
1275 size_t bufspace;
1276 size_t xfrcount;
1277 int pollout = 0;
1278
1279 DPRINTFN(6, ("midiwrite: %p, unit=%d, count=%lu\n", sc, unit,
1280 (unsigned long)uio->uio_resid));
1281
1282 if (sc->dying)
1283 return EIO;
1284
1285 error = 0;
1286 while (uio->uio_resid > 0 && !error) {
1287
1288 /*
1289 * block if necessary for the minimum buffer space to guarantee
1290 * we can write something.
1291 */
1292 MIDI_OUT_LOCK(sc,s);
1293 MIDI_BUF_PRODUCER_INIT(mb,idx); /* init can't go above loop; */
1294 MIDI_BUF_PRODUCER_INIT(mb,buf); /* real_writebytes moves cur */
1295 for ( ;; ) {
1296 idxspace = MIDI_BUF_PRODUCER_REFRESH(mb,idx) - idx_cur;
1297 bufspace = MIDI_BUF_PRODUCER_REFRESH(mb,buf) - buf_cur;
1298 if ( idxspace >= 1 && bufspace >= 3 && !pollout )
1299 break;
1300 DPRINTFN(8,("midi_write: sleep idx=%d buf=%d\n",
1301 idxspace, bufspace));
1302 if (ioflag & IO_NDELAY) {
1303 error = EWOULDBLOCK;
1304 /*
1305 * If some amount has already been transferred,
1306 * the common syscall code will automagically
1307 * convert this to success with a short count.
1308 */
1309 goto locked_exit;
1310 }
1311 if ( pollout ) {
1312 preempt(0); /* see midi_poll_output */
1313 pollout = 0;
1314 } else
1315 error = midi_sleep(&sc->wchan, "mid wr",
1316 &sc->out_lock);
1317 if (error)
1318 /*
1319 * Similarly, the common code will handle
1320 * EINTR and ERESTART properly here, changing to
1321 * a short count if something transferred.
1322 */
1323 goto locked_exit;
1324 }
1325 MIDI_OUT_UNLOCK(sc,s);
1326
1327 /*
1328 * The number of bytes we can safely extract from the uio
1329 * depends on the available idx and buf space. Worst case,
1330 * every byte is a message so 1 idx is required per byte.
1331 * Worst case, the first byte completes a 3-byte msg in prior
1332 * state, and every subsequent byte is a Program Change or
1333 * Channel Pressure msg with running status and expands to 2
1334 * bytes, so the buf space reqd is 3+2(n-1) or 2n+1. So limit
1335 * the transfer to the min of idxspace and (bufspace-1)>>1.
1336 */
1337 xfrcount = (bufspace - 1) >> 1;
1338 if ( xfrcount > idxspace )
1339 xfrcount = idxspace;
1340 if ( xfrcount > sizeof inp )
1341 xfrcount = sizeof inp;
1342 if ( xfrcount > uio->uio_resid )
1343 xfrcount = uio->uio_resid;
1344
1345 error = uiomove(inp, xfrcount, uio);
1346 #ifdef MIDI_DEBUG
1347 if (error)
1348 printf("midi_write:(1) uiomove failed %d; "
1349 "xfrcount=%d inp=%p\n",
1350 error, xfrcount, inp);
1351 #endif
1352 if ( error )
1353 break;
1354
1355 /*
1356 * The number of bytes we extracted being calculated to
1357 * definitely fit in the buffer even with canonicalization,
1358 * there is no excuse for real_writebytes to return EWOULDBLOCK.
1359 */
1360 error = real_writebytes(sc, inp, xfrcount);
1361 KASSERT(error != EWOULDBLOCK);
1362
1363 if ( error )
1364 break;
1365 /*
1366 * If this is a polling device and we just sent a buffer, let's
1367 * not send another without giving some other process a chance.
1368 */
1369 if ( ! (sc->props & MIDI_PROP_OUT_INTR) )
1370 pollout = 1;
1371 DPRINTFN(8,("midiwrite: uio_resid now %u, props=%d\n",
1372 uio->uio_resid, sc->props));
1373 }
1374 return error;
1375
1376 locked_exit:
1377 MIDI_OUT_UNLOCK(sc,s);
1378 return error;
1379 }
1380
1381 /*
1382 * This write routine is only called from sequencer code and expects
1383 * a write that is smaller than the MIDI buffer.
1384 */
1385 int
1386 midi_writebytes(int unit, u_char *buf, int cc)
1387 {
1388 struct midi_softc *sc = midi_cd.cd_devs[unit];
1389
1390 DPRINTFN(7, ("midi_writebytes: %p, unit=%d, cc=%d %#02x %#02x %#02x\n",
1391 sc, unit, cc, buf[0], buf[1], buf[2]));
1392 return real_writebytes(sc, buf, cc);
1393 }
1394
1395 int
1396 midiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
1397 {
1398 int unit = MIDIUNIT(dev);
1399 struct midi_softc *sc = midi_cd.cd_devs[unit];
1400 struct midi_hw_if *hw = sc->hw_if;
1401 int error;
1402 int s;
1403 MIDI_BUF_DECLARE(buf);
1404
1405 DPRINTFN(5,("midiioctl: %p cmd=0x%08lx\n", sc, cmd));
1406
1407 if (sc->dying)
1408 return EIO;
1409
1410 error = 0;
1411 switch (cmd) {
1412 case FIONBIO:
1413 /* All handled in the upper FS layer. */
1414 break;
1415
1416 case FIONREAD:
1417 /*
1418 * This code relies on the current implementation of midi_in
1419 * always updating buf and idx together in a critical section,
1420 * so buf always ends at a message boundary. Document this
1421 * ioctl as always returning a value such that the last message
1422 * included is complete (SysEx the only exception), and then
1423 * make sure the implementation doesn't regress. NB that
1424 * means if this ioctl returns n and the proc then issues a
1425 * read of n, n bytes will be read, but if the proc issues a
1426 * read of m < n, fewer than m bytes may be read to ensure the
1427 * read ends at a message boundary.
1428 */
1429 MIDI_IN_LOCK(sc,s);
1430 MIDI_BUF_CONSUMER_INIT(&sc->inbuf,buf);
1431 MIDI_IN_UNLOCK(sc,s);
1432 *(int *)addr = buf_lim - buf_cur;
1433 break;
1434
1435 case FIOASYNC:
1436 if (*(int *)addr) {
1437 if (sc->async)
1438 return EBUSY;
1439 sc->async = p;
1440 DPRINTFN(5,("midi_ioctl: FIOASYNC %p\n", p));
1441 } else
1442 sc->async = 0;
1443 break;
1444
1445 #if 0
1446 case MIDI_PRETIME:
1447 /* XXX OSS
1448 * This should set up a read timeout, but that's
1449 * why we have poll(), so there's nothing yet. */
1450 error = EINVAL;
1451 break;
1452 #endif
1453
1454 #ifdef MIDI_SAVE
1455 case MIDI_GETSAVE:
1456 error = copyout(&midisave, *(void **)addr, sizeof midisave);
1457 break;
1458 #endif
1459
1460 default:
1461 if (hw->ioctl)
1462 error = hw->ioctl(sc->hw_hdl, cmd, addr, flag, p);
1463 else
1464 error = EINVAL;
1465 break;
1466 }
1467 return error;
1468 }
1469
1470 int
1471 midipoll(dev_t dev, int events, struct proc *p)
1472 {
1473 int unit = MIDIUNIT(dev);
1474 struct midi_softc *sc = midi_cd.cd_devs[unit];
1475 int revents = 0;
1476 int s;
1477 MIDI_BUF_DECLARE(idx);
1478 MIDI_BUF_DECLARE(buf);
1479
1480 DPRINTFN(6,("midipoll: %p events=0x%x\n", sc, events));
1481
1482 if (sc->dying)
1483 return EIO;
1484
1485 s = splaudio();
1486
1487 if ((sc->flags&FREAD) && (events & (POLLIN | POLLRDNORM))) {
1488 simple_lock(&sc->in_lock);
1489 MIDI_BUF_CONSUMER_INIT(&sc->inbuf,idx);
1490 if (idx_cur < idx_lim)
1491 revents |= events & (POLLIN | POLLRDNORM);
1492 else
1493 selrecord(p, &sc->rsel);
1494 simple_unlock(&sc->in_lock);
1495 }
1496
1497 if ((sc->flags&FWRITE) && (events & (POLLOUT | POLLWRNORM))) {
1498 simple_lock(&sc->out_lock);
1499 MIDI_BUF_PRODUCER_INIT(&sc->outbuf,idx);
1500 MIDI_BUF_PRODUCER_INIT(&sc->outbuf,buf);
1501 if ( idx_lim - idx_cur >= 1 && buf_lim - buf_cur >= 3 )
1502 revents |= events & (POLLOUT | POLLWRNORM);
1503 else
1504 selrecord(p, &sc->wsel);
1505 simple_unlock(&sc->out_lock);
1506 }
1507
1508 splx(s);
1509 return revents;
1510 }
1511
1512 static void
1513 filt_midirdetach(struct knote *kn)
1514 {
1515 struct midi_softc *sc = kn->kn_hook;
1516 int s;
1517
1518 s = splaudio();
1519 SLIST_REMOVE(&sc->rsel.sel_klist, kn, knote, kn_selnext);
1520 splx(s);
1521 }
1522
1523 static int
1524 filt_midiread(struct knote *kn, long hint)
1525 {
1526 struct midi_softc *sc = kn->kn_hook;
1527 int s;
1528 MIDI_BUF_DECLARE(buf);
1529
1530 /* XXXLUKEM (thorpej): please make sure this is correct. */
1531
1532 MIDI_IN_LOCK(sc,s);
1533 MIDI_BUF_CONSUMER_INIT(&sc->inbuf,buf);
1534 kn->kn_data = buf_lim - buf_cur;
1535 MIDI_IN_UNLOCK(sc,s);
1536 return (kn->kn_data > 0);
1537 }
1538
1539 static const struct filterops midiread_filtops =
1540 { 1, NULL, filt_midirdetach, filt_midiread };
1541
1542 static void
1543 filt_midiwdetach(struct knote *kn)
1544 {
1545 struct midi_softc *sc = kn->kn_hook;
1546 int s;
1547
1548 s = splaudio();
1549 SLIST_REMOVE(&sc->wsel.sel_klist, kn, knote, kn_selnext);
1550 splx(s);
1551 }
1552
1553 static int
1554 filt_midiwrite(struct knote *kn, long hint)
1555 {
1556 struct midi_softc *sc = kn->kn_hook;
1557 int s;
1558 MIDI_BUF_DECLARE(idx);
1559 MIDI_BUF_DECLARE(buf);
1560
1561 /* XXXLUKEM (thorpej): please make sure this is correct. */
1562
1563 MIDI_OUT_LOCK(sc,s);
1564 MIDI_BUF_PRODUCER_INIT(&sc->outbuf,idx);
1565 MIDI_BUF_PRODUCER_INIT(&sc->outbuf,buf);
1566 kn->kn_data = ((buf_lim - buf_cur)-1)>>1;
1567 if ( kn->kn_data > idx_lim - idx_cur )
1568 kn->kn_data = idx_lim - idx_cur;
1569 MIDI_OUT_UNLOCK(sc,s);
1570 return (kn->kn_data > 0);
1571 }
1572
1573 static const struct filterops midiwrite_filtops =
1574 { 1, NULL, filt_midiwdetach, filt_midiwrite };
1575
1576 int
1577 midikqfilter(dev_t dev, struct knote *kn)
1578 {
1579 int unit = MIDIUNIT(dev);
1580 struct midi_softc *sc = midi_cd.cd_devs[unit];
1581 struct klist *klist;
1582 int s;
1583
1584 switch (kn->kn_filter) {
1585 case EVFILT_READ:
1586 klist = &sc->rsel.sel_klist;
1587 kn->kn_fop = &midiread_filtops;
1588 break;
1589
1590 case EVFILT_WRITE:
1591 klist = &sc->wsel.sel_klist;
1592 kn->kn_fop = &midiwrite_filtops;
1593 break;
1594
1595 default:
1596 return (1);
1597 }
1598
1599 kn->kn_hook = sc;
1600
1601 s = splaudio();
1602 SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1603 splx(s);
1604
1605 return (0);
1606 }
1607
1608 void
1609 midi_getinfo(dev_t dev, struct midi_info *mi)
1610 {
1611 struct midi_softc *sc;
1612
1613 sc = device_lookup(&midi_cd, MIDIUNIT(dev));
1614 if (sc == NULL)
1615 return;
1616 if (sc->dying)
1617 return;
1618
1619 sc->hw_if->getinfo(sc->hw_hdl, mi);
1620 }
1621
1622 #endif /* NMIDI > 0 */
1623
1624 #if NMIDI > 0 || NMIDIBUS > 0
1625
1626 int audioprint(void *, const char *);
1627
1628 struct device *
1629 midi_attach_mi(struct midi_hw_if *mhwp, void *hdlp, struct device *dev)
1630 {
1631 struct audio_attach_args arg;
1632
1633 #ifdef DIAGNOSTIC
1634 if (mhwp == NULL) {
1635 aprint_error("midi_attach_mi: NULL\n");
1636 return (0);
1637 }
1638 #endif
1639 arg.type = AUDIODEV_TYPE_MIDI;
1640 arg.hwif = mhwp;
1641 arg.hdl = hdlp;
1642 return (config_found(dev, &arg, audioprint));
1643 }
1644
1645 #endif /* NMIDI > 0 || NMIDIBUS > 0 */
1646