[BACK]Return to sock.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / aucat

Annotation of src/usr.bin/aucat/sock.c, Revision 1.14

1.14    ! ratchov     1: /*     $OpenBSD: sock.c,v 1.13 2009/02/04 20:35:14 ratchov Exp $       */
1.1       ratchov     2: /*
                      3:  * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17: /*
                     18:  * TODO:
                     19:  *
                     20:  *     change f->bufsz to contain only socket-side buffer,
                     21:  *     because it's less error prone
                     22:  */
                     23:
                     24: #include <stdio.h>
                     25: #include <stdlib.h>
                     26: #include <string.h>
                     27: #include "aproc.h"
                     28: #include "abuf.h"
                     29: #include "sock.h"
                     30: #include "dev.h"
                     31: #include "conf.h"
                     32:
                     33: int sock_attach(struct sock *, int);
                     34: int sock_read(struct sock *);
                     35: int sock_write(struct sock *);
                     36: int sock_execmsg(struct sock *);
                     37: void sock_reset(struct sock *);
                     38:
                     39: struct fileops sock_ops = {
                     40:        "sock",
                     41:        sizeof(struct sock),
                     42:                pipe_close,
                     43:        pipe_read,
                     44:        pipe_write,
                     45:        NULL, /* start */
                     46:        NULL, /* stop */
                     47:        pipe_nfds,
                     48:        pipe_pollfd,
                     49:        pipe_revents
                     50: };
                     51:
                     52: void
                     53: rsock_done(struct aproc *p)
                     54: {
                     55:        struct sock *f = (struct sock *)p->u.io.file;
                     56:
                     57:        DPRINTFN(1, "rsock_done: %p\n", f);
1.11      ratchov    58:        if (f == NULL)
                     59:                return;
1.1       ratchov    60:        sock_reset(f);
                     61:        f->pipe.file.rproc = NULL;
                     62:        if (f->pipe.file.wproc) {
                     63:                aproc_del(f->pipe.file.wproc);
                     64:                file_del(&f->pipe.file);
                     65:        }
1.11      ratchov    66:        p->u.io.file = NULL;
1.1       ratchov    67: }
                     68:
                     69: int
                     70: rsock_in(struct aproc *p, struct abuf *ibuf_dummy)
                     71: {
                     72:        struct sock *f = (struct sock *)p->u.io.file;
                     73:        struct abuf *obuf;
                     74:
                     75:        DPRINTFN(4, "rsock_in: %p\n", f);
                     76:
                     77:        if (!sock_read(f))
                     78:                return 0;
                     79:        obuf = LIST_FIRST(&p->obuflist);
                     80:        if (obuf) {
                     81:                if (!abuf_flush(obuf))
                     82:                        return 0;
                     83:        }
                     84:        return 1;
                     85: }
                     86:
                     87: int
                     88: rsock_out(struct aproc *p, struct abuf *obuf)
                     89: {
                     90:        struct sock *f = (struct sock *)p->u.io.file;
                     91:
                     92:        if (f->pipe.file.refs > 0)
                     93:                return 0;
                     94:
                     95:        DPRINTFN(4, "rsock_out: %p\n", f);
                     96:
1.12      ratchov    97:        /*
1.1       ratchov    98:         * when calling sock_read(), we may receive a ``STOP'' command,
                     99:         * and detach ``obuf''. In this case, there's no more caller and
                    100:         * we'll stop processing further messages, resulting in a dead lock.
                    101:         * The solution is to iterate over sock_read() in order to
                    102:         * consume all messages().
                    103:         */
                    104:        for (;;) {
                    105:                if (!sock_read(f))
1.12      ratchov   106:                        return 0;
1.1       ratchov   107:        }
                    108:        return 1;
                    109: }
                    110:
                    111: void
                    112: rsock_eof(struct aproc *p, struct abuf *ibuf_dummy)
                    113: {
                    114:        DPRINTFN(3, "rsock_eof: %p\n", p->u.io.file);
                    115:        aproc_del(p);
                    116: }
                    117:
                    118: void
                    119: rsock_hup(struct aproc *p, struct abuf *ibuf)
                    120: {
                    121:        DPRINTFN(3, "rsock_hup: %p\n", p->u.io.file);
                    122:        aproc_del(p);
                    123: }
                    124:
                    125: void
                    126: rsock_opos(struct aproc *p, struct abuf *obuf, int delta)
                    127: {
                    128:        struct sock *f = (struct sock *)p->u.io.file;
                    129:
1.14    ! ratchov   130:        if (!(f->mode & AMSG_PLAY))
        !           131:                return;
        !           132:
        !           133:        f->delta += delta;
        !           134:        DPRINTFN(3, "rsock_opos: %p: delta = %d, f->delta = %d\n",
        !           135:            f, delta, f->delta);
1.1       ratchov   136:
                    137:        /*
                    138:         * negative deltas are xrun notifications for internal uses
                    139:         * only. Dont generate a packet for this, the client will be
                    140:         * notified later.
                    141:         */
1.14    ! ratchov   142:        if (delta < 0)
1.1       ratchov   143:                return;
1.14    ! ratchov   144:        f->tickpending++;
1.1       ratchov   145:        for (;;) {
                    146:                if (!sock_write(f))
                    147:                        break;
                    148:        }
                    149: }
                    150:
                    151: struct aproc_ops rsock_ops = {
                    152:        "rsock",
                    153:        rsock_in,
                    154:        rsock_out,
                    155:        rsock_eof,
                    156:        rsock_hup,
                    157:        NULL, /* newin */
                    158:        NULL, /* newout */
                    159:        NULL, /* ipos */
                    160:        rsock_opos,
                    161:        rsock_done
                    162: };
                    163:
                    164: void
                    165: wsock_done(struct aproc *p)
                    166: {
                    167:        struct sock *f = (struct sock *)p->u.io.file;
                    168:
                    169:        DPRINTFN(1, "wsock_done: %p\n", f);
1.11      ratchov   170:        if (f == NULL)
                    171:                return;
1.1       ratchov   172:        sock_reset(f);
                    173:        f->pipe.file.wproc = NULL;
                    174:        if (f->pipe.file.rproc) {
                    175:                aproc_del(f->pipe.file.rproc);
                    176:                file_del(&f->pipe.file);
                    177:        }
1.11      ratchov   178:        p->u.io.file = NULL;
1.1       ratchov   179: }
                    180:
                    181: int
                    182: wsock_in(struct aproc *p, struct abuf *ibuf)
                    183: {
                    184:        struct sock *f = (struct sock *)p->u.io.file;
                    185:
                    186:        if (f->pipe.file.refs > 0)
                    187:                return 0;
                    188:
                    189:        DPRINTFN(4, "wsock_in: %p\n", f);
                    190:
                    191:        /*
                    192:         * see remark in rsock_out()
                    193:         */
                    194:        for (;;) {
                    195:                if (!sock_write(f))
                    196:                        return 0;
                    197:        }
                    198:        return 1;
                    199: }
                    200:
                    201: int
                    202: wsock_out(struct aproc *p, struct abuf *obuf_dummy)
                    203: {
                    204:        struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
                    205:        struct sock *f = (struct sock *)p->u.io.file;
                    206:
                    207:        DPRINTFN(3, "wsock_out: %p\n", f);
                    208:
                    209:        if (ibuf) {
                    210:                DPRINTFN(3, "wsock_out: %p, filling ibuf\n", f);
                    211:                if (!abuf_fill(ibuf))
                    212:                        return 0;
                    213:        }
                    214:        if (!sock_write(f))
                    215:                return 0;
                    216:        return 1;
                    217: }
                    218:
                    219: void
                    220: wsock_eof(struct aproc *p, struct abuf *obuf)
                    221: {
                    222:        DPRINTFN(3, "wsock_eof: %p\n", p->u.io.file);
                    223:        aproc_del(p);
                    224: }
                    225:
                    226: void
                    227: wsock_hup(struct aproc *p, struct abuf *obuf_dummy)
                    228: {
                    229:        DPRINTFN(3, "wsock_hup: %p\n", p->u.io.file);
                    230:        aproc_del(p);
                    231: }
                    232:
                    233: void
                    234: wsock_ipos(struct aproc *p, struct abuf *obuf, int delta)
                    235: {
                    236:        struct sock *f = (struct sock *)p->u.io.file;
                    237:
1.14    ! ratchov   238:        if (!(f->mode & AMSG_REC))
        !           239:                return;
1.1       ratchov   240:
1.14    ! ratchov   241:        f->delta += delta;
        !           242:        DPRINTFN(3, "wsock_ipos: %p, delta = %d, f->delta = %d\n",
        !           243:            f, delta, f->delta);
1.1       ratchov   244:        /*
                    245:         * negative deltas are xrun notifications for internal uses
                    246:         * only. Dont generate a packet for this, the client will be
                    247:         * notified later.
                    248:         */
1.14    ! ratchov   249:        if (delta < 0)
1.1       ratchov   250:                return;
1.14    ! ratchov   251:        f->tickpending++;
1.1       ratchov   252:        for (;;) {
                    253:                if (!sock_write(f))
                    254:                        break;
                    255:        }
                    256: }
                    257:
                    258: struct aproc_ops wsock_ops = {
                    259:        "wsock",
                    260:        wsock_in,
                    261:        wsock_out,
                    262:        wsock_eof,
                    263:        wsock_hup,
                    264:        NULL, /* newin */
                    265:        NULL, /* newout */
                    266:        wsock_ipos,
                    267:        NULL, /* opos */
                    268:        wsock_done
                    269: };
                    270:
                    271: /*
                    272:  * initialise socket in the SOCK_INIT state with default
                    273:  * parameters
                    274:  */
                    275: struct sock *
