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