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