[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.6

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