Annotation of sys/dev/sequencer.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: sequencer.c,v 1.13 2007/06/06 19:42:28 mk Exp $ */
! 2: /* $NetBSD: sequencer.c,v 1.13 1998/11/25 22:17:07 augustss Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1998 The NetBSD Foundation, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * This code is derived from software contributed to The NetBSD Foundation
! 9: * by Lennart Augustsson (augustss@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 "sequencer.h"
! 41: #if NSEQUENCER > 0
! 42:
! 43: #include <sys/param.h>
! 44: #include <sys/ioctl.h>
! 45: #include <sys/fcntl.h>
! 46: #include <sys/vnode.h>
! 47: #include <sys/selinfo.h>
! 48: #include <sys/poll.h>
! 49: #include <sys/malloc.h>
! 50: #include <sys/proc.h>
! 51: #include <sys/systm.h>
! 52: #include <sys/syslog.h>
! 53: #include <sys/kernel.h>
! 54: #include <sys/signalvar.h>
! 55: #include <sys/conf.h>
! 56: #include <sys/audioio.h>
! 57: #include <sys/midiio.h>
! 58: #include <sys/device.h>
! 59:
! 60: #include <dev/midi_if.h>
! 61: #include <dev/midivar.h>
! 62: #include <dev/sequencervar.h>
! 63:
! 64: #ifndef splaudio
! 65: #define splaudio() splbio() /* XXX found in audio_if.h normally */
! 66: #endif
! 67:
! 68: #define ADDTIMEVAL(a, b) ( \
! 69: (a)->tv_sec += (b)->tv_sec, \
! 70: (a)->tv_usec += (b)->tv_usec, \
! 71: (a)->tv_usec >= 1000000 ? ((a)->tv_sec++, (a)->tv_usec -= 1000000) : 0\
! 72: )
! 73:
! 74: #define SUBTIMEVAL(a, b) ( \
! 75: (a)->tv_sec -= (b)->tv_sec, \
! 76: (a)->tv_usec -= (b)->tv_usec, \
! 77: (a)->tv_usec < 0 ? ((a)->tv_sec--, (a)->tv_usec += 1000000) : 0\
! 78: )
! 79:
! 80: #ifdef AUDIO_DEBUG
! 81: #define DPRINTF(x) if (sequencerdebug) printf x
! 82: #define DPRINTFN(n,x) if (sequencerdebug >= (n)) printf x
! 83: int sequencerdebug = 0;
! 84: #else
! 85: #define DPRINTF(x)
! 86: #define DPRINTFN(n,x)
! 87: #endif
! 88:
! 89: #define SEQ_CMD(b) ((b)->arr[0])
! 90:
! 91: #define SEQ_EDEV(b) ((b)->arr[1])
! 92: #define SEQ_ECMD(b) ((b)->arr[2])
! 93: #define SEQ_ECHAN(b) ((b)->arr[3])
! 94: #define SEQ_ENOTE(b) ((b)->arr[4])
! 95: #define SEQ_EPARM(b) ((b)->arr[5])
! 96:
! 97: #define SEQ_EP1(b) ((b)->arr[4])
! 98: #define SEQ_EP2(b) ((b)->arr[5])
! 99:
! 100: #define SEQ_XCMD(b) ((b)->arr[1])
! 101: #define SEQ_XDEV(b) ((b)->arr[2])
! 102: #define SEQ_XCHAN(b) ((b)->arr[3])
! 103: #define SEQ_XNOTE(b) ((b)->arr[4])
! 104: #define SEQ_XVEL(b) ((b)->arr[5])
! 105:
! 106: #define SEQ_TCMD(b) ((b)->arr[1])
! 107: #define SEQ_TPARM(b) ((b)->arr[4])
! 108:
! 109: #define SEQ_NOTE_MAX 128
! 110: #define SEQ_NOTE_XXX 255
! 111: #define SEQ_VEL_OFF 0
! 112:
! 113: #define RECALC_TICK(t) ((t)->tick = 60 * 1000000L / ((t)->tempo * (t)->timebase))
! 114:
! 115: struct sequencer_softc seqdevs[NSEQUENCER];
! 116:
! 117: void sequencerattach(int);
! 118: void seq_reset(struct sequencer_softc *);
! 119: int seq_do_command(struct sequencer_softc *, seq_event_rec *);
! 120: int seq_do_extcommand(struct sequencer_softc *, seq_event_rec *);
! 121: int seq_do_chnvoice(struct sequencer_softc *, seq_event_rec *);
! 122: int seq_do_chncommon(struct sequencer_softc *, seq_event_rec *);
! 123: int seq_do_timing(struct sequencer_softc *, seq_event_rec *);
! 124: int seq_do_local(struct sequencer_softc *, seq_event_rec *);
! 125: int seq_do_sysex(struct sequencer_softc *, seq_event_rec *);
! 126: int seq_do_fullsize(struct sequencer_softc *, seq_event_rec *,
! 127: struct uio *);
! 128: int seq_timer(struct sequencer_softc *, int, int, seq_event_rec *);
! 129: static int seq_input_event(struct sequencer_softc *, seq_event_rec *);
! 130: int seq_drain(struct sequencer_softc *);
! 131: void seq_startoutput(struct sequencer_softc *);
! 132: void seq_timeout(void *);
! 133: int seq_to_new(seq_event_rec *, struct uio *);
! 134: static int seq_sleep_timo(int *, char *, int);
! 135: static int seq_sleep(int *, char *);
! 136: static void seq_wakeup(int *);
! 137:
! 138: struct midi_softc;
! 139: int midiseq_out(struct midi_dev *, u_char *, u_int, int);
! 140: struct midi_dev *midiseq_open(int, int);
! 141: void midiseq_close(struct midi_dev *);
! 142: void midiseq_reset(struct midi_dev *);
! 143: int midiseq_noteon(struct midi_dev *, int, int, int);
! 144: int midiseq_noteoff(struct midi_dev *, int, int, int);
! 145: int midiseq_keypressure(struct midi_dev *, int, int, int);
! 146: int midiseq_pgmchange(struct midi_dev *, int, int);
! 147: int midiseq_chnpressure(struct midi_dev *, int, int);
! 148: int midiseq_ctlchange(struct midi_dev *, int, int, int);
! 149: int midiseq_pitchbend(struct midi_dev *, int, int);
! 150: int midiseq_loadpatch(struct midi_dev *, struct sysex_info *,
! 151: struct uio *);
! 152: int midiseq_putc(struct midi_dev *, int);
! 153: void midiseq_in(struct midi_dev *, u_char *, int);
! 154:
! 155: void
! 156: sequencerattach(int n)
! 157: {
! 158: }
! 159:
! 160: int
! 161: sequenceropen(dev_t dev, int flags, int ifmt, struct proc *p)
! 162: {
! 163: int unit = SEQUENCERUNIT(dev);
! 164: struct sequencer_softc *sc;
! 165: struct midi_dev *md;
! 166: int nmidi;
! 167:
! 168: DPRINTF(("sequenceropen\n"));
! 169:
! 170: if (unit >= NSEQUENCER)
! 171: return (ENXIO);
! 172: sc = &seqdevs[unit];
! 173: if (sc->isopen)
! 174: return (EBUSY);
! 175: if (SEQ_IS_OLD(dev))
! 176: sc->mode = SEQ_OLD;
! 177: else
! 178: sc->mode = SEQ_NEW;
! 179: sc->isopen++;
! 180: sc->flags = flags & (FREAD|FWRITE);
! 181: sc->rchan = 0;
! 182: sc->wchan = 0;
! 183: sc->pbus = 0;
! 184: sc->async = 0;
! 185: sc->input_stamp = ~0;
! 186:
! 187: sc->nmidi = 0;
! 188: nmidi = midi_unit_count();
! 189:
! 190: sc->devs = malloc(nmidi * sizeof(struct midi_dev *),
! 191: M_DEVBUF, M_WAITOK);
! 192: for (unit = 0; unit < nmidi; unit++) {
! 193: md = midiseq_open(unit, flags);
! 194: if (md) {
! 195: sc->devs[sc->nmidi++] = md;
! 196: md->seq = sc;
! 197: }
! 198: }
! 199:
! 200: sc->timer.timebase = 100;
! 201: sc->timer.tempo = 60;
! 202: sc->doingsysex = 0;
! 203: RECALC_TICK(&sc->timer);
! 204: sc->timer.last = 0;
! 205: microtime(&sc->timer.start);
! 206:
! 207: SEQ_QINIT(&sc->inq);
! 208: SEQ_QINIT(&sc->outq);
! 209: sc->lowat = SEQ_MAXQ / 2;
! 210: timeout_set(&sc->timo, seq_timeout, sc);
! 211:
! 212: seq_reset(sc);
! 213:
! 214: DPRINTF(("sequenceropen: mode=%d, nmidi=%d\n", sc->mode, sc->nmidi));
! 215: return (0);
! 216: }
! 217:
! 218: static int
! 219: seq_sleep_timo(int *chan, char *label, int timo)
! 220: {
! 221: int st;
! 222:
! 223: if (!label)
! 224: label = "seq";
! 225:
! 226: DPRINTFN(5, ("seq_sleep_timo: %p %s %d\n", chan, label, timo));
! 227: *chan = 1;
! 228: st = tsleep(chan, PWAIT | PCATCH, label, timo);
! 229: *chan = 0;
! 230: #ifdef MIDI_DEBUG
! 231: if (st != 0)
! 232: printf("seq_sleep: %d\n", st);
! 233: #endif
! 234: return (st);
! 235: }
! 236:
! 237: static int
! 238: seq_sleep(int *chan, char *label)
! 239: {
! 240: return (seq_sleep_timo(chan, label, 0));
! 241: }
! 242:
! 243: static void
! 244: seq_wakeup(int *chan)
! 245: {
! 246: if (*chan) {
! 247: DPRINTFN(5, ("seq_wakeup: %p\n", chan));
! 248: wakeup(chan);
! 249: *chan = 0;
! 250: }
! 251: }
! 252:
! 253: int
! 254: seq_drain(struct sequencer_softc *sc)
! 255: {
! 256: int error;
! 257:
! 258: DPRINTFN(3, ("seq_drain: %p, len=%d\n", sc, SEQ_QLEN(&sc->outq)));
! 259: seq_startoutput(sc);
! 260: error = 0;
! 261: while(!SEQ_QEMPTY(&sc->outq) && !error)
! 262: error = seq_sleep_timo(&sc->wchan, "seq_dr", 60*hz);
! 263: return (error);
! 264: }
! 265:
! 266: void
! 267: seq_timeout(void *addr)
! 268: {
! 269: struct sequencer_softc *sc = addr;
! 270: DPRINTFN(4, ("seq_timeout: %p\n", sc));
! 271: sc->timeout = 0;
! 272: seq_startoutput(sc);
! 273: if (SEQ_QLEN(&sc->outq) < sc->lowat) {
! 274: seq_wakeup(&sc->wchan);
! 275: selwakeup(&sc->wsel);
! 276: if (sc->async)
! 277: psignal(sc->async, SIGIO);
! 278: }
! 279:
! 280: }
! 281:
! 282: void
! 283: seq_startoutput(struct sequencer_softc *sc)
! 284: {
! 285: struct sequencer_queue *q = &sc->outq;
! 286: seq_event_rec cmd;
! 287:
! 288: if (sc->timeout)
! 289: return;
! 290: DPRINTFN(4, ("seq_startoutput: %p, len=%d\n", sc, SEQ_QLEN(q)));
! 291: while(!SEQ_QEMPTY(q) && !sc->timeout) {
! 292: SEQ_QGET(q, cmd);
! 293: seq_do_command(sc, &cmd);
! 294: }
! 295: }
! 296:
! 297: int
! 298: sequencerclose(dev_t dev, int flags, int ifmt, struct proc *p)
! 299: {
! 300: struct sequencer_softc *sc = &seqdevs[SEQUENCERUNIT(dev)];
! 301: int n, s;
! 302:
! 303: DPRINTF(("sequencerclose: %p\n", sc));
! 304:
! 305: seq_drain(sc);
! 306: s = splaudio();
! 307: if (sc->timeout) {
! 308: timeout_del(&sc->timo);
! 309: sc->timeout = 0;
! 310: }
! 311: splx(s);
! 312:
! 313: for (n = 0; n < sc->nmidi; n++)
! 314: midiseq_close(sc->devs[n]);
! 315: free(sc->devs, M_DEVBUF);
! 316: sc->isopen = 0;
! 317: return (0);
! 318: }
! 319:
! 320: static int
! 321: seq_input_event(struct sequencer_softc *sc, seq_event_rec *cmd)
! 322: {
! 323: struct sequencer_queue *q = &sc->inq;
! 324:
! 325: DPRINTFN(2, ("seq_input_event: %02x %02x %02x %02x %02x %02x %02x %02x\n",
! 326: cmd->arr[0], cmd->arr[1], cmd->arr[2], cmd->arr[3],
! 327: cmd->arr[4], cmd->arr[5], cmd->arr[6], cmd->arr[7]));
! 328: if (SEQ_QFULL(q))
! 329: return (ENOMEM);
! 330: SEQ_QPUT(q, *cmd);
! 331: seq_wakeup(&sc->rchan);
! 332: selwakeup(&sc->rsel);
! 333: if (sc->async)
! 334: psignal(sc->async, SIGIO);
! 335: return (0);
! 336: }
! 337:
! 338: void
! 339: seq_event_intr(void *addr, seq_event_rec *iev)
! 340: {
! 341: struct sequencer_softc *sc = addr;
! 342: union {
! 343: u_int32_t l;
! 344: u_int8_t b[4];
! 345: } u;
! 346: u_long t;
! 347: struct timeval now;
! 348: seq_event_rec ev;
! 349:
! 350: microtime(&now);
! 351: SUBTIMEVAL(&now, &sc->timer.start);
! 352: t = now.tv_sec * 1000000 + now.tv_usec;
! 353: t /= sc->timer.tick;
! 354: if (t != sc->input_stamp) {
! 355: ev.arr[0] = SEQ_TIMING;
! 356: ev.arr[1] = TMR_WAIT_ABS;
! 357: ev.arr[2] = 0;
! 358: ev.arr[3] = 0;
! 359: u.l = t;
! 360: ev.arr[4] = u.b[0];
! 361: ev.arr[5] = u.b[1];
! 362: ev.arr[6] = u.b[2];
! 363: ev.arr[7] = u.b[3];
! 364: seq_input_event(sc, &ev);
! 365: sc->input_stamp = t;
! 366: }
! 367: seq_input_event(sc, iev);
! 368: }
! 369:
! 370: int
! 371: sequencerread(dev_t dev, struct uio *uio, int ioflag)
! 372: {
! 373: struct sequencer_softc *sc = &seqdevs[SEQUENCERUNIT(dev)];
! 374: struct sequencer_queue *q = &sc->inq;
! 375: seq_event_rec ev;
! 376: int error, s;
! 377:
! 378: DPRINTFN(20, ("sequencerread: %p, count=%d, ioflag=%x\n",
! 379: sc, uio->uio_resid, ioflag));
! 380:
! 381: if (sc->mode == SEQ_OLD) {
! 382: DPRINTFN(-1,("sequencerread: old read\n"));
! 383: return (EINVAL); /* XXX unimplemented */
! 384: }
! 385:
! 386: error = 0;
! 387: while (SEQ_QEMPTY(q)) {
! 388: if (ioflag & IO_NDELAY)
! 389: return (EWOULDBLOCK);
! 390: else {
! 391: error = seq_sleep(&sc->rchan, "seq rd");
! 392: if (error)
! 393: return (error);
! 394: }
! 395: }
! 396: s = splaudio();
! 397: while (uio->uio_resid >= sizeof ev && !error && !SEQ_QEMPTY(q)) {
! 398: SEQ_QGET(q, ev);
! 399: error = uiomove((caddr_t)&ev, sizeof ev, uio);
! 400: }
! 401: splx(s);
! 402: return (error);
! 403: }
! 404:
! 405: int
! 406: sequencerwrite(dev_t dev, struct uio *uio, int ioflag)
! 407: {
! 408: struct sequencer_softc *sc = &seqdevs[SEQUENCERUNIT(dev)];
! 409: struct sequencer_queue *q = &sc->outq;
! 410: int error;
! 411: seq_event_rec cmdbuf;
! 412: int size;
! 413:
! 414: DPRINTFN(2, ("sequencerwrite: %p, count=%d\n", sc, uio->uio_resid));
! 415:
! 416: error = 0;
! 417: size = sc->mode == SEQ_NEW ? sizeof cmdbuf : SEQOLD_CMDSIZE;
! 418: while (uio->uio_resid >= size) {
! 419: error = uiomove((caddr_t)&cmdbuf, size, uio);
! 420: if (error)
! 421: break;
! 422: if (sc->mode == SEQ_OLD)
! 423: if (seq_to_new(&cmdbuf, uio))
! 424: continue;
! 425: if (SEQ_CMD(&cmdbuf) == SEQ_FULLSIZE) {
! 426: /* We do it like OSS does, asynchronously */
! 427: error = seq_do_fullsize(sc, &cmdbuf, uio);
! 428: if (error)
! 429: break;
! 430: continue;
! 431: }
! 432: while (SEQ_QFULL(q)) {
! 433: seq_startoutput(sc);
! 434: if (SEQ_QFULL(q)) {
! 435: if (ioflag & IO_NDELAY)
! 436: return (EWOULDBLOCK);
! 437: error = seq_sleep(&sc->wchan, "seq_wr");
! 438: if (error)
! 439: return (error);
! 440: }
! 441: }
! 442: SEQ_QPUT(q, cmdbuf);
! 443: }
! 444: seq_startoutput(sc);
! 445:
! 446: #ifdef SEQUENCER_DEBUG
! 447: if (error)
! 448: DPRINTFN(2, ("sequencerwrite: error=%d\n", error));
! 449: #endif
! 450: return (error);
! 451: }
! 452:
! 453: int
! 454: sequencerioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
! 455: {
! 456: struct sequencer_softc *sc = &seqdevs[SEQUENCERUNIT(dev)];
! 457: struct synth_info *si;
! 458: struct midi_dev *md;
! 459: int devno;
! 460: int error;
! 461: int t;
! 462:
! 463: DPRINTFN(2, ("sequencerioctl: %p cmd=0x%08lx\n", sc, cmd));
! 464:
! 465: error = 0;
! 466: switch (cmd) {
! 467: case FIONBIO:
! 468: /* All handled in the upper FS layer. */
! 469: break;
! 470:
! 471: case FIOASYNC:
! 472: if (*(int *)addr) {
! 473: if (sc->async)
! 474: return (EBUSY);
! 475: sc->async = p;
! 476: DPRINTF(("sequencer_ioctl: FIOASYNC %p\n", p));
! 477: } else
! 478: sc->async = 0;
! 479: break;
! 480:
! 481: case SEQUENCER_RESET:
! 482: seq_reset(sc);
! 483: break;
! 484:
! 485: case SEQUENCER_PANIC:
! 486: seq_reset(sc);
! 487: /* Do more? OSS doesn't */
! 488: break;
! 489:
! 490: case SEQUENCER_SYNC:
! 491: if (sc->flags == FREAD)
! 492: return (0);
! 493: seq_drain(sc);
! 494: error = 0;
! 495: break;
! 496:
! 497: case SEQUENCER_INFO:
! 498: si = (struct synth_info*)addr;
! 499: devno = si->device;
! 500: if (devno < 0 || devno >= sc->nmidi)
! 501: return (EINVAL);
! 502: md = sc->devs[devno];
! 503: strncpy(si->name, md->name, sizeof si->name);
! 504: si->synth_type = SYNTH_TYPE_MIDI;
! 505: si->synth_subtype = md->subtype;
! 506: si->nr_voices = md->nr_voices;
! 507: si->instr_bank_size = md->instr_bank_size;
! 508: si->capabilities = md->capabilities;
! 509: break;
! 510:
! 511: case SEQUENCER_NRSYNTHS:
! 512: *(int *)addr = sc->nmidi;
! 513: break;
! 514:
! 515: case SEQUENCER_NRMIDIS:
! 516: *(int *)addr = sc->nmidi;
! 517: break;
! 518:
! 519: case SEQUENCER_OUTOFBAND:
! 520: DPRINTFN(3, ("sequencer_ioctl: OOB=%02x %02x %02x %02x %02x %02x %02x %02x\n",
! 521: *(u_char *)addr, *(u_char *)(addr+1),
! 522: *(u_char *)(addr+2), *(u_char *)(addr+3),
! 523: *(u_char *)(addr+4), *(u_char *)(addr+5),
! 524: *(u_char *)(addr+6), *(u_char *)(addr+7)));
! 525: error = seq_do_command(sc, (seq_event_rec *)addr);
! 526: break;
! 527:
! 528: case SEQUENCER_TMR_TIMEBASE:
! 529: t = *(int *)addr;
! 530: if (t < 1)
! 531: t = 1;
! 532: if (t > 1000)
! 533: t = 1000;
! 534: sc->timer.timebase = t;
! 535: *(int *)addr = t;
! 536: RECALC_TICK(&sc->timer);
! 537: break;
! 538:
! 539: case SEQUENCER_TMR_START:
! 540: error = seq_timer(sc, TMR_START, 0, 0);
! 541: break;
! 542:
! 543: case SEQUENCER_TMR_STOP:
! 544: error = seq_timer(sc, TMR_STOP, 0, 0);
! 545: break;
! 546:
! 547: case SEQUENCER_TMR_CONTINUE:
! 548: error = seq_timer(sc, TMR_CONTINUE, 0, 0);
! 549: break;
! 550:
! 551: case SEQUENCER_TMR_TEMPO:
! 552: t = *(int *)addr;
! 553: if (t < 8)
! 554: t = 8;
! 555: if (t > 250)
! 556: t = 250;
! 557: sc->timer.tempo = t;
! 558: *(int *)addr = t;
! 559: RECALC_TICK(&sc->timer);
! 560: break;
! 561:
! 562: case SEQUENCER_TMR_SOURCE:
! 563: *(int *)addr = SEQUENCER_TMR_INTERNAL;
! 564: break;
! 565:
! 566: case SEQUENCER_TMR_METRONOME:
! 567: /* noop */
! 568: break;
! 569:
! 570: case SEQUENCER_THRESHOLD:
! 571: t = SEQ_MAXQ - *(int *)addr / sizeof (seq_event_rec);
! 572: if (t < 1)
! 573: t = 1;
! 574: if (t > SEQ_MAXQ)
! 575: t = SEQ_MAXQ;
! 576: sc->lowat = t;
! 577: break;
! 578:
! 579: case SEQUENCER_CTRLRATE:
! 580: *(int *)addr = (sc->timer.tempo*sc->timer.timebase + 30) / 60;
! 581: break;
! 582:
! 583: case SEQUENCER_GETTIME:
! 584: {
! 585: struct timeval now;
! 586: u_long t;
! 587: microtime(&now);
! 588: SUBTIMEVAL(&now, &sc->timer.start);
! 589: t = now.tv_sec * 1000000 + now.tv_usec;
! 590: t /= sc->timer.tick;
! 591: *(int *)addr = t;
! 592: break;
! 593: }
! 594:
! 595: default:
! 596: DPRINTFN(-1,("sequencer_ioctl: unimpl %08lx\n", cmd));
! 597: error = ENOTTY;
! 598: break;
! 599: }
! 600: return (error);
! 601: }
! 602:
! 603: int
! 604: sequencerpoll(dev_t dev, int events, struct proc *p)
! 605: {
! 606: struct sequencer_softc *sc = &seqdevs[SEQUENCERUNIT(dev)];
! 607: int revents = 0;
! 608:
! 609: DPRINTF(("sequencerpoll: %p rw=0x%x\n", sc, events));
! 610:
! 611: if (events & (POLLIN | POLLRDNORM)) {
! 612: if (!SEQ_QEMPTY(&sc->inq))
! 613: revents |= events & (POLLIN | POLLRDNORM);
! 614: }
! 615: if (events & (POLLOUT | POLLWRNORM)) {
! 616: if (SEQ_QLEN(&sc->outq) < sc->lowat)
! 617: revents |= events & (POLLOUT | POLLWRNORM);
! 618: }
! 619: if (revents == 0) {
! 620: if (events & (POLLIN | POLLRDNORM))
! 621: selrecord(p, &sc->rsel);
! 622: if (events & (POLLOUT | POLLWRNORM))
! 623: selrecord(p, &sc->wsel);
! 624: }
! 625: return (revents);
! 626: }
! 627:
! 628: void
! 629: seq_reset(struct sequencer_softc *sc)
! 630: {
! 631: int i, chn;
! 632: struct midi_dev *md;
! 633:
! 634: for (i = 0; i < sc->nmidi; i++) {
! 635: md = sc->devs[i];
! 636: midiseq_reset(md);
! 637: for (chn = 0; chn < MAXCHAN; chn++) {
! 638: midiseq_ctlchange(md, chn, MIDI_CTRL_ALLOFF, 0);
! 639: midiseq_ctlchange(md, chn, MIDI_CTRL_RESET, 0);
! 640: midiseq_pitchbend(md, chn, MIDI_BEND_NEUTRAL);
! 641: }
! 642: }
! 643: }
! 644:
! 645: int
! 646: seq_do_command(struct sequencer_softc *sc, seq_event_rec *b)
! 647: {
! 648: int dev;
! 649:
! 650: DPRINTFN(4, ("seq_do_command: %p cmd=0x%02x\n", sc, SEQ_CMD(b)));
! 651:
! 652: switch(SEQ_CMD(b)) {
! 653: case SEQ_LOCAL:
! 654: return (seq_do_local(sc, b));
! 655: case SEQ_TIMING:
! 656: return (seq_do_timing(sc, b));
! 657: case SEQ_CHN_VOICE:
! 658: return (seq_do_chnvoice(sc, b));
! 659: case SEQ_CHN_COMMON:
! 660: return (seq_do_chncommon(sc, b));
! 661: case SEQ_SYSEX:
! 662: return (seq_do_sysex(sc, b));
! 663: /* COMPAT */
! 664: case SEQOLD_MIDIPUTC:
! 665: dev = b->arr[2];
! 666: if (dev < 0 || dev >= sc->nmidi)
! 667: return (ENXIO);
! 668: return (midiseq_putc(sc->devs[dev], b->arr[1]));
! 669: default:
! 670: DPRINTFN(-1,("seq_do_command: unimpl command %02x\n",
! 671: SEQ_CMD(b)));
! 672: return (EINVAL);
! 673: }
! 674: }
! 675:
! 676: int
! 677: seq_do_chnvoice(struct sequencer_softc *sc, seq_event_rec *b)
! 678: {
! 679: int cmd, dev, chan, note, parm, voice;
! 680: int error;
! 681: struct midi_dev *md;
! 682:
! 683: dev = SEQ_EDEV(b);
! 684: if (dev < 0 || dev >= sc->nmidi)
! 685: return (ENXIO);
! 686: md = sc->devs[dev];
! 687: cmd = SEQ_ECMD(b);
! 688: chan = SEQ_ECHAN(b);
! 689: note = SEQ_ENOTE(b);
! 690: parm = SEQ_EPARM(b);
! 691: DPRINTFN(2,("seq_do_chnvoice: cmd=%02x dev=%d chan=%d note=%d parm=%d\n",
! 692: cmd, dev, chan, note, parm));
! 693: voice = chan;
! 694: if (cmd == MIDI_NOTEON && parm == 0) {
! 695: cmd = MIDI_NOTEOFF;
! 696: parm = MIDI_HALF_VEL;
! 697: }
! 698: switch(cmd) {
! 699: case MIDI_NOTEON:
! 700: DPRINTFN(5, ("seq_do_chnvoice: noteon %p %d %d %d\n",
! 701: md, voice, note, parm));
! 702: error = midiseq_noteon(md, voice, note, parm);
! 703: break;
! 704: case MIDI_NOTEOFF:
! 705: error = midiseq_noteoff(md, voice, note, parm);
! 706: break;
! 707: case MIDI_KEY_PRESSURE:
! 708: error = midiseq_keypressure(md, voice, note, parm);
! 709: break;
! 710: default:
! 711: DPRINTFN(-1,("seq_do_chnvoice: unimpl command %02x\n", cmd));
! 712: error = EINVAL;
! 713: break;
! 714: }
! 715: return (error);
! 716: }
! 717:
! 718: int
! 719: seq_do_chncommon(struct sequencer_softc *sc, seq_event_rec *b)
! 720: {
! 721: int cmd, dev, chan, p1, w14;
! 722: int error;
! 723: struct midi_dev *md;
! 724: union {
! 725: int16_t s;
! 726: u_int8_t b[2];
! 727: } u;
! 728:
! 729: dev = SEQ_EDEV(b);
! 730: if (dev < 0 || dev >= sc->nmidi)
! 731: return (ENXIO);
! 732: md = sc->devs[dev];
! 733: cmd = SEQ_ECMD(b);
! 734: chan = SEQ_ECHAN(b);
! 735: p1 = SEQ_EP1(b);
! 736: u.b[0] = b->arr[6];
! 737: u.b[1] = b->arr[7];
! 738: w14 = u.s;
! 739: DPRINTFN(2,("seq_do_chncommon: %02x\n", cmd));
! 740:
! 741: error = 0;
! 742: switch(cmd) {
! 743: case MIDI_PGM_CHANGE:
! 744: error = midiseq_pgmchange(md, chan, p1);
! 745: break;
! 746: case MIDI_CTL_CHANGE:
! 747: if (chan > 15 || p1 > 127)
! 748: return (0); /* EINVAL */
! 749: error = midiseq_ctlchange(md, chan, p1, w14);
! 750: break;
! 751: case MIDI_PITCH_BEND:
! 752: error = midiseq_pitchbend(md, chan, w14);
! 753: break;
! 754: case MIDI_CHN_PRESSURE:
! 755: error = midiseq_chnpressure(md, chan, p1);
! 756: break;
! 757: default:
! 758: DPRINTFN(-1,("seq_do_chncommon: unimpl command %02x\n", cmd));
! 759: error = EINVAL;
! 760: break;
! 761: }
! 762: return (error);
! 763: }
! 764:
! 765: int
! 766: seq_do_timing(struct sequencer_softc *sc, seq_event_rec *b)
! 767: {
! 768: union {
! 769: int32_t i;
! 770: u_int8_t b[4];
! 771: } u;
! 772:
! 773: u.b[0] = b->arr[4];
! 774: u.b[1] = b->arr[5];
! 775: u.b[2] = b->arr[6];
! 776: u.b[3] = b->arr[7];
! 777: return (seq_timer(sc, SEQ_TCMD(b), u.i, b));
! 778: }
! 779:
! 780: int
! 781: seq_do_local(struct sequencer_softc *sc, seq_event_rec *b)
! 782: {
! 783: return (EINVAL);
! 784: }
! 785:
! 786: int
! 787: seq_do_sysex(struct sequencer_softc *sc, seq_event_rec *b)
! 788: {
! 789: int dev, i;
! 790: struct midi_dev *md;
! 791: u_int8_t c, *buf = &b->arr[2];
! 792:
! 793: dev = SEQ_EDEV(b);
! 794: if (dev < 0 || dev >= sc->nmidi)
! 795: return (ENXIO);
! 796: DPRINTF(("seq_do_sysex: dev=%d\n", dev));
! 797: md = sc->devs[dev];
! 798:
! 799: if (!sc->doingsysex) {
! 800: c = MIDI_SYSEX_START;
! 801: midiseq_out(md, &c, 1, 0);
! 802: sc->doingsysex = 1;
! 803: }
! 804:
! 805: for (i = 0; i < 6 && buf[i] != 0xff; i++)
! 806: ;
! 807: midiseq_out(md, buf, i, 0);
! 808: if (i < 6 || (i > 0 && buf[i-1] == MIDI_SYSEX_END))
! 809: sc->doingsysex = 0;
! 810: return (0);
! 811: }
! 812:
! 813: int
! 814: seq_timer(struct sequencer_softc *sc, int cmd, int parm, seq_event_rec *b)
! 815: {
! 816: struct syn_timer *t = &sc->timer;
! 817: struct timeval when;
! 818: int ticks;
! 819: int error;
! 820: long long usec;
! 821:
! 822: DPRINTFN(2,("seq_timer: %02x %d\n", cmd, parm));
! 823:
! 824: error = 0;
! 825: switch(cmd) {
! 826: case TMR_WAIT_REL:
! 827: parm += t->last;
! 828: /* FALLTHROUGH */
! 829: case TMR_WAIT_ABS:
! 830: t->last = parm;
! 831: usec = (long long)parm * (long long)t->tick; /* convert to usec */
! 832: when.tv_sec = usec / 1000000;
! 833: when.tv_usec = usec % 1000000;
! 834: DPRINTFN(4, ("seq_timer: parm=%d, sleep when=%ld.%06ld", parm,
! 835: when.tv_sec, when.tv_usec));
! 836: ADDTIMEVAL(&when, &t->start); /* abstime for end */
! 837: ticks = hzto(&when);
! 838: DPRINTFN(4, (" when+start=%ld.%06ld, ticks=%d\n",
! 839: when.tv_sec, when.tv_usec, ticks));
! 840: if (ticks > 0) {
! 841: #ifdef DIAGNOSTIC
! 842: if (ticks > 20 * hz) {
! 843: /* Waiting more than 20s */
! 844: printf("seq_timer: funny ticks=%d, usec=%lld, parm=%d, tick=%ld\n",
! 845: ticks, usec, parm, t->tick);
! 846: }
! 847: #endif
! 848: sc->timeout = 1;
! 849: timeout_add(&sc->timo, ticks);
! 850: }
! 851: #ifdef SEQUENCER_DEBUG
! 852: else if (ticks < 0)
! 853: DPRINTF(("seq_timer: ticks = %d\n", ticks));
! 854: #endif
! 855: break;
! 856: case TMR_START:
! 857: microtime(&t->start);
! 858: t->running = 1;
! 859: break;
! 860: case TMR_STOP:
! 861: microtime(&t->stop);
! 862: t->running = 0;
! 863: break;
! 864: case TMR_CONTINUE:
! 865: microtime(&when);
! 866: SUBTIMEVAL(&when, &t->stop);
! 867: ADDTIMEVAL(&t->start, &when);
! 868: t->running = 1;
! 869: break;
! 870: case TMR_TEMPO:
! 871: /* parm is ticks per minute / timebase */
! 872: if (parm < 8)
! 873: parm = 8;
! 874: if (parm > 360)
! 875: parm = 360;
! 876: t->tempo = parm;
! 877: RECALC_TICK(t);
! 878: break;
! 879: case TMR_ECHO:
! 880: error = seq_input_event(sc, b);
! 881: break;
! 882: case TMR_RESET:
! 883: t->last = 0;
! 884: microtime(&t->start);
! 885: break;
! 886: default:
! 887: DPRINTF(("seq_timer: unknown %02x\n", cmd));
! 888: error = EINVAL;
! 889: break;
! 890: }
! 891: return (error);
! 892: }
! 893:
! 894: int
! 895: seq_do_fullsize(struct sequencer_softc *sc, seq_event_rec *b, struct uio *uio)
! 896: {
! 897: struct sysex_info sysex;
! 898: u_int dev;
! 899:
! 900: #ifdef DIAGNOSTIC
! 901: if (sizeof(seq_event_rec) != SEQ_SYSEX_HDRSIZE) {
! 902: printf("seq_do_fullsize: sysex size ??\n");
! 903: return (EINVAL);
! 904: }
! 905: #endif
! 906: memcpy(&sysex, b, sizeof sysex);
! 907: dev = sysex.device_no;
! 908: DPRINTFN(2, ("seq_do_fullsize: fmt=%04x, dev=%d, len=%d\n",
! 909: sysex.key, dev, sysex.len));
! 910: return (midiseq_loadpatch(sc->devs[dev], &sysex, uio));
! 911: }
! 912:
! 913: /* Convert an old sequencer event to a new one. */
! 914: int
! 915: seq_to_new(seq_event_rec *ev, struct uio *uio)
! 916: {
! 917: int cmd, chan, note, parm;
! 918: u_int32_t delay;
! 919: int error;
! 920:
! 921: cmd = SEQ_CMD(ev);
! 922: chan = ev->arr[1];
! 923: note = ev->arr[2];
! 924: parm = ev->arr[3];
! 925: DPRINTFN(3, ("seq_to_new: 0x%02x %d %d %d\n", cmd, chan, note, parm));
! 926:
! 927: if (cmd >= 0x80) {
! 928: /* Fill the event record */
! 929: if (uio->uio_resid >= sizeof *ev - SEQOLD_CMDSIZE) {
! 930: error = uiomove(&ev->arr[SEQOLD_CMDSIZE],
! 931: sizeof *ev - SEQOLD_CMDSIZE, uio);
! 932: if (error)
! 933: return (error);
! 934: } else
! 935: return (EINVAL);
! 936: }
! 937:
! 938: switch(cmd) {
! 939: case SEQOLD_NOTEOFF:
! 940: note = 255;
! 941: SEQ_ECMD(ev) = MIDI_NOTEOFF;
! 942: goto onoff;
! 943: case SEQOLD_NOTEON:
! 944: SEQ_ECMD(ev) = MIDI_NOTEON;
! 945: onoff:
! 946: SEQ_CMD(ev) = SEQ_CHN_VOICE;
! 947: SEQ_EDEV(ev) = 0;
! 948: SEQ_ECHAN(ev) = chan;
! 949: SEQ_ENOTE(ev) = note;
! 950: SEQ_EPARM(ev) = parm;
! 951: break;
! 952: case SEQOLD_WAIT:
! 953: delay = *(u_int32_t *)ev->arr >> 8;
! 954: SEQ_CMD(ev) = SEQ_TIMING;
! 955: SEQ_TCMD(ev) = TMR_WAIT_REL;
! 956: *(u_int32_t *)&ev->arr[4] = delay;
! 957: break;
! 958: case SEQOLD_SYNCTIMER:
! 959: SEQ_CMD(ev) = SEQ_TIMING;
! 960: SEQ_TCMD(ev) = TMR_RESET;
! 961: break;
! 962: case SEQOLD_PGMCHANGE:
! 963: SEQ_ECMD(ev) = MIDI_PGM_CHANGE;
! 964: SEQ_CMD(ev) = SEQ_CHN_COMMON;
! 965: SEQ_EDEV(ev) = 0;
! 966: SEQ_ECHAN(ev) = chan;
! 967: SEQ_EP1(ev) = note;
! 968: break;
! 969: case SEQOLD_MIDIPUTC:
! 970: break; /* interpret in normal mode */
! 971: case SEQOLD_ECHO:
! 972: case SEQOLD_PRIVATE:
! 973: case SEQOLD_EXTENDED:
! 974: default:
! 975: DPRINTF(("seq_to_new: not impl 0x%02x\n", cmd));
! 976: return (EINVAL);
! 977: /* In case new events show up */
! 978: case SEQ_TIMING:
! 979: case SEQ_CHN_VOICE:
! 980: case SEQ_CHN_COMMON:
! 981: case SEQ_FULLSIZE:
! 982: break;
! 983: }
! 984: return (0);
! 985: }
! 986:
! 987: /**********************************************/
! 988:
! 989: void
! 990: midiseq_in(struct midi_dev *md, u_char *msg, int len)
! 991: {
! 992: int unit = md->unit;
! 993: seq_event_rec ev;
! 994: int status, chan;
! 995:
! 996: DPRINTFN(2, ("midiseq_in: %p %02x %02x %02x\n",
! 997: md, msg[0], msg[1], msg[2]));
! 998:
! 999: status = MIDI_GET_STATUS(msg[0]);
! 1000: chan = MIDI_GET_CHAN(msg[0]);
! 1001: switch (status) {
! 1002: case MIDI_NOTEON:
! 1003: if (msg[2] == 0) {
! 1004: status = MIDI_NOTEOFF;
! 1005: msg[2] = MIDI_HALF_VEL;
! 1006: }
! 1007: /* FALLTHROUGH */
! 1008: case MIDI_NOTEOFF:
! 1009: case MIDI_KEY_PRESSURE:
! 1010: SEQ_MK_CHN_VOICE(&ev, unit, status, chan, msg[1], msg[2]);
! 1011: break;
! 1012: case MIDI_CTL_CHANGE:
! 1013: SEQ_MK_CHN_COMMON(&ev, unit, status, chan, msg[1], 0, msg[2]);
! 1014: break;
! 1015: case MIDI_PGM_CHANGE:
! 1016: case MIDI_CHN_PRESSURE:
! 1017: SEQ_MK_CHN_COMMON(&ev, unit, status, chan, msg[1], 0, 0);
! 1018: break;
! 1019: case MIDI_PITCH_BEND:
! 1020: SEQ_MK_CHN_COMMON(&ev, unit, status, chan, 0, 0,
! 1021: (msg[1] & 0x7f) | ((msg[2] & 0x7f) << 7));
! 1022: break;
! 1023: default:
! 1024: return;
! 1025: }
! 1026: seq_event_intr(md->seq, &ev);
! 1027: }
! 1028:
! 1029: struct midi_dev *
! 1030: midiseq_open(int unit, int flags)
! 1031: {
! 1032: extern struct cfdriver midi_cd;
! 1033: int error;
! 1034: struct midi_dev *md;
! 1035: struct midi_softc *sc;
! 1036: struct midi_info mi;
! 1037:
! 1038: DPRINTFN(2, ("midiseq_open: %d %d\n", unit, flags));
! 1039: error = midiopen(makedev(0, unit), flags, 0, 0);
! 1040: if (error)
! 1041: return (0);
! 1042: sc = midi_cd.cd_devs[unit];
! 1043: sc->seqopen = 1;
! 1044: md = malloc(sizeof *md, M_DEVBUF, M_WAITOK);
! 1045: sc->seq_md = md;
! 1046: memset(md, 0, sizeof *md);
! 1047: md->msc = sc;
! 1048: midi_getinfo(makedev(0, unit), &mi);
! 1049: md->unit = unit;
! 1050: md->name = mi.name;
! 1051: md->subtype = 0;
! 1052: md->nr_voices = 128; /* XXX */
! 1053: md->instr_bank_size = 128; /* XXX */
! 1054: if (mi.props & MIDI_PROP_CAN_INPUT)
! 1055: md->capabilities |= SYNTH_CAP_INPUT;
! 1056: return (md);
! 1057: }
! 1058:
! 1059: void
! 1060: midiseq_close(struct midi_dev *md)
! 1061: {
! 1062: DPRINTFN(2, ("midiseq_close: %d\n", md->unit));
! 1063: midiclose(makedev(0, md->unit), 0, 0, 0);
! 1064: free(md, M_DEVBUF);
! 1065: }
! 1066:
! 1067: void
! 1068: midiseq_reset(struct midi_dev *md)
! 1069: {
! 1070: /* XXX send GM reset? */
! 1071: DPRINTFN(3, ("midiseq_reset: %d\n", md->unit));
! 1072: }
! 1073:
! 1074: int
! 1075: midiseq_out(struct midi_dev *md, u_char *buf, u_int cc, int chk)
! 1076: {
! 1077: DPRINTFN(5, ("midiseq_out: m=%p, unit=%d, buf[0]=0x%02x, cc=%d\n",
! 1078: md->msc, md->unit, buf[0], cc));
! 1079:
! 1080: /* The MIDI "status" byte does not have to be repeated. */
! 1081: if (chk && md->last_cmd == buf[0])
! 1082: buf++, cc--;
! 1083: else
! 1084: md->last_cmd = buf[0];
! 1085: return (midi_writebytes(md->unit, buf, cc));
! 1086: }
! 1087:
! 1088: int
! 1089: midiseq_noteon(struct midi_dev *md, int chan, int note, int vel)
! 1090: {
! 1091: u_char buf[3];
! 1092:
! 1093: DPRINTFN(6, ("midiseq_noteon 0x%02x %d %d\n",
! 1094: MIDI_NOTEON | chan, note, vel));
! 1095: if (chan < 0 || chan > 15 ||
! 1096: note < 0 || note > 127)
! 1097: return (EINVAL);
! 1098: if (vel < 0) vel = 0;
! 1099: if (vel > 127) vel = 127;
! 1100: buf[0] = MIDI_NOTEON | chan;
! 1101: buf[1] = note;
! 1102: buf[2] = vel;
! 1103: return (midiseq_out(md, buf, 3, 1));
! 1104: }
! 1105:
! 1106: int
! 1107: midiseq_noteoff(struct midi_dev *md, int chan, int note, int vel)
! 1108: {
! 1109: u_char buf[3];
! 1110:
! 1111: if (chan < 0 || chan > 15 ||
! 1112: note < 0 || note > 127)
! 1113: return (EINVAL);
! 1114: if (vel < 0) vel = 0;
! 1115: if (vel > 127) vel = 127;
! 1116: buf[0] = MIDI_NOTEOFF | chan;
! 1117: buf[1] = note;
! 1118: buf[2] = vel;
! 1119: return (midiseq_out(md, buf, 3, 1));
! 1120: }
! 1121:
! 1122: int
! 1123: midiseq_keypressure(struct midi_dev *md, int chan, int note, int vel)
! 1124: {
! 1125: u_char buf[3];
! 1126:
! 1127: if (chan < 0 || chan > 15 ||
! 1128: note < 0 || note > 127)
! 1129: return (EINVAL);
! 1130: if (vel < 0) vel = 0;
! 1131: if (vel > 127) vel = 127;
! 1132: buf[0] = MIDI_KEY_PRESSURE | chan;
! 1133: buf[1] = note;
! 1134: buf[2] = vel;
! 1135: return (midiseq_out(md, buf, 3, 1));
! 1136: }
! 1137:
! 1138: int
! 1139: midiseq_pgmchange(struct midi_dev *md, int chan, int parm)
! 1140: {
! 1141: u_char buf[2];
! 1142:
! 1143: if (chan < 0 || chan > 15 ||
! 1144: parm < 0 || parm > 127)
! 1145: return (EINVAL);
! 1146: buf[0] = MIDI_PGM_CHANGE | chan;
! 1147: buf[1] = parm;
! 1148: return (midiseq_out(md, buf, 2, 1));
! 1149: }
! 1150:
! 1151: int
! 1152: midiseq_chnpressure(struct midi_dev *md, int chan, int parm)
! 1153: {
! 1154: u_char buf[2];
! 1155:
! 1156: if (chan < 0 || chan > 15 ||
! 1157: parm < 0 || parm > 127)
! 1158: return (EINVAL);
! 1159: buf[0] = MIDI_CHN_PRESSURE | chan;
! 1160: buf[1] = parm;
! 1161: return (midiseq_out(md, buf, 2, 1));
! 1162: }
! 1163:
! 1164: int
! 1165: midiseq_ctlchange(struct midi_dev *md, int chan, int parm, int w14)
! 1166: {
! 1167: u_char buf[3];
! 1168:
! 1169: if (chan < 0 || chan > 15 ||
! 1170: parm < 0 || parm > 127)
! 1171: return (EINVAL);
! 1172: buf[0] = MIDI_CTL_CHANGE | chan;
! 1173: buf[1] = parm;
! 1174: buf[2] = w14 & 0x7f;
! 1175: return (midiseq_out(md, buf, 3, 1));
! 1176: }
! 1177:
! 1178: int
! 1179: midiseq_pitchbend(struct midi_dev *md, int chan, int parm)
! 1180: {
! 1181: u_char buf[3];
! 1182:
! 1183: if (chan < 0 || chan > 15)
! 1184: return (EINVAL);
! 1185: buf[0] = MIDI_PITCH_BEND | chan;
! 1186: buf[1] = parm & 0x7f;
! 1187: buf[2] = (parm >> 7) & 0x7f;
! 1188: return (midiseq_out(md, buf, 3, 1));
! 1189: }
! 1190:
! 1191: int
! 1192: midiseq_loadpatch(struct midi_dev *md, struct sysex_info *sysex, struct uio *uio)
! 1193: {
! 1194: u_char c, buf[128];
! 1195: int i, cc, error;
! 1196:
! 1197: if (sysex->key != SEQ_SYSEX_PATCH) {
! 1198: DPRINTFN(-1,("midiseq_loadpatch: bad patch key 0x%04x\n",
! 1199: sysex->key));
! 1200: return (EINVAL);
! 1201: }
! 1202: if (uio->uio_resid < sysex->len)
! 1203: /* adjust length, should be an error */
! 1204: sysex->len = uio->uio_resid;
! 1205:
! 1206: DPRINTFN(2, ("midiseq_loadpatch: len=%d\n", sysex->len));
! 1207: if (sysex->len == 0)
! 1208: return (EINVAL);
! 1209: error = uiomove(&c, 1, uio);
! 1210: if (error)
! 1211: return error;
! 1212: if (c != MIDI_SYSEX_START) /* must start like this */
! 1213: return (EINVAL);
! 1214: error = midiseq_out(md, &c, 1, 0);
! 1215: if (error)
! 1216: return (error);
! 1217: --sysex->len;
! 1218: while (sysex->len > 0) {
! 1219: cc = sysex->len;
! 1220: if (cc > sizeof buf)
! 1221: cc = sizeof buf;
! 1222: error = uiomove(buf, cc, uio);
! 1223: if (error)
! 1224: break;
! 1225: for(i = 0; i < cc && !MIDI_IS_STATUS(buf[i]); i++)
! 1226: ;
! 1227: error = midiseq_out(md, buf, i, 0);
! 1228: if (error)
! 1229: break;
! 1230: sysex->len -= i;
! 1231: if (i != cc)
! 1232: break;
! 1233: }
! 1234: /* Any leftover data in uio is rubbish;
! 1235: * the SYSEX should be one write ending in SYSEX_END.
! 1236: */
! 1237: uio->uio_resid = 0;
! 1238: c = MIDI_SYSEX_END;
! 1239: return (midiseq_out(md, &c, 1, 0));
! 1240: }
! 1241:
! 1242: int
! 1243: midiseq_putc(struct midi_dev *md, int data)
! 1244: {
! 1245: u_char c = data;
! 1246: DPRINTFN(4,("midiseq_putc: 0x%02x\n", data));
! 1247: return (midiseq_out(md, &c, 1, 0));
! 1248: }
! 1249:
! 1250: #include "midi.h"
! 1251: #if NMIDI == 0
! 1252: /*
! 1253: * If someone has a sequencer, but no midi devices there will
! 1254: * be unresolved references, so we provide little stubs.
! 1255: */
! 1256:
! 1257: int
! 1258: midi_unit_count()
! 1259: {
! 1260: return (0);
! 1261: }
! 1262:
! 1263: int
! 1264: midiopen(dev_t dev, int flags, int ifmt, struct proc *p)
! 1265: {
! 1266: return (ENXIO);
! 1267: }
! 1268:
! 1269: struct cfdriver midi_cd;
! 1270:
! 1271: void
! 1272: midi_getinfo(dev_t dev, struct midi_info *mi)
! 1273: {
! 1274: }
! 1275:
! 1276: int
! 1277: midiclose(dev_t dev, int flags, int ifmt, struct proc *p)
! 1278: {
! 1279: return (ENXIO);
! 1280: }
! 1281:
! 1282: int
! 1283: midi_writebytes(int unit, u_char *buf, int cc)
! 1284: {
! 1285: return (ENXIO);
! 1286: }
! 1287: #endif /* NMIDI == 0 */
! 1288:
! 1289: #endif /* NSEQUENCER > 0 */
! 1290:
CVSweb