Annotation of src/usr.bin/aucat/sock.c, Revision 1.5
1.5 ! ratchov 1: /* $OpenBSD: sock.c,v 1.4 2008/11/16 16:30:22 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: }
1.5 ! ratchov 665: #ifdef DEBUG
1.1 ratchov 666: if (debug_level > 0) {
667: fprintf(stderr, "sock_setpar: %p: rpar=", f);
668: aparams_print(&f->rpar);
669: fprintf(stderr, ", wpar=");
670: aparams_print(&f->wpar);
671: fprintf(stderr, ", mode=%u, bufsz=%u\n", f->mode, f->bufsz);
672: }
1.5 ! ratchov 673: #endif
1.1 ratchov 674: return 1;
675: }
676:
677: /*
678: * execute message in f->rmsg and change the state accordingly; return 1
679: * on success, and 0 on failure, in which case the socket is destroyed.
680: */
681: int
682: sock_execmsg(struct sock *f)
683: {
684: struct amsg *m = &f->rmsg;
685:
686: switch (m->cmd) {
687: case AMSG_DATA:
688: DPRINTFN(4, "sock_execmsg: %p: DATA\n", f);
689: if (f->pstate != SOCK_RUN && f->pstate != SOCK_START) {
690: DPRINTF("sock_execmsg: %p: DATA, bad state\n", f);
691: aproc_del(f->pipe.file.rproc);
692: return 0;
693: }
694: f->rstate = SOCK_RDATA;
695: f->rtodo = m->u.data.size;
696: if (f->rtodo == 0) {
697: DPRINTF("sock_execmsg: zero-length data chunk\n");
698: aproc_del(f->pipe.file.rproc);
699: return 0;
700: }
701: break;
702: case AMSG_START:
703: DPRINTFN(2, "sock_execmsg: %p: START\n", f);
704: if (f->pstate != SOCK_INIT) {
705: DPRINTF("sock_execmsg: %p: START, bad state\n", f);
706: aproc_del(f->pipe.file.rproc);
707: return 0;
708: }
709: sock_allocbuf(f);
710: f->rstate = SOCK_RMSG;
711: f->rtodo = sizeof(struct amsg);
712: break;
713: case AMSG_STOP:
714: DPRINTFN(2, "sock_execmsg: %p: STOP\n", f);
715: if (f->pstate != SOCK_RUN && f->pstate != SOCK_START) {
716: DPRINTF("sock_execmsg: %p: STOP, bad state\n", f);
717: aproc_del(f->pipe.file.rproc);
718: return 0;
719: }
720: if (f->pstate == SOCK_START)
721: (void)sock_attach(f, 1);
722: sock_freebuf(f);
723: AMSG_INIT(m);
724: m->cmd = AMSG_ACK;
725: f->rstate = SOCK_RRET;
726: f->rtodo = sizeof(struct amsg);
727: break;
728: case AMSG_SETPAR:
729: DPRINTFN(2, "sock_execmsg: %p: SETPAR\n", f);
730: if (f->pstate != SOCK_INIT) {
731: DPRINTF("sock_execmsg: %p: SETPAR, bad state\n", f);
732: aproc_del(f->pipe.file.rproc);
733: return 0;
734: }
735: if (!sock_setpar(f)) {
736: aproc_del(f->pipe.file.rproc);
737: return 0;
738: }
739: f->rtodo = sizeof(struct amsg);
740: f->rstate = SOCK_RMSG;
741: break;
742: case AMSG_GETPAR:
743: DPRINTFN(2, "sock_execmsg: %p: GETPAR\n", f);
744: if (f->pstate != SOCK_INIT) {
745: DPRINTF("sock_execmsg: %p: GETPAR, bad state\n", f);
746: aproc_del(f->pipe.file.rproc);
747: return 0;
748: }
749: AMSG_INIT(m);
750: m->cmd = AMSG_GETPAR;
751: m->u.par.mode = f->mode;
752: m->u.par.bits = f->rpar.bits;
753: m->u.par.bps = f->rpar.bps;
754: m->u.par.sig = f->rpar.sig;
755: m->u.par.le = f->rpar.le;
756: m->u.par.msb = f->rpar.msb;
757: m->u.par.rate = f->rpar.rate;
758: m->u.par.rchan = f->wpar.cmax - f->wpar.cmin + 1;
759: m->u.par.pchan = f->rpar.cmax - f->rpar.cmin + 1;
760: m->u.par.bufsz = f->bufsz;
761: m->u.par.round = f->round;
762: f->rstate = SOCK_RRET;
763: f->rtodo = sizeof(struct amsg);
764: break;
765: case AMSG_GETCAP:
766: DPRINTFN(2, "sock_execmsg: %p: GETCAP\n", f);
767: if (f->pstate != SOCK_INIT) {
768: DPRINTF("sock_execmsg: %p: GETCAP, bad state\n", f);
769: aproc_del(f->pipe.file.rproc);
770: return 0;
771: }
772: AMSG_INIT(m);
773: m->cmd = AMSG_GETCAP;
774: m->u.cap.rate = dev_rate;
775: m->u.cap.rate_div = dev_rate_div;
776: m->u.cap.pchan = dev_opar.cmax - dev_opar.cmin + 1;
777: m->u.cap.rchan = dev_ipar.cmax - dev_ipar.cmin + 1;
778: m->u.cap.bits = sizeof(short) * 8;
779: m->u.cap.bps = sizeof(short);
780: f->rstate = SOCK_RRET;
781: f->rtodo = sizeof(struct amsg);
1.3 ratchov 782: break;
783: case AMSG_SETVOL:
784: DPRINTFN(2, "sock_execmsg: %p: SETVOL\n", f);
785: if (f->pstate != SOCK_RUN &&
786: f->pstate != SOCK_START && f->pstate != SOCK_INIT) {
787: DPRINTF("sock_execmsg: %p: SETVOL, bad state\n", f);
788: aproc_del(f->pipe.file.rproc);
789: return 0;
790: }
791: if (m->u.vol.ctl > MIDI_MAXCTL) {
792: DPRINTF("sock_execmsg: %p: SETVOL, out of range\n", f);
793: aproc_del(f->pipe.file.rproc);
794: return 0;
795: }
796: DPRINTF("sock_execmsg: SETVOL %u\n", m->u.vol.ctl);
797: sock_setvol(f, MIDI_TO_ADATA(m->u.vol.ctl));
798: f->rtodo = sizeof(struct amsg);
799: f->rstate = SOCK_RMSG;
1.1 ratchov 800: break;
801: default:
802: DPRINTF("sock_execmsg: %p bogus command\n", f);
803: aproc_del(f->pipe.file.rproc);
804: return 0;
805: }
806: if (f->rstate == SOCK_RRET) {
807: if (f->wstate != SOCK_WIDLE ||
808: !sock_wmsg(f, &f->rmsg, &f->rtodo))
809: return 0;
810: DPRINTF("sock_execmsg: %p RRET done\n", f);
811: f->rtodo = sizeof(struct amsg);
812: f->rstate = SOCK_RMSG;
813: }
814: return 1;
815: }
816:
817: /*
818: * create a new data/pos message
819: */
820: int
821: sock_buildmsg(struct sock *f)
822: {
823: struct aproc *p;
824: struct abuf *ibuf;
825: int *pdelta;
826:
827: /*
828: * if pos changed, build a MOVE message
829: */
830: pdelta = (f->mode & AMSG_REC) ? &f->idelta : &f->odelta;
831: if ((f->pstate == SOCK_RUN && *pdelta > 0) ||
832: (f->pstate == SOCK_START && *pdelta < 0)) {
833: DPRINTFN(4, "sock_buildmsg: %p: POS: %d\n", f, *pdelta);
834: AMSG_INIT(&f->wmsg);
835: f->wmsg.cmd = AMSG_MOVE;
836: f->wmsg.u.ts.delta = *pdelta;
837: *pdelta = 0;
838: f->wtodo = sizeof(struct amsg);
839: f->wstate = SOCK_WMSG;
840: return 1;
841: }
842:
843: /*
844: * if data available, build a DATA message
845: */
846: p = f->pipe.file.wproc;
847: ibuf = LIST_FIRST(&p->ibuflist);
848: if (ibuf && ABUF_ROK(ibuf)) {
849: AMSG_INIT(&f->wmsg);
850: f->wmsg.cmd = AMSG_DATA;
851: f->wmsg.u.data.size = ibuf->used - (ibuf->used % ibuf->bpf);
852: if (f->wmsg.u.data.size > AMSG_DATAMAX)
853: f->wmsg.u.data.size =
854: AMSG_DATAMAX - (AMSG_DATAMAX % ibuf->bpf);
855: f->wtodo = sizeof(struct amsg);
856: f->wstate = SOCK_WMSG;
857: return 1;
858: }
859:
860: DPRINTFN(4, "sock_buildmsg: %p: idling...\n", f);
861: f->wstate = SOCK_WIDLE;
862: return 0;
863: }
864:
865: /*
866: * read from the socket file descriptor, fill input buffer and update
867: * the state. Return 1 if at least one message or 1 data byte was
868: * processed, 0 if something blocked.
869: */
870: int
871: sock_read(struct sock *f)
872: {
873: DPRINTFN(4, "sock_read: %p; rstate = %u, rtodo = %u\n",
874: f, f->rstate, f->rtodo);
875:
876: switch (f->rstate) {
877: case SOCK_RMSG:
878: if (!sock_rmsg(f))
879: return 0;
880: if (!sock_execmsg(f))
881: return 0;
882: break;
883: case SOCK_RDATA:
884: if (!sock_rdata(f))
885: return 0;
886: if (f->rtodo == 0) {
887: f->rstate = SOCK_RMSG;
888: f->rtodo = sizeof(struct amsg);
889: }
890: if (f->pstate == SOCK_START)
891: (void)sock_attach(f, 0);
892: break;
893: case SOCK_RRET:
894: DPRINTF("sock_read: %p: blocked in RRET\n", f);
895: return 0;
896: }
897: DPRINTFN(4, "sock_read: %p: done, rstate = %u\n", f, f->rstate);
898: return 1;
899: }
900:
901: /*
902: * process messages to return
903: */
904: int
905: sock_return(struct sock *f)
906: {
907: struct aproc *rp;
908:
909: while (f->rstate == SOCK_RRET) {
910: if (!sock_wmsg(f, &f->rmsg, &f->rtodo))
911: return 0;
912: DPRINTF("sock_return: %p: done\n", f);
913: f->rstate = SOCK_RMSG;
914: f->rtodo = sizeof(struct amsg);
915: for (;;) {
916: /*
917: * in() may trigger rsock_done and destroy the
918: * wsock
919: */
920: rp = f->pipe.file.rproc;
921: if (!rp || !rp->ops->in(rp, NULL))
922: break;
923: }
924: if (f->pipe.file.wproc == NULL)
925: return 0;
926: }
927: return 1;
928: }
929:
930: /*
931: * write messages and data on the socket file descriptor. Return 1 if
932: * at least one message or one data byte was processed, 0 if something
933: * blocked.
934: */
935: int
936: sock_write(struct sock *f)
937: {
938: DPRINTFN(4, "sock_write: %p: wstate = %u, wtodo = %u\n",
939: f, f->wstate, f->wtodo);
940:
941: switch (f->wstate) {
942: case SOCK_WMSG:
943: if (!sock_wmsg(f, &f->wmsg, &f->wtodo))
944: return 0;
945: if (f->wmsg.cmd != AMSG_DATA) {
946: f->wstate = SOCK_WIDLE;
947: f->wtodo = 0xdeadbeef;
948: break;
949: }
950: f->wstate = SOCK_WDATA;
951: f->wtodo = f->wmsg.u.data.size;
952: /* PASSTHROUGH */
953: case SOCK_WDATA:
954: if (!sock_wdata(f))
955: return 0;
956: if (f->wtodo > 0)
957: break;
958: f->wstate = SOCK_WIDLE;
959: f->wtodo = 0xdeadbeef;
960: /* PASSTHROUGH */
961: case SOCK_WIDLE:
962: if (!sock_return(f))
963: return 0;
964: if (!sock_buildmsg(f))
965: return 0;
966: break;
967: default:
968: fprintf(stderr, "sock_write: unknown state\n");
969: abort();
970: }
971: return 1;
972: }
973: