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: }