1.6       ratchov   276: sock_new(struct fileops *ops, int fd, char *name,
                    277:     struct aparams *wpar, struct aparams *rpar, int maxweight)
1.1       ratchov   278: {
                    279:        struct aproc *rproc, *wproc;
                    280:        struct sock *f;
                    281:
                    282:        f = (struct sock *)pipe_new(ops, fd, name);
1.13      ratchov   283:        if (f == NULL)
                    284:                return NULL;
1.1       ratchov   285:        f->pstate = SOCK_INIT;
                    286:        f->mode = 0;
1.6       ratchov   287:        if (dev_rec) {
                    288:                f->templ_wpar = *wpar;
                    289:                f->wpar = f->templ_wpar;
1.1       ratchov   290:                f->mode |= AMSG_REC;
                    291:        }
                    292:        if (dev_play) {
1.6       ratchov   293:                f->templ_rpar = *rpar;
                    294:                f->rpar = f->templ_rpar;
1.1       ratchov   295:                f->mode |= AMSG_PLAY;
                    296:        }
                    297:        f->xrun = AMSG_IGNORE;
1.10      ratchov   298:        f->bufsz = dev_bufsz;
1.1       ratchov   299:        f->round = dev_round;
1.14    ! ratchov   300:        f->delta = 0;
        !           301:        f->tickpending = 0;
1.4       ratchov   302:        f->maxweight = maxweight;
1.3       ratchov   303:        f->vol = ADATA_UNIT;
1.1       ratchov   304:
                    305:        wproc = aproc_new(&wsock_ops, name);
                    306:        wproc->u.io.file = &f->pipe.file;
                    307:        f->pipe.file.wproc = wproc;
                    308:        f->wstate = SOCK_WIDLE;
                    309:        f->wtodo = 0xdeadbeef;
                    310:
                    311:        rproc = aproc_new(&rsock_ops, name);
                    312:        rproc->u.io.file = &f->pipe.file;
                    313:        f->pipe.file.rproc = rproc;
                    314:        f->rstate = SOCK_RMSG;
                    315:        f->rtodo = sizeof(struct amsg);
                    316:        return f;
                    317: }
                    318:
                    319: /*
                    320:  * free buffers
                    321:  */
                    322: void
                    323: sock_freebuf(struct sock *f)
                    324: {
                    325:        struct abuf *rbuf, *wbuf;
1.12      ratchov   326:
1.1       ratchov   327:        f->pstate = SOCK_INIT;
                    328:        DPRINTF("sock_freebuf:\n");
                    329:        rbuf = LIST_FIRST(&f->pipe.file.rproc->obuflist);
                    330:        if (rbuf)
                    331:                abuf_eof(rbuf);
                    332:        wbuf = LIST_FIRST(&f->pipe.file.wproc->ibuflist);
                    333:        if (wbuf)
                    334:                abuf_hup(wbuf);
                    335: }
                    336:
                    337: /*
                    338:  * allocate buffers, so client can start filling write-end.
                    339:  */
                    340: void
                    341: sock_allocbuf(struct sock *f)
                    342: {
                    343:        struct abuf *rbuf = NULL, *wbuf = NULL;
                    344:
                    345:        if (f->mode & AMSG_PLAY) {
1.10      ratchov   346:                rbuf = abuf_new(f->bufsz, &f->rpar);
1.1       ratchov   347:                aproc_setout(f->pipe.file.rproc, rbuf);
                    348:        }
                    349:        if (f->mode & AMSG_REC) {
1.10      ratchov   350:                wbuf = abuf_new(f->bufsz, &f->wpar);
1.1       ratchov   351:                aproc_setin(f->pipe.file.wproc, wbuf);
                    352:        }
1.14    ! ratchov   353:        f->delta = 0;
        !           354:        f->tickpending = 0;
1.1       ratchov   355:
1.10      ratchov   356:        DPRINTF("sock_allocbuf: %p, using %u frames buffer\n", f, f->bufsz);
1.1       ratchov   357:
                    358:        f->pstate = SOCK_START;
                    359:        if (!(f->mode & AMSG_PLAY))
                    360:                (void)sock_attach(f, 0);
                    361: }
                    362:
                    363: /*
1.3       ratchov   364:  * free buffers
                    365:  */
                    366: void
                    367: sock_setvol(struct sock *f, int vol)
                    368: {
                    369:        struct abuf *rbuf;
1.12      ratchov   370:
1.3       ratchov   371:        f->vol = vol;
1.12      ratchov   372:        rbuf = LIST_FIRST(&f->pipe.file.rproc->obuflist);
1.3       ratchov   373:        if (!rbuf) {
                    374:                DPRINTF("sock_setvol: no read buffer yet\n");
                    375:                return;
                    376:        }
                    377:        dev_setvol(rbuf, vol);
                    378: }
                    379:
                    380: /*
1.1       ratchov   381:  * attach play and/or record buffers to dev_mix and/or dev_sub
                    382:  */
                    383: int
                    384: sock_attach(struct sock *f, int force)
                    385: {
                    386:        struct abuf *rbuf, *wbuf;
                    387:
                    388:        rbuf = LIST_FIRST(&f->pipe.file.rproc->obuflist);
                    389:        wbuf = LIST_FIRST(&f->pipe.file.wproc->ibuflist);
                    390:
                    391:        /*
                    392:         * if in SOCK_START state, dont attach until
                    393:         * the buffer isn't completely filled
                    394:         */
                    395:        if (!force && rbuf && ABUF_WOK(rbuf))
                    396:                return 0;
1.12      ratchov   397:
1.1       ratchov   398:        DPRINTF("sock_attach: %p\n", f);
                    399:        f->pstate = SOCK_RUN;
                    400:
                    401:        /*
                    402:         * attach them to the device
                    403:         */
                    404:        dev_attach(f->pipe.file.name,
                    405:            (f->mode & AMSG_PLAY) ? rbuf : NULL, &f->rpar, f->xrun,
1.4       ratchov   406:            (f->mode & AMSG_REC)  ? wbuf : NULL, &f->wpar, f->xrun,
                    407:            f->maxweight);
1.3       ratchov   408:        if (f->mode & AMSG_PLAY)
                    409:                dev_setvol(rbuf, f->vol);
                    410:
1.1       ratchov   411:        /*
                    412:         * send the initial position, if needed
                    413:         */
                    414:        for (;;) {
                    415:                if (!sock_write(f))
                    416:                        break;
                    417:        }
                    418:        return 1;
                    419: }
                    420:
                    421: void
                    422: sock_reset(struct sock *f)
                    423: {
                    424:        switch (f->pstate) {
                    425:        case SOCK_START:
                    426:                (void)sock_attach(f, 1);
                    427:                f->pstate = SOCK_RUN;
                    428:                /* PASSTHROUGH */
                    429:        case SOCK_RUN:
                    430:                sock_freebuf(f);
                    431:                f->pstate = SOCK_INIT;
                    432:                /* PASSTHROUGH */
                    433:        case SOCK_INIT:
                    434:                /* nothing yet */
                    435:                break;
                    436:        }
                    437: }
                    438:
                    439: /*
                    440:  * read a message from the file descriptor, return 1 if done, 0
                    441:  * otherwise. The message is stored in f->rmsg
                    442:  */
                    443: int
                    444: sock_rmsg(struct sock *f)
                    445: {
                    446:        unsigned count;
                    447:        unsigned char *data;
                    448:
                    449:        while (f->rtodo > 0) {
                    450:                if (!(f->pipe.file.state & FILE_ROK)) {
                    451:                        DPRINTFN(4, "sock_rmsg: blk, rtodo = %u\n", f->rtodo);
                    452:                        return 0;
                    453:                }
                    454:                data = (unsigned char *)&f->rmsg;
                    455:                data += sizeof(struct amsg) - f->rtodo;
                    456:                count = file_read(&f->pipe.file, data, f->rtodo);
                    457:                if (count == 0)
                    458:                        return 0;
                    459:                f->rtodo -= count;
                    460:        }
                    461:        DPRINTFN(4, "sock_rmsg: %p: done\n", f);
                    462:        return 1;
                    463: }
                    464:
                    465: /*
                    466:  * write a message to the file descriptor, return 1 if done, 0
                    467:  * otherwise.  The "m" argument is f->rmsg or f->wmsg, and the "ptodo"
                    468:  * points to the f->rtodo or f->wtodo respectively.
                    469:  */
                    470: int
                    471: sock_wmsg(struct sock *f, struct amsg *m, unsigned *ptodo)
                    472: {
                    473:        unsigned count;
                    474:        unsigned char *data;
                    475:
                    476:        while (*ptodo > 0) {
                    477:                if (!(f->pipe.file.state & FILE_WOK)) {
                    478:                        DPRINTFN(4, "sock_wmsg: blk, *ptodo = %u\n", *ptodo);
                    479:                        return 0;
                    480:                }
                    481:                data = (unsigned char *)m;
                    482:                data += sizeof(struct amsg) - *ptodo;
                    483:                count = file_write(&f->pipe.file, data, *ptodo);
                    484:                if (count == 0)
                    485:                        return 0;
                    486:                *ptodo -= count;
                    487:        }
                    488:        DPRINTFN(4, "sock_wmsg: %p: done\n", f);
                    489:        return 1;
                    490: }
                    491:
                    492: /*
                    493:  * read data chunk from the file descriptor, return 1 if at least one
                    494:  * byte was read, 0 if the file blocked.
                    495:  */
                    496: int
                    497: sock_rdata(struct sock *f)
                    498: {
                    499:        struct aproc *p;
                    500:        struct abuf *obuf;
                    501:        unsigned char *data;
                    502:        unsigned count, n;
                    503:
                    504: #ifdef DEBUG
                    505:        if (f->rtodo == 0) {
                    506:                fprintf(stderr, "sock_rdata: bad call: zero arg\n");
                    507:                abort();
                    508:        }
                    509: #endif
                    510:        p = f->pipe.file.rproc;
                    511:        obuf = LIST_FIRST(&p->obuflist);
                    512:        if (ABUF_FULL(obuf) || !(f->pipe.file.state & FILE_ROK))
                    513:                return 0;
                    514:        data = abuf_wgetblk(obuf, &count, 0);
                    515:        if (count > f->rtodo)
                    516:                count = f->rtodo;
                    517:        n = file_read(&f->pipe.file, data, count);
                    518:        if (n == 0)
                    519:                return 0;
                    520:        abuf_wcommit(obuf, n);
                    521:        f->rtodo -= n;
                    522:        return 1;
                    523: }
                    524:
                    525: /*
                    526:  * write data chunk to the file descriptor, return 1 if at least one
                    527:  * byte was written, 0 if the file blocked.
                    528:  */
                    529: int
                    530: sock_wdata(struct sock *f)
                    531: {
                    532:        struct aproc *p;
                    533:        struct abuf *ibuf;
                    534:        unsigned char *data;
                    535:        unsigned count, n;
                    536: #define ZERO_MAX 0x1000
                    537:        static char zero[ZERO_MAX];
                    538:
                    539: #ifdef DEBUG
                    540:        if (f->wtodo == 0) {
                    541:                fprintf(stderr, "sock_wdata: bad call: zero arg\n");
                    542:                abort();
                    543:        }
                    544: #endif
                    545:        if (!(f->pipe.file.state & FILE_WOK))
                    546:                return 0;
                    547:        p = f->pipe.file.wproc;
                    548:        ibuf = LIST_FIRST(&p->ibuflist);
                    549:        if (ibuf) {
                    550:                if (ABUF_EMPTY(ibuf))
                    551:                        return 0;
                    552:                data = abuf_rgetblk(ibuf, &count, 0);
                    553:                if (count > f->wtodo)
                    554:                        count = f->wtodo;
                    555:                n = file_write(&f->pipe.file, data, count);
                    556:                if (n == 0)
                    557:                        return 0;
                    558:                abuf_rdiscard(ibuf, n);
                    559:                f->wtodo -= n;
                    560:        } else {
                    561:                /*
                    562:                 * there's no dev_detach() routine yet,
                    563:                 * so now we abruptly destroy the buffer.
                    564:                 * Until we implement dev_detach, complete
                    565:                 * the packet with zeros...
                    566:                 */
                    567:                count = ZERO_MAX;
                    568:                if (count > f->wtodo)
                    569:                        count = f->wtodo;
                    570:                n = file_write(&f->pipe.file, zero, count);
                    571:                if (n == 0)
                    572:                        return 0;
                    573:                f->wtodo -= n;
1.12      ratchov   574:        }
1.1       ratchov   575:        return 1;
                    576: }
                    577:
                    578: int
                    579: sock_setpar(struct sock *f)
                    580: {
                    581:        struct amsg_par *p = &f->rmsg.u.par;
1.9       ratchov   582:        unsigned min, max, rate;
1.12      ratchov   583:
1.1       ratchov   584:        if (AMSG_ISSET(p->mode)) {
                    585:                if ((p->mode & ~(AMSG_PLAY | AMSG_REC)) || p->mode == 0) {
                    586:                        DPRINTF("sock_setpar: bad mode %x\n", p->mode);
                    587:                        return 0;
                    588:                }
                    589:                f->mode = 0;
                    590:                if ((p->mode & AMSG_PLAY) && dev_mix)
                    591:                        f->mode |= AMSG_PLAY;
                    592:                if ((p->mode & AMSG_REC) && dev_sub)
                    593:                        f->mode |= AMSG_REC;
                    594:                DPRINTF("sock_setpar: mode -> %x\n", f->mode);
                    595:        }
                    596:        if (AMSG_ISSET(p->bits)) {
                    597:                if (p->bits < BITS_MIN || p->bits > BITS_MAX) {
                    598:                        DPRINTF("sock_setpar: bits out of bounds\n");
                    599:                        return 0;
                    600:                }
                    601:                if (AMSG_ISSET(p->bps)) {
                    602:                        if (p->bps < ((p->bits + 7) / 8) || p->bps > 4) {
                    603:                                DPRINTF("sock_setpar: bps out of bounds\n");
                    604:                                return 0;
                    605:                        }
                    606:                } else
                    607:                        p->bps = APARAMS_BPS(p->bits);
                    608:                f->rpar.bits = f->wpar.bits = p->bits;
                    609:                f->rpar.bps = f->wpar.bps = p->bps;
                    610:                DPRINTF("sock_setpar: bits/bps -> %u/%u\n", p->bits, p->bps);
                    611:        }
                    612:        if (AMSG_ISSET(p->sig))
                    613:                f->rpar.sig = f->wpar.sig = p->sig ? 1 : 0;
                    614:        if (AMSG_ISSET(p->le))
                    615:                f->rpar.le = f->wpar.le = p->le ? 1 : 0;
                    616:        if (AMSG_ISSET(p->msb))
                    617:                f->rpar.msb = f->wpar.msb = p->msb ? 1 : 0;
                    618:        if (AMSG_ISSET(p->rchan) && (f->mode & AMSG_REC)) {
                    619:                if (p->rchan < 1)
                    620:                        p->rchan = 1;
1.6       ratchov   621:                if (p->rchan > NCHAN_MAX)
                    622:                        p->rchan = NCHAN_MAX;
                    623:                f->wpar.cmin = f->templ_wpar.cmin;
                    624:                f->wpar.cmax = f->templ_wpar.cmin + p->rchan - 1;
1.7       ratchov   625:                if (f->wpar.cmax > f->templ_wpar.cmax)
                    626:                        f->wpar.cmax = f->templ_wpar.cmax;
1.6       ratchov   627:                DPRINTF("sock_setpar: rchan -> %u:%u\n",
                    628:                    f->wpar.cmin, f->wpar.cmax);
1.1       ratchov   629:        }
                    630:        if (AMSG_ISSET(p->pchan) && (f->mode & AMSG_PLAY)) {
                    631:                if (p->pchan < 1)
                    632:                        p->pchan = 1;
1.6       ratchov   633:                if (p->pchan > NCHAN_MAX)
                    634:                        p->pchan = NCHAN_MAX;
                    635:                f->rpar.cmin = f->templ_rpar.cmin;
1.7       ratchov   636:                f->rpar.cmax = f->templ_rpar.cmin + p->pchan - 1;
                    637:                if (f->rpar.cmax > f->templ_rpar.cmax)
                    638:                        f->rpar.cmax = f->templ_rpar.cmax;
1.6       ratchov   639:                DPRINTF("sock_setpar: pchan -> %u:%u\n",
                    640:                    f->rpar.cmin, f->rpar.cmax);
1.1       ratchov   641:        }
                    642:        if (AMSG_ISSET(p->rate)) {
                    643:                if (p->rate < RATE_MIN)
                    644:                        p->rate = RATE_MIN;
                    645:                if (p->rate > RATE_MAX)
                    646:                        p->rate = RATE_MAX;
1.9       ratchov   647:                f->round = dev_roundof(p->rate);
1.1       ratchov   648:                f->rpar.rate = f->wpar.rate = p->rate;
1.10      ratchov   649:                if (!AMSG_ISSET(p->appbufsz)) {
                    650:                        p->appbufsz = dev_bufsz / dev_round * f->round;
                    651:                        DPRINTF("sock_setpar: appbufsz -> %u\n", p->appbufsz);
                    652:                }
1.9       ratchov   653:                DPRINTF("sock_setpar: rate -> %u, round -> %u\n",
                    654:                    p->rate, f->round);
1.1       ratchov   655:        }
                    656:        if (AMSG_ISSET(p->xrun)) {
                    657:                if (p->xrun != AMSG_IGNORE &&
                    658:                    p->xrun != AMSG_SYNC &&
                    659:                    p->xrun != AMSG_ERROR) {
                    660:                        DPRINTF("sock_setpar: bad xrun: %u\n", p->xrun);
                    661:                        return 0;
                    662:                }
                    663:                f->xrun = p->xrun;
                    664:                DPRINTF("sock_setpar: xrun -> %u\n", f->xrun);
                    665:        }
                    666:        if (AMSG_ISSET(p->bufsz)) {
1.10      ratchov   667:                /*
                    668:                 * XXX: bufsz will become read-only, but for now
                    669:                 *      allow old library to properly work
                    670:                 */
                    671:                DPRINTF("sock_setpar: bufsz: %u\n", p->bufsz);
                    672:                min = (dev_bufsz / dev_round) * f->round;
                    673:                if (p->bufsz < min)
                    674:                        p->bufsz = min;
                    675:                p->appbufsz = p->bufsz - min;
                    676:        }
                    677:        if (AMSG_ISSET(p->appbufsz)) {
1.9       ratchov   678:                rate = (f->mode & AMSG_PLAY) ? f->rpar.rate : f->wpar.rate;
1.10      ratchov   679:                min = 1;
                    680:                max = 1 + rate / dev_round;
1.9       ratchov   681:                min *= f->round;
                    682:                max *= f->round;
1.10      ratchov   683:                p->appbufsz += f->round - 1;
                    684:                p->appbufsz -= p->appbufsz % f->round;
                    685:                if (p->appbufsz < min)
                    686:                        p->appbufsz = min;
                    687:                if (p->appbufsz > max)
                    688:                        p->appbufsz = max;
                    689:                f->bufsz = p->appbufsz;
1.1       ratchov   690:                DPRINTF("sock_setpar: bufsz -> %u\n", f->bufsz);
                    691:        }
1.5       ratchov   692: #ifdef DEBUG
1.1       ratchov   693:        if (debug_level > 0) {
                    694:                fprintf(stderr, "sock_setpar: %p: rpar=", f);
                    695:                aparams_print(&f->rpar);
                    696:                fprintf(stderr, ", wpar=");
                    697:                aparams_print(&f->wpar);
                    698:                fprintf(stderr, ", mode=%u, bufsz=%u\n", f->mode, f->bufsz);
                    699:        }
1.5       ratchov   700: #endif
1.1       ratchov   701:        return 1;
                    702: }
                    703:
                    704: /*
                    705:  * execute message in f->rmsg and change the state accordingly; return 1
                    706:  * on success, and 0 on failure, in which case the socket is destroyed.
                    707:  */
                    708: int
                    709: sock_execmsg(struct sock *f)
                    710: {
                    711:        struct amsg *m = &f->rmsg;
                    712:
                    713:        switch (m->cmd) {
                    714:        case AMSG_DATA:
                    715:                DPRINTFN(4, "sock_execmsg: %p: DATA\n", f);
                    716:                if (f->pstate != SOCK_RUN && f->pstate != SOCK_START) {
                    717:                        DPRINTF("sock_execmsg: %p: DATA, bad state\n", f);
1.8       ratchov   718:                        aproc_del(f->pipe.file.rproc);
                    719:                        return 0;
                    720:                }
                    721:                if (!(f->mode & AMSG_PLAY)) {
                    722:                        DPRINTF("sock_execmsg: %p: DATA, not allowed\n", f);
1.1       ratchov   723:                        aproc_del(f->pipe.file.rproc);
                    724:                        return 0;
                    725:                }
                    726:                f->rstate = SOCK_RDATA;
                    727:                f->rtodo = m->u.data.size;
                    728:                if (f->rtodo == 0) {
                    729:                        DPRINTF("sock_execmsg: zero-length data chunk\n");
                    730:                        aproc_del(f->pipe.file.rproc);
                    731:                        return 0;
                    732:                }
                    733:                break;
                    734:        case AMSG_START:
                    735:                DPRINTFN(2, "sock_execmsg: %p: START\n", f);
                    736:                if (f->pstate != SOCK_INIT) {
                    737:                        DPRINTF("sock_execmsg: %p: START, bad state\n", f);
                    738:                        aproc_del(f->pipe.file.rproc);
                    739:                        return 0;
                    740:                }
                    741:                sock_allocbuf(f);
                    742:                f->rstate = SOCK_RMSG;
                    743:                f->rtodo = sizeof(struct amsg);
                    744:                break;
                    745:        case AMSG_STOP:
                    746:                DPRINTFN(2, "sock_execmsg: %p: STOP\n", f);
                    747:                if (f->pstate != SOCK_RUN && f->pstate != SOCK_START) {
                    748:                        DPRINTF("sock_execmsg: %p: STOP, bad state\n", f);
                    749:                        aproc_del(f->pipe.file.rproc);
                    750:                        return 0;
                    751:                }
                    752:                if (f->pstate == SOCK_START)
                    753:                        (void)sock_attach(f, 1);
                    754:                sock_freebuf(f);
                    755:                AMSG_INIT(m);
                    756:                m->cmd = AMSG_ACK;
                    757:                f->rstate = SOCK_RRET;
                    758:                f->rtodo = sizeof(struct amsg);
                    759:                break;
                    760:        case AMSG_SETPAR:
                    761:                DPRINTFN(2, "sock_execmsg: %p: SETPAR\n", f);
                    762:                if (f->pstate != SOCK_INIT) {
                    763:                        DPRINTF("sock_execmsg: %p: SETPAR, bad state\n", f);
                    764:                        aproc_del(f->pipe.file.rproc);
                    765:                        return 0;
                    766:                }
                    767:                if (!sock_setpar(f)) {
                    768:                        aproc_del(f->pipe.file.rproc);
                    769:                        return 0;
                    770:                }
                    771:                f->rtodo = sizeof(struct amsg);
                    772:                f->rstate = SOCK_RMSG;
                    773:                break;
                    774:        case AMSG_GETPAR:
                    775:                DPRINTFN(2, "sock_execmsg: %p: GETPAR\n", f);
                    776:                if (f->pstate != SOCK_INIT) {
                    777:                        DPRINTF("sock_execmsg: %p: GETPAR, bad state\n", f);
                    778:                        aproc_del(f->pipe.file.rproc);
                    779:                        return 0;
                    780:                }
                    781:                AMSG_INIT(m);
                    782:                m->cmd = AMSG_GETPAR;
                    783:                m->u.par.mode = f->mode;
                    784:                m->u.par.bits = f->rpar.bits;
                    785:                m->u.par.bps = f->rpar.bps;
                    786:                m->u.par.sig = f->rpar.sig;
                    787:                m->u.par.le = f->rpar.le;
                    788:                m->u.par.msb = f->rpar.msb;
                    789:                m->u.par.rate = f->rpar.rate;
                    790:                m->u.par.rchan = f->wpar.cmax - f->wpar.cmin + 1;
                    791:                m->u.par.pchan = f->rpar.cmax - f->rpar.cmin + 1;
1.10      ratchov   792:                m->u.par.appbufsz = f->bufsz;
1.12      ratchov   793:                m->u.par.bufsz =
1.10      ratchov   794:                    f->bufsz + (dev_bufsz / dev_round) * f->round;
1.1       ratchov   795:                m->u.par.round = f->round;
                    796:                f->rstate = SOCK_RRET;
                    797:                f->rtodo = sizeof(struct amsg);
                    798:                break;
                    799:        case AMSG_GETCAP:
                    800:                DPRINTFN(2, "sock_execmsg: %p: GETCAP\n", f);
                    801:                if (f->pstate != SOCK_INIT) {
                    802:                        DPRINTF("sock_execmsg: %p: GETCAP, bad state\n", f);
                    803:                        aproc_del(f->pipe.file.rproc);
                    804:                        return 0;
                    805:                }
                    806:                AMSG_INIT(m);
                    807:                m->cmd = AMSG_GETCAP;
                    808:                m->u.cap.rate = dev_rate;
1.6       ratchov   809:                m->u.cap.pchan = dev_mix ?
                    810:                    (f->templ_rpar.cmax - f->templ_rpar.cmin + 1) : 0;
                    811:                m->u.cap.rchan = dev_sub ?
                    812:                    (f->templ_wpar.cmax - f->templ_wpar.cmin + 1) : 0;
1.1       ratchov   813:                m->u.cap.bits = sizeof(short) * 8;
                    814:                m->u.cap.bps = sizeof(short);
                    815:                f->rstate = SOCK_RRET;
                    816:                f->rtodo = sizeof(struct amsg);
1.3       ratchov   817:                break;
                    818:        case AMSG_SETVOL:
                    819:                DPRINTFN(2, "sock_execmsg: %p: SETVOL\n", f);
                    820:                if (f->pstate != SOCK_RUN &&
                    821:                    f->pstate != SOCK_START && f->pstate != SOCK_INIT) {
                    822:                        DPRINTF("sock_execmsg: %p: SETVOL, bad state\n", f);
                    823:                        aproc_del(f->pipe.file.rproc);
                    824:                        return 0;
                    825:                }
                    826:                if (m->u.vol.ctl > MIDI_MAXCTL) {
                    827:                        DPRINTF("sock_execmsg: %p: SETVOL, out of range\n", f);
                    828:                        aproc_del(f->pipe.file.rproc);
                    829:                        return 0;
                    830:                }
                    831:                DPRINTF("sock_execmsg: SETVOL %u\n", m->u.vol.ctl);
                    832:                sock_setvol(f, MIDI_TO_ADATA(m->u.vol.ctl));
                    833:                f->rtodo = sizeof(struct amsg);
                    834:                f->rstate = SOCK_RMSG;
1.1       ratchov   835:                break;
                    836:        default:
                    837:                DPRINTF("sock_execmsg: %p bogus command\n", f);
                    838:                aproc_del(f->pipe.file.rproc);
                    839:                return 0;
                    840:        }
                    841:        if (f->rstate == SOCK_RRET) {
                    842:                if (f->wstate != SOCK_WIDLE ||
                    843:                    !sock_wmsg(f, &f->rmsg, &f->rtodo))
                    844:                        return 0;
                    845:                DPRINTF("sock_execmsg: %p RRET done\n", f);
                    846:                f->rtodo = sizeof(struct amsg);
                    847:                f->rstate = SOCK_RMSG;
                    848:        }
                    849:        return 1;
                    850: }
                    851:
                    852: /*
                    853:  * create a new data/pos message
                    854:  */
                    855: int
                    856: sock_buildmsg(struct sock *f)
                    857: {
                    858:        struct aproc *p;
                    859:        struct abuf *ibuf;
1.12      ratchov   860:
1.1       ratchov   861:        /*
                    862:         * if pos changed, build a MOVE message
                    863:         */
1.14    ! ratchov   864:        if (f->tickpending && f->delta >= 0) {
        !           865:                DPRINTFN(4, "sock_buildmsg: %p: POS: %d\n", f, f->delta);
1.1       ratchov   866:                AMSG_INIT(&f->wmsg);
                    867:                f->wmsg.cmd = AMSG_MOVE;
1.14    ! ratchov   868:                f->wmsg.u.ts.delta = f->delta;
1.1       ratchov   869:                f->wtodo = sizeof(struct amsg);
                    870:                f->wstate = SOCK_WMSG;
1.14    ! ratchov   871:                f->delta = 0;
        !           872:                f->tickpending = 0;
1.1       ratchov   873:                return 1;
                    874:        }
                    875:
                    876:        /*
                    877:         * if data available, build a DATA message
                    878:         */
                    879:        p = f->pipe.file.wproc;
                    880:        ibuf = LIST_FIRST(&p->ibuflist);
                    881:        if (ibuf && ABUF_ROK(ibuf)) {
                    882:                AMSG_INIT(&f->wmsg);
                    883:                f->wmsg.cmd = AMSG_DATA;
                    884:                f->wmsg.u.data.size = ibuf->used - (ibuf->used % ibuf->bpf);
                    885:                if (f->wmsg.u.data.size > AMSG_DATAMAX)
                    886:                        f->wmsg.u.data.size =
                    887:                            AMSG_DATAMAX - (AMSG_DATAMAX % ibuf->bpf);
                    888:                f->wtodo = sizeof(struct amsg);
                    889:                f->wstate = SOCK_WMSG;
                    890:                return 1;
                    891:        }
                    892:
                    893:        DPRINTFN(4, "sock_buildmsg: %p: idling...\n", f);
                    894:        f->wstate = SOCK_WIDLE;
                    895:        return 0;
                    896: }
                    897:
                    898: /*
                    899:  * read from the socket file descriptor, fill input buffer and update
                    900:  * the state. Return 1 if at least one message or 1 data byte was
                    901:  * processed, 0 if something blocked.
                    902:  */
                    903: int
                    904: sock_read(struct sock *f)
                    905: {
                    906:        DPRINTFN(4, "sock_read: %p; rstate = %u, rtodo = %u\n",
                    907:            f, f->rstate, f->rtodo);
                    908:
                    909:        switch (f->rstate) {
                    910:        case SOCK_RMSG:
                    911:                if (!sock_rmsg(f))
                    912:                        return 0;
                    913:                if (!sock_execmsg(f))
                    914:                        return 0;
                    915:                break;
                    916:        case SOCK_RDATA:
                    917:                if (!sock_rdata(f))
                    918:                        return 0;
                    919:                if (f->rtodo == 0) {
                    920:                        f->rstate = SOCK_RMSG;
                    921:                        f->rtodo = sizeof(struct amsg);
                    922:                }
                    923:                if (f->pstate == SOCK_START)
                    924:                        (void)sock_attach(f, 0);
                    925:                break;
                    926:        case SOCK_RRET:
                    927:                DPRINTF("sock_read: %p: blocked in RRET\n", f);
                    928:                return 0;
                    929:        }
                    930:        DPRINTFN(4, "sock_read: %p: done, rstate = %u\n", f, f->rstate);
                    931:        return 1;
                    932: }
                    933:
                    934: /*
                    935:  * process messages to return
                    936:  */
                    937: int
                    938: sock_return(struct sock *f)
                    939: {
                    940:        struct aproc *rp;
                    941:
                    942:        while (f->rstate == SOCK_RRET) {
                    943:                if (!sock_wmsg(f, &f->rmsg, &f->rtodo))
                    944:                        return 0;
                    945:                DPRINTF("sock_return: %p: done\n", f);
                    946:                f->rstate = SOCK_RMSG;
                    947:                f->rtodo = sizeof(struct amsg);
                    948:                for (;;) {
                    949:                        /*
                    950:                         * in() may trigger rsock_done and destroy the
                    951:                         * wsock
                    952:                         */
                    953:                        rp = f->pipe.file.rproc;
                    954:                        if (!rp || !rp->ops->in(rp, NULL))
                    955:                                break;
                    956:                }
                    957:                if (f->pipe.file.wproc == NULL)
                    958:                        return 0;
                    959:        }
                    960:        return 1;
                    961: }
                    962:
                    963: /*
                    964:  * write messages and data on the socket file descriptor. Return 1 if
                    965:  * at least one message or one data byte was processed, 0 if something
                    966:  * blocked.
                    967:  */
                    968: int
                    969: sock_write(struct sock *f)
                    970: {
                    971:        DPRINTFN(4, "sock_write: %p: wstate = %u, wtodo = %u\n",
                    972:            f, f->wstate, f->wtodo);
                    973:
                    974:        switch (f->wstate) {
                    975:        case SOCK_WMSG:
                    976:                if (!sock_wmsg(f, &f->wmsg, &f->wtodo))
                    977:                        return 0;
                    978:                if (f->wmsg.cmd != AMSG_DATA) {
                    979:                        f->wstate = SOCK_WIDLE;
                    980:                        f->wtodo = 0xdeadbeef;
                    981:                        break;
                    982:                }
                    983:                f->wstate = SOCK_WDATA;
                    984:                f->wtodo = f->wmsg.u.data.size;
                    985:                /* PASSTHROUGH */
                    986:        case SOCK_WDATA:
                    987:                if (!sock_wdata(f))
                    988:                        return 0;
                    989:                if (f->wtodo > 0)
                    990:                        break;
                    991:                f->wstate = SOCK_WIDLE;
                    992:                f->wtodo = 0xdeadbeef;
                    993:                /* PASSTHROUGH */
                    994:        case SOCK_WIDLE:
                    995:                if (!sock_return(f))
                    996:                        return 0;
                    997:                if (!sock_buildmsg(f))
                    998:                        return 0;
                    999:                break;
                   1000:        default:
                   1001:                fprintf(stderr, "sock_write: unknown state\n");
                   1002:                abort();
                   1003:        }
                   1004:        return 1;
                   1005: }