Annotation of src/usr.bin/aucat/sock.c, Revision 1.3
1.3 ! ratchov 1: /* $OpenBSD: sock.c,v 1.2 2008/11/03 22:25:13 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 *
263: sock_new(struct fileops *ops, int fd, char *name)
264: {
265: struct aproc *rproc, *wproc;
266: struct sock *f;
267:
268: f = (struct sock *)pipe_new(ops, fd, name);
269: f->pstate = SOCK_INIT;
270: f->mode = 0;
271: if (dev_rec) {
272: f->wpar = dev_ipar;
273: f->mode |= AMSG_REC;
274: }
275: if (dev_play) {
276: f->rpar = dev_opar;
277: f->mode |= AMSG_PLAY;
278: }
279: f->xrun = AMSG_IGNORE;
280: f->bufsz = 2 * dev_bufsz;
281: f->round = dev_round;
282: f->odelta = f->idelta = 0;
1.3 ! ratchov 283: f->vol = ADATA_UNIT;
1.1 ratchov 284:
285: wproc = aproc_new(&wsock_ops, name);
286: wproc->u.io.file = &f->pipe.file;
287: f->pipe.file.wproc = wproc;
288: f->wstate = SOCK_WIDLE;
289: f->wtodo = 0xdeadbeef;
290:
291: rproc = aproc_new(&rsock_ops, name);
292: rproc->u.io.file = &f->pipe.file;
293: f->pipe.file.rproc = rproc;
294: f->rstate = SOCK_RMSG;
295: f->rtodo = sizeof(struct amsg);
296: return f;
297: }
298:
299: /*
300: * free buffers
301: */
302: void
303: sock_freebuf(struct sock *f)
304: {
305: struct abuf *rbuf, *wbuf;
306:
307: f->pstate = SOCK_INIT;
308: DPRINTF("sock_freebuf:\n");
309: rbuf = LIST_FIRST(&f->pipe.file.rproc->obuflist);
310: if (rbuf)
311: abuf_eof(rbuf);
312: wbuf = LIST_FIRST(&f->pipe.file.wproc->ibuflist);
313: if (wbuf)
314: abuf_hup(wbuf);
315: }
316:
317: /*
318: * allocate buffers, so client can start filling write-end.
319: */
320: void
321: sock_allocbuf(struct sock *f)
322: {
323: struct abuf *rbuf = NULL, *wbuf = NULL;
324: unsigned nfr = 0;
325:
326: if (f->mode & AMSG_PLAY) {
327: nfr = f->bufsz - dev_bufsz * f->rpar.rate / dev_rate;
1.2 ratchov 328: rbuf = abuf_new(nfr, &f->rpar);
1.1 ratchov 329: aproc_setout(f->pipe.file.rproc, rbuf);
330: f->odelta = 0;
331: }
332: if (f->mode & AMSG_REC) {
333: nfr = f->bufsz - dev_bufsz * f->wpar.rate / dev_rate;
1.2 ratchov 334: wbuf = abuf_new(nfr, &f->wpar);
1.1 ratchov 335: aproc_setin(f->pipe.file.wproc, wbuf);
336: f->idelta = 0;
337: }
338:
339: DPRINTF("sock_allocbuf: %p, using %u/%u frames buffer\n",
340: f, nfr, f->bufsz);
341:
342: f->pstate = SOCK_START;
343: if (!(f->mode & AMSG_PLAY))
344: (void)sock_attach(f, 0);
345: }
346:
347: /*
1.3 ! ratchov 348: * free buffers
! 349: */
! 350: void
! 351: sock_setvol(struct sock *f, int vol)
! 352: {
! 353: struct abuf *rbuf;
! 354:
! 355: f->vol = vol;
! 356: rbuf = LIST_FIRST(&f->pipe.file.rproc->obuflist);
! 357: if (!rbuf) {
! 358: DPRINTF("sock_setvol: no read buffer yet\n");
! 359: return;
! 360: }
! 361: dev_setvol(rbuf, vol);
! 362: }
! 363:
! 364: /*
1.1 ratchov 365: * attach play and/or record buffers to dev_mix and/or dev_sub
366: */
367: int
368: sock_attach(struct sock *f, int force)
369: {
370: struct abuf *rbuf, *wbuf;
371:
372: rbuf = LIST_FIRST(&f->pipe.file.rproc->obuflist);
373: wbuf = LIST_FIRST(&f->pipe.file.wproc->ibuflist);
374:
375: /*
376: * if in SOCK_START state, dont attach until
377: * the buffer isn't completely filled
378: */
379: if (!force && rbuf && ABUF_WOK(rbuf))
380: return 0;
381:
382: DPRINTF("sock_attach: %p\n", f);
383: f->pstate = SOCK_RUN;
384:
385: /*
386: * attach them to the device
387: */
388: dev_attach(f->pipe.file.name,
389: (f->mode & AMSG_PLAY) ? rbuf : NULL, &f->rpar, f->xrun,
390: (f->mode & AMSG_REC) ? wbuf : NULL, &f->wpar, f->xrun);
1.3 ! ratchov 391: if (f->mode & AMSG_PLAY)
! 392: dev_setvol(rbuf, f->vol);
! 393:
1.1 ratchov 394: /*
395: * send the initial position, if needed
396: */
397: for (;;) {
398: if (!sock_write(f))
399: break;
400: }
401: return 1;
402: }
403:
404: void
405: sock_reset(struct sock *f)
406: {
407: switch (f->pstate) {
408: case SOCK_START:
409: (void)sock_attach(f, 1);
410: f->pstate = SOCK_RUN;
411: /* PASSTHROUGH */
412: case SOCK_RUN:
413: sock_freebuf(f);
414: f->pstate = SOCK_INIT;
415: /* PASSTHROUGH */
416: case SOCK_INIT:
417: /* nothing yet */
418: break;
419: }
420: }
421:
422: /*
423: * read a message from the file descriptor, return 1 if done, 0
424: * otherwise. The message is stored in f->rmsg
425: */
426: int
427: sock_rmsg(struct sock *f)
428: {
429: unsigned count;
430: unsigned char *data;
431:
432: while (f->rtodo > 0) {
433: if (!(f->pipe.file.state & FILE_ROK)) {
434: DPRINTFN(4, "sock_rmsg: blk, rtodo = %u\n", f->rtodo);
435: return 0;
436: }
437: data = (unsigned char *)&f->rmsg;
438: data += sizeof(struct amsg) - f->rtodo;
439: count = file_read(&f->pipe.file, data, f->rtodo);
440: if (count == 0)
441: return 0;
442: f->rtodo -= count;
443: }
444: DPRINTFN(4, "sock_rmsg: %p: done\n", f);
445: return 1;
446: }
447:
448: /*
449: * write a message to the file descriptor, return 1 if done, 0
450: * otherwise. The "m" argument is f->rmsg or f->wmsg, and the "ptodo"
451: * points to the f->rtodo or f->wtodo respectively.
452: */
453: int
454: sock_wmsg(struct sock *f, struct amsg *m, unsigned *ptodo)
455: {
456: unsigned count;
457: unsigned char *data;
458:
459: while (*ptodo > 0) {
460: if (!(f->pipe.file.state & FILE_WOK)) {
461: DPRINTFN(4, "sock_wmsg: blk, *ptodo = %u\n", *ptodo);
462: return 0;
463: }
464: data = (unsigned char *)m;
465: data += sizeof(struct amsg) - *ptodo;
466: count = file_write(&f->pipe.file, data, *ptodo);
467: if (count == 0)
468: return 0;
469: *ptodo -= count;
470: }
471: DPRINTFN(4, "sock_wmsg: %p: done\n", f);
472: return 1;
473: }
474:
475: /*
476: * read data chunk from the file descriptor, return 1 if at least one
477: * byte was read, 0 if the file blocked.
478: */
479: int
480: sock_rdata(struct sock *f)
481: {
482: struct aproc *p;
483: struct abuf *obuf;
484: unsigned char *data;
485: unsigned count, n;
486:
487: #ifdef DEBUG
488: if (f->rtodo == 0) {
489: fprintf(stderr, "sock_rdata: bad call: zero arg\n");
490: abort();
491: }
492: #endif
493: p = f->pipe.file.rproc;
494: obuf = LIST_FIRST(&p->obuflist);
495: if (ABUF_FULL(obuf) || !(f->pipe.file.state & FILE_ROK))
496: return 0;
497: data = abuf_wgetblk(obuf, &count, 0);
498: if (count > f->rtodo)
499: count = f->rtodo;
500: n = file_read(&f->pipe.file, data, count);
501: if (n == 0)
502: return 0;
503: abuf_wcommit(obuf, n);
504: f->rtodo -= n;
505: return 1;
506: }
507:
508: /*
509: * write data chunk to the file descriptor, return 1 if at least one
510: * byte was written, 0 if the file blocked.
511: */
512: int
513: sock_wdata(struct sock *f)
514: {
515: struct aproc *p;
516: struct abuf *ibuf;
517: unsigned char *data;
518: unsigned count, n;
519: #define ZERO_MAX 0x1000
520: static char zero[ZERO_MAX];
521:
522: #ifdef DEBUG
523: if (f->wtodo == 0) {
524: fprintf(stderr, "sock_wdata: bad call: zero arg\n");
525: abort();
526: }
527: #endif
528: if (!(f->pipe.file.state & FILE_WOK))
529: return 0;
530: p = f->pipe.file.wproc;
531: ibuf = LIST_FIRST(&p->ibuflist);
532: if (ibuf) {
533: if (ABUF_EMPTY(ibuf))
534: return 0;
535: data = abuf_rgetblk(ibuf, &count, 0);
536: if (count > f->wtodo)
537: count = f->wtodo;
538: n = file_write(&f->pipe.file, data, count);
539: if (n == 0)
540: return 0;
541: abuf_rdiscard(ibuf, n);
542: f->wtodo -= n;
543: } else {
544: /*
545: * there's no dev_detach() routine yet,
546: * so now we abruptly destroy the buffer.
547: * Until we implement dev_detach, complete
548: * the packet with zeros...
549: */
550: count = ZERO_MAX;
551: if (count > f->wtodo)
552: count = f->wtodo;
553: n = file_write(&f->pipe.file, zero, count);
554: if (n == 0)
555: return 0;
556: f->wtodo -= n;
557: }
558: return 1;
559: }
560:
561: int
562: sock_setpar(struct sock *f)
563: {
564: struct amsg_par *p = &f->rmsg.u.par;
565: unsigned minbuf, maxbuf;
566:
567: if (AMSG_ISSET(p->mode)) {
568: if ((p->mode & ~(AMSG_PLAY | AMSG_REC)) || p->mode == 0) {
569: DPRINTF("sock_setpar: bad mode %x\n", p->mode);
570: return 0;
571: }
572: f->mode = 0;
573: if ((p->mode & AMSG_PLAY) && dev_mix)
574: f->mode |= AMSG_PLAY;
575: if ((p->mode & AMSG_REC) && dev_sub)
576: f->mode |= AMSG_REC;
577: DPRINTF("sock_setpar: mode -> %x\n", f->mode);
578: }
579: if (AMSG_ISSET(p->bits)) {
580: if (p->bits < BITS_MIN || p->bits > BITS_MAX) {
581: DPRINTF("sock_setpar: bits out of bounds\n");
582: return 0;
583: }
584: if (AMSG_ISSET(p->bps)) {
585: if (p->bps < ((p->bits + 7) / 8) || p->bps > 4) {
586: DPRINTF("sock_setpar: bps out of bounds\n");
587: return 0;
588: }
589: } else
590: p->bps = APARAMS_BPS(p->bits);
591: f->rpar.bits = f->wpar.bits = p->bits;
592: f->rpar.bps = f->wpar.bps = p->bps;
593: DPRINTF("sock_setpar: bits/bps -> %u/%u\n", p->bits, p->bps);
594: }
595: if (AMSG_ISSET(p->sig))
596: f->rpar.sig = f->wpar.sig = p->sig ? 1 : 0;
597: if (AMSG_ISSET(p->le))
598: f->rpar.le = f->wpar.le = p->le ? 1 : 0;
599: if (AMSG_ISSET(p->msb))
600: f->rpar.msb = f->wpar.msb = p->msb ? 1 : 0;
601: if (AMSG_ISSET(p->rchan) && (f->mode & AMSG_REC)) {
602: if (p->rchan < 1)
603: p->rchan = 1;
604: if (p->rchan > NCHAN_MAX - 1)
605: p->rchan = NCHAN_MAX - 1;
606: f->wpar.cmin = 0;
607: f->wpar.cmax = p->rchan - 1;
608: DPRINTF("sock_setpar: rchan -> %u\n", p->rchan);
609: }
610: if (AMSG_ISSET(p->pchan) && (f->mode & AMSG_PLAY)) {
611: if (p->pchan < 1)
612: p->pchan = 1;
613: if (p->pchan > NCHAN_MAX - 1)
614: p->pchan = NCHAN_MAX - 1;
615: f->rpar.cmin = 0;
616: f->rpar.cmax = p->pchan - 1;
617: DPRINTF("sock_setpar: pchan -> %u\n", p->pchan);
618: }
619: if (AMSG_ISSET(p->rate)) {
620: if (p->rate < RATE_MIN)
621: p->rate = RATE_MIN;
622: if (p->rate > RATE_MAX)
623: p->rate = RATE_MAX;
624: dev_roundrate(&p->rate, &f->round);
625: f->rpar.rate = f->wpar.rate = p->rate;
626: if (f->mode & AMSG_PLAY)
627: f->bufsz = 2 * dev_bufsz * f->rpar.rate / dev_rate;
628: else
629: f->bufsz = 2 * dev_bufsz * f->wpar.rate / dev_rate;
630: DPRINTF("sock_setpar: rate -> %u\n", p->rate);
631: }
632: if (AMSG_ISSET(p->xrun)) {
633: if (p->xrun != AMSG_IGNORE &&
634: p->xrun != AMSG_SYNC &&
635: p->xrun != AMSG_ERROR) {
636: DPRINTF("sock_setpar: bad xrun: %u\n", p->xrun);
637: return 0;
638: }
639: f->xrun = p->xrun;
640: DPRINTF("sock_setpar: xrun -> %u\n", f->xrun);
641: }
642: if (AMSG_ISSET(p->bufsz)) {
643: minbuf = 3 * dev_bufsz / 2;
644: minbuf -= minbuf % dev_round;
645: maxbuf = dev_bufsz;
646: if (f->mode & AMSG_PLAY) {
647: minbuf = minbuf * f->rpar.rate / dev_rate;
648: maxbuf = maxbuf * f->rpar.rate / dev_rate;
649: maxbuf += f->rpar.rate;
650: } else {
651: minbuf = minbuf * f->wpar.rate / dev_rate;
652: maxbuf = maxbuf * f->wpar.rate / dev_rate;
653: maxbuf += f->wpar.rate;
654: }
655: if (p->bufsz < minbuf)
656: p->bufsz = minbuf;
657: if (p->bufsz > maxbuf)
658: p->bufsz = maxbuf;
659: f->bufsz = p->bufsz + f->round - 1;
660: f->bufsz -= f->bufsz % f->round;
661: DPRINTF("sock_setpar: bufsz -> %u\n", f->bufsz);
662: }
663: if (debug_level > 0) {
664: fprintf(stderr, "sock_setpar: %p: rpar=", f);
665: aparams_print(&f->rpar);
666: fprintf(stderr, ", wpar=");
667: aparams_print(&f->wpar);
668: fprintf(stderr, ", mode=%u, bufsz=%u\n", f->mode, f->bufsz);
669: }
670: return 1;
671: }
672:
673: /*
674: * execute message in f->rmsg and change the state accordingly; return 1
675: * on success, and 0 on failure, in which case the socket is destroyed.
676: */
677: int
678: sock_execmsg(struct sock *f)
679: {
680: struct amsg *m = &f->rmsg;
681:
682: switch (m->cmd) {
683: case AMSG_DATA:
684: DPRINTFN(4, "sock_execmsg: %p: DATA\n", f);
685: if (f->pstate != SOCK_RUN && f->pstate != SOCK_START) {
686: DPRINTF("sock_execmsg: %p: DATA, bad state\n", f);
687: aproc_del(f->pipe.file.rproc);
688: return 0;
689: }
690: f->rstate = SOCK_RDATA;
691: f->rtodo = m->u.data.size;
692: if (f->rtodo == 0) {
693: DPRINTF("sock_execmsg: zero-length data chunk\n");
694: aproc_del(f->pipe.file.rproc);
695: return 0;
696: }
697: break;
698: case AMSG_START:
699: DPRINTFN(2, "sock_execmsg: %p: START\n", f);
700: if (f->pstate != SOCK_INIT) {
701: DPRINTF("sock_execmsg: %p: START, bad state\n", f);
702: aproc_del(f->pipe.file.rproc);
703: return 0;
704: }
705: sock_allocbuf(f);
706: f->rstate = SOCK_RMSG;
707: f->rtodo = sizeof(struct amsg);
708: break;
709: case AMSG_STOP:
710: DPRINTFN(2, "sock_execmsg: %p: STOP\n", f);
711: if (f->pstate != SOCK_RUN && f->pstate != SOCK_START) {
712: DPRINTF("sock_execmsg: %p: STOP, bad state\n", f);
713: aproc_del(f->pipe.file.rproc);
714: return 0;
715: }
716: if (f->pstate == SOCK_START)
717: (void)sock_attach(f, 1);
718: sock_freebuf(f);
719: AMSG_INIT(m);
720: m->cmd = AMSG_ACK;
721: f->rstate = SOCK_RRET;
722: f->rtodo = sizeof(struct amsg);
723: break;
724: case AMSG_SETPAR:
725: DPRINTFN(2, "sock_execmsg: %p: SETPAR\n", f);
726: if (f->pstate != SOCK_INIT) {
727: DPRINTF("sock_execmsg: %p: SETPAR, bad state\n", f);
728: aproc_del(f->pipe.file.rproc);
729: return 0;
730: }
731: if (!sock_setpar(f)) {
732: aproc_del(f->pipe.file.rproc);
733: return 0;
734: }
735: f->rtodo = sizeof(struct amsg);
736: f->rstate = SOCK_RMSG;
737: break;
738: case AMSG_GETPAR:
739: DPRINTFN(2, "sock_execmsg: %p: GETPAR\n", f);
740: if (f->pstate != SOCK_INIT) {
741: DPRINTF("sock_execmsg: %p: GETPAR, bad state\n", f);
742: aproc_del(f->pipe.file.rproc);
743: return 0;
744: }
745: AMSG_INIT(m);
746: m->cmd = AMSG_GETPAR;
747: m->u.par.mode = f->mode;
748: m->u.par.bits = f->rpar.bits;
749: m->u.par.bps = f->rpar.bps;
750: m->u.par.sig = f->rpar.sig;
751: m->u.par.le = f->rpar.le;
752: m->u.par.msb = f->rpar.msb;
753: m->u.par.rate = f->rpar.rate;
754: m->u.par.rchan = f->wpar.cmax - f->wpar.cmin + 1;
755: m->u.par.pchan = f->rpar.cmax - f->rpar.cmin + 1;
756: m->u.par.bufsz = f->bufsz;
757: m->u.par.round = f->round;
758: f->rstate = SOCK_RRET;
759: f->rtodo = sizeof(struct amsg);
760: break;
761: case AMSG_GETCAP:
762: DPRINTFN(2, "sock_execmsg: %p: GETCAP\n", f);
763: if (f->pstate != SOCK_INIT) {
764: DPRINTF("sock_execmsg: %p: GETCAP, bad state\n", f);
765: aproc_del(f->pipe.file.rproc);
766: return 0;
767: }
768: AMSG_INIT(m);
769: m->cmd = AMSG_GETCAP;
770: m->u.cap.rate = dev_rate;
771: m->u.cap.rate_div = dev_rate_div;
772: m->u.cap.pchan = dev_opar.cmax - dev_opar.cmin + 1;
773: m->u.cap.rchan = dev_ipar.cmax - dev_ipar.cmin + 1;
774: m->u.cap.bits = sizeof(short) * 8;
775: m->u.cap.bps = sizeof(short);
776: f->rstate = SOCK_RRET;
777: f->rtodo = sizeof(struct amsg);
1.3 ! ratchov 778: break;
! 779: case AMSG_SETVOL:
! 780: DPRINTFN(2, "sock_execmsg: %p: SETVOL\n", f);
! 781: if (f->pstate != SOCK_RUN &&
! 782: f->pstate != SOCK_START && f->pstate != SOCK_INIT) {
! 783: DPRINTF("sock_execmsg: %p: SETVOL, bad state\n", f);
! 784: aproc_del(f->pipe.file.rproc);
! 785: return 0;
! 786: }
! 787: if (m->u.vol.ctl > MIDI_MAXCTL) {
! 788: DPRINTF("sock_execmsg: %p: SETVOL, out of range\n", f);
! 789: aproc_del(f->pipe.file.rproc);
! 790: return 0;
! 791: }
! 792: DPRINTF("sock_execmsg: SETVOL %u\n", m->u.vol.ctl);
! 793: sock_setvol(f, MIDI_TO_ADATA(m->u.vol.ctl));
! 794: f->rtodo = sizeof(struct amsg);
! 795: f->rstate = SOCK_RMSG;
1.1 ratchov 796: break;
797: default:
798: DPRINTF("sock_execmsg: %p bogus command\n", f);
799: aproc_del(f->pipe.file.rproc);
800: return 0;
801: }
802: if (f->rstate == SOCK_RRET) {
803: if (f->wstate != SOCK_WIDLE ||
804: !sock_wmsg(f, &f->rmsg, &f->rtodo))
805: return 0;
806: DPRINTF("sock_execmsg: %p RRET done\n", f);
807: f->rtodo = sizeof(struct amsg);
808: f->rstate = SOCK_RMSG;
809: }
810: return 1;
811: }
812:
813: /*
814: * create a new data/pos message
815: */
816: int
817: sock_buildmsg(struct sock *f)
818: {
819: struct aproc *p;
820: struct abuf *ibuf;
821: int *pdelta;
822:
823: /*
824: * if pos changed, build a MOVE message
825: */
826: pdelta = (f->mode & AMSG_REC) ? &f->idelta : &f->odelta;
827: if ((f->pstate == SOCK_RUN && *pdelta > 0) ||
828: (f->pstate == SOCK_START && *pdelta < 0)) {
829: DPRINTFN(4, "sock_buildmsg: %p: POS: %d\n", f, *pdelta);
830: AMSG_INIT(&f->wmsg);
831: f->wmsg.cmd = AMSG_MOVE;
832: f->wmsg.u.ts.delta = *pdelta;
833: *pdelta = 0;
834: f->wtodo = sizeof(struct amsg);
835: f->wstate = SOCK_WMSG;
836: return 1;
837: }
838:
839: /*
840: * if data available, build a DATA message
841: */
842: p = f->pipe.file.wproc;
843: ibuf = LIST_FIRST(&p->ibuflist);
844: if (ibuf && ABUF_ROK(ibuf)) {
845: AMSG_INIT(&f->wmsg);
846: f->wmsg.cmd = AMSG_DATA;
847: f->wmsg.u.data.size = ibuf->used - (ibuf->used % ibuf->bpf);
848: if (f->wmsg.u.data.size > AMSG_DATAMAX)
849: f->wmsg.u.data.size =
850: AMSG_DATAMAX - (AMSG_DATAMAX % ibuf->bpf);
851: f->wtodo = sizeof(struct amsg);
852: f->wstate = SOCK_WMSG;
853: return 1;
854: }
855:
856: DPRINTFN(4, "sock_buildmsg: %p: idling...\n", f);
857: f->wstate = SOCK_WIDLE;
858: return 0;
859: }
860:
861: /*
862: * read from the socket file descriptor, fill input buffer and update
863: * the state. Return 1 if at least one message or 1 data byte was
864: * processed, 0 if something blocked.
865: */
866: int
867: sock_read(struct sock *f)
868: {
869: DPRINTFN(4, "sock_read: %p; rstate = %u, rtodo = %u\n",
870: f, f->rstate, f->rtodo);
871:
872: switch (f->rstate) {
873: case SOCK_RMSG:
874: if (!sock_rmsg(f))
875: return 0;
876: if (!sock_execmsg(f))
877: return 0;
878: break;
879: case SOCK_RDATA:
880: if (!sock_rdata(f))
881: return 0;
882: if (f->rtodo == 0) {
883: f->rstate = SOCK_RMSG;
884: f->rtodo = sizeof(struct amsg);
885: }
886: if (f->pstate == SOCK_START)
887: (void)sock_attach(f, 0);
888: break;
889: case SOCK_RRET:
890: DPRINTF("sock_read: %p: blocked in RRET\n", f);
891: return 0;
892: }
893: DPRINTFN(4, "sock_read: %p: done, rstate = %u\n", f, f->rstate);
894: return 1;
895: }
896:
897: /*
898: * process messages to return
899: */
900: int
901: sock_return(struct sock *f)
902: {
903: struct aproc *rp;
904:
905: while (f->rstate == SOCK_RRET) {
906: if (!sock_wmsg(f, &f->rmsg, &f->rtodo))
907: return 0;
908: DPRINTF("sock_return: %p: done\n", f);
909: f->rstate = SOCK_RMSG;
910: f->rtodo = sizeof(struct amsg);
911: for (;;) {
912: /*
913: * in() may trigger rsock_done and destroy the
914: * wsock
915: */
916: rp = f->pipe.file.rproc;
917: if (!rp || !rp->ops->in(rp, NULL))
918: break;
919: }
920: if (f->pipe.file.wproc == NULL)
921: return 0;
922: }
923: return 1;
924: }
925:
926: /*
927: * write messages and data on the socket file descriptor. Return 1 if
928: * at least one message or one data byte was processed, 0 if something
929: * blocked.
930: */
931: int
932: sock_write(struct sock *f)
933: {
934: DPRINTFN(4, "sock_write: %p: wstate = %u, wtodo = %u\n",
935: f, f->wstate, f->wtodo);
936:
937: switch (f->wstate) {
938: case SOCK_WMSG:
939: if (!sock_wmsg(f, &f->wmsg, &f->wtodo))
940: return 0;
941: if (f->wmsg.cmd != AMSG_DATA) {
942: f->wstate = SOCK_WIDLE;
943: f->wtodo = 0xdeadbeef;
944: break;
945: }
946: f->wstate = SOCK_WDATA;
947: f->wtodo = f->wmsg.u.data.size;
948: /* PASSTHROUGH */
949: case SOCK_WDATA:
950: if (!sock_wdata(f))
951: return 0;
952: if (f->wtodo > 0)
953: break;
954: f->wstate = SOCK_WIDLE;
955: f->wtodo = 0xdeadbeef;
956: /* PASSTHROUGH */
957: case SOCK_WIDLE:
958: if (!sock_return(f))
959: return 0;
960: if (!sock_buildmsg(f))
961: return 0;
962: break;
963: default:
964: fprintf(stderr, "sock_write: unknown state\n");
965: abort();
966: }
967: return 1;
968: }
969: