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