root/dev/midi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. midi_iintr
  2. midiread
  3. midi_ointr
  4. midi_out_start
  5. midi_out_stop
  6. midi_out_do
  7. midiwrite
  8. midipoll
  9. midiioctl
  10. midiopen
  11. midiclose
  12. midiprobe
  13. midi_attach
  14. midiattach
  15. mididetach
  16. midiprint
  17. midi_getinfo
  18. midi_attach_mi
  19. midi_unit_count
  20. midi_toevent
  21. midi_writebytes

    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 */

/* [<][>][^][v][top][bottom][index][help] */