[BACK]Return to midi.c CVS log [TXT][DIR] Up to [local] / sys / dev

Annotation of sys/dev/midi.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: midi.c,v 1.16 2006/12/21 02:28:47 krw Exp $   */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2003, 2004 Alexandre Ratchov
        !             5:  *
        !             6:  * Permission to use, copy, modify, and distribute this software for any
        !             7:  * purpose with or without fee is hereby granted, provided that the above
        !             8:  * copyright notice and this permission notice appear in all copies.
        !             9:  *
        !            10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            17:  */
        !            18:
        !            19: /*
        !            20:  * TODO
        !            21:  *     - put the sequencer stuff in sequencer.c and sequencervar.h
        !            22:  *       there is no reason to have it here. The sequencer
        !            23:  *       driver need only to open the midi hw_if thus it does not
        !            24:  *       need this driver
        !            25:  */
        !            26:
        !            27: #include "midi.h"
        !            28: #include "sequencer.h"
        !            29: #if NMIDI > 0
        !            30:
        !            31: #include <sys/param.h>
        !            32: #include <sys/fcntl.h>
        !            33: #include <sys/systm.h>
        !            34: #include <sys/ioctl.h>
        !            35: #include <sys/exec.h>
        !            36: #include <sys/conf.h>
        !            37: #include <sys/lkm.h>
        !            38: #include <sys/proc.h>
        !            39: #include <sys/poll.h>
        !            40: #include <sys/kernel.h>
        !            41: #include <sys/timeout.h>
        !            42: #include <sys/vnode.h>
        !            43: #include <sys/signalvar.h>
        !            44: #include <sys/malloc.h>
        !            45: #include <sys/device.h>
        !            46:
        !            47: #include <dev/midi_if.h>
        !            48: #include <dev/audio_if.h>
        !            49: #include <dev/midivar.h>
        !            50:
        !            51:
        !            52: int     midiopen(dev_t, int, int, struct proc *);
        !            53: int     midiclose(dev_t, int, int, struct proc *);
        !            54: int     midiread(dev_t, struct uio *, int);
        !            55: int     midiwrite(dev_t, struct uio *, int);
        !            56: int     midipoll(dev_t, int, struct proc *);
        !            57: int    midiioctl(dev_t, u_long, caddr_t, int, struct proc *);
        !            58: int    midiprobe(struct device *, void *, void *);
        !            59: void   midiattach(struct device *, struct device *, void *);
        !            60: int    mididetach(struct device *, int);
        !            61: int    midiprint(void *, const char *);
        !            62:
        !            63: void   midi_iintr(void *, int);
        !            64: void   midi_ointr(void *);
        !            65: void   midi_out_start(struct midi_softc *);
        !            66: void   midi_out_stop(struct midi_softc *);
        !            67: void   midi_out_do(struct midi_softc *);
        !            68: void   midi_attach(struct midi_softc *, struct device *);
        !            69:
        !            70:
        !            71: #if NSEQUENCER > 0
        !            72: int               midi_unit_count(void);
        !            73: struct midi_hw_if *midi_get_hwif(int);
        !            74: void              midi_toevent(struct midi_softc *, int);
        !            75: int               midi_writebytes(int, u_char *, int);
        !            76: void              midiseq_in(struct midi_dev *, u_char *, int);
        !            77: #endif
        !            78:
        !            79: struct cfattach midi_ca = {
        !            80:        sizeof(struct midi_softc), midiprobe, midiattach, mididetach
        !            81: };
        !            82:
        !            83: struct cfdriver midi_cd = {
        !            84:        NULL, "midi", DV_DULL
        !            85: };
        !            86:
        !            87:
        !            88: void
        !            89: midi_iintr(void *addr, int data)
        !            90: {
        !            91:        struct midi_softc  *sc = (struct midi_softc *)addr;
        !            92:        struct midi_buffer *mb = &sc->inbuf;
        !            93:
        !            94:        if (sc->isdying || !sc->isopen || !(sc->flags & FREAD)) return;
        !            95:
        !            96: #if NSEQUENCER > 0
        !            97:        if (sc->seqopen) {
        !            98:                midi_toevent(sc, data);
        !            99:                return;
        !           100:        }
        !           101: #endif
        !           102:        if (MIDIBUF_ISFULL(mb))
        !           103:                return; /* discard data */
        !           104:        if (MIDIBUF_ISEMPTY(mb)) {
        !           105:                if (sc->rchan) {
        !           106:                        sc->rchan = 0;
        !           107:                        wakeup(&sc->rchan);
        !           108:                }
        !           109:                selwakeup(&sc->rsel);
        !           110:                if (sc->async)
        !           111:                        psignal(sc->async, SIGIO);
        !           112:        }
        !           113:        MIDIBUF_WRITE(mb, data);
        !           114: }
        !           115:
        !           116:
        !           117: int
        !           118: midiread(dev_t dev, struct uio *uio, int ioflag)
        !           119: {
        !           120:        struct midi_softc  *sc = MIDI_DEV2SC(dev);
        !           121:        struct midi_buffer *mb = &sc->inbuf;
        !           122:        unsigned            count;
        !           123:        int                 s, error;
        !           124:
        !           125:        if (!(sc->flags & FREAD))
        !           126:                return ENXIO;
        !           127:
        !           128:        /* if there is no data then sleep (unless IO_NDELAY flag is set) */
        !           129:
        !           130:        s = splaudio();
        !           131:        while(MIDIBUF_ISEMPTY(mb)) {
        !           132:                if (sc->isdying) {
        !           133:                        splx(s);
        !           134:                        return EIO;
        !           135:                }
        !           136:                if (ioflag & IO_NDELAY) {
        !           137:                        splx(s);
        !           138:                        return EWOULDBLOCK;
        !           139:                }
        !           140:                sc->rchan = 1;
        !           141:                error = tsleep(&sc->rchan, PWAIT|PCATCH, "mid_rd", 0);
        !           142:                if (error) {
        !           143:                        splx(s);
        !           144:                        return error;
        !           145:                }
        !           146:        }
        !           147:
        !           148:        /* at this stage, there is at least 1 byte */
        !           149:
        !           150:        while (uio->uio_resid > 0  &&  mb->used > 0) {
        !           151:                count = MIDIBUF_SIZE - mb->start;
        !           152:                if (count > mb->used)
        !           153:                        count = mb->used;
        !           154:                if (count > uio->uio_resid)
        !           155:                        count = uio->uio_resid;
        !           156:                error = uiomove(mb->data + mb->start, count, uio);
        !           157:                if (error) {
        !           158:                        splx(s);
        !           159:                        return error;
        !           160:                }
        !           161:                MIDIBUF_REMOVE(mb, count);
        !           162:        }
        !           163:        splx(s);
        !           164:        return 0;
        !           165: }
        !           166:
        !           167:
        !           168: void
        !           169: midi_ointr(void *addr)
        !           170: {
        !           171:        struct midi_softc  *sc = (struct midi_softc *)addr;
        !           172:        struct midi_buffer *mb;
        !           173:        int                s;
        !           174:
        !           175:        if (sc->isopen && !sc->isdying) {
        !           176: #ifdef MIDI_DEBUG
        !           177:                if (!sc->isbusy) {
        !           178:                        printf("midi_ointr: output should be busy\n");
        !           179:                }
        !           180: #endif
        !           181:                mb = &sc->outbuf;
        !           182:                s = splaudio();
        !           183:                if (mb->used == 0)
        !           184:                        midi_out_stop(sc);
        !           185:                else
        !           186:                        midi_out_do(sc); /* restart output */
        !           187:                splx(s);
        !           188:        }
        !           189: }
        !           190:
        !           191:
        !           192: void
        !           193: midi_out_start(struct midi_softc *sc)
        !           194: {
        !           195:        if (!sc->isbusy) {
        !           196:                sc->isbusy = 1;
        !           197:                midi_out_do(sc);
        !           198:        }
        !           199: }
        !           200:
        !           201: void
        !           202: midi_out_stop(struct midi_softc *sc)
        !           203: {
        !           204:        sc->isbusy = 0;
        !           205:        if (sc->wchan) {
        !           206:                sc->wchan = 0;
        !           207:                wakeup(&sc->wchan);
        !           208:        }
        !           209:        selwakeup(&sc->wsel);
        !           210:        if (sc->async)
        !           211:                psignal(sc->async, SIGIO);
        !           212: }
        !           213:
        !           214:
        !           215:        /*
        !           216:         * drain output buffer, must be called with
        !           217:         * interrupts disabled
        !           218:         */
        !           219: void
        !           220: midi_out_do(struct midi_softc *sc)
        !           221: {
        !           222:        struct midi_buffer *mb = &sc->outbuf;
        !           223:        unsigned            i, max;
        !           224:        int                 error;
        !           225:
        !           226:        /*
        !           227:         * If output interrupts are not supported then we write MIDI_MAXWRITE
        !           228:         * bytes instead of 1, and then we wait sc->wait
        !           229:         */
        !           230:
        !           231:        max = sc->props & MIDI_PROP_OUT_INTR ? 1 : MIDI_MAXWRITE;
        !           232:        for (i = max; i != 0;) {
        !           233:                if (mb->used == 0)
        !           234:                        break;
        !           235:                error = sc->hw_if->output(sc->hw_hdl, mb->data[mb->start]);
        !           236:                /*
        !           237:                 * 0 means that data is being sent, an interrupt will
        !           238:                 * be generated when the interface becomes ready again
        !           239:                 *
        !           240:                 * EINPROGRESS means that data has been queued, but
        !           241:                 * will not be sent immediately and thus will not
        !           242:                 * generate interrupt, in this case we can send
        !           243:                 * another byte. The flush() method can be called
        !           244:                 * to force the transfer.
        !           245:                 *
        !           246:                 * EAGAIN means that data cannot be queued or sent;
        !           247:                 * because the interface isn't ready. An interrupt
        !           248:                 * will be generated once the interface is ready again
        !           249:                 *
        !           250:                 * any other (fatal) error code means that data couldn't
        !           251:                 * be sent and was lost, interrupt will not be generated
        !           252:                 */
        !           253:                if (error == EINPROGRESS) {
        !           254:                        MIDIBUF_REMOVE(mb, 1);
        !           255:                        if (MIDIBUF_ISEMPTY(mb)) {
        !           256:                                if (sc->hw_if->flush != NULL)
        !           257:                                        sc->hw_if->flush(sc->hw_hdl);
        !           258:                                midi_out_stop(sc);
        !           259:                                return;
        !           260:                        }
        !           261:                } else if (error == 0) {
        !           262:                        MIDIBUF_REMOVE(mb, 1);
        !           263:                        i--;
        !           264:                } else if (error == EAGAIN) {
        !           265:                        break;
        !           266:                } else {
        !           267:                        MIDIBUF_INIT(mb);
        !           268:                        midi_out_stop(sc);
        !           269:                        return;
        !           270:                }
        !           271:        }
        !           272:
        !           273:        if (!(sc->props & MIDI_PROP_OUT_INTR)) {
        !           274:                if (MIDIBUF_ISEMPTY(mb))
        !           275:                        midi_out_stop(sc);
        !           276:                else
        !           277:                        timeout_add(&sc->timeo, sc->wait);
        !           278:        }
        !           279: }
        !           280:
        !           281:
        !           282: int
        !           283: midiwrite(dev_t dev, struct uio *uio, int ioflag)
        !           284: {
        !           285:        struct midi_softc  *sc = MIDI_DEV2SC(dev);
        !           286:        struct midi_buffer *mb = &sc->outbuf;
        !           287:        unsigned            count;
        !           288:        int                 s, error;
        !           289:
        !           290:        if (!(sc->flags & FWRITE))
        !           291:                return ENXIO;
        !           292:        if (sc->isdying)
        !           293:                return EIO;
        !           294:
        !           295:        /*
        !           296:         * If IO_NDELAY flag is set then check if there is enough room
        !           297:         * in the buffer to store at least one byte. If not then dont
        !           298:         * start the write process.
        !           299:         */
        !           300:
        !           301:        if ((ioflag & IO_NDELAY) &&  MIDIBUF_ISFULL(mb)  &&
        !           302:            (uio->uio_resid > 0))
        !           303:                return EWOULDBLOCK;
        !           304:
        !           305:        while (uio->uio_resid > 0) {
        !           306:                s = splaudio();
        !           307:                while (MIDIBUF_ISFULL(mb)) {
        !           308:                        if (ioflag & IO_NDELAY) {
        !           309:                                /*
        !           310:                                 * At this stage at least one byte is already
        !           311:                                 * moved so we do not return EWOULDBLOCK
        !           312:                                 */
        !           313:                                splx(s);
        !           314:                                return 0;
        !           315:                        }
        !           316:                        sc->wchan = 1;
        !           317:                        error = tsleep(&sc->wchan, PWAIT|PCATCH, "mid_wr", 0);
        !           318:                        if (error) {
        !           319:                                splx(s);
        !           320:                                return error;
        !           321:                        }
        !           322:                        if (sc->isdying) {
        !           323:                                splx(s);
        !           324:                                return EIO;
        !           325:                        }
        !           326:                }
        !           327:
        !           328:                count = MIDIBUF_SIZE - MIDIBUF_END(mb);
        !           329:                if (count > MIDIBUF_AVAIL(mb))
        !           330:                        count = MIDIBUF_AVAIL(mb);
        !           331:                if (count > uio->uio_resid)
        !           332:                        count = uio->uio_resid;
        !           333:                error = uiomove(mb->data + MIDIBUF_END(mb), count, uio);
        !           334:                if (error) {
        !           335:                        splx(s);
        !           336:                        return error;
        !           337:                }
        !           338:                mb->used += count;
        !           339:                midi_out_start(sc);
        !           340:                splx(s);
        !           341:        }
        !           342:        return 0;
        !           343: }
        !           344:
        !           345:
        !           346: int
        !           347: midipoll(dev_t dev, int events, struct proc *p)
        !           348: {
        !           349:        struct midi_softc *sc = MIDI_DEV2SC(dev);
        !           350:        int                s, revents;
        !           351:
        !           352:        if (sc->isdying)
        !           353:                return POLLERR;
        !           354:
        !           355:        revents = 0;
        !           356:        s = splaudio();
        !           357:        if (events & (POLLIN | POLLRDNORM)) {
        !           358:                if (!MIDIBUF_ISEMPTY(&sc->inbuf))
        !           359:                        revents |= events & (POLLIN | POLLRDNORM);
        !           360:        }
        !           361:        if (events & (POLLOUT | POLLWRNORM)) {
        !           362:                if (!MIDIBUF_ISFULL(&sc->outbuf))
        !           363:                        revents |= events & (POLLOUT | POLLWRNORM);
        !           364:        }
        !           365:        if (revents == 0) {
        !           366:                if (events & (POLLIN | POLLRDNORM))
        !           367:                        selrecord(p, &sc->rsel);
        !           368:                if (events & (POLLOUT | POLLWRNORM))
        !           369:                        selrecord(p, &sc->wsel);
        !           370:        }
        !           371:        splx(s);
        !           372:        return (revents);
        !           373: }
        !           374:
        !           375:
        !           376: int
        !           377: midiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
        !           378: {
        !           379:        struct midi_softc *sc = MIDI_DEV2SC(dev);
        !           380:
        !           381:        if (sc->isdying) return EIO;
        !           382:
        !           383:        switch(cmd) {
        !           384:        case FIONBIO:
        !           385:                /* All handled in the upper FS layer */
        !           386:                break;
        !           387:        case FIOASYNC:
        !           388:                if (*(int *)addr) {
        !           389:                        if (sc->async) return EBUSY;
        !           390:                        sc->async = p;
        !           391:                } else
        !           392:                        sc->async = 0;
        !           393:                break;
        !           394:        default:
        !           395:                return ENOTTY;
        !           396:                break;
        !           397:        }
        !           398:        return 0;
        !           399: }
        !           400:
        !           401:
        !           402: int
        !           403: midiopen(dev_t dev, int flags, int mode, struct proc *p)
        !           404: {
        !           405:        struct midi_softc *sc;
        !           406:        int                err;
        !           407:
        !           408:        if (MIDI_UNIT(dev) >= midi_cd.cd_ndevs)
        !           409:                return ENXIO;
        !           410:        sc = MIDI_DEV2SC(dev);
        !           411:        if (sc == NULL)         /* there may be more units than devices */
        !           412:                return ENXIO;
        !           413:        if (sc->isdying)
        !           414:                return EIO;
        !           415:        if (sc->isopen)
        !           416:                return EBUSY;
        !           417:
        !           418:        MIDIBUF_INIT(&sc->inbuf);
        !           419:        MIDIBUF_INIT(&sc->outbuf);
        !           420:        sc->isbusy = 0;
        !           421:        sc->rchan = sc->wchan = 0;
        !           422:        sc->async = 0;
        !           423:        sc->flags = flags;
        !           424:
        !           425:        err = sc->hw_if->open(sc->hw_hdl, flags, midi_iintr, midi_ointr, sc);
        !           426:        if (err)
        !           427:                return err;
        !           428:        sc->isopen = 1;
        !           429: #if NSEQUENCER > 0
        !           430:        sc->seq_md = 0;
        !           431:        sc->seqopen = 0;
        !           432:        sc->evstatus = 0xff;
        !           433: #endif
        !           434:        return 0;
        !           435: }
        !           436:
        !           437:
        !           438: int
        !           439: midiclose(dev_t dev, int fflag, int devtype, struct proc *p)
        !           440: {
        !           441:        struct midi_softc  *sc = MIDI_DEV2SC(dev);
        !           442:        struct midi_buffer *mb;
        !           443:        int                 error;
        !           444:        int                 s;
        !           445:
        !           446:        mb = &sc->outbuf;
        !           447:        if (!sc->isdying) {
        !           448:                /* start draining output buffer */
        !           449:                s = splaudio();
        !           450:                if (!MIDIBUF_ISEMPTY(mb))
        !           451:                        midi_out_start(sc);
        !           452:                while (sc->isbusy) {
        !           453:                        sc->wchan = 1;
        !           454:                        error = tsleep(&sc->wchan, PWAIT|PCATCH, "mid_dr", 0);
        !           455:                        if (error || sc->isdying)
        !           456:                                break;
        !           457:                }
        !           458:                splx(s);
        !           459:        }
        !           460:
        !           461:        /*
        !           462:         * some hw_if->close() reset immediately the midi uart
        !           463:         * which flushes the internal buffer of the uart device,
        !           464:         * so we may lose some (important) data. To avoid this, we sleep 2*wait,
        !           465:         * which gives the time to the uart to drain its internal buffers.
        !           466:         *
        !           467:         * Note: we'd better sleep in the corresponding hw_if->close()
        !           468:         */
        !           469:
        !           470:        tsleep(&sc->wchan, PWAIT|PCATCH, "mid_cl", 2 * sc->wait);
        !           471:        sc->hw_if->close(sc->hw_hdl);
        !           472:        sc->isopen = 0;
        !           473:        return 0;
        !           474: }
        !           475:
        !           476:
        !           477: int
        !           478: midiprobe(struct device *parent, void *match, void *aux)
        !           479: {
        !           480:        struct audio_attach_args *sa = aux;
        !           481:        return (sa != NULL && (sa->type == AUDIODEV_TYPE_MIDI) ? 1 : 0);
        !           482: }
        !           483:
        !           484:
        !           485: void
        !           486: midi_attach(struct midi_softc *sc, struct device *parent)
        !           487: {
        !           488:        struct midi_info          mi;
        !           489:
        !           490:        sc->isdying = 0;
        !           491:        sc->wait = (hz * MIDI_MAXWRITE) /  MIDI_RATE;
        !           492:        if (sc->wait == 0)
        !           493:                sc->wait = 1;
        !           494:        sc->hw_if->getinfo(sc->hw_hdl, &mi);
        !           495:        sc->props = mi.props;
        !           496:        sc->isopen = 0;
        !           497:        timeout_set(&sc->timeo, midi_ointr, sc);
        !           498:        printf(": <%s>\n", mi.name);
        !           499: }
        !           500:
        !           501:
        !           502: void
        !           503: midiattach(struct device *parent, struct device *self, void *aux)
        !           504: {
        !           505:        struct midi_softc        *sc = (struct midi_softc *)self;
        !           506:        struct audio_attach_args *sa = (struct audio_attach_args *)aux;
        !           507:        struct midi_hw_if        *hwif = sa->hwif;
        !           508:        void                     *hdl = sa->hdl;
        !           509:
        !           510: #ifdef DIAGNOSTIC
        !           511:        if (hwif == 0 ||
        !           512:            hwif->open == 0 ||
        !           513:            hwif->close == 0 ||
        !           514:            hwif->output == 0 ||
        !           515:            hwif->getinfo == 0) {
        !           516:                printf("midi: missing method\n");
        !           517:                return;
        !           518:        }
        !           519: #endif
        !           520:        sc->hw_if = hwif;
        !           521:        sc->hw_hdl = hdl;
        !           522:        midi_attach(sc, parent);
        !           523: }
        !           524:
        !           525:
        !           526: int
        !           527: mididetach(struct device *self, int flags)
        !           528: {
        !           529:        struct midi_softc *sc = (struct midi_softc *)self;
        !           530:        int    maj, mn;
        !           531:
        !           532:        sc->isdying = 1;
        !           533:        if (sc->wchan) {
        !           534:                sc->wchan = 0;
        !           535:                wakeup(&sc->wchan);
        !           536:        }
        !           537:        if (sc->rchan) {
        !           538:                sc->rchan = 0;
        !           539:                wakeup(&sc->rchan);
        !           540:        }
        !           541:
        !           542:        /* locate the major number */
        !           543:         for (maj = 0; maj < nchrdev; maj++)
        !           544:                 if (cdevsw[maj].d_open == midiopen)
        !           545:                         break;
        !           546:
        !           547:         /* Nuke the vnodes for any open instances (calls close). */
        !           548:         mn = self->dv_unit;
        !           549:         vdevgone(maj, mn, mn, VCHR);
        !           550:
        !           551:        return 0;
        !           552: }
        !           553:
        !           554:
        !           555: int
        !           556: midiprint(void *aux, const char *pnp)
        !           557: {
        !           558:        if (pnp)
        !           559:                printf("midi at %s", pnp);
        !           560:        return (UNCONF);
        !           561: }
        !           562:
        !           563:
        !           564: void
        !           565: midi_getinfo(dev_t dev, struct midi_info *mi)
        !           566: {
        !           567:        struct midi_softc *sc = MIDI_DEV2SC(dev);
        !           568:        if (MIDI_UNIT(dev) >= midi_cd.cd_ndevs || sc == NULL || sc->isdying) {
        !           569:                mi->name = "unconfigured";
        !           570:                mi->props = 0;
        !           571:                return;
        !           572:        }
        !           573:        sc->hw_if->getinfo(sc->hw_hdl, mi);
        !           574: }
        !           575:
        !           576:
        !           577: struct device *
        !           578: midi_attach_mi(struct midi_hw_if *hwif, void *hdl, struct device *dev)
        !           579: {
        !           580:        struct audio_attach_args arg;
        !           581:
        !           582:        arg.type = AUDIODEV_TYPE_MIDI;
        !           583:        arg.hwif = hwif;
        !           584:        arg.hdl = hdl;
        !           585:        return config_found(dev, &arg, midiprint);
        !           586: }
        !           587:
        !           588:
        !           589: int
        !           590: midi_unit_count(void)
        !           591: {
        !           592:        return midi_cd.cd_ndevs;
        !           593: }
        !           594:
        !           595:
        !           596: #if NSEQUENCER > 0
        !           597: #define MIDI_EVLEN(status)     (midi_evlen[((status) >> 4) & 7])
        !           598: unsigned midi_evlen[] = { 2, 2, 2, 2, 1, 1, 2 };
        !           599:
        !           600: void
        !           601: midi_toevent(struct midi_softc *sc, int data)
        !           602: {
        !           603:        unsigned char mesg[3];
        !           604:
        !           605:        if (data >= 0xf8) {             /* is it a realtime message ? */
        !           606:                switch(data) {
        !           607:                case 0xf8:              /* midi timer tic */
        !           608:                case 0xfa:              /* midi timer start */
        !           609:                case 0xfb:              /* midi timer continue (after stop) */
        !           610:                case 0xfc:              /* midi timer stop */
        !           611:                        mesg[0] = data;
        !           612:                        midiseq_in(sc->seq_md, mesg, 1);
        !           613:                        break;
        !           614:                default:
        !           615:                        break;
        !           616:                }
        !           617:        } else if (data >= 0x80) {      /* is it a common or voice message ? */
        !           618:                sc->evstatus = data;
        !           619:                sc->evindex = 0;
        !           620:        } else {                        /* else it is a data byte */
        !           621:                /* strip common messages and bogus data */
        !           622:                if (sc->evstatus >= 0xf0 || sc->evstatus < 0x80)
        !           623:                        return;
        !           624:
        !           625:                sc->evdata[sc->evindex++] = data;
        !           626:                if (sc->evindex == MIDI_EVLEN(sc->evstatus)) {
        !           627:                        sc->evindex = 0;
        !           628:                        mesg[0] = sc->evstatus;
        !           629:                        mesg[1] = sc->evdata[0];
        !           630:                        mesg[2] = sc->evdata[1];
        !           631:                        midiseq_in(sc->seq_md, mesg, 1 + MIDI_EVLEN(sc->evstatus));
        !           632:                }
        !           633:        }
        !           634: }
        !           635:
        !           636:
        !           637: int
        !           638: midi_writebytes(int unit, unsigned char *mesg, int mesglen)
        !           639: {
        !           640:        struct midi_softc  *sc = midi_cd.cd_devs[unit];
        !           641:        struct midi_buffer *mb = &sc->outbuf;
        !           642:        unsigned            count;
        !           643:        int                 s;
        !           644:
        !           645:        s = splaudio();
        !           646:        if (mesglen > MIDIBUF_AVAIL(mb)) {
        !           647:                splx(s);
        !           648:                return EWOULDBLOCK;
        !           649:        }
        !           650:
        !           651:        while (mesglen > 0) {
        !           652:                count = MIDIBUF_SIZE - MIDIBUF_END(mb);
        !           653:                if (count > MIDIBUF_AVAIL(mb)) count = MIDIBUF_AVAIL(mb);
        !           654:                if (count > mesglen) count = mesglen;
        !           655:                bcopy(mesg, mb->data + MIDIBUF_END(mb), count);
        !           656:                mb->used += count;
        !           657:                mesg += count;
        !           658:                mesglen -= count;
        !           659:                midi_out_start(sc);
        !           660:        }
        !           661:        splx(s);
        !           662:        return 0;
        !           663: }
        !           664:
        !           665: #endif /* NSEQUENCER > 0 */
        !           666: #endif /* NMIDI > 0 */

CVSweb