Annotation of src/usr.bin/aucat/sock.c, Revision 1.64
1.64 ! ratchov 1: /* $OpenBSD: sock.c,v 1.63 2012/04/11 06:05:43 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:
1.44 ratchov 18: #include <sys/types.h>
19: #include <sys/socket.h>
20: #include <unistd.h>
1.1 ratchov 21: #include <stdio.h>
22: #include <stdlib.h>
23: #include <string.h>
1.20 ratchov 24:
25: #include "abuf.h"
1.1 ratchov 26: #include "aproc.h"
1.20 ratchov 27: #include "conf.h"
1.1 ratchov 28: #include "dev.h"
1.19 ratchov 29: #include "midi.h"
30: #include "opt.h"
1.20 ratchov 31: #include "sock.h"
1.37 ratchov 32: #ifdef DEBUG
33: #include "dbg.h"
34: #endif
1.1 ratchov 35:
1.42 ratchov 36: void sock_attach(struct sock *, int);
1.1 ratchov 37: int sock_read(struct sock *);
38: int sock_write(struct sock *);
39: int sock_execmsg(struct sock *);
40: void sock_reset(struct sock *);
1.44 ratchov 41: void sock_close(struct file *);
1.1 ratchov 42:
43: struct fileops sock_ops = {
44: "sock",
45: sizeof(struct sock),
1.44 ratchov 46: sock_close,
1.1 ratchov 47: pipe_read,
48: pipe_write,
49: NULL, /* start */
50: NULL, /* stop */
51: pipe_nfds,
52: pipe_pollfd,
53: pipe_revents
54: };
1.30 ratchov 55:
1.37 ratchov 56: #ifdef DEBUG
57: void
58: sock_dbg(struct sock *f)
59: {
1.51 ratchov 60: static char *pstates[] = {
1.58 ratchov 61: "aut", "hel", "ini", "sta", "rdy", "run", "stp", "mid"
1.51 ratchov 62: };
1.37 ratchov 63: static char *rstates[] = { "rdat", "rmsg", "rret" };
64: static char *wstates[] = { "widl", "wmsg", "wdat" };
65:
1.62 ratchov 66: if (f->slot >= 0) {
67: dbg_puts(f->dev->slot[f->slot].name);
68: dbg_putu(f->dev->slot[f->slot].unit);
1.37 ratchov 69: } else
70: dbg_puts(f->pipe.file.name);
71: dbg_puts("/");
72: dbg_puts(pstates[f->pstate]);
73: dbg_puts("|");
74: dbg_puts(rstates[f->rstate]);
75: dbg_puts("|");
76: dbg_puts(wstates[f->wstate]);
77: }
78: #endif
1.1 ratchov 79:
1.63 ratchov 80: void sock_setvol(void *, unsigned int);
1.35 ratchov 81: void sock_startreq(void *);
1.42 ratchov 82: void sock_stopreq(void *);
1.48 ratchov 83: void sock_quitreq(void *);
1.63 ratchov 84: void sock_locreq(void *, unsigned int);
1.34 ratchov 85:
86: struct ctl_ops ctl_sockops = {
87: sock_setvol,
1.42 ratchov 88: sock_startreq,
89: sock_stopreq,
1.48 ratchov 90: sock_locreq,
91: sock_quitreq
1.34 ratchov 92: };
93:
1.63 ratchov 94: unsigned int sock_sesrefs = 0; /* connections to the session */
1.57 ratchov 95: uint8_t sock_sescookie[AMSG_COOKIELEN]; /* owner of the session */
1.44 ratchov 96:
97: void
1.48 ratchov 98: sock_close(struct file *arg)
1.44 ratchov 99: {
1.48 ratchov 100: struct sock *f = (struct sock *)arg;
101:
1.57 ratchov 102: if (f->pstate != SOCK_AUTH)
103: sock_sesrefs--;
1.48 ratchov 104: pipe_close(&f->pipe.file);
105: if (f->dev) {
106: dev_unref(f->dev);
107: f->dev = NULL;
108: }
1.44 ratchov 109: }
110:
1.1 ratchov 111: void
112: rsock_done(struct aproc *p)
113: {
114: struct sock *f = (struct sock *)p->u.io.file;
115:
1.11 ratchov 116: if (f == NULL)
117: return;
1.1 ratchov 118: sock_reset(f);
119: f->pipe.file.rproc = NULL;
120: if (f->pipe.file.wproc) {
1.34 ratchov 121: if (f->slot >= 0)
1.62 ratchov 122: dev_slotdel(f->dev, f->slot);
1.1 ratchov 123: aproc_del(f->pipe.file.wproc);
124: file_del(&f->pipe.file);
125: }
1.11 ratchov 126: p->u.io.file = NULL;
1.1 ratchov 127: }
128:
129: int
130: rsock_in(struct aproc *p, struct abuf *ibuf_dummy)
131: {
132: struct sock *f = (struct sock *)p->u.io.file;
133: struct abuf *obuf;
134:
135: if (!sock_read(f))
136: return 0;
1.45 ratchov 137: obuf = LIST_FIRST(&p->outs);
1.34 ratchov 138: if (obuf && f->pstate >= SOCK_RUN) {
1.1 ratchov 139: if (!abuf_flush(obuf))
140: return 0;
141: }
142: return 1;
143: }
144:
145: int
146: rsock_out(struct aproc *p, struct abuf *obuf)
147: {
148: struct sock *f = (struct sock *)p->u.io.file;
149:
1.19 ratchov 150: if (f->pipe.file.state & FILE_RINUSE)
1.1 ratchov 151: return 0;
152:
1.12 ratchov 153: /*
1.20 ratchov 154: * When calling sock_read(), we may receive a ``STOP'' command,
1.1 ratchov 155: * and detach ``obuf''. In this case, there's no more caller and
1.20 ratchov 156: * we'll stop processing further messages, resulting in a deadlock.
1.1 ratchov 157: * The solution is to iterate over sock_read() in order to
158: * consume all messages().
159: */
160: for (;;) {
161: if (!sock_read(f))
1.12 ratchov 162: return 0;
1.1 ratchov 163: }
164: return 1;
165: }
166:
167: void
168: rsock_eof(struct aproc *p, struct abuf *ibuf_dummy)
169: {
170: aproc_del(p);
171: }
172:
173: void
174: rsock_hup(struct aproc *p, struct abuf *ibuf)
175: {
176: aproc_del(p);
177: }
178:
179: void
180: rsock_opos(struct aproc *p, struct abuf *obuf, int delta)
181: {
182: struct sock *f = (struct sock *)p->u.io.file;
183:
1.51 ratchov 184: if (f->mode & MODE_RECMASK)
1.14 ratchov 185: return;
186:
187: f->delta += delta;
1.37 ratchov 188: #ifdef DEBUG
189: if (debug_level >= 4) {
190: aproc_dbg(p);
191: dbg_puts(": moved to delta = ");
192: dbg_puti(f->delta);
193: dbg_puts("\n");
194: }
195: #endif
1.14 ratchov 196: f->tickpending++;
1.1 ratchov 197: for (;;) {
198: if (!sock_write(f))
199: break;
200: }
201: }
202:
203: struct aproc_ops rsock_ops = {
204: "rsock",
205: rsock_in,
206: rsock_out,
207: rsock_eof,
208: rsock_hup,
209: NULL, /* newin */
210: NULL, /* newout */
211: NULL, /* ipos */
212: rsock_opos,
213: rsock_done
214: };
215:
216: void
217: wsock_done(struct aproc *p)
218: {
219: struct sock *f = (struct sock *)p->u.io.file;
220:
1.11 ratchov 221: if (f == NULL)
222: return;
1.1 ratchov 223: sock_reset(f);
224: f->pipe.file.wproc = NULL;
225: if (f->pipe.file.rproc) {
1.34 ratchov 226: if (f->slot >= 0)
1.62 ratchov 227: dev_slotdel(f->dev, f->slot);
1.1 ratchov 228: aproc_del(f->pipe.file.rproc);
229: file_del(&f->pipe.file);
230: }
1.11 ratchov 231: p->u.io.file = NULL;
1.1 ratchov 232: }
233:
234: int
235: wsock_in(struct aproc *p, struct abuf *ibuf)
236: {
237: struct sock *f = (struct sock *)p->u.io.file;
238:
1.19 ratchov 239: if (f->pipe.file.state & FILE_WINUSE)
1.1 ratchov 240: return 0;
241: /*
1.20 ratchov 242: * See remark in rsock_out().
1.1 ratchov 243: */
244: for (;;) {
245: if (!sock_write(f))
246: return 0;
247: }
248: return 1;
249: }
250:
251: int
252: wsock_out(struct aproc *p, struct abuf *obuf_dummy)
253: {
1.45 ratchov 254: struct abuf *ibuf = LIST_FIRST(&p->ins);
1.1 ratchov 255: struct sock *f = (struct sock *)p->u.io.file;
256:
257: if (ibuf) {
258: if (!abuf_fill(ibuf))
259: return 0;
260: }
261: if (!sock_write(f))
262: return 0;
263: return 1;
264: }
265:
266: void
267: wsock_eof(struct aproc *p, struct abuf *obuf)
268: {
269: aproc_del(p);
270: }
271:
272: void
273: wsock_hup(struct aproc *p, struct abuf *obuf_dummy)
274: {
275: aproc_del(p);
276: }
277:
278: void
279: wsock_ipos(struct aproc *p, struct abuf *obuf, int delta)
280: {
281: struct sock *f = (struct sock *)p->u.io.file;
282:
1.51 ratchov 283: if (!(f->mode & MODE_RECMASK))
1.14 ratchov 284: return;
1.1 ratchov 285:
1.14 ratchov 286: f->delta += delta;
1.37 ratchov 287: #ifdef DEBUG
288: if (debug_level >= 4) {
289: aproc_dbg(p);
290: dbg_puts(": moved to delta = ");
291: dbg_puti(f->delta);
292: dbg_puts("\n");
293: }
294: #endif
1.33 ratchov 295: f->tickpending++;
1.1 ratchov 296: for (;;) {
297: if (!sock_write(f))
298: break;
299: }
300: }
301:
302: struct aproc_ops wsock_ops = {
303: "wsock",
304: wsock_in,
305: wsock_out,
306: wsock_eof,
307: wsock_hup,
308: NULL, /* newin */
309: NULL, /* newout */
310: wsock_ipos,
311: NULL, /* opos */
312: wsock_done
313: };
314:
315: /*
1.20 ratchov 316: * Initialise socket in the SOCK_HELLO state with default
317: * parameters.
1.1 ratchov 318: */
319: struct sock *
1.19 ratchov 320: sock_new(struct fileops *ops, int fd)
1.1 ratchov 321: {
322: struct aproc *rproc, *wproc;
323: struct sock *f;
324:
1.19 ratchov 325: f = (struct sock *)pipe_new(ops, fd, "sock");
1.46 ratchov 326: if (f == NULL) {
327: close(fd);
328: return NULL;
329: }
1.57 ratchov 330: f->pstate = SOCK_AUTH;
1.1 ratchov 331: f->mode = 0;
1.48 ratchov 332: f->opt = NULL;
333: f->dev = NULL;
1.51 ratchov 334: f->xrun = XRUN_IGNORE;
1.14 ratchov 335: f->delta = 0;
336: f->tickpending = 0;
1.49 ratchov 337: f->startpos = 0;
1.42 ratchov 338: f->startpending = 0;
1.25 ratchov 339: f->vol = f->lastvol = MIDI_MAXCTL;
1.24 ratchov 340: f->slot = -1;
1.1 ratchov 341:
1.19 ratchov 342: wproc = aproc_new(&wsock_ops, f->pipe.file.name);
1.1 ratchov 343: wproc->u.io.file = &f->pipe.file;
1.42 ratchov 344: wproc->u.io.partial = 0;
1.1 ratchov 345: f->pipe.file.wproc = wproc;
346: f->wstate = SOCK_WIDLE;
347: f->wtodo = 0xdeadbeef;
348:
1.19 ratchov 349: rproc = aproc_new(&rsock_ops, f->pipe.file.name);
1.1 ratchov 350: rproc->u.io.file = &f->pipe.file;
1.42 ratchov 351: rproc->u.io.partial = 0;
1.1 ratchov 352: f->pipe.file.rproc = rproc;
353: f->rstate = SOCK_RMSG;
354: f->rtodo = sizeof(struct amsg);
355: return f;
356: }
357:
358: /*
1.20 ratchov 359: * Free buffers.
1.1 ratchov 360: */
361: void
362: sock_freebuf(struct sock *f)
363: {
364: struct abuf *rbuf, *wbuf;
1.12 ratchov 365:
1.1 ratchov 366: f->pstate = SOCK_INIT;
1.37 ratchov 367: #ifdef DEBUG
368: if (debug_level >= 3) {
369: sock_dbg(f);
370: dbg_puts(": freeing buffers\n");
371: }
372: #endif
1.45 ratchov 373: wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
374: rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.35 ratchov 375: if (rbuf || wbuf)
1.62 ratchov 376: dev_slotstop(f->dev, f->slot);
1.1 ratchov 377: if (rbuf)
378: abuf_eof(rbuf);
379: if (wbuf)
380: abuf_hup(wbuf);
1.32 ratchov 381: f->tickpending = 0;
1.42 ratchov 382: f->startpending = 0;
1.1 ratchov 383: }
384:
385: /*
1.20 ratchov 386: * Allocate buffers, so client can start filling write-end.
1.1 ratchov 387: */
388: void
389: sock_allocbuf(struct sock *f)
390: {
391: struct abuf *rbuf = NULL, *wbuf = NULL;
1.63 ratchov 392: unsigned int bufsz;
1.1 ratchov 393:
1.50 ratchov 394: bufsz = f->bufsz + f->dev->bufsz / f->dev->round * f->round;
1.42 ratchov 395: f->pstate = SOCK_START;
1.51 ratchov 396: if (f->mode & MODE_PLAY) {
1.50 ratchov 397: rbuf = abuf_new(bufsz, &f->rpar);
1.1 ratchov 398: aproc_setout(f->pipe.file.rproc, rbuf);
1.42 ratchov 399: if (!ABUF_WOK(rbuf) || (f->pipe.file.state & FILE_EOF))
400: f->pstate = SOCK_READY;
1.50 ratchov 401: f->rmax = bufsz * aparams_bpf(&f->rpar);
1.1 ratchov 402: }
1.51 ratchov 403: if (f->mode & MODE_RECMASK) {
1.50 ratchov 404: wbuf = abuf_new(bufsz, &f->wpar);
1.1 ratchov 405: aproc_setin(f->pipe.file.wproc, wbuf);
1.42 ratchov 406: f->walign = f->round;
1.50 ratchov 407: f->wmax = 0;
1.1 ratchov 408: }
1.14 ratchov 409: f->delta = 0;
1.49 ratchov 410: f->startpos = 0;
1.14 ratchov 411: f->tickpending = 0;
1.42 ratchov 412: f->startpending = 0;
1.37 ratchov 413: #ifdef DEBUG
414: if (debug_level >= 3) {
415: sock_dbg(f);
416: dbg_puts(": allocating ");
417: dbg_putu(f->bufsz);
1.50 ratchov 418: dbg_puts("/");
419: dbg_putu(bufsz);
1.42 ratchov 420: dbg_puts(" fr buffers, rmax = ");
421: dbg_putu(f->rmax);
422: dbg_puts("\n");
1.37 ratchov 423: }
424: #endif
1.51 ratchov 425: if (f->mode & MODE_PLAY) {
1.42 ratchov 426: f->pstate = SOCK_START;
427: } else {
428: f->pstate = SOCK_READY;
1.62 ratchov 429: if (dev_slotstart(f->dev, f->slot))
1.42 ratchov 430: (void)sock_attach(f, 0);
431: }
1.1 ratchov 432: }
433:
434: /*
1.25 ratchov 435: * Set volume. Callback invoked when volume is modified externally
1.3 ratchov 436: */
437: void
1.63 ratchov 438: sock_setvol(void *arg, unsigned int vol)
1.3 ratchov 439: {
1.25 ratchov 440: struct sock *f = (struct sock *)arg;
1.3 ratchov 441: struct abuf *rbuf;
1.12 ratchov 442:
1.3 ratchov 443: f->vol = vol;
1.45 ratchov 444: rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.3 ratchov 445: if (!rbuf) {
1.37 ratchov 446: #ifdef DEBUG
447: if (debug_level >= 3) {
448: sock_dbg(f);
449: dbg_puts(": no read buffer to set volume yet\n");
450: }
451: #endif
1.3 ratchov 452: return;
453: }
1.48 ratchov 454: dev_setvol(f->dev, rbuf, MIDI_TO_ADATA(vol));
1.3 ratchov 455: }
456:
457: /*
1.35 ratchov 458: * Attach the stream. Callback invoked when MMC start
459: */
460: void
461: sock_startreq(void *arg)
462: {
463: struct sock *f = (struct sock *)arg;
464:
1.37 ratchov 465: #ifdef DEBUG
1.42 ratchov 466: if (f->pstate != SOCK_READY) {
1.37 ratchov 467: sock_dbg(f);
1.42 ratchov 468: dbg_puts(": not in READY state\n");
1.37 ratchov 469: dbg_panic();
470: }
471: #endif
1.35 ratchov 472: (void)sock_attach(f, 0);
1.52 ratchov 473: }
474:
475: /*
1.42 ratchov 476: * Callback invoked by MMC stop
477: */
478: void
479: sock_stopreq(void *arg)
480: {
481: #ifdef DEBUG
482: struct sock *f = (struct sock *)arg;
483:
484: if (debug_level >= 3) {
485: sock_dbg(f);
486: dbg_puts(": ignored STOP signal\n");
487: }
488: #endif
489: }
490:
491: /*
492: * Callback invoked by MMC relocate, ignored
493: */
494: void
1.63 ratchov 495: sock_locreq(void *arg, unsigned int mmcpos)
1.42 ratchov 496: {
497: #ifdef DEBUG
498: struct sock *f = (struct sock *)arg;
499:
500: if (debug_level >= 3) {
501: sock_dbg(f);
502: dbg_puts(": ignored RELOCATE signal\n");
503: }
504: #endif
505: }
506:
507: /*
1.48 ratchov 508: * Callback invoked when slot is gone
509: */
510: void
511: sock_quitreq(void *arg)
512: {
513: struct sock *f = (struct sock *)arg;
514:
515: #ifdef DEBUG
516: if (debug_level >= 3) {
517: sock_dbg(f);
518: dbg_puts(": slot gone\n");
519: }
520: #endif
521: file_close(&f->pipe.file);
522: }
523:
524: /*
1.51 ratchov 525: * Attach play and/or record buffers to the device
1.1 ratchov 526: */
1.42 ratchov 527: void
1.1 ratchov 528: sock_attach(struct sock *f, int force)
529: {
530: struct abuf *rbuf, *wbuf;
1.63 ratchov 531: unsigned int rch, wch;
1.1 ratchov 532:
1.45 ratchov 533: rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
534: wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
1.1 ratchov 535:
536: /*
1.20 ratchov 537: * If in SOCK_START state, dont attach until
538: * the buffer isn't completely filled.
1.1 ratchov 539: */
540: if (!force && rbuf && ABUF_WOK(rbuf))
1.42 ratchov 541: return;
1.12 ratchov 542:
1.42 ratchov 543: /*
1.46 ratchov 544: * start the device (dev_getpos() and dev_attach() must
545: * be called on a started device
546: */
1.48 ratchov 547: dev_wakeup(f->dev);
1.46 ratchov 548:
549: /*
1.42 ratchov 550: * get the current position, the origin is when
551: * the first sample is played/recorded
552: */
1.49 ratchov 553: f->startpos = dev_getpos(f->dev) * (int)f->round / (int)f->dev->round;
1.42 ratchov 554: f->startpending = 1;
555: f->pstate = SOCK_RUN;
1.37 ratchov 556: #ifdef DEBUG
557: if (debug_level >= 3) {
558: sock_dbg(f);
1.42 ratchov 559: dbg_puts(": attaching at ");
1.49 ratchov 560: dbg_puti(f->startpos);
1.42 ratchov 561: dbg_puts("\n");
1.37 ratchov 562: }
563: #endif
1.1 ratchov 564: /*
1.42 ratchov 565: * We dont check whether the device is dying,
566: * because dev_xxx() functions are supposed to
567: * work (i.e., not to crash)
1.1 ratchov 568: */
1.60 ratchov 569: if (f->opt->join) {
570: rch = f->opt->rpar.cmax - f->opt->rpar.cmin + 1;
571: wch = f->opt->wpar.cmax - f->opt->wpar.cmin + 1;
572: } else
573: rch = wch = 0;
1.48 ratchov 574: dev_attach(f->dev, f->pipe.file.name, f->mode,
1.60 ratchov 575: rbuf, &f->rpar, rch, wbuf, &f->wpar, wch,
1.43 ratchov 576: f->xrun, f->opt->maxweight);
1.51 ratchov 577: if (f->mode & MODE_PLAY)
1.48 ratchov 578: dev_setvol(f->dev, rbuf, MIDI_TO_ADATA(f->vol));
1.1 ratchov 579: }
580:
581: void
582: sock_reset(struct sock *f)
583: {
584: switch (f->pstate) {
585: case SOCK_START:
1.42 ratchov 586: case SOCK_READY:
1.62 ratchov 587: if (dev_slotstart(f->dev, f->slot)) {
1.35 ratchov 588: (void)sock_attach(f, 1);
589: f->pstate = SOCK_RUN;
590: }
1.1 ratchov 591: /* PASSTHROUGH */
592: case SOCK_RUN:
593: sock_freebuf(f);
594: f->pstate = SOCK_INIT;
595: /* PASSTHROUGH */
596: case SOCK_INIT:
597: /* nothing yet */
598: break;
599: }
600: }
601:
602: /*
1.20 ratchov 603: * Read a message from the file descriptor, return 1 if done, 0
604: * otherwise. The message is stored in f->rmsg.
1.1 ratchov 605: */
606: int
607: sock_rmsg(struct sock *f)
608: {
1.63 ratchov 609: unsigned int count;
1.1 ratchov 610: unsigned char *data;
611:
612: while (f->rtodo > 0) {
613: if (!(f->pipe.file.state & FILE_ROK)) {
1.37 ratchov 614: #ifdef DEBUG
615: if (debug_level >= 4) {
616: sock_dbg(f);
617: dbg_puts(": reading message blocked, ");
618: dbg_putu(f->rtodo);
619: dbg_puts(" bytes remaining\n");
620: }
621: #endif
1.1 ratchov 622: return 0;
623: }
624: data = (unsigned char *)&f->rmsg;
625: data += sizeof(struct amsg) - f->rtodo;
626: count = file_read(&f->pipe.file, data, f->rtodo);
627: if (count == 0)
628: return 0;
629: f->rtodo -= count;
630: }
1.37 ratchov 631: #ifdef DEBUG
632: if (debug_level >= 4) {
633: sock_dbg(f);
634: dbg_puts(": read full message\n");
635: }
636: #endif
1.1 ratchov 637: return 1;
638: }
639:
640: /*
1.20 ratchov 641: * Write a message to the file descriptor, return 1 if done, 0
1.1 ratchov 642: * otherwise. The "m" argument is f->rmsg or f->wmsg, and the "ptodo"
643: * points to the f->rtodo or f->wtodo respectively.
644: */
645: int
1.63 ratchov 646: sock_wmsg(struct sock *f, struct amsg *m, unsigned int *ptodo)
1.1 ratchov 647: {
1.63 ratchov 648: unsigned int count;
1.1 ratchov 649: unsigned char *data;
650:
651: while (*ptodo > 0) {
652: if (!(f->pipe.file.state & FILE_WOK)) {
1.37 ratchov 653: #ifdef DEBUG
654: if (debug_level >= 4) {
655: sock_dbg(f);
656: dbg_puts(": writing message blocked, ");
657: dbg_putu(*ptodo);
658: dbg_puts(" bytes remaining\n");
659: }
660: #endif
1.1 ratchov 661: return 0;
662: }
663: data = (unsigned char *)m;
664: data += sizeof(struct amsg) - *ptodo;
665: count = file_write(&f->pipe.file, data, *ptodo);
666: if (count == 0)
667: return 0;
668: *ptodo -= count;
669: }
1.37 ratchov 670: #ifdef DEBUG
671: if (debug_level >= 4) {
672: sock_dbg(f);
673: dbg_puts(": wrote full message\n");
674: }
675: #endif
1.1 ratchov 676: return 1;
677: }
678:
679: /*
1.20 ratchov 680: * Read data chunk from the file descriptor, return 1 if at least one
1.1 ratchov 681: * byte was read, 0 if the file blocked.
682: */
683: int
684: sock_rdata(struct sock *f)
685: {
686: struct aproc *p;
687: struct abuf *obuf;
1.63 ratchov 688: unsigned int n;
1.1 ratchov 689:
1.37 ratchov 690: #ifdef DEBUG
1.55 ratchov 691: if (f->rtodo == 0) {
1.37 ratchov 692: sock_dbg(f);
693: dbg_puts(": data block already read\n");
694: dbg_panic();
695: }
696: #endif
1.1 ratchov 697: p = f->pipe.file.rproc;
1.45 ratchov 698: obuf = LIST_FIRST(&p->outs);
1.19 ratchov 699: if (obuf == NULL)
700: return 0;
1.42 ratchov 701: if (!ABUF_WOK(obuf) || !(f->pipe.file.state & FILE_ROK))
1.41 ratchov 702: return 0;
1.55 ratchov 703: if (!rfile_do(p, f->rtodo, &n))
704: return 0;
705: f->rtodo -= n;
706: if (f->pstate == SOCK_START) {
707: if (!ABUF_WOK(obuf) || (f->pipe.file.state & FILE_EOF))
708: f->pstate = SOCK_READY;
1.42 ratchov 709: }
1.1 ratchov 710: return 1;
711: }
712:
713: /*
1.20 ratchov 714: * Write data chunk to the file descriptor, return 1 if at least one
1.1 ratchov 715: * byte was written, 0 if the file blocked.
716: */
717: int
718: sock_wdata(struct sock *f)
719: {
720: struct aproc *p;
721: struct abuf *ibuf;
1.63 ratchov 722: unsigned int n;
1.1 ratchov 723:
1.37 ratchov 724: #ifdef DEBUG
1.55 ratchov 725: if (f->wtodo == 0) {
1.37 ratchov 726: sock_dbg(f);
727: dbg_puts(": attempted to write zero-sized data block\n");
728: dbg_panic();
729: }
730: #endif
1.1 ratchov 731: if (!(f->pipe.file.state & FILE_WOK))
732: return 0;
733: p = f->pipe.file.wproc;
1.45 ratchov 734: ibuf = LIST_FIRST(&p->ins);
1.42 ratchov 735: #ifdef DEBUG
1.55 ratchov 736: if (ibuf == NULL) {
1.42 ratchov 737: sock_dbg(f);
738: dbg_puts(": attempted to write on detached buffer\n");
739: dbg_panic();
740: }
741: #endif
742: if (ibuf == NULL)
743: return 0;
744: if (!ABUF_ROK(ibuf))
745: return 0;
1.55 ratchov 746: if (!wfile_do(p, f->wtodo, &n))
747: return 0;
748: f->wtodo -= n;
1.1 ratchov 749: return 1;
750: }
751:
752: int
753: sock_setpar(struct sock *f)
754: {
755: struct amsg_par *p = &f->rmsg.u.par;
1.63 ratchov 756: unsigned int min, max, rate, pchan, rchan, appbufsz;
1.59 ratchov 757:
758: rchan = ntohs(p->rchan);
759: pchan = ntohs(p->pchan);
760: appbufsz = ntohl(p->appbufsz);
761: rate = ntohl(p->rate);
1.12 ratchov 762:
1.1 ratchov 763: if (AMSG_ISSET(p->bits)) {
764: if (p->bits < BITS_MIN || p->bits > BITS_MAX) {
1.37 ratchov 765: #ifdef DEBUG
766: if (debug_level >= 1) {
767: sock_dbg(f);
768: dbg_puts(": ");
769: dbg_putu(p->bits);
770: dbg_puts(": bits out of bounds\n");
771: }
772: #endif
1.1 ratchov 773: return 0;
774: }
775: if (AMSG_ISSET(p->bps)) {
776: if (p->bps < ((p->bits + 7) / 8) || p->bps > 4) {
1.37 ratchov 777: #ifdef DEBUG
778: if (debug_level >= 1) {
779: sock_dbg(f);
780: dbg_puts(": ");
781: dbg_putu(p->bps);
782: dbg_puts(": wrong bytes per sample\n");
783: }
784: #endif
1.1 ratchov 785: return 0;
786: }
787: } else
788: p->bps = APARAMS_BPS(p->bits);
789: f->rpar.bits = f->wpar.bits = p->bits;
790: f->rpar.bps = f->wpar.bps = p->bps;
1.37 ratchov 791: #ifdef DEBUG
792: if (debug_level >= 3) {
793: sock_dbg(f);
794: dbg_puts(": using ");
795: dbg_putu(p->bits);
796: dbg_puts("bits, ");
797: dbg_putu(p->bps);
798: dbg_puts(" bytes per sample\n");
799: }
800: #endif
1.1 ratchov 801: }
802: if (AMSG_ISSET(p->sig))
803: f->rpar.sig = f->wpar.sig = p->sig ? 1 : 0;
804: if (AMSG_ISSET(p->le))
805: f->rpar.le = f->wpar.le = p->le ? 1 : 0;
806: if (AMSG_ISSET(p->msb))
807: f->rpar.msb = f->wpar.msb = p->msb ? 1 : 0;
1.59 ratchov 808: if (AMSG_ISSET(rchan) && (f->mode & MODE_RECMASK)) {
809: if (rchan < 1)
810: rchan = 1;
811: if (rchan > NCHAN_MAX)
812: rchan = NCHAN_MAX;
1.19 ratchov 813: f->wpar.cmin = f->opt->wpar.cmin;
1.59 ratchov 814: f->wpar.cmax = f->opt->wpar.cmin + rchan - 1;
1.19 ratchov 815: if (f->wpar.cmax > f->opt->wpar.cmax)
816: f->wpar.cmax = f->opt->wpar.cmax;
1.37 ratchov 817: #ifdef DEBUG
818: if (debug_level >= 3) {
819: sock_dbg(f);
820: dbg_puts(": using recording channels ");
821: dbg_putu(f->wpar.cmin);
822: dbg_puts("..");
823: dbg_putu(f->wpar.cmax);
824: dbg_puts("\n");
825: }
826: #endif
1.1 ratchov 827: }
1.59 ratchov 828: if (AMSG_ISSET(pchan) && (f->mode & MODE_PLAY)) {
829: if (pchan < 1)
830: pchan = 1;
831: if (pchan > NCHAN_MAX)
832: pchan = NCHAN_MAX;
1.19 ratchov 833: f->rpar.cmin = f->opt->rpar.cmin;
1.59 ratchov 834: f->rpar.cmax = f->opt->rpar.cmin + pchan - 1;
1.19 ratchov 835: if (f->rpar.cmax > f->opt->rpar.cmax)
836: f->rpar.cmax = f->opt->rpar.cmax;
1.37 ratchov 837: #ifdef DEBUG
838: if (debug_level >= 3) {
839: sock_dbg(f);
840: dbg_puts(": using playback channels ");
841: dbg_putu(f->rpar.cmin);
842: dbg_puts("..");
843: dbg_putu(f->rpar.cmax);
844: dbg_puts("\n");
845: }
846: #endif
1.1 ratchov 847: }
1.59 ratchov 848: if (AMSG_ISSET(rate)) {
849: if (rate < RATE_MIN)
850: rate = RATE_MIN;
851: if (rate > RATE_MAX)
852: rate = RATE_MAX;
853: f->round = dev_roundof(f->dev, rate);
854: f->rpar.rate = f->wpar.rate = rate;
855: if (!AMSG_ISSET(appbufsz)) {
856: appbufsz = f->dev->bufsz / f->dev->round * f->round;
1.37 ratchov 857: #ifdef DEBUG
858: if (debug_level >= 3) {
859: sock_dbg(f);
860: dbg_puts(": using ");
1.59 ratchov 861: dbg_putu(appbufsz);
1.37 ratchov 862: dbg_puts(" fr app buffer size\n");
863: }
864: #endif
865: }
866: #ifdef DEBUG
867: if (debug_level >= 3) {
868: sock_dbg(f);
869: dbg_puts(": using ");
1.59 ratchov 870: dbg_putu(rate);
1.37 ratchov 871: dbg_puts("Hz sample rate, ");
872: dbg_putu(f->round);
873: dbg_puts(" fr block size\n");
1.10 ratchov 874: }
1.37 ratchov 875: #endif
1.1 ratchov 876: }
877: if (AMSG_ISSET(p->xrun)) {
1.51 ratchov 878: if (p->xrun != XRUN_IGNORE &&
879: p->xrun != XRUN_SYNC &&
880: p->xrun != XRUN_ERROR) {
1.37 ratchov 881: #ifdef DEBUG
882: if (debug_level >= 1) {
883: sock_dbg(f);
884: dbg_puts(": ");
885: dbg_putx(p->xrun);
886: dbg_puts(": bad xrun policy\n");
887: }
888: #endif
1.1 ratchov 889: return 0;
890: }
891: f->xrun = p->xrun;
1.51 ratchov 892: if (f->opt->mmc && f->xrun == XRUN_IGNORE)
893: f->xrun = XRUN_SYNC;
1.37 ratchov 894: #ifdef DEBUG
895: if (debug_level >= 3) {
896: sock_dbg(f);
897: dbg_puts(": using 0x");
898: dbg_putx(f->xrun);
899: dbg_puts(" xrun policy\n");
900: }
901: #endif
1.1 ratchov 902: }
1.59 ratchov 903: if (AMSG_ISSET(appbufsz)) {
1.51 ratchov 904: rate = (f->mode & MODE_PLAY) ? f->rpar.rate : f->wpar.rate;
1.42 ratchov 905: min = 1;
1.48 ratchov 906: max = 1 + rate / f->dev->round;
1.9 ratchov 907: min *= f->round;
908: max *= f->round;
1.59 ratchov 909: appbufsz += f->round - 1;
910: appbufsz -= appbufsz % f->round;
911: if (appbufsz < min)
912: appbufsz = min;
913: if (appbufsz > max)
914: appbufsz = max;
915: f->bufsz = appbufsz;
1.37 ratchov 916: #ifdef DEBUG
917: if (debug_level >= 3) {
918: sock_dbg(f);
919: dbg_puts(": using ");
920: dbg_putu(f->bufsz);
921: dbg_puts(" buffer size\n");
922: }
923: #endif
924: }
925: #ifdef DEBUG
926: if (debug_level >= 2) {
1.62 ratchov 927: dbg_puts(f->dev->slot[f->slot].name);
928: dbg_putu(f->dev->slot[f->slot].unit);
1.37 ratchov 929: dbg_puts(": buffer size = ");
930: dbg_putu(f->bufsz);
1.51 ratchov 931: if (f->mode & MODE_PLAY) {
1.37 ratchov 932: dbg_puts(", play = ");
933: aparams_dbg(&f->rpar);
934: }
1.51 ratchov 935: if (f->mode & MODE_RECMASK) {
1.37 ratchov 936: dbg_puts(", rec:");
937: aparams_dbg(&f->wpar);
938: }
939: dbg_puts("\n");
1.1 ratchov 940: }
1.37 ratchov 941: #endif
1.1 ratchov 942: return 1;
943: }
944:
1.19 ratchov 945: /*
946: * allocate buffers, so client can start filling write-end.
947: */
948: void
1.51 ratchov 949: sock_midiattach(struct sock *f)
1.19 ratchov 950: {
951: struct abuf *rbuf = NULL, *wbuf = NULL;
952:
1.51 ratchov 953: if (f->mode & MODE_MIDIOUT) {
1.22 ratchov 954: rbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
1.19 ratchov 955: aproc_setout(f->pipe.file.rproc, rbuf);
956: }
1.51 ratchov 957: if (f->mode & MODE_MIDIIN) {
1.22 ratchov 958: wbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
1.19 ratchov 959: aproc_setin(f->pipe.file.wproc, wbuf);
960: }
1.51 ratchov 961: f->pstate = SOCK_MIDI;
1.48 ratchov 962: dev_midiattach(f->dev, rbuf, wbuf);
1.19 ratchov 963: }
964:
1.17 ratchov 965: int
1.57 ratchov 966: sock_auth(struct sock *f)
967: {
968: struct amsg_auth *p = &f->rmsg.u.auth;
969:
970: if (sock_sesrefs == 0) {
971: /* start a new session */
972: memcpy(sock_sescookie, p->cookie, AMSG_COOKIELEN);
973: } else if (memcmp(sock_sescookie, p->cookie, AMSG_COOKIELEN) != 0) {
974: /* another session is active, drop connection */
975: return 0;
976: }
977: sock_sesrefs++;
978: f->pstate = SOCK_HELLO;
979: return 1;
980: }
981:
982: int
1.17 ratchov 983: sock_hello(struct sock *f)
984: {
985: struct amsg_hello *p = &f->rmsg.u.hello;
1.63 ratchov 986: unsigned int mode;
1.17 ratchov 987:
1.59 ratchov 988: mode = ntohs(p->mode);
1.37 ratchov 989: #ifdef DEBUG
990: if (debug_level >= 3) {
991: sock_dbg(f);
992: dbg_puts(": hello from <");
993: dbg_puts(p->who);
1.51 ratchov 994: dbg_puts(">, mode = ");
1.59 ratchov 995: dbg_putx(mode);
1.37 ratchov 996: dbg_puts(", ver ");
997: dbg_putu(p->version);
998: dbg_puts("\n");
999: }
1000: #endif
1.33 ratchov 1001: if (p->version != AMSG_VERSION) {
1.37 ratchov 1002: #ifdef DEBUG
1003: if (debug_level >= 1) {
1004: sock_dbg(f);
1005: dbg_puts(": ");
1006: dbg_putu(p->version);
1.51 ratchov 1007: dbg_puts(": unsupported protocol version\n");
1008: }
1009: #endif
1010: return 0;
1011: }
1.59 ratchov 1012: switch (mode) {
1.51 ratchov 1013: case MODE_MIDIIN:
1014: case MODE_MIDIOUT:
1015: case MODE_MIDIOUT | MODE_MIDIIN:
1016: case MODE_REC:
1017: case MODE_PLAY:
1018: case MODE_PLAY | MODE_REC:
1019: break;
1020: default:
1021: #ifdef DEBUG
1022: if (debug_level >= 1) {
1023: sock_dbg(f);
1024: dbg_puts(": ");
1.59 ratchov 1025: dbg_putx(mode);
1.51 ratchov 1026: dbg_puts(": unsupported mode\n");
1.37 ratchov 1027: }
1028: #endif
1.33 ratchov 1029: return 0;
1030: }
1.61 ratchov 1031: f->opt = opt_byname(p->opt, AMSG_ISSET(p->devnum) ? p->devnum : 0);
1.48 ratchov 1032: if (f->opt == NULL)
1033: return 0;
1.61 ratchov 1034: #ifdef DEBUG
1035: if (debug_level >= 3) {
1036: sock_dbg(f);
1037: dbg_puts(": using ");
1038: dev_dbg(f->opt->dev);
1039: dbg_puts(".");
1040: dbg_puts(f->opt->name);
1041: dbg_puts("\n");
1042: }
1043: #endif
1.48 ratchov 1044: if (!dev_ref(f->opt->dev))
1045: return 0;
1.59 ratchov 1046: if ((mode & MODE_REC) && (f->opt->mode & MODE_MON)) {
1047: mode &= ~MODE_REC;
1048: mode |= MODE_MON;
1.51 ratchov 1049: }
1.48 ratchov 1050: f->dev = f->opt->dev;
1.59 ratchov 1051: f->mode = (mode & f->opt->mode) & f->dev->mode;
1.37 ratchov 1052: #ifdef DEBUG
1.51 ratchov 1053: if (debug_level >= 3) {
1054: sock_dbg(f);
1055: dbg_puts(": using mode = ");
1056: dbg_putx(f->mode);
1057: dbg_puts("\n");
1058: }
1.37 ratchov 1059: #endif
1.59 ratchov 1060: if (f->mode != mode) {
1.37 ratchov 1061: #ifdef DEBUG
1062: if (debug_level >= 1) {
1063: sock_dbg(f);
1.51 ratchov 1064: dbg_puts(": requested mode not available\n");
1.37 ratchov 1065: }
1066: #endif
1.17 ratchov 1067: return 0;
1068: }
1.51 ratchov 1069: if (f->mode & (MODE_MIDIOUT | MODE_MIDIIN)) {
1070: sock_midiattach(f);
1071: return 1;
1.24 ratchov 1072: }
1.51 ratchov 1073: if (f->mode & MODE_PLAY)
1074: f->rpar = f->opt->rpar;
1075: if (f->mode & MODE_RECMASK)
1076: f->wpar = f->opt->wpar;
1077: f->xrun = (f->opt->mmc) ? XRUN_SYNC : XRUN_IGNORE;
1078: f->bufsz = f->dev->bufsz;
1079: f->round = f->dev->round;
1.62 ratchov 1080: f->slot = dev_slotnew(f->dev, p->who, &ctl_sockops, f, f->opt->mmc);
1.51 ratchov 1081: if (f->slot < 0)
1082: return 0;
1.18 ratchov 1083: f->pstate = SOCK_INIT;
1.17 ratchov 1084: return 1;
1085: }
1086:
1.1 ratchov 1087: /*
1.20 ratchov 1088: * Execute message in f->rmsg and change the state accordingly; return 1
1.1 ratchov 1089: * on success, and 0 on failure, in which case the socket is destroyed.
1090: */
1091: int
1092: sock_execmsg(struct sock *f)
1093: {
1094: struct amsg *m = &f->rmsg;
1.42 ratchov 1095: struct abuf *obuf;
1.63 ratchov 1096: unsigned int size, ctl;
1.1 ratchov 1097:
1.59 ratchov 1098: switch (ntohl(m->cmd)) {
1.1 ratchov 1099: case AMSG_DATA:
1.37 ratchov 1100: #ifdef DEBUG
1101: if (debug_level >= 4) {
1102: sock_dbg(f);
1103: dbg_puts(": DATA message\n");
1104: }
1105: #endif
1.55 ratchov 1106: if (f->pstate != SOCK_MIDI && f->pstate != SOCK_RUN &&
1107: f->pstate != SOCK_START && f->pstate != SOCK_READY) {
1.37 ratchov 1108: #ifdef DEBUG
1109: if (debug_level >= 1) {
1110: sock_dbg(f);
1111: dbg_puts(": DATA, bad state\n");
1112: }
1113: #endif
1.8 ratchov 1114: aproc_del(f->pipe.file.rproc);
1115: return 0;
1116: }
1.55 ratchov 1117: if (!(f->mode & (MODE_PLAY | MODE_MIDIOUT))) {
1.37 ratchov 1118: #ifdef DEBUG
1119: if (debug_level >= 1) {
1120: sock_dbg(f);
1121: dbg_puts(": DATA not allowed in record-only mode\n");
1122: }
1123: #endif
1.1 ratchov 1124: aproc_del(f->pipe.file.rproc);
1125: return 0;
1126: }
1.45 ratchov 1127: obuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.42 ratchov 1128: if (f->pstate == SOCK_START && !ABUF_WOK(obuf)) {
1.37 ratchov 1129: #ifdef DEBUG
1130: if (debug_level >= 1) {
1131: sock_dbg(f);
1132: dbg_puts(": DATA client violates flow control\n");
1133: }
1134: #endif
1.34 ratchov 1135: aproc_del(f->pipe.file.rproc);
1136: return 0;
1137: }
1.59 ratchov 1138: size = ntohl(m->u.data.size);
1139: if (size % obuf->bpf != 0) {
1.42 ratchov 1140: #ifdef DEBUG
1141: if (debug_level >= 1) {
1142: sock_dbg(f);
1143: dbg_puts(": unaligned data chunk\n");
1144: }
1145: #endif
1146: aproc_del(f->pipe.file.rproc);
1147: return 0;
1148: }
1.1 ratchov 1149: f->rstate = SOCK_RDATA;
1.59 ratchov 1150: f->rtodo = size / obuf->bpf;
1.42 ratchov 1151: #ifdef DEBUG
1.55 ratchov 1152: if (debug_level >= 2 &&
1153: f->pstate != SOCK_MIDI && f->rtodo > f->rmax) {
1.42 ratchov 1154: sock_dbg(f);
1155: dbg_puts(": received past current position, rtodo = ");
1156: dbg_putu(f->rtodo);
1157: dbg_puts(", rmax = ");
1158: dbg_putu(f->rmax);
1159: dbg_puts("\n");
1160: aproc_del(f->pipe.file.rproc);
1161: return 0;
1162: }
1163: #endif
1.55 ratchov 1164: if (f->pstate != SOCK_MIDI)
1165: f->rmax -= f->rtodo;
1.1 ratchov 1166: if (f->rtodo == 0) {
1.37 ratchov 1167: #ifdef DEBUG
1168: if (debug_level >= 1) {
1169: sock_dbg(f);
1170: dbg_puts(": zero-length data chunk\n");
1171: }
1172: #endif
1.1 ratchov 1173: aproc_del(f->pipe.file.rproc);
1174: return 0;
1175: }
1176: break;
1177: case AMSG_START:
1.37 ratchov 1178: #ifdef DEBUG
1179: if (debug_level >= 3) {
1180: sock_dbg(f);
1181: dbg_puts(": START message\n");
1182: }
1183: #endif
1.1 ratchov 1184: if (f->pstate != SOCK_INIT) {
1.37 ratchov 1185: #ifdef DEBUG
1186: if (debug_level >= 1) {
1187: sock_dbg(f);
1188: dbg_puts(": START, bad state\n");
1189: }
1190: #endif
1.1 ratchov 1191: aproc_del(f->pipe.file.rproc);
1192: return 0;
1193: }
1194: sock_allocbuf(f);
1195: f->rstate = SOCK_RMSG;
1196: f->rtodo = sizeof(struct amsg);
1197: break;
1198: case AMSG_STOP:
1.37 ratchov 1199: #ifdef DEBUG
1200: if (debug_level >= 3) {
1201: sock_dbg(f);
1202: dbg_puts(": STOP message\n");
1203: }
1204: #endif
1.42 ratchov 1205: if (f->pstate != SOCK_RUN &&
1206: f->pstate != SOCK_START && f->pstate != SOCK_READY) {
1.37 ratchov 1207: #ifdef DEBUG
1208: if (debug_level >= 1) {
1209: sock_dbg(f);
1210: dbg_puts(": STOP, bad state\n");
1211: }
1212: #endif
1.1 ratchov 1213: aproc_del(f->pipe.file.rproc);
1214: return 0;
1.52 ratchov 1215: }
1.42 ratchov 1216: /*
1217: * XXX: device could have desappeared at this point,
1218: * see how this is fixed in wav.c
1219: */
1220: if ((f->pstate == SOCK_START || f->pstate == SOCK_READY) &&
1.62 ratchov 1221: dev_slotstart(f->dev, f->slot))
1.1 ratchov 1222: (void)sock_attach(f, 1);
1.42 ratchov 1223: if (f->wstate != SOCK_WDATA || f->wtodo == 0)
1224: sock_freebuf(f);
1225: else
1226: f->pstate = SOCK_STOP;
1.1 ratchov 1227: AMSG_INIT(m);
1.59 ratchov 1228: m->cmd = htonl(AMSG_STOP);
1.1 ratchov 1229: f->rstate = SOCK_RRET;
1230: f->rtodo = sizeof(struct amsg);
1231: break;
1232: case AMSG_SETPAR:
1.37 ratchov 1233: #ifdef DEBUG
1234: if (debug_level >= 3) {
1235: sock_dbg(f);
1236: dbg_puts(": SETPAR message\n");
1237: }
1238: #endif
1.1 ratchov 1239: if (f->pstate != SOCK_INIT) {
1.37 ratchov 1240: #ifdef DEBUG
1241: if (debug_level >= 1) {
1242: sock_dbg(f);
1243: dbg_puts(": SETPAR, bad state\n");
1244: }
1245: #endif
1.1 ratchov 1246: aproc_del(f->pipe.file.rproc);
1247: return 0;
1248: }
1249: if (!sock_setpar(f)) {
1250: aproc_del(f->pipe.file.rproc);
1251: return 0;
1252: }
1253: f->rtodo = sizeof(struct amsg);
1254: f->rstate = SOCK_RMSG;
1255: break;
1256: case AMSG_GETPAR:
1.37 ratchov 1257: #ifdef DEBUG
1258: if (debug_level >= 3) {
1259: sock_dbg(f);
1260: dbg_puts(": GETPAR message\n");
1261: }
1262: #endif
1.1 ratchov 1263: if (f->pstate != SOCK_INIT) {
1.37 ratchov 1264: #ifdef DEBUG
1265: if (debug_level >= 1) {
1266: sock_dbg(f);
1267: dbg_puts(": GETPAR, bad state\n");
1268: }
1269: #endif
1.1 ratchov 1270: aproc_del(f->pipe.file.rproc);
1271: return 0;
1272: }
1273: AMSG_INIT(m);
1.59 ratchov 1274: m->cmd = htonl(AMSG_GETPAR);
1.18 ratchov 1275: m->u.par.legacy_mode = f->mode;
1.51 ratchov 1276: if (f->mode & MODE_PLAY) {
1.42 ratchov 1277: m->u.par.bits = f->rpar.bits;
1278: m->u.par.bps = f->rpar.bps;
1279: m->u.par.sig = f->rpar.sig;
1280: m->u.par.le = f->rpar.le;
1281: m->u.par.msb = f->rpar.msb;
1.59 ratchov 1282: m->u.par.rate = htonl(f->rpar.rate);
1283: m->u.par.pchan = htons(f->rpar.cmax - f->rpar.cmin + 1);
1.42 ratchov 1284: }
1.51 ratchov 1285: if (f->mode & MODE_RECMASK) {
1.42 ratchov 1286: m->u.par.bits = f->wpar.bits;
1287: m->u.par.bps = f->wpar.bps;
1288: m->u.par.sig = f->wpar.sig;
1289: m->u.par.le = f->wpar.le;
1290: m->u.par.msb = f->wpar.msb;
1.59 ratchov 1291: m->u.par.rate = htonl(f->wpar.rate);
1292: m->u.par.rchan = htons(f->wpar.cmax - f->wpar.cmin + 1);
1.42 ratchov 1293: }
1.59 ratchov 1294: m->u.par.appbufsz = htonl(f->bufsz);
1295: m->u.par.bufsz = htonl(
1296: f->bufsz + (f->dev->bufsz / f->dev->round) * f->round);
1297: m->u.par.round = htonl(f->round);
1.1 ratchov 1298: f->rstate = SOCK_RRET;
1299: f->rtodo = sizeof(struct amsg);
1.3 ratchov 1300: break;
1301: case AMSG_SETVOL:
1.37 ratchov 1302: #ifdef DEBUG
1303: if (debug_level >= 3) {
1304: sock_dbg(f);
1305: dbg_puts(": SETVOL message\n");
1306: }
1307: #endif
1.42 ratchov 1308: if (f->pstate != SOCK_RUN && f->pstate != SOCK_START &&
1309: f->pstate != SOCK_INIT && f->pstate != SOCK_READY) {
1.37 ratchov 1310: #ifdef DEBUG
1311: if (debug_level >= 1) {
1312: sock_dbg(f);
1313: dbg_puts(": SETVOL, bad state\n");
1314: }
1315: #endif
1.3 ratchov 1316: aproc_del(f->pipe.file.rproc);
1317: return 0;
1318: }
1.59 ratchov 1319: ctl = ntohl(m->u.vol.ctl);
1320: if (ctl > MIDI_MAXCTL) {
1.37 ratchov 1321: #ifdef DEBUG
1322: if (debug_level >= 1) {
1323: sock_dbg(f);
1324: dbg_puts(": SETVOL, volume out of range\n");
1325: }
1326: #endif
1.3 ratchov 1327: aproc_del(f->pipe.file.rproc);
1328: return 0;
1329: }
1.59 ratchov 1330: sock_setvol(f, ctl);
1.34 ratchov 1331: if (f->slot >= 0)
1.62 ratchov 1332: dev_slotvol(f->dev, f->slot, ctl);
1.3 ratchov 1333: f->rtodo = sizeof(struct amsg);
1334: f->rstate = SOCK_RMSG;
1.57 ratchov 1335: break;
1336: case AMSG_AUTH:
1337: #ifdef DEBUG
1338: if (debug_level >= 3) {
1339: sock_dbg(f);
1340: dbg_puts(": AUTH message\n");
1341: }
1342: #endif
1343: if (f->pstate != SOCK_AUTH) {
1344: #ifdef DEBUG
1345: if (debug_level >= 1) {
1346: sock_dbg(f);
1347: dbg_puts(": AUTH, bad state\n");
1348: }
1349: #endif
1350: aproc_del(f->pipe.file.rproc);
1351: return 0;
1352: }
1353: if (!sock_auth(f)) {
1354: aproc_del(f->pipe.file.rproc);
1355: return 0;
1356: }
1357: f->rstate = SOCK_RMSG;
1358: f->rtodo = sizeof(struct amsg);
1.17 ratchov 1359: break;
1360: case AMSG_HELLO:
1.37 ratchov 1361: #ifdef DEBUG
1362: if (debug_level >= 3) {
1363: sock_dbg(f);
1364: dbg_puts(": HELLO message\n");
1365: }
1366: #endif
1.18 ratchov 1367: if (f->pstate != SOCK_HELLO) {
1.37 ratchov 1368: #ifdef DEBUG
1369: if (debug_level >= 1) {
1370: sock_dbg(f);
1371: dbg_puts(": HELLO, bad state\n");
1372: }
1373: #endif
1.17 ratchov 1374: aproc_del(f->pipe.file.rproc);
1375: return 0;
1376: }
1377: if (!sock_hello(f)) {
1378: aproc_del(f->pipe.file.rproc);
1379: return 0;
1380: }
1381: AMSG_INIT(m);
1.59 ratchov 1382: m->cmd = htonl(AMSG_ACK);
1.17 ratchov 1383: f->rstate = SOCK_RRET;
1384: f->rtodo = sizeof(struct amsg);
1.1 ratchov 1385: break;
1.28 ratchov 1386: case AMSG_BYE:
1.37 ratchov 1387: #ifdef DEBUG
1388: if (debug_level >= 3) {
1389: sock_dbg(f);
1390: dbg_puts(": BYE message\n");
1391: }
1392: #endif
1.55 ratchov 1393: if (f->pstate != SOCK_INIT && f->pstate != SOCK_MIDI) {
1.37 ratchov 1394: #ifdef DEBUG
1395: if (debug_level >= 1) {
1396: sock_dbg(f);
1397: dbg_puts(": BYE, bad state\n");
1398: }
1399: #endif
1.29 ratchov 1400: }
1.28 ratchov 1401: aproc_del(f->pipe.file.rproc);
1402: return 0;
1.1 ratchov 1403: default:
1.37 ratchov 1404: #ifdef DEBUG
1405: if (debug_level >= 1) {
1406: sock_dbg(f);
1407: dbg_puts(": unknown command in message\n");
1408: }
1409: #endif
1.1 ratchov 1410: aproc_del(f->pipe.file.rproc);
1411: return 0;
1412: }
1413: return 1;
1414: }
1415:
1416: /*
1.20 ratchov 1417: * Create a new data/pos message.
1.1 ratchov 1418: */
1419: int
1420: sock_buildmsg(struct sock *f)
1421: {
1422: struct aproc *p;
1423: struct abuf *ibuf;
1.63 ratchov 1424: unsigned int size, max;
1.12 ratchov 1425:
1.1 ratchov 1426: /*
1.49 ratchov 1427: * Send initial position
1428: */
1429: if (f->startpending) {
1430: #ifdef DEBUG
1431: if (debug_level >= 4) {
1432: sock_dbg(f);
1433: dbg_puts(": building POS message, pos = ");
1434: dbg_puti(f->startpos);
1435: dbg_puts("\n");
1436: }
1437: #endif
1438: AMSG_INIT(&f->wmsg);
1.59 ratchov 1439: f->wmsg.cmd = htonl(AMSG_POS);
1440: f->wmsg.u.ts.delta = htonl(f->startpos);
1.50 ratchov 1441: f->rmax += f->startpos;
1.49 ratchov 1442: f->wtodo = sizeof(struct amsg);
1443: f->wstate = SOCK_WMSG;
1444: f->startpending = 0;
1445: return 1;
1446: }
1447:
1448: /*
1.20 ratchov 1449: * If pos changed, build a MOVE message.
1.1 ratchov 1450: */
1.49 ratchov 1451: if (f->tickpending) {
1.37 ratchov 1452: #ifdef DEBUG
1453: if (debug_level >= 4) {
1454: sock_dbg(f);
1.49 ratchov 1455: dbg_puts(": building MOVE message, delta = ");
1.37 ratchov 1456: dbg_puti(f->delta);
1457: dbg_puts("\n");
1458: }
1459: #endif
1.42 ratchov 1460: f->wmax += f->delta;
1.49 ratchov 1461: f->rmax += f->delta;
1.1 ratchov 1462: AMSG_INIT(&f->wmsg);
1.59 ratchov 1463: f->wmsg.cmd = htonl(AMSG_MOVE);
1464: f->wmsg.u.ts.delta = htonl(f->delta);
1.1 ratchov 1465: f->wtodo = sizeof(struct amsg);
1466: f->wstate = SOCK_WMSG;
1.14 ratchov 1467: f->delta = 0;
1468: f->tickpending = 0;
1.25 ratchov 1469: return 1;
1470: }
1471:
1472: /*
1473: * if volume changed build a SETVOL message
1474: */
1.27 ratchov 1475: if (f->pstate >= SOCK_START && f->vol != f->lastvol) {
1.37 ratchov 1476: #ifdef DEBUG
1477: if (debug_level >= 4) {
1478: sock_dbg(f);
1479: dbg_puts(": building SETVOL message, vol = ");
1480: dbg_puti(f->vol);
1481: dbg_puts("\n");
1482: }
1483: #endif
1.25 ratchov 1484: AMSG_INIT(&f->wmsg);
1.59 ratchov 1485: f->wmsg.cmd = htonl(AMSG_SETVOL);
1486: f->wmsg.u.vol.ctl = htonl(f->vol);
1.25 ratchov 1487: f->wtodo = sizeof(struct amsg);
1488: f->wstate = SOCK_WMSG;
1489: f->lastvol = f->vol;
1.1 ratchov 1490: return 1;
1491: }
1492:
1493: /*
1.20 ratchov 1494: * If data available, build a DATA message.
1.1 ratchov 1495: */
1496: p = f->pipe.file.wproc;
1.45 ratchov 1497: ibuf = LIST_FIRST(&p->ins);
1.1 ratchov 1498: if (ibuf && ABUF_ROK(ibuf)) {
1.42 ratchov 1499: #ifdef DEBUG
1.55 ratchov 1500: if (debug_level >= 3 &&
1501: f->pstate != SOCK_MIDI && ibuf->used > f->wmax) {
1.42 ratchov 1502: sock_dbg(f);
1.46 ratchov 1503: dbg_puts(": attempt to send past current position: used = ");
1504: dbg_putu(ibuf->used);
1505: dbg_puts(" wmax = ");
1506: dbg_putu(f->wmax);
1507: dbg_puts("\n");
1.42 ratchov 1508: }
1509: #endif
1510: size = ibuf->used;
1.55 ratchov 1511: if (f->pstate == SOCK_MIDI) {
1512: if (size > AMSG_DATAMAX)
1513: size = AMSG_DATAMAX;
1514: if (size == 0)
1515: return 0;
1516: } else {
1517: max = AMSG_DATAMAX / ibuf->bpf;
1518: if (size > max)
1519: size = max;
1520: if (size > f->walign)
1521: size = f->walign;
1522: if (size > f->wmax)
1523: size = f->wmax;
1524: if (size == 0)
1525: return 0;
1526: f->walign -= size;
1527: f->wmax -= size;
1528: if (f->walign == 0)
1529: f->walign = f->round;
1530: size *= ibuf->bpf;
1531: }
1.1 ratchov 1532: AMSG_INIT(&f->wmsg);
1.59 ratchov 1533: f->wmsg.cmd = htonl(AMSG_DATA);
1534: f->wmsg.u.data.size = htonl(size);
1.1 ratchov 1535: f->wtodo = sizeof(struct amsg);
1536: f->wstate = SOCK_WMSG;
1537: return 1;
1538: }
1.37 ratchov 1539: #ifdef DEBUG
1540: if (debug_level >= 4) {
1541: sock_dbg(f);
1542: dbg_puts(": no messages to build anymore, idling...\n");
1543: }
1544: #endif
1.1 ratchov 1545: f->wstate = SOCK_WIDLE;
1546: return 0;
1547: }
1548:
1549: /*
1.20 ratchov 1550: * Read from the socket file descriptor, fill input buffer and update
1.1 ratchov 1551: * the state. Return 1 if at least one message or 1 data byte was
1552: * processed, 0 if something blocked.
1553: */
1554: int
1555: sock_read(struct sock *f)
1556: {
1.64 ! ratchov 1557: int rc;
! 1558:
1.37 ratchov 1559: #ifdef DEBUG
1560: if (debug_level >= 4) {
1561: sock_dbg(f);
1.39 ratchov 1562: dbg_puts(": reading ");
1.37 ratchov 1563: dbg_putu(f->rtodo);
1.39 ratchov 1564: dbg_puts(" todo\n");
1.37 ratchov 1565: }
1566: #endif
1.1 ratchov 1567: switch (f->rstate) {
1568: case SOCK_RMSG:
1569: if (!sock_rmsg(f))
1570: return 0;
1571: if (!sock_execmsg(f))
1572: return 0;
1573: break;
1574: case SOCK_RDATA:
1575: if (!sock_rdata(f))
1576: return 0;
1.55 ratchov 1577: if (f->rtodo == 0) {
1.1 ratchov 1578: f->rstate = SOCK_RMSG;
1579: f->rtodo = sizeof(struct amsg);
1580: }
1.35 ratchov 1581: /*
1.42 ratchov 1582: * XXX: sock_attach() may not start if there's not enough
1.62 ratchov 1583: * samples queued, if so dev_slotstart() will trigger
1.42 ratchov 1584: * other streams, but this one won't start.
1.35 ratchov 1585: */
1.62 ratchov 1586: if (f->pstate == SOCK_READY && dev_slotstart(f->dev, f->slot))
1.1 ratchov 1587: (void)sock_attach(f, 0);
1588: break;
1589: case SOCK_RRET:
1.37 ratchov 1590: #ifdef DEBUG
1591: if (debug_level >= 4) {
1592: sock_dbg(f);
1593: dbg_puts(": blocked by pending RRET message\n");
1594: }
1595: #endif
1.1 ratchov 1596: return 0;
1597: }
1.54 ratchov 1598: for (;;) {
1599: /*
1600: * send pending ACKs, initial positions, initial volumes
1601: */
1.64 ! ratchov 1602: f->pipe.file.state |= FILE_WINUSE;
! 1603: rc = sock_write(f);
! 1604: f->pipe.file.state &= ~FILE_WINUSE;
! 1605: if (f->pipe.file.state & FILE_ZOMB) {
! 1606: file_del(&f->pipe.file);
! 1607: return 0;
! 1608: }
! 1609: if (!rc)
1.54 ratchov 1610: break;
1611: }
1.1 ratchov 1612: return 1;
1613: }
1614:
1615: /*
1.20 ratchov 1616: * Process messages to return.
1.1 ratchov 1617: */
1618: int
1619: sock_return(struct sock *f)
1620: {
1621: struct aproc *rp;
1622:
1623: while (f->rstate == SOCK_RRET) {
1624: if (!sock_wmsg(f, &f->rmsg, &f->rtodo))
1625: return 0;
1.37 ratchov 1626: #ifdef DEBUG
1627: if (debug_level >= 4) {
1628: sock_dbg(f);
1629: dbg_puts(": sent RRET message\n");
1630: }
1631: #endif
1.55 ratchov 1632: f->rstate = SOCK_RMSG;
1633: f->rtodo = sizeof(struct amsg);
1.19 ratchov 1634: if (f->pipe.file.state & FILE_RINUSE)
1635: break;
1636: f->pipe.file.state |= FILE_RINUSE;
1.1 ratchov 1637: for (;;) {
1638: /*
1639: * in() may trigger rsock_done and destroy the
1.20 ratchov 1640: * wsock.
1.1 ratchov 1641: */
1642: rp = f->pipe.file.rproc;
1.64 ! ratchov 1643: if (!rp)
1.1 ratchov 1644: break;
1.64 ! ratchov 1645: #ifdef DEBUG
! 1646: if (debug_level >= 4) {
! 1647: aproc_dbg(rp);
! 1648: dbg_puts(": in\n");
! 1649: }
! 1650: #endif
! 1651: if (!rp->ops->in(rp, NULL)) {
! 1652: break;
! 1653: }
1.1 ratchov 1654: }
1.19 ratchov 1655: f->pipe.file.state &= ~FILE_RINUSE;
1.64 ! ratchov 1656: if (f->pipe.file.state & FILE_ZOMB) {
! 1657: file_del(&f->pipe.file);
1.1 ratchov 1658: return 0;
1.64 ! ratchov 1659: }
1.1 ratchov 1660: }
1661: return 1;
1662: }
1663:
1664: /*
1.20 ratchov 1665: * Write messages and data on the socket file descriptor. Return 1 if
1.1 ratchov 1666: * at least one message or one data byte was processed, 0 if something
1667: * blocked.
1668: */
1669: int
1670: sock_write(struct sock *f)
1671: {
1.37 ratchov 1672: #ifdef DEBUG
1673: if (debug_level >= 4) {
1674: sock_dbg(f);
1.54 ratchov 1675: dbg_puts(": writing");
1676: if (f->wstate != SOCK_WIDLE) {
1677: dbg_puts(" todo = ");
1678: dbg_putu(f->wtodo);
1679: }
1680: dbg_puts("\n");
1.37 ratchov 1681: }
1682: #endif
1.1 ratchov 1683: switch (f->wstate) {
1684: case SOCK_WMSG:
1685: if (!sock_wmsg(f, &f->wmsg, &f->wtodo))
1686: return 0;
1.59 ratchov 1687: if (ntohl(f->wmsg.cmd) != AMSG_DATA) {
1.1 ratchov 1688: f->wstate = SOCK_WIDLE;
1689: f->wtodo = 0xdeadbeef;
1690: break;
1691: }
1.42 ratchov 1692: /*
1693: * XXX: why not set f->wtodo in sock_wmsg() ?
1694: */
1.1 ratchov 1695: f->wstate = SOCK_WDATA;
1.59 ratchov 1696: f->wtodo = ntohl(f->wmsg.u.data.size) /
1.45 ratchov 1697: LIST_FIRST(&f->pipe.file.wproc->ins)->bpf;
1.1 ratchov 1698: /* PASSTHROUGH */
1699: case SOCK_WDATA:
1700: if (!sock_wdata(f))
1701: return 0;
1.55 ratchov 1702: if (f->wtodo > 0)
1.1 ratchov 1703: break;
1704: f->wstate = SOCK_WIDLE;
1705: f->wtodo = 0xdeadbeef;
1.42 ratchov 1706: if (f->pstate == SOCK_STOP)
1707: sock_freebuf(f);
1.1 ratchov 1708: /* PASSTHROUGH */
1709: case SOCK_WIDLE:
1710: if (!sock_return(f))
1711: return 0;
1712: if (!sock_buildmsg(f))
1713: return 0;
1714: break;
1.37 ratchov 1715: #ifdef DEBUG
1716: default:
1717: sock_dbg(f);
1718: dbg_puts(": bad writing end state\n");
1719: dbg_panic();
1720: #endif
1.1 ratchov 1721: }
1722: return 1;
1723: }