midi.c revision 1.43.2.8 1 /* $NetBSD: midi.c,v 1.43.2.8 2006/05/20 03:19:02 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.8 2006/05/20 03:19:02 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 s->msg[0] = c;
402 switch ( c ) {
403 case 0xf0: s->state = MIDI_IN_SYX1_3; break;
404 case 0xf1: s->state = MIDI_IN_COM0_1; break;
405 case 0xf2: s->state = MIDI_IN_COM0_2; break;
406 case 0xf3: s->state = MIDI_IN_COM0_1; break;
407 case 0xf6: s->state = MIDI_IN_START; FST_RETURN(0,1,FST_COM);
408 default: goto protocol_violation;
409 }
410 break;
411
412 case MIDI_IN_RUN1_1 | MIDI_CAT_STATUS1:
413 if ( c == s->msg[0] ) {
414 s->state = MIDI_IN_RNX0_1;
415 break;
416 }
417 /* FALLTHROUGH */
418 case MIDI_IN_RUN2_2 | MIDI_CAT_STATUS1:
419 case MIDI_IN_START | MIDI_CAT_STATUS1:
420 s->state = MIDI_IN_RUN0_1;
421 s->msg[0] = c;
422 break;
423
424 case MIDI_IN_RUN2_2 | MIDI_CAT_STATUS2:
425 if ( c == s->msg[0] ) {
426 s->state = MIDI_IN_RNX0_2;
427 break;
428 }
429 /* FALLTHROUGH */
430 case MIDI_IN_RUN1_1 | MIDI_CAT_STATUS2:
431 case MIDI_IN_START | MIDI_CAT_STATUS2:
432 s->state = MIDI_IN_RUN0_2;
433 s->msg[0] = c;
434 break;
435
436 case MIDI_IN_COM0_1 | MIDI_CAT_DATA:
437 s->state = MIDI_IN_START;
438 s->msg[1] = c;
439 FST_RETURN(0,2,FST_COM);
440
441 case MIDI_IN_COM0_2 | MIDI_CAT_DATA:
442 s->state = MIDI_IN_COM1_2;
443 s->msg[1] = c;
444 break;
445
446 case MIDI_IN_COM1_2 | MIDI_CAT_DATA:
447 s->state = MIDI_IN_START;
448 s->msg[2] = c;
449 FST_RETURN(0,3,FST_COM);
450
451 case MIDI_IN_RUN0_1 | MIDI_CAT_DATA:
452 s->state = MIDI_IN_RUN1_1;
453 s->msg[1] = c;
454 FST_RETURN(0,2,FST_CHN);
455
456 case MIDI_IN_RUN1_1 | MIDI_CAT_DATA:
457 case MIDI_IN_RNX0_1 | MIDI_CAT_DATA:
458 s->state = MIDI_IN_RUN1_1;
459 s->msg[1] = c;
460 FST_RETURN(compress,2,FST_CHN);
461
462 case MIDI_IN_RUN0_2 | MIDI_CAT_DATA:
463 s->state = MIDI_IN_RUN1_2;
464 s->msg[1] = c;
465 break;
466
467 case MIDI_IN_RUN1_2 | MIDI_CAT_DATA:
468 s->state = MIDI_IN_RUN2_2;
469 s->msg[2] = c;
470 FST_RETURN(0,3,FST_CHN);
471
472 case MIDI_IN_RUN2_2 | MIDI_CAT_DATA:
473 s->state = MIDI_IN_RNX1_2;
474 s->msg[1] = c;
475 break;
476
477 case MIDI_IN_RNX0_2 | MIDI_CAT_DATA:
478 s->state = MIDI_IN_RNY1_2;
479 s->msg[1] = c;
480 break;
481
482 case MIDI_IN_RNX1_2 | MIDI_CAT_DATA:
483 case MIDI_IN_RNY1_2 | MIDI_CAT_DATA:
484 s->state = MIDI_IN_RUN2_2;
485 s->msg[2] = c;
486 FST_RETURN(compress,3,FST_CHN);
487
488 case MIDI_IN_SYX1_3 | MIDI_CAT_DATA:
489 s->state = MIDI_IN_SYX2_3;
490 s->msg[1] = c;
491 break;
492
493 case MIDI_IN_SYX2_3 | MIDI_CAT_DATA:
494 s->state = MIDI_IN_SYX0_3;
495 s->msg[2] = c;
496 FST_RETURN(0,3,FST_SYX);
497
498 case MIDI_IN_SYX0_3 | MIDI_CAT_DATA:
499 s->state = MIDI_IN_SYX1_3;
500 s->msg[0] = c;
501 break;
502
503 case MIDI_IN_SYX2_3 | MIDI_CAT_COMMON:
504 ++ syxpos;
505 /* FALLTHROUGH */
506 case MIDI_IN_SYX1_3 | MIDI_CAT_COMMON:
507 ++ syxpos;
508 /* FALLTHROUGH */
509 case MIDI_IN_SYX0_3 | MIDI_CAT_COMMON:
510 if ( c == 0xf7 ) {
511 s->state = MIDI_IN_START;
512 s->msg[syxpos] = c;
513 FST_RETURN(0,1+syxpos,FST_SYX);
514 }
515 /* FALLTHROUGH */
516
517 default:
518 protocol_violation:
519 DPRINTF(("midi_fst: unexpected %#02x in state %u\n",
520 c, s->state));
521 switch ( s->state ) {
522 case MIDI_IN_RUN1_1: /* can only get here by seeing an */
523 case MIDI_IN_RUN2_2: /* INVALID System Common message */
524 s->state = MIDI_IN_START;
525 /* FALLTHROUGH */
526 case MIDI_IN_START:
527 s->bytesDiscarded.ev_count++;
528 return FST_ERR;
529 case MIDI_IN_COM1_2:
530 case MIDI_IN_RUN1_2:
531 case MIDI_IN_SYX2_3:
532 case MIDI_IN_RNY1_2:
533 s->bytesDiscarded.ev_count++;
534 /* FALLTHROUGH */
535 case MIDI_IN_COM0_1:
536 case MIDI_IN_RUN0_1:
537 case MIDI_IN_RNX0_1:
538 case MIDI_IN_COM0_2:
539 case MIDI_IN_RUN0_2:
540 case MIDI_IN_RNX0_2:
541 case MIDI_IN_RNX1_2:
542 case MIDI_IN_SYX1_3:
543 s->bytesDiscarded.ev_count++;
544 /* FALLTHROUGH */
545 case MIDI_IN_SYX0_3:
546 s->incompleteMessages.ev_count++;
547 break;
548 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
549 default:
550 printf("midi_fst: mishandled %#02x(%u) in state %u?!\n",
551 c, MIDI_CAT(c), s->state);
552 #endif
553 }
554 s->state = MIDI_IN_START;
555 return FST_HUH;
556 }
557 return FST_MORE;
558 }
559
560 void
561 midi_in(void *addr, int data)
562 {
563 struct midi_softc *sc = addr;
564 struct midi_buffer *mb = &sc->inbuf;
565 int i;
566 int count;
567 enum fst_ret got;
568 int s; /* hw may have various spls so impose our own */
569 MIDI_BUF_DECLARE(idx);
570 MIDI_BUF_DECLARE(buf);
571
572 if (!sc->isopen)
573 return;
574
575 if (!(sc->flags & FREAD))
576 return; /* discard data if not reading */
577
578 do
579 got = midi_fst(&sc->rcv, data, 0);
580 while ( got == FST_HUH );
581
582 switch ( got ) {
583 case FST_MORE:
584 case FST_ERR:
585 return;
586 case FST_CHN:
587 case FST_COM:
588 case FST_RT:
589 #if NSEQUENCER > 0
590 if (sc->seqopen) {
591 extern void midiseq_in(struct midi_dev *,u_char *,int);
592 count = sc->rcv.end - sc->rcv.pos;
593 midiseq_in(sc->seq_md, sc->rcv.pos, count);
594 return;
595 }
596 #endif
597 /*
598 * Pass Active Sense to the sequencer if it's open, but not to
599 * a raw reader. (Really should do something intelligent with
600 * it then, though....)
601 */
602 if ( got == FST_RT && MIDI_ACK == sc->rcv.pos[0] )
603 return;
604 /* FALLTHROUGH */
605 /*
606 * Ultimately SysEx msgs should be offered to the sequencer also; the
607 * sequencer API addresses them - but maybe our sequencer can't handle
608 * them yet, so offer only to raw reader. (Which means, ultimately,
609 * discard them if the sequencer's open, as it's not doing reads!)
610 */
611 case FST_SYX:
612 count = sc->rcv.end - sc->rcv.pos;
613 MIDI_IN_LOCK(sc,s);
614 MIDI_BUF_PRODUCER_INIT(mb,idx);
615 MIDI_BUF_PRODUCER_INIT(mb,buf);
616 if (count > buf_lim - buf_cur
617 || 1 > idx_lim - idx_cur) {
618 sc->rcv.bytesDiscarded.ev_count += count;
619 MIDI_IN_UNLOCK(sc,s);
620 DPRINTF(("midi_in: buffer full, discard data=0x%02x\n",
621 sc->rcv.pos[0]));
622 return;
623 }
624 for (i = 0; i < count; i++) {
625 *buf_cur++ = sc->rcv.pos[i];
626 MIDI_BUF_WRAP(buf);
627 }
628 *idx_cur++ = PACK_MB_IDX(got,count);
629 MIDI_BUF_WRAP(idx);
630 MIDI_BUF_PRODUCER_WBACK(mb,buf);
631 MIDI_BUF_PRODUCER_WBACK(mb,idx);
632 midi_wakeup(&sc->rchan);
633 selnotify(&sc->rsel, 0);
634 if (sc->async)
635 psignal(sc->async, SIGIO);
636 MIDI_IN_UNLOCK(sc,s);
637 break;
638 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
639 default:
640 printf("midi_in: midi_fst returned %d?!\n", got);
641 #endif
642 }
643 }
644
645 void
646 midi_out(void *addr)
647 {
648 struct midi_softc *sc = addr;
649
650 if (!sc->isopen)
651 return;
652 DPRINTFN(8, ("midi_out: %p\n", sc));
653 midi_intr_out(sc);
654 }
655
656 int
657 midiopen(dev_t dev, int flags, int ifmt, struct proc *p)
658 {
659 struct midi_softc *sc;
660 struct midi_hw_if *hw;
661 int error;
662
663 sc = device_lookup(&midi_cd, MIDIUNIT(dev));
664 if (sc == NULL)
665 return (ENXIO);
666 if (sc->dying)
667 return (EIO);
668
669 DPRINTFN(3,("midiopen %p\n", sc));
670
671 hw = sc->hw_if;
672 if (!hw)
673 return ENXIO;
674 if (sc->isopen)
675 return EBUSY;
676
677 /* put both state machines into known states */
678 sc->rcv.state = MIDI_IN_START;
679 sc->rcv.pos = sc->rcv.msg;
680 sc->rcv.end = sc->rcv.msg;
681 sc->xmt.state = MIDI_IN_START;
682 sc->xmt.pos = sc->xmt.msg;
683 sc->xmt.end = sc->xmt.msg;
684
685 /* and the buffers */
686 midi_initbuf(&sc->outbuf);
687 midi_initbuf(&sc->inbuf);
688
689 error = hw->open(sc->hw_hdl, flags, midi_in, midi_out, sc);
690 if (error)
691 return error;
692 sc->isopen++;
693 sc->flags = flags;
694 sc->rchan = 0;
695 sc->wchan = 0;
696 sc->pbus = 0;
697 sc->async = 0;
698
699 #ifdef MIDI_SAVE
700 if (midicnt != 0) {
701 midisave.cnt = midicnt;
702 midicnt = 0;
703 }
704 #endif
705
706 return 0;
707 }
708
709 int
710 midiclose(dev_t dev, int flags, int ifmt, struct proc *p)
711 {
712 int unit = MIDIUNIT(dev);
713 struct midi_softc *sc = midi_cd.cd_devs[unit];
714 struct midi_hw_if *hw = sc->hw_if;
715 int s, error;
716
717 DPRINTFN(3,("midiclose %p\n", sc));
718
719 /* midi_start_output(sc); anything buffered => pbus already set! */
720 error = 0;
721 MIDI_OUT_LOCK(sc,s);
722 while (sc->pbus) {
723 DPRINTFN(8,("midiclose sleep ...\n"));
724 error =
725 midi_sleep_timo(&sc->wchan, "mid_dr", 30*hz, &sc->out_lock);
726 }
727 MIDI_OUT_UNLOCK(sc,s);
728 callout_stop(&sc->sc_callout); /* xxx fix this - sleep? */
729 sc->isopen = 0;
730 hw->close(sc->hw_hdl);
731 #if NSEQUENCER > 0
732 sc->seqopen = 0;
733 sc->seq_md = 0;
734 #endif
735 return 0;
736 }
737
738 int
739 midiread(dev_t dev, struct uio *uio, int ioflag)
740 {
741 int unit = MIDIUNIT(dev);
742 struct midi_softc *sc = midi_cd.cd_devs[unit];
743 struct midi_buffer *mb = &sc->inbuf;
744 int error;
745 int s;
746 MIDI_BUF_DECLARE(idx);
747 MIDI_BUF_DECLARE(buf);
748 int appetite;
749 int first = 1;
750
751 DPRINTFN(6,("midiread: %p, count=%lu\n", sc,
752 (unsigned long)uio->uio_resid));
753
754 if (sc->dying)
755 return EIO;
756 if ( !(sc->props & MIDI_PROP_CAN_INPUT) )
757 return ENXIO;
758
759 MIDI_IN_LOCK(sc,s);
760 MIDI_BUF_CONSUMER_INIT(mb,idx);
761 MIDI_BUF_CONSUMER_INIT(mb,buf);
762 MIDI_IN_UNLOCK(sc,s);
763
764 error = 0;
765 for ( ;; ) {
766 /*
767 * If the used portion of idx wraps around the end, just take
768 * the first part on this iteration, and we'll get the rest on
769 * the next.
770 */
771 if ( idx_lim > idx_end )
772 idx_lim = idx_end;
773 /*
774 * Count bytes through the last complete message that will
775 * fit in the requested read.
776 */
777 for (appetite = uio->uio_resid; idx_cur < idx_lim; ++idx_cur) {
778 if ( appetite < MB_IDX_LEN(*idx_cur) )
779 break;
780 appetite -= MB_IDX_LEN(*idx_cur);
781 }
782 appetite = uio->uio_resid - appetite;
783 /*
784 * Only if the read is too small to hold even the first
785 * complete message will we return a partial one (updating idx
786 * to reflect the remaining length of the message).
787 */
788 if ( appetite == 0 && idx_cur < idx_lim ) {
789 if ( !first )
790 goto unlocked_exit; /* idx_cur not advanced */
791 appetite = uio->uio_resid;
792 *idx_cur = PACK_MB_IDX(MB_IDX_CAT(*idx_cur),
793 MB_IDX_LEN(*idx_cur) - appetite);
794 }
795 KASSERT(buf_cur + appetite <= buf_lim);
796
797 /* move the bytes */
798 if ( appetite > 0 ) {
799 first = 0; /* we know we won't return empty-handed */
800 /* do two uiomoves if data wrap around end of buf */
801 if ( buf_cur + appetite > buf_end ) {
802 DPRINTFN(8,
803 ("midiread: uiomove cc=%d (prewrap)\n",
804 buf_end - buf_cur));
805 error = uiomove(buf_cur, buf_end-buf_cur, uio);
806 if ( error )
807 goto unlocked_exit;
808 appetite -= buf_end - buf_cur;
809 buf_cur = mb->buf;
810 }
811 DPRINTFN(8, ("midiread: uiomove cc=%d\n", appetite));
812 error = uiomove(buf_cur, appetite, uio);
813 if ( error )
814 goto unlocked_exit;
815 buf_cur += appetite;
816 }
817
818 MIDI_BUF_WRAP(idx);
819 MIDI_BUF_WRAP(buf);
820
821 MIDI_IN_LOCK(sc,s);
822 MIDI_BUF_CONSUMER_WBACK(mb,idx);
823 MIDI_BUF_CONSUMER_WBACK(mb,buf);
824 if ( 0 == uio->uio_resid ) /* if read satisfied, we're done */
825 break;
826 MIDI_BUF_CONSUMER_REFRESH(mb,idx);
827 if ( idx_cur == idx_lim ) { /* need to wait for data? */
828 if ( !first ) /* never block reader if */
829 break; /* any data already in hand */
830 if (ioflag & IO_NDELAY) {
831 error = EWOULDBLOCK;
832 break;
833 }
834 error = midi_sleep(&sc->rchan, "mid rd", &sc->in_lock);
835 if ( error )
836 break;
837 MIDI_BUF_CONSUMER_REFRESH(mb,idx); /* what'd we get? */
838 }
839 MIDI_BUF_CONSUMER_REFRESH(mb,buf);
840 MIDI_IN_UNLOCK(sc,s);
841 if ( sc->dying )
842 return EIO;
843 }
844 MIDI_IN_UNLOCK(sc,s);
845
846 unlocked_exit:
847 return error;
848 }
849
850 void
851 midi_timeout(void *arg)
852 {
853 struct midi_softc *sc = arg;
854 int s;
855 int error;
856 int armed;
857
858 MIDI_OUT_LOCK(sc,s);
859 if ( sc->pbus ) {
860 MIDI_OUT_UNLOCK(sc,s);
861 return;
862 }
863 sc->pbus = 1;
864 DPRINTFN(8,("midi_timeout: %p\n", sc));
865
866 if ( sc->props & MIDI_PROP_OUT_INTR ) {
867 error = sc->hw_if->output(sc->hw_hdl, MIDI_ACK);
868 armed = (error == 0);
869 } else { /* polled output, do with interrupts unmasked */
870 MIDI_OUT_UNLOCK(sc,s);
871 error = sc->hw_if->output(sc->hw_hdl, MIDI_ACK);
872 MIDI_OUT_LOCK(sc,s);
873 armed = 0;
874 }
875
876 if ( !armed ) {
877 sc->pbus = 0;
878 callout_schedule(&sc->sc_callout, mstohz(275));
879 }
880
881 MIDI_OUT_UNLOCK(sc,s);
882 }
883
884 /*
885 * The way this function was hacked up to plug into poll_out and intr_out
886 * after they were written won't win it any beauty contests, but it'll work
887 * (code in haste, refactor at leisure). This may be called with the lock
888 * (by intr_out) or without the lock (by poll_out) so it only does what could
889 * be safe either way.
890 */
891 int midi_msg_out(struct midi_softc *sc,
892 u_char **idx, u_char **idxl, u_char **buf, u_char **bufl) {
893 MIDI_BUF_DECLARE(idx);
894 MIDI_BUF_DECLARE(buf);
895 MIDI_BUF_EXTENT_INIT(&sc->outbuf,idx);
896 MIDI_BUF_EXTENT_INIT(&sc->outbuf,buf);
897 int length;
898 int error;
899 u_char contig[3];
900 u_char *cp = contig;
901
902 idx_cur = *idx;
903 idx_lim = *idxl;
904 buf_cur = *buf;
905 buf_lim = *bufl;
906
907 length = MB_IDX_LEN(*idx_cur);
908
909 while ( length --> 0 ) {
910 *cp++ = *buf_cur++;
911 MIDI_BUF_WRAP(buf);
912 }
913
914 switch ( MB_IDX_CAT(*idx_cur) ) {
915 case FST_CHN:
916 error = sc->hw_if_ext->channel(sc->hw_hdl,
917 MIDI_GET_STATUS(contig[0]),
918 MIDI_GET_CHAN(contig[0]),
919 contig, cp - contig);
920 break;
921 case FST_COM:
922 error = sc->hw_if_ext->common(sc->hw_hdl,
923 MIDI_GET_STATUS(contig[0]),
924 contig, cp - contig);
925 break;
926 case FST_SYX:
927 error = sc->hw_if_ext->sysex(sc->hw_hdl,
928 contig, cp - contig);
929 break;
930 case FST_RT:
931 error = sc->hw_if->output(sc->hw_hdl, **buf);
932 break;
933 default:
934 error = EIO;
935 }
936
937 if ( !error ) {
938 ++ idx_cur;
939 MIDI_BUF_WRAP(idx);
940 *idx = idx_cur;
941 *idxl = idx_lim;
942 *buf = buf_cur;
943 *bufl = buf_lim;
944 }
945
946 return error;
947 }
948
949 /*
950 * midi_poll_out is intended for the midi hw (the vast majority of MIDI UARTs
951 * on sound cards, apparently) that _do not have transmit-ready interrupts_.
952 * Every call to hw_if->output for one of these may busy-wait to output the
953 * byte; at the standard midi data rate that'll be 320us per byte. The
954 * technique of writing only MIDI_MAX_WRITE bytes in a row and then waiting
955 * for MIDI_WAIT does not reduce the total time spent busy-waiting, and it
956 * adds arbitrary delays in transmission (and, since MIDI_WAIT is roughly the
957 * same as the time to send MIDI_MAX_WRITE bytes, it effectively halves the
958 * data rate). Here, a somewhat bolder approach is taken. Since midi traffic
959 * is bursty but time-sensitive--most of the time there will be none at all,
960 * but when there is it should go out ASAP--the strategy is to just get it
961 * over with, and empty the buffer in one go. The effect this can have on
962 * the rest of the system will be limited by the size of the buffer and the
963 * sparseness of the traffic. But some precautions are in order. Interrupts
964 * should all be unmasked when this is called, and midiwrite should not fill
965 * the buffer more than once (when MIDI_PROP_CAN_INTR is false) without a
966 * yield() so some other process can get scheduled. If the write is nonblocking,
967 * midiwrite should return a short count rather than yield.
968 *
969 * Someday when there is fine-grained MP support, this should be reworked to
970 * run in a callout so the writing process really could proceed concurrently.
971 * But obviously where performance is a concern, interrupt-driven hardware
972 * such as USB midi or (apparently) clcs will always be preferable.
973 */
974 int
975 midi_poll_out(struct midi_softc *sc)
976 {
977 struct midi_buffer *mb = &sc->outbuf;
978 int error;
979 int msglen;
980 int s;
981 MIDI_BUF_DECLARE(idx);
982 MIDI_BUF_DECLARE(buf);
983
984 error = 0;
985
986 MIDI_OUT_LOCK(sc,s);
987 MIDI_BUF_CONSUMER_INIT(mb,idx);
988 MIDI_BUF_CONSUMER_INIT(mb,buf);
989 MIDI_OUT_UNLOCK(sc,s);
990
991 for ( ;; ) {
992 while ( idx_cur != idx_lim ) {
993 if ( sc->hw_if_ext ) {
994 error = midi_msg_out(sc, &idx_cur, &idx_lim,
995 &buf_cur, &buf_lim);
996 if ( error )
997 goto ioerror;
998 continue;
999 }
1000 /* or, lacking hw_if_ext ... */
1001 msglen = MB_IDX_LEN(*idx_cur);
1002 error = sc->hw_if->output(sc->hw_hdl, *buf_cur);
1003 if ( error )
1004 goto ioerror;
1005 ++ buf_cur;
1006 MIDI_BUF_WRAP(buf);
1007 -- msglen;
1008 if ( msglen )
1009 *idx_cur = PACK_MB_IDX(MB_IDX_CAT(*idx_cur),
1010 msglen);
1011 else {
1012 ++ idx_cur;
1013 MIDI_BUF_WRAP(idx);
1014 }
1015 }
1016 KASSERT(buf_cur == buf_lim);
1017 MIDI_OUT_LOCK(sc,s);
1018 MIDI_BUF_CONSUMER_WBACK(mb,idx);
1019 MIDI_BUF_CONSUMER_WBACK(mb,buf);
1020 MIDI_BUF_CONSUMER_REFRESH(mb,idx); /* any more to transmit? */
1021 MIDI_BUF_CONSUMER_REFRESH(mb,buf);
1022 if ( idx_lim == idx_cur )
1023 break; /* still holding lock */
1024 MIDI_OUT_UNLOCK(sc,s);
1025 }
1026 goto disarm; /* lock held */
1027
1028 ioerror:
1029 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
1030 printf("%s: midi_poll_output error %d\n",
1031 sc->dev.dv_xname, error);
1032 #endif
1033 MIDI_OUT_LOCK(sc,s);
1034 MIDI_BUF_CONSUMER_WBACK(mb,idx);
1035 MIDI_BUF_CONSUMER_WBACK(mb,buf);
1036
1037 disarm:
1038 sc->pbus = 0;
1039 callout_schedule(&sc->sc_callout, mstohz(275));
1040 MIDI_OUT_UNLOCK(sc,s);
1041 return error;
1042 }
1043
1044 /*
1045 * The interrupt flavor acquires spl and lock once and releases at the end,
1046 * as it expects to write only one byte or message. The interface convention
1047 * is that if hw_if->output returns 0, it has initiated transmission and the
1048 * completion interrupt WILL be forthcoming; if it has not returned 0, NO
1049 * interrupt will be forthcoming, and if it returns EINPROGRESS it wants
1050 * another byte right away.
1051 */
1052 int
1053 midi_intr_out(struct midi_softc *sc)
1054 {
1055 struct midi_buffer *mb = &sc->outbuf;
1056 int error;
1057 int msglen;
1058 int s;
1059 MIDI_BUF_DECLARE(idx);
1060 MIDI_BUF_DECLARE(buf);
1061 int armed = 0;
1062
1063 error = 0;
1064
1065 MIDI_OUT_LOCK(sc,s);
1066 MIDI_BUF_CONSUMER_INIT(mb,idx);
1067 MIDI_BUF_CONSUMER_INIT(mb,buf);
1068
1069 while ( idx_cur != idx_lim ) {
1070 if ( sc->hw_if_ext ) {
1071 error = midi_msg_out(sc, &idx_cur, &idx_lim,
1072 &buf_cur, &buf_lim);
1073 if ( !error ) /* no EINPROGRESS from extended hw_if */
1074 armed = 1;
1075 break;
1076 }
1077 /* or, lacking hw_if_ext ... */
1078 msglen = MB_IDX_LEN(*idx_cur);
1079 error = sc->hw_if->output(sc->hw_hdl, *buf_cur);
1080 if ( error && error != EINPROGRESS )
1081 break;
1082 ++ buf_cur;
1083 MIDI_BUF_WRAP(buf);
1084 -- msglen;
1085 if ( msglen )
1086 *idx_cur = PACK_MB_IDX(MB_IDX_CAT(*idx_cur),msglen);
1087 else {
1088 ++ idx_cur;
1089 MIDI_BUF_WRAP(idx);
1090 }
1091 if ( !error ) {
1092 armed = 1;
1093 break;
1094 }
1095 }
1096 MIDI_BUF_CONSUMER_WBACK(mb,idx);
1097 MIDI_BUF_CONSUMER_WBACK(mb,buf);
1098 if ( !armed ) {
1099 sc->pbus = 0;
1100 callout_schedule(&sc->sc_callout, mstohz(275));
1101 }
1102 midi_wakeup(&sc->wchan);
1103 selnotify(&sc->wsel, 0);
1104 if ( sc->async )
1105 psignal(sc->async, SIGIO);
1106 MIDI_OUT_UNLOCK(sc,s);
1107
1108 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
1109 if ( error )
1110 printf("%s: midi_intr_output error %d\n",
1111 sc->dev.dv_xname, error);
1112 #endif
1113 return error;
1114 }
1115
1116 int
1117 midi_start_output(struct midi_softc *sc)
1118 {
1119 if (sc->dying)
1120 return EIO;
1121
1122 if ( sc->props & MIDI_PROP_OUT_INTR )
1123 return midi_intr_out(sc);
1124 return midi_poll_out(sc);
1125 }
1126
1127 static int
1128 real_writebytes(struct midi_softc *sc, u_char *buf, int cc)
1129 {
1130 u_char *bufe = buf + cc;
1131 struct midi_buffer *mb = &sc->outbuf;
1132 int arming = 0;
1133 int count;
1134 int s;
1135 int got;
1136 MIDI_BUF_DECLARE(idx);
1137 MIDI_BUF_DECLARE(buf);
1138
1139 MIDI_OUT_LOCK(sc,s);
1140 MIDI_BUF_PRODUCER_INIT(mb,idx);
1141 MIDI_BUF_PRODUCER_INIT(mb,buf);
1142 MIDI_OUT_UNLOCK(sc,s);
1143
1144 if (sc->dying)
1145 return EIO;
1146
1147 while ( buf < bufe ) {
1148 do
1149 got = midi_fst(&sc->xmt, *buf, 0);
1150 while ( got == FST_HUH );
1151 ++ buf;
1152 switch ( got ) {
1153 case FST_MORE:
1154 continue;
1155 case FST_ERR:
1156 #if defined(EPROTO) /* most appropriate SUSv3 errno, but not in errno.h yet */
1157 return EPROTO;
1158 #else
1159 return EIO;
1160 #endif
1161 case FST_CHN:
1162 case FST_COM:
1163 case FST_RT:
1164 case FST_SYX:
1165 break; /* go add to buffer */
1166 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
1167 default:
1168 printf("midi_wr: midi_fst returned %d?!\n", got);
1169 #endif
1170 }
1171 count = sc->xmt.end - sc->xmt.pos;
1172 /*
1173 * return EWOULDBLOCK if the data passed will not fit in
1174 * the buffer; the caller should have taken steps to avoid that.
1175 */
1176 if ( idx_cur == idx_lim || count > buf_lim - buf_cur ) {
1177 MIDI_OUT_LOCK(sc,s);
1178 MIDI_BUF_PRODUCER_REFRESH(mb,idx); /* get the most */
1179 MIDI_BUF_PRODUCER_REFRESH(mb,buf); /* current facts */
1180 MIDI_OUT_UNLOCK(sc,s);
1181 if ( idx_cur == idx_lim || count > buf_lim - buf_cur )
1182 return EWOULDBLOCK; /* caller's problem */
1183 }
1184 *idx_cur++ = PACK_MB_IDX(got,count);
1185 MIDI_BUF_WRAP(idx);
1186 while ( count ) {
1187 *buf_cur++ = *(sc->xmt.pos)++;
1188 MIDI_BUF_WRAP(buf);
1189 -- count;
1190 }
1191 }
1192 MIDI_OUT_LOCK(sc,s);
1193 MIDI_BUF_PRODUCER_WBACK(mb,buf);
1194 MIDI_BUF_PRODUCER_WBACK(mb,idx);
1195 /*
1196 * If the output transfer is not already busy, and there is a message
1197 * buffered, mark it busy, stop the Active Sense callout (what if we're
1198 * too late and it's expired already? No big deal, an extra Active Sense
1199 * never hurt anybody) and start the output transfer once we're out of
1200 * the critical section (pbus==1 will stop anyone else doing the same).
1201 */
1202 if ( !sc->pbus && idx_cur < MIDI_BUF_PRODUCER_REFRESH(mb,idx) ) {
1203 sc->pbus = 1;
1204 callout_stop(&sc->sc_callout);
1205 arming = 1;
1206 }
1207 MIDI_OUT_UNLOCK(sc,s);
1208 return arming ? midi_start_output(sc) : 0;
1209 }
1210
1211 int
1212 midiwrite(dev_t dev, struct uio *uio, int ioflag)
1213 {
1214 int unit = MIDIUNIT(dev);
1215 struct midi_softc *sc = midi_cd.cd_devs[unit];
1216 struct midi_buffer *mb = &sc->outbuf;
1217 int error;
1218 u_char inp[256];
1219 int s;
1220 MIDI_BUF_DECLARE(idx);
1221 MIDI_BUF_DECLARE(buf);
1222 size_t idxspace;
1223 size_t bufspace;
1224 size_t xfrcount;
1225 int pollout = 0;
1226
1227 DPRINTFN(6, ("midiwrite: %p, unit=%d, count=%lu\n", sc, unit,
1228 (unsigned long)uio->uio_resid));
1229
1230 if (sc->dying)
1231 return EIO;
1232
1233 error = 0;
1234 while (uio->uio_resid > 0 && !error) {
1235
1236 /*
1237 * block if necessary for the minimum buffer space to guarantee
1238 * we can write something.
1239 */
1240 MIDI_OUT_LOCK(sc,s);
1241 MIDI_BUF_PRODUCER_INIT(mb,idx); /* init can't go above loop; */
1242 MIDI_BUF_PRODUCER_INIT(mb,buf); /* real_writebytes moves cur */
1243 for ( ;; ) {
1244 idxspace = MIDI_BUF_PRODUCER_REFRESH(mb,idx) - idx_cur;
1245 bufspace = MIDI_BUF_PRODUCER_REFRESH(mb,buf) - buf_cur;
1246 if ( idxspace >= 1 && bufspace >= 3 && !pollout )
1247 break;
1248 DPRINTFN(8,("midi_write: sleep idx=%d buf=%d\n",
1249 idxspace, bufspace));
1250 if (ioflag & IO_NDELAY) {
1251 error = EWOULDBLOCK;
1252 /*
1253 * If some amount has already been transferred,
1254 * the common syscall code will automagically
1255 * convert this to success with a short count.
1256 */
1257 goto locked_exit;
1258 }
1259 if ( pollout ) {
1260 preempt(0); /* see midi_poll_output */
1261 pollout = 0;
1262 } else
1263 error = midi_sleep(&sc->wchan, "mid wr",
1264 &sc->out_lock);
1265 if (error)
1266 /*
1267 * Similarly, the common code will handle
1268 * EINTR and ERESTART properly here, changing to
1269 * a short count if something transferred.
1270 */
1271 goto locked_exit;
1272 }
1273 MIDI_OUT_UNLOCK(sc,s);
1274
1275 /*
1276 * The number of bytes we can safely extract from the uio
1277 * depends on the available idx and buf space. Worst case,
1278 * every byte is a message so 1 idx is required per byte.
1279 * Worst case, the first byte completes a 3-byte msg in prior
1280 * state, and every subsequent byte is a Program Change or
1281 * Channel Pressure msg with running status and expands to 2
1282 * bytes, so the buf space reqd is 3+2(n-1) or 2n+1. So limit
1283 * the transfer to the min of idxspace and (bufspace-1)>>1.
1284 */
1285 xfrcount = (bufspace - 1) >> 1;
1286 if ( xfrcount > idxspace )
1287 xfrcount = idxspace;
1288 if ( xfrcount > sizeof inp )
1289 xfrcount = sizeof inp;
1290 if ( xfrcount > uio->uio_resid )
1291 xfrcount = uio->uio_resid;
1292
1293 error = uiomove(inp, xfrcount, uio);
1294 #ifdef MIDI_DEBUG
1295 if (error)
1296 printf("midi_write:(1) uiomove failed %d; "
1297 "xfrcount=%d inp=%p\n",
1298 error, xfrcount, inp);
1299 #endif
1300 if ( error )
1301 break;
1302
1303 /*
1304 * The number of bytes we extracted being calculated to
1305 * definitely fit in the buffer even with canonicalization,
1306 * there is no excuse for real_writebytes to return EWOULDBLOCK.
1307 */
1308 error = real_writebytes(sc, inp, xfrcount);
1309 KASSERT(error != EWOULDBLOCK);
1310
1311 if ( error )
1312 break;
1313 /*
1314 * If this is a polling device and we just sent a buffer, let's
1315 * not send another without giving some other process a chance.
1316 */
1317 if ( ! (sc->props & MIDI_PROP_OUT_INTR) )
1318 pollout = 1;
1319 DPRINTFN(8,("midiwrite: uio_resid now %u, props=%d\n",
1320 uio->uio_resid, sc->props));
1321 }
1322 return error;
1323
1324 locked_exit:
1325 MIDI_OUT_UNLOCK(sc,s);
1326 return error;
1327 }
1328
1329 /*
1330 * This write routine is only called from sequencer code and expects
1331 * a write that is smaller than the MIDI buffer.
1332 */
1333 int
1334 midi_writebytes(int unit, u_char *buf, int cc)
1335 {
1336 struct midi_softc *sc = midi_cd.cd_devs[unit];
1337
1338 DPRINTFN(7, ("midi_writebytes: %p, unit=%d, cc=%d %#02x %#02x %#02x\n",
1339 sc, unit, cc, buf[0], buf[1], buf[2]));
1340 return real_writebytes(sc, buf, cc);
1341 }
1342
1343 int
1344 midiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
1345 {
1346 int unit = MIDIUNIT(dev);
1347 struct midi_softc *sc = midi_cd.cd_devs[unit];
1348 struct midi_hw_if *hw = sc->hw_if;
1349 int error;
1350 int s;
1351 MIDI_BUF_DECLARE(buf);
1352
1353 DPRINTFN(5,("midiioctl: %p cmd=0x%08lx\n", sc, cmd));
1354
1355 if (sc->dying)
1356 return EIO;
1357
1358 error = 0;
1359 switch (cmd) {
1360 case FIONBIO:
1361 /* All handled in the upper FS layer. */
1362 break;
1363
1364 case FIONREAD:
1365 /*
1366 * This code relies on the current implementation of midi_in
1367 * always updating buf and idx together in a critical section,
1368 * so buf always ends at a message boundary. Document this
1369 * ioctl as always returning a value such that the last message
1370 * included is complete (SysEx the only exception), and then
1371 * make sure the implementation doesn't regress. NB that
1372 * means if this ioctl returns n and the proc then issues a
1373 * read of n, n bytes will be read, but if the proc issues a
1374 * read of m < n, fewer than m bytes may be read to ensure the
1375 * read ends at a message boundary.
1376 */
1377 MIDI_IN_LOCK(sc,s);
1378 MIDI_BUF_CONSUMER_INIT(&sc->inbuf,buf);
1379 MIDI_IN_UNLOCK(sc,s);
1380 *(int *)addr = buf_lim - buf_cur;
1381 break;
1382
1383 case FIOASYNC:
1384 if (*(int *)addr) {
1385 if (sc->async)
1386 return EBUSY;
1387 sc->async = p;
1388 DPRINTFN(5,("midi_ioctl: FIOASYNC %p\n", p));
1389 } else
1390 sc->async = 0;
1391 break;
1392
1393 #if 0
1394 case MIDI_PRETIME:
1395 /* XXX OSS
1396 * This should set up a read timeout, but that's
1397 * why we have poll(), so there's nothing yet. */
1398 error = EINVAL;
1399 break;
1400 #endif
1401
1402 #ifdef MIDI_SAVE
1403 case MIDI_GETSAVE:
1404 error = copyout(&midisave, *(void **)addr, sizeof midisave);
1405 break;
1406 #endif
1407
1408 default:
1409 if (hw->ioctl)
1410 error = hw->ioctl(sc->hw_hdl, cmd, addr, flag, p);
1411 else
1412 error = EINVAL;
1413 break;
1414 }
1415 return error;
1416 }
1417
1418 int
1419 midipoll(dev_t dev, int events, struct proc *p)
1420 {
1421 int unit = MIDIUNIT(dev);
1422 struct midi_softc *sc = midi_cd.cd_devs[unit];
1423 int revents = 0;
1424 int s;
1425 MIDI_BUF_DECLARE(idx);
1426 MIDI_BUF_DECLARE(buf);
1427
1428 DPRINTFN(6,("midipoll: %p events=0x%x\n", sc, events));
1429
1430 if (sc->dying)
1431 return EIO;
1432
1433 s = splaudio();
1434
1435 if ((sc->flags&FREAD) && (events & (POLLIN | POLLRDNORM))) {
1436 simple_lock(&sc->in_lock);
1437 MIDI_BUF_CONSUMER_INIT(&sc->inbuf,idx);
1438 if (idx_cur < idx_lim)
1439 revents |= events & (POLLIN | POLLRDNORM);
1440 else
1441 selrecord(p, &sc->rsel);
1442 simple_unlock(&sc->in_lock);
1443 }
1444
1445 if ((sc->flags&FWRITE) && (events & (POLLOUT | POLLWRNORM))) {
1446 simple_lock(&sc->out_lock);
1447 MIDI_BUF_PRODUCER_INIT(&sc->outbuf,idx);
1448 MIDI_BUF_PRODUCER_INIT(&sc->outbuf,buf);
1449 if ( idx_lim - idx_cur >= 1 && buf_lim - buf_cur >= 3 )
1450 revents |= events & (POLLOUT | POLLWRNORM);
1451 else
1452 selrecord(p, &sc->wsel);
1453 simple_unlock(&sc->out_lock);
1454 }
1455
1456 splx(s);
1457 return revents;
1458 }
1459
1460 static void
1461 filt_midirdetach(struct knote *kn)
1462 {
1463 struct midi_softc *sc = kn->kn_hook;
1464 int s;
1465
1466 s = splaudio();
1467 SLIST_REMOVE(&sc->rsel.sel_klist, kn, knote, kn_selnext);
1468 splx(s);
1469 }
1470
1471 static int
1472 filt_midiread(struct knote *kn, long hint)
1473 {
1474 struct midi_softc *sc = kn->kn_hook;
1475 int s;
1476 MIDI_BUF_DECLARE(buf);
1477
1478 /* XXXLUKEM (thorpej): please make sure this is correct. */
1479
1480 MIDI_IN_LOCK(sc,s);
1481 MIDI_BUF_CONSUMER_INIT(&sc->inbuf,buf);
1482 kn->kn_data = buf_lim - buf_cur;
1483 MIDI_IN_UNLOCK(sc,s);
1484 return (kn->kn_data > 0);
1485 }
1486
1487 static const struct filterops midiread_filtops =
1488 { 1, NULL, filt_midirdetach, filt_midiread };
1489
1490 static void
1491 filt_midiwdetach(struct knote *kn)
1492 {
1493 struct midi_softc *sc = kn->kn_hook;
1494 int s;
1495
1496 s = splaudio();
1497 SLIST_REMOVE(&sc->wsel.sel_klist, kn, knote, kn_selnext);
1498 splx(s);
1499 }
1500
1501 static int
1502 filt_midiwrite(struct knote *kn, long hint)
1503 {
1504 struct midi_softc *sc = kn->kn_hook;
1505 int s;
1506 MIDI_BUF_DECLARE(idx);
1507 MIDI_BUF_DECLARE(buf);
1508
1509 /* XXXLUKEM (thorpej): please make sure this is correct. */
1510
1511 MIDI_OUT_LOCK(sc,s);
1512 MIDI_BUF_PRODUCER_INIT(&sc->outbuf,idx);
1513 MIDI_BUF_PRODUCER_INIT(&sc->outbuf,buf);
1514 kn->kn_data = ((buf_lim - buf_cur)-1)>>1;
1515 if ( kn->kn_data > idx_lim - idx_cur )
1516 kn->kn_data = idx_lim - idx_cur;
1517 MIDI_OUT_UNLOCK(sc,s);
1518 return (kn->kn_data > 0);
1519 }
1520
1521 static const struct filterops midiwrite_filtops =
1522 { 1, NULL, filt_midiwdetach, filt_midiwrite };
1523
1524 int
1525 midikqfilter(dev_t dev, struct knote *kn)
1526 {
1527 int unit = MIDIUNIT(dev);
1528 struct midi_softc *sc = midi_cd.cd_devs[unit];
1529 struct klist *klist;
1530 int s;
1531
1532 switch (kn->kn_filter) {
1533 case EVFILT_READ:
1534 klist = &sc->rsel.sel_klist;
1535 kn->kn_fop = &midiread_filtops;
1536 break;
1537
1538 case EVFILT_WRITE:
1539 klist = &sc->wsel.sel_klist;
1540 kn->kn_fop = &midiwrite_filtops;
1541 break;
1542
1543 default:
1544 return (1);
1545 }
1546
1547 kn->kn_hook = sc;
1548
1549 s = splaudio();
1550 SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1551 splx(s);
1552
1553 return (0);
1554 }
1555
1556 void
1557 midi_getinfo(dev_t dev, struct midi_info *mi)
1558 {
1559 struct midi_softc *sc;
1560
1561 sc = device_lookup(&midi_cd, MIDIUNIT(dev));
1562 if (sc == NULL)
1563 return;
1564 if (sc->dying)
1565 return;
1566
1567 sc->hw_if->getinfo(sc->hw_hdl, mi);
1568 }
1569
1570 #endif /* NMIDI > 0 */
1571
1572 #if NMIDI > 0 || NMIDIBUS > 0
1573
1574 int audioprint(void *, const char *);
1575
1576 struct device *
1577 midi_attach_mi(struct midi_hw_if *mhwp, void *hdlp, struct device *dev)
1578 {
1579 struct audio_attach_args arg;
1580
1581 #ifdef DIAGNOSTIC
1582 if (mhwp == NULL) {
1583 aprint_error("midi_attach_mi: NULL\n");
1584 return (0);
1585 }
1586 #endif
1587 arg.type = AUDIODEV_TYPE_MIDI;
1588 arg.hwif = mhwp;
1589 arg.hdl = hdlp;
1590 return (config_found(dev, &arg, audioprint));
1591 }
1592
1593 #endif /* NMIDI > 0 || NMIDIBUS > 0 */
1594