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