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