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