Annotation of src/usr.bin/aucat/sock.c, Revision 1.52
1.52 ! ratchov 1: /* $OpenBSD: sock.c,v 1.51 2010/10/21 18:57:42 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.44 ratchov 96: unsigned sock_sesrefs = 0; /* connections to the session */
97: uid_t sock_sesuid; /* owner of the session */
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.44 ratchov 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.48 ratchov 123: ctl_slotdel(f->dev->midi, 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.48 ratchov 228: ctl_slotdel(f->dev->midi, 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;
1.44 ratchov 325: uid_t uid, gid;
326:
327: /*
328: * ensure that all connections belong to the same user,
329: * for privacy reasons.
330: *
331: * XXX: is there a portable way of doing this ?
332: */
333: if (getpeereid(fd, &uid, &gid) < 0) {
334: close(fd);
335: return NULL;
336: }
337: if (sock_sesrefs == 0) {
338: /* start a new session */
339: sock_sesuid = uid;
340: } else if (uid != sock_sesuid) {
341: /* session owned by another user, drop connection */
342: close(fd);
343: return NULL;
344: }
345: sock_sesrefs++;
1.1 ratchov 346:
1.19 ratchov 347: f = (struct sock *)pipe_new(ops, fd, "sock");
1.46 ratchov 348: if (f == NULL) {
349: close(fd);
350: return NULL;
351: }
1.18 ratchov 352: f->pstate = SOCK_HELLO;
1.1 ratchov 353: f->mode = 0;
1.48 ratchov 354: f->opt = NULL;
355: f->dev = NULL;
1.51 ratchov 356: f->xrun = XRUN_IGNORE;
1.14 ratchov 357: f->delta = 0;
358: f->tickpending = 0;
1.49 ratchov 359: f->startpos = 0;
1.42 ratchov 360: f->startpending = 0;
1.25 ratchov 361: f->vol = f->lastvol = MIDI_MAXCTL;
1.24 ratchov 362: f->slot = -1;
1.1 ratchov 363:
1.19 ratchov 364: wproc = aproc_new(&wsock_ops, f->pipe.file.name);
1.1 ratchov 365: wproc->u.io.file = &f->pipe.file;
1.42 ratchov 366: wproc->u.io.partial = 0;
1.1 ratchov 367: f->pipe.file.wproc = wproc;
368: f->wstate = SOCK_WIDLE;
369: f->wtodo = 0xdeadbeef;
370:
1.19 ratchov 371: rproc = aproc_new(&rsock_ops, f->pipe.file.name);
1.1 ratchov 372: rproc->u.io.file = &f->pipe.file;
1.42 ratchov 373: rproc->u.io.partial = 0;
1.1 ratchov 374: f->pipe.file.rproc = rproc;
375: f->rstate = SOCK_RMSG;
376: f->rtodo = sizeof(struct amsg);
377: return f;
378: }
379:
380: /*
1.20 ratchov 381: * Free buffers.
1.1 ratchov 382: */
383: void
384: sock_freebuf(struct sock *f)
385: {
386: struct abuf *rbuf, *wbuf;
1.12 ratchov 387:
1.1 ratchov 388: f->pstate = SOCK_INIT;
1.37 ratchov 389: #ifdef DEBUG
390: if (debug_level >= 3) {
391: sock_dbg(f);
392: dbg_puts(": freeing buffers\n");
393: }
394: #endif
1.45 ratchov 395: wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
396: rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.35 ratchov 397: if (rbuf || wbuf)
1.48 ratchov 398: ctl_slotstop(f->dev->midi, f->slot);
1.1 ratchov 399: if (rbuf)
400: abuf_eof(rbuf);
401: if (wbuf)
402: abuf_hup(wbuf);
1.32 ratchov 403: f->tickpending = 0;
1.42 ratchov 404: f->startpending = 0;
1.1 ratchov 405: }
406:
407: /*
1.20 ratchov 408: * Allocate buffers, so client can start filling write-end.
1.1 ratchov 409: */
410: void
411: sock_allocbuf(struct sock *f)
412: {
413: struct abuf *rbuf = NULL, *wbuf = NULL;
1.50 ratchov 414: unsigned bufsz;
1.1 ratchov 415:
1.50 ratchov 416: bufsz = f->bufsz + f->dev->bufsz / f->dev->round * f->round;
1.42 ratchov 417: f->pstate = SOCK_START;
1.51 ratchov 418: if (f->mode & MODE_PLAY) {
1.50 ratchov 419: rbuf = abuf_new(bufsz, &f->rpar);
1.1 ratchov 420: aproc_setout(f->pipe.file.rproc, rbuf);
1.42 ratchov 421: if (!ABUF_WOK(rbuf) || (f->pipe.file.state & FILE_EOF))
422: f->pstate = SOCK_READY;
1.50 ratchov 423: f->rmax = bufsz * aparams_bpf(&f->rpar);
1.1 ratchov 424: }
1.51 ratchov 425: if (f->mode & MODE_RECMASK) {
1.50 ratchov 426: wbuf = abuf_new(bufsz, &f->wpar);
1.1 ratchov 427: aproc_setin(f->pipe.file.wproc, wbuf);
1.42 ratchov 428: f->walign = f->round;
1.50 ratchov 429: f->wmax = 0;
1.1 ratchov 430: }
1.14 ratchov 431: f->delta = 0;
1.49 ratchov 432: f->startpos = 0;
1.14 ratchov 433: f->tickpending = 0;
1.42 ratchov 434: f->startpending = 0;
1.37 ratchov 435: #ifdef DEBUG
436: if (debug_level >= 3) {
437: sock_dbg(f);
438: dbg_puts(": allocating ");
439: dbg_putu(f->bufsz);
1.50 ratchov 440: dbg_puts("/");
441: dbg_putu(bufsz);
1.42 ratchov 442: dbg_puts(" fr buffers, rmax = ");
443: dbg_putu(f->rmax);
444: dbg_puts("\n");
1.37 ratchov 445: }
446: #endif
1.51 ratchov 447: if (f->mode & MODE_PLAY) {
1.42 ratchov 448: f->pstate = SOCK_START;
449: } else {
450: f->pstate = SOCK_READY;
1.48 ratchov 451: if (ctl_slotstart(f->dev->midi, f->slot))
1.42 ratchov 452: (void)sock_attach(f, 0);
453: }
1.1 ratchov 454: }
455:
456: /*
1.25 ratchov 457: * Set volume. Callback invoked when volume is modified externally
1.3 ratchov 458: */
459: void
1.25 ratchov 460: sock_setvol(void *arg, unsigned vol)
1.3 ratchov 461: {
1.25 ratchov 462: struct sock *f = (struct sock *)arg;
1.3 ratchov 463: struct abuf *rbuf;
1.12 ratchov 464:
1.3 ratchov 465: f->vol = vol;
1.45 ratchov 466: rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.3 ratchov 467: if (!rbuf) {
1.37 ratchov 468: #ifdef DEBUG
469: if (debug_level >= 3) {
470: sock_dbg(f);
471: dbg_puts(": no read buffer to set volume yet\n");
472: }
473: #endif
1.3 ratchov 474: return;
475: }
1.48 ratchov 476: dev_setvol(f->dev, rbuf, MIDI_TO_ADATA(vol));
1.3 ratchov 477: }
478:
479: /*
1.35 ratchov 480: * Attach the stream. Callback invoked when MMC start
481: */
482: void
483: sock_startreq(void *arg)
484: {
485: struct sock *f = (struct sock *)arg;
486:
1.37 ratchov 487: #ifdef DEBUG
1.42 ratchov 488: if (f->pstate != SOCK_READY) {
1.37 ratchov 489: sock_dbg(f);
1.42 ratchov 490: dbg_puts(": not in READY state\n");
1.37 ratchov 491: dbg_panic();
492: }
493: #endif
1.35 ratchov 494: (void)sock_attach(f, 0);
1.52 ! ratchov 495: }
! 496:
! 497: /*
1.42 ratchov 498: * Callback invoked by MMC stop
499: */
500: void
501: sock_stopreq(void *arg)
502: {
503: #ifdef DEBUG
504: struct sock *f = (struct sock *)arg;
505:
506: if (debug_level >= 3) {
507: sock_dbg(f);
508: dbg_puts(": ignored STOP signal\n");
509: }
510: #endif
511: }
512:
513: /*
514: * Callback invoked by MMC relocate, ignored
515: */
516: void
517: sock_locreq(void *arg, unsigned mmcpos)
518: {
519: #ifdef DEBUG
520: struct sock *f = (struct sock *)arg;
521:
522: if (debug_level >= 3) {
523: sock_dbg(f);
524: dbg_puts(": ignored RELOCATE signal\n");
525: }
526: #endif
527: }
528:
529: /*
1.48 ratchov 530: * Callback invoked when slot is gone
531: */
532: void
533: sock_quitreq(void *arg)
534: {
535: struct sock *f = (struct sock *)arg;
536:
537: #ifdef DEBUG
538: if (debug_level >= 3) {
539: sock_dbg(f);
540: dbg_puts(": slot gone\n");
541: }
542: #endif
543: file_close(&f->pipe.file);
544: }
545:
546: /*
1.51 ratchov 547: * Attach play and/or record buffers to the device
1.1 ratchov 548: */
1.42 ratchov 549: void
1.1 ratchov 550: sock_attach(struct sock *f, int force)
551: {
552: struct abuf *rbuf, *wbuf;
553:
1.45 ratchov 554: rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
555: wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
1.1 ratchov 556:
557: /*
1.20 ratchov 558: * If in SOCK_START state, dont attach until
559: * the buffer isn't completely filled.
1.1 ratchov 560: */
561: if (!force && rbuf && ABUF_WOK(rbuf))
1.42 ratchov 562: return;
1.12 ratchov 563:
1.42 ratchov 564: /*
1.46 ratchov 565: * start the device (dev_getpos() and dev_attach() must
566: * be called on a started device
567: */
1.48 ratchov 568: dev_wakeup(f->dev);
1.46 ratchov 569:
570: /*
1.42 ratchov 571: * get the current position, the origin is when
572: * the first sample is played/recorded
573: */
1.49 ratchov 574: f->startpos = dev_getpos(f->dev) * (int)f->round / (int)f->dev->round;
1.42 ratchov 575: f->startpending = 1;
576: f->pstate = SOCK_RUN;
1.37 ratchov 577: #ifdef DEBUG
578: if (debug_level >= 3) {
579: sock_dbg(f);
1.42 ratchov 580: dbg_puts(": attaching at ");
1.49 ratchov 581: dbg_puti(f->startpos);
1.42 ratchov 582: dbg_puts("\n");
1.37 ratchov 583: }
584: #endif
1.1 ratchov 585: /*
1.42 ratchov 586: * We dont check whether the device is dying,
587: * because dev_xxx() functions are supposed to
588: * work (i.e., not to crash)
1.1 ratchov 589: */
1.48 ratchov 590: dev_attach(f->dev, f->pipe.file.name, f->mode,
1.43 ratchov 591: rbuf, &f->rpar,
592: f->opt->join ? f->opt->rpar.cmax - f->opt->rpar.cmin + 1 : 0,
593: wbuf, &f->wpar,
594: f->opt->join ? f->opt->wpar.cmax - f->opt->wpar.cmin + 1 : 0,
595: f->xrun, f->opt->maxweight);
1.51 ratchov 596: if (f->mode & MODE_PLAY)
1.48 ratchov 597: dev_setvol(f->dev, rbuf, MIDI_TO_ADATA(f->vol));
1.3 ratchov 598:
1.1 ratchov 599: /*
1.20 ratchov 600: * Send the initial position, if needed.
1.1 ratchov 601: */
602: for (;;) {
603: if (!sock_write(f))
604: break;
605: }
606: }
607:
608: void
609: sock_reset(struct sock *f)
610: {
611: switch (f->pstate) {
612: case SOCK_START:
1.42 ratchov 613: case SOCK_READY:
1.48 ratchov 614: if (ctl_slotstart(f->dev->midi, f->slot)) {
1.35 ratchov 615: (void)sock_attach(f, 1);
616: f->pstate = SOCK_RUN;
617: }
1.1 ratchov 618: /* PASSTHROUGH */
619: case SOCK_RUN:
620: sock_freebuf(f);
621: f->pstate = SOCK_INIT;
622: /* PASSTHROUGH */
623: case SOCK_INIT:
624: /* nothing yet */
625: break;
626: }
627: }
628:
629: /*
1.20 ratchov 630: * Read a message from the file descriptor, return 1 if done, 0
631: * otherwise. The message is stored in f->rmsg.
1.1 ratchov 632: */
633: int
634: sock_rmsg(struct sock *f)
635: {
636: unsigned count;
637: unsigned char *data;
638:
639: while (f->rtodo > 0) {
640: if (!(f->pipe.file.state & FILE_ROK)) {
1.37 ratchov 641: #ifdef DEBUG
642: if (debug_level >= 4) {
643: sock_dbg(f);
644: dbg_puts(": reading message blocked, ");
645: dbg_putu(f->rtodo);
646: dbg_puts(" bytes remaining\n");
647: }
648: #endif
1.1 ratchov 649: return 0;
650: }
651: data = (unsigned char *)&f->rmsg;
652: data += sizeof(struct amsg) - f->rtodo;
653: count = file_read(&f->pipe.file, data, f->rtodo);
654: if (count == 0)
655: return 0;
656: f->rtodo -= count;
657: }
1.37 ratchov 658: #ifdef DEBUG
659: if (debug_level >= 4) {
660: sock_dbg(f);
661: dbg_puts(": read full message\n");
662: }
663: #endif
1.1 ratchov 664: return 1;
665: }
666:
667: /*
1.20 ratchov 668: * Write a message to the file descriptor, return 1 if done, 0
1.1 ratchov 669: * otherwise. The "m" argument is f->rmsg or f->wmsg, and the "ptodo"
670: * points to the f->rtodo or f->wtodo respectively.
671: */
672: int
673: sock_wmsg(struct sock *f, struct amsg *m, unsigned *ptodo)
674: {
675: unsigned count;
676: unsigned char *data;
677:
678: while (*ptodo > 0) {
679: if (!(f->pipe.file.state & FILE_WOK)) {
1.37 ratchov 680: #ifdef DEBUG
681: if (debug_level >= 4) {
682: sock_dbg(f);
683: dbg_puts(": writing message blocked, ");
684: dbg_putu(*ptodo);
685: dbg_puts(" bytes remaining\n");
686: }
687: #endif
1.1 ratchov 688: return 0;
689: }
690: data = (unsigned char *)m;
691: data += sizeof(struct amsg) - *ptodo;
692: count = file_write(&f->pipe.file, data, *ptodo);
693: if (count == 0)
694: return 0;
695: *ptodo -= count;
696: }
1.37 ratchov 697: #ifdef DEBUG
698: if (debug_level >= 4) {
699: sock_dbg(f);
700: dbg_puts(": wrote full message\n");
701: }
702: #endif
1.1 ratchov 703: return 1;
704: }
705:
706: /*
1.20 ratchov 707: * Read data chunk from the file descriptor, return 1 if at least one
1.1 ratchov 708: * byte was read, 0 if the file blocked.
709: */
710: int
711: sock_rdata(struct sock *f)
712: {
713: struct aproc *p;
714: struct abuf *obuf;
1.42 ratchov 715: unsigned n;
1.1 ratchov 716:
1.37 ratchov 717: #ifdef DEBUG
718: if (f->pstate != SOCK_MIDI && f->rtodo == 0) {
719: sock_dbg(f);
720: dbg_puts(": data block already read\n");
721: dbg_panic();
722: }
723: #endif
1.1 ratchov 724: p = f->pipe.file.rproc;
1.45 ratchov 725: obuf = LIST_FIRST(&p->outs);
1.19 ratchov 726: if (obuf == NULL)
727: return 0;
1.42 ratchov 728: if (!ABUF_WOK(obuf) || !(f->pipe.file.state & FILE_ROK))
1.41 ratchov 729: return 0;
1.42 ratchov 730: if (f->pstate == SOCK_MIDI) {
731: if (!rfile_do(p, obuf->len, NULL))
732: return 0;
733: } else {
734: if (!rfile_do(p, f->rtodo, &n))
735: return 0;
1.19 ratchov 736: f->rtodo -= n;
1.42 ratchov 737: if (f->pstate == SOCK_START) {
738: if (!ABUF_WOK(obuf) || (f->pipe.file.state & FILE_EOF))
739: f->pstate = SOCK_READY;
740: }
741: }
1.1 ratchov 742: return 1;
743: }
744:
745: /*
1.20 ratchov 746: * Write data chunk to the file descriptor, return 1 if at least one
1.1 ratchov 747: * byte was written, 0 if the file blocked.
748: */
749: int
750: sock_wdata(struct sock *f)
751: {
752: struct aproc *p;
753: struct abuf *ibuf;
1.42 ratchov 754: unsigned n;
1.1 ratchov 755:
1.37 ratchov 756: #ifdef DEBUG
757: if (f->pstate != SOCK_MIDI && f->wtodo == 0) {
758: sock_dbg(f);
759: dbg_puts(": attempted to write zero-sized data block\n");
760: dbg_panic();
761: }
762: #endif
1.1 ratchov 763: if (!(f->pipe.file.state & FILE_WOK))
764: return 0;
765: p = f->pipe.file.wproc;
1.45 ratchov 766: ibuf = LIST_FIRST(&p->ins);
1.42 ratchov 767: #ifdef DEBUG
768: if (f->pstate != SOCK_MIDI && ibuf == NULL) {
769: sock_dbg(f);
770: dbg_puts(": attempted to write on detached buffer\n");
771: dbg_panic();
772: }
773: #endif
774: if (ibuf == NULL)
775: return 0;
776: if (!ABUF_ROK(ibuf))
777: return 0;
778: if (f->pstate == SOCK_MIDI) {
779: if (!wfile_do(p, ibuf->len, NULL))
1.1 ratchov 780: return 0;
781: } else {
1.42 ratchov 782: if (!wfile_do(p, f->wtodo, &n))
1.1 ratchov 783: return 0;
784: f->wtodo -= n;
1.12 ratchov 785: }
1.1 ratchov 786: return 1;
787: }
788:
789: int
790: sock_setpar(struct sock *f)
791: {
792: struct amsg_par *p = &f->rmsg.u.par;
1.9 ratchov 793: unsigned min, max, rate;
1.12 ratchov 794:
1.1 ratchov 795: if (AMSG_ISSET(p->bits)) {
796: if (p->bits < BITS_MIN || p->bits > BITS_MAX) {
1.37 ratchov 797: #ifdef DEBUG
798: if (debug_level >= 1) {
799: sock_dbg(f);
800: dbg_puts(": ");
801: dbg_putu(p->bits);
802: dbg_puts(": bits out of bounds\n");
803: }
804: #endif
1.1 ratchov 805: return 0;
806: }
807: if (AMSG_ISSET(p->bps)) {
808: if (p->bps < ((p->bits + 7) / 8) || p->bps > 4) {
1.37 ratchov 809: #ifdef DEBUG
810: if (debug_level >= 1) {
811: sock_dbg(f);
812: dbg_puts(": ");
813: dbg_putu(p->bps);
814: dbg_puts(": wrong bytes per sample\n");
815: }
816: #endif
1.1 ratchov 817: return 0;
818: }
819: } else
820: p->bps = APARAMS_BPS(p->bits);
821: f->rpar.bits = f->wpar.bits = p->bits;
822: f->rpar.bps = f->wpar.bps = p->bps;
1.37 ratchov 823: #ifdef DEBUG
824: if (debug_level >= 3) {
825: sock_dbg(f);
826: dbg_puts(": using ");
827: dbg_putu(p->bits);
828: dbg_puts("bits, ");
829: dbg_putu(p->bps);
830: dbg_puts(" bytes per sample\n");
831: }
832: #endif
1.1 ratchov 833: }
834: if (AMSG_ISSET(p->sig))
835: f->rpar.sig = f->wpar.sig = p->sig ? 1 : 0;
836: if (AMSG_ISSET(p->le))
837: f->rpar.le = f->wpar.le = p->le ? 1 : 0;
838: if (AMSG_ISSET(p->msb))
839: f->rpar.msb = f->wpar.msb = p->msb ? 1 : 0;
1.51 ratchov 840: if (AMSG_ISSET(p->rchan) && (f->mode & MODE_RECMASK)) {
1.1 ratchov 841: if (p->rchan < 1)
842: p->rchan = 1;
1.6 ratchov 843: if (p->rchan > NCHAN_MAX)
844: p->rchan = NCHAN_MAX;
1.19 ratchov 845: f->wpar.cmin = f->opt->wpar.cmin;
846: f->wpar.cmax = f->opt->wpar.cmin + p->rchan - 1;
847: if (f->wpar.cmax > f->opt->wpar.cmax)
848: f->wpar.cmax = f->opt->wpar.cmax;
1.37 ratchov 849: #ifdef DEBUG
850: if (debug_level >= 3) {
851: sock_dbg(f);
852: dbg_puts(": using recording channels ");
853: dbg_putu(f->wpar.cmin);
854: dbg_puts("..");
855: dbg_putu(f->wpar.cmax);
856: dbg_puts("\n");
857: }
858: #endif
1.1 ratchov 859: }
1.51 ratchov 860: if (AMSG_ISSET(p->pchan) && (f->mode & MODE_PLAY)) {
1.1 ratchov 861: if (p->pchan < 1)
862: p->pchan = 1;
1.6 ratchov 863: if (p->pchan > NCHAN_MAX)
864: p->pchan = NCHAN_MAX;
1.19 ratchov 865: f->rpar.cmin = f->opt->rpar.cmin;
866: f->rpar.cmax = f->opt->rpar.cmin + p->pchan - 1;
867: if (f->rpar.cmax > f->opt->rpar.cmax)
868: f->rpar.cmax = f->opt->rpar.cmax;
1.37 ratchov 869: #ifdef DEBUG
870: if (debug_level >= 3) {
871: sock_dbg(f);
872: dbg_puts(": using playback channels ");
873: dbg_putu(f->rpar.cmin);
874: dbg_puts("..");
875: dbg_putu(f->rpar.cmax);
876: dbg_puts("\n");
877: }
878: #endif
1.1 ratchov 879: }
880: if (AMSG_ISSET(p->rate)) {
881: if (p->rate < RATE_MIN)
882: p->rate = RATE_MIN;
883: if (p->rate > RATE_MAX)
884: p->rate = RATE_MAX;
1.48 ratchov 885: f->round = dev_roundof(f->dev, p->rate);
1.1 ratchov 886: f->rpar.rate = f->wpar.rate = p->rate;
1.10 ratchov 887: if (!AMSG_ISSET(p->appbufsz)) {
1.48 ratchov 888: p->appbufsz = f->dev->bufsz / f->dev->round * f->round;
1.37 ratchov 889: #ifdef DEBUG
890: if (debug_level >= 3) {
891: sock_dbg(f);
892: dbg_puts(": using ");
893: dbg_putu(p->appbufsz);
894: dbg_puts(" fr app buffer size\n");
895: }
896: #endif
897: }
898: #ifdef DEBUG
899: if (debug_level >= 3) {
900: sock_dbg(f);
901: dbg_puts(": using ");
902: dbg_putu(p->rate);
903: dbg_puts("Hz sample rate, ");
904: dbg_putu(f->round);
905: dbg_puts(" fr block size\n");
1.10 ratchov 906: }
1.37 ratchov 907: #endif
1.1 ratchov 908: }
909: if (AMSG_ISSET(p->xrun)) {
1.51 ratchov 910: if (p->xrun != XRUN_IGNORE &&
911: p->xrun != XRUN_SYNC &&
912: p->xrun != XRUN_ERROR) {
1.37 ratchov 913: #ifdef DEBUG
914: if (debug_level >= 1) {
915: sock_dbg(f);
916: dbg_puts(": ");
917: dbg_putx(p->xrun);
918: dbg_puts(": bad xrun policy\n");
919: }
920: #endif
1.1 ratchov 921: return 0;
922: }
923: f->xrun = p->xrun;
1.51 ratchov 924: if (f->opt->mmc && f->xrun == XRUN_IGNORE)
925: f->xrun = XRUN_SYNC;
1.37 ratchov 926: #ifdef DEBUG
927: if (debug_level >= 3) {
928: sock_dbg(f);
929: dbg_puts(": using 0x");
930: dbg_putx(f->xrun);
931: dbg_puts(" xrun policy\n");
932: }
933: #endif
1.1 ratchov 934: }
1.10 ratchov 935: if (AMSG_ISSET(p->appbufsz)) {
1.51 ratchov 936: rate = (f->mode & MODE_PLAY) ? f->rpar.rate : f->wpar.rate;
1.42 ratchov 937: min = 1;
1.48 ratchov 938: max = 1 + rate / f->dev->round;
1.9 ratchov 939: min *= f->round;
940: max *= f->round;
1.10 ratchov 941: p->appbufsz += f->round - 1;
942: p->appbufsz -= p->appbufsz % f->round;
943: if (p->appbufsz < min)
944: p->appbufsz = min;
945: if (p->appbufsz > max)
946: p->appbufsz = max;
947: f->bufsz = p->appbufsz;
1.37 ratchov 948: #ifdef DEBUG
949: if (debug_level >= 3) {
950: sock_dbg(f);
951: dbg_puts(": using ");
952: dbg_putu(f->bufsz);
953: dbg_puts(" buffer size\n");
954: }
955: #endif
956: }
957: #ifdef DEBUG
958: if (debug_level >= 2) {
1.48 ratchov 959: if (APROC_OK(f->dev->midi)) {
960: dbg_puts(f->dev->midi->u.ctl.slot[f->slot].name);
961: dbg_putu(f->dev->midi->u.ctl.slot[f->slot].unit);
1.37 ratchov 962: } else
963: dbg_puts(f->pipe.file.name);
964: dbg_puts(": buffer size = ");
965: dbg_putu(f->bufsz);
1.51 ratchov 966: if (f->mode & MODE_PLAY) {
1.37 ratchov 967: dbg_puts(", play = ");
968: aparams_dbg(&f->rpar);
969: }
1.51 ratchov 970: if (f->mode & MODE_RECMASK) {
1.37 ratchov 971: dbg_puts(", rec:");
972: aparams_dbg(&f->wpar);
973: }
974: dbg_puts("\n");
1.1 ratchov 975: }
1.37 ratchov 976: #endif
1.1 ratchov 977: return 1;
978: }
979:
1.19 ratchov 980: /*
981: * allocate buffers, so client can start filling write-end.
982: */
983: void
1.51 ratchov 984: sock_midiattach(struct sock *f)
1.19 ratchov 985: {
986: struct abuf *rbuf = NULL, *wbuf = NULL;
987:
1.51 ratchov 988: if (f->mode & MODE_MIDIOUT) {
1.22 ratchov 989: rbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
1.19 ratchov 990: aproc_setout(f->pipe.file.rproc, rbuf);
991: }
1.51 ratchov 992: if (f->mode & MODE_MIDIIN) {
1.22 ratchov 993: wbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
1.19 ratchov 994: aproc_setin(f->pipe.file.wproc, wbuf);
995: }
1.51 ratchov 996: f->pstate = SOCK_MIDI;
1.48 ratchov 997: dev_midiattach(f->dev, rbuf, wbuf);
1.19 ratchov 998: }
999:
1.17 ratchov 1000: int
1001: sock_hello(struct sock *f)
1002: {
1003: struct amsg_hello *p = &f->rmsg.u.hello;
1004:
1.37 ratchov 1005: #ifdef DEBUG
1006: if (debug_level >= 3) {
1007: sock_dbg(f);
1008: dbg_puts(": hello from <");
1009: dbg_puts(p->who);
1.51 ratchov 1010: dbg_puts(">, mode = ");
1011: dbg_putx(p->mode);
1.37 ratchov 1012: dbg_puts(", ver ");
1013: dbg_putu(p->version);
1014: dbg_puts("\n");
1015: }
1016: #endif
1.33 ratchov 1017: if (p->version != AMSG_VERSION) {
1.37 ratchov 1018: #ifdef DEBUG
1019: if (debug_level >= 1) {
1020: sock_dbg(f);
1021: dbg_puts(": ");
1022: dbg_putu(p->version);
1.51 ratchov 1023: dbg_puts(": unsupported protocol version\n");
1024: }
1025: #endif
1026: return 0;
1027: }
1028: switch (p->mode) {
1029: case MODE_MIDIIN:
1030: case MODE_MIDIOUT:
1031: case MODE_MIDIOUT | MODE_MIDIIN:
1032: case MODE_REC:
1033: case MODE_PLAY:
1034: case MODE_PLAY | MODE_REC:
1035: break;
1036: default:
1037: #ifdef DEBUG
1038: if (debug_level >= 1) {
1039: sock_dbg(f);
1040: dbg_puts(": ");
1041: dbg_putx(p->mode);
1042: dbg_puts(": unsupported mode\n");
1.37 ratchov 1043: }
1044: #endif
1.33 ratchov 1045: return 0;
1046: }
1.48 ratchov 1047: f->opt = opt_byname(p->opt);
1048: if (f->opt == NULL)
1049: return 0;
1050: if (!dev_ref(f->opt->dev))
1051: return 0;
1.51 ratchov 1052: if ((p->mode & MODE_REC) && (f->opt->mode & MODE_MON)) {
1053: p->mode &= ~MODE_REC;
1054: p->mode |= MODE_MON;
1055: }
1.48 ratchov 1056: f->dev = f->opt->dev;
1.51 ratchov 1057: f->mode = (p->mode & f->opt->mode) & f->dev->mode;
1.37 ratchov 1058: #ifdef DEBUG
1.51 ratchov 1059: if (debug_level >= 3) {
1060: sock_dbg(f);
1061: dbg_puts(": using mode = ");
1062: dbg_putx(f->mode);
1063: dbg_puts("\n");
1064: }
1.37 ratchov 1065: #endif
1.51 ratchov 1066: if (f->mode != p->mode) {
1.37 ratchov 1067: #ifdef DEBUG
1068: if (debug_level >= 1) {
1069: sock_dbg(f);
1.51 ratchov 1070: dbg_puts(": requested mode not available\n");
1.37 ratchov 1071: }
1072: #endif
1.17 ratchov 1073: return 0;
1074: }
1.51 ratchov 1075: if (f->mode & (MODE_MIDIOUT | MODE_MIDIIN)) {
1076: sock_midiattach(f);
1077: return 1;
1.24 ratchov 1078: }
1.51 ratchov 1079: if (f->mode & MODE_PLAY)
1080: f->rpar = f->opt->rpar;
1081: if (f->mode & MODE_RECMASK)
1082: f->wpar = f->opt->wpar;
1083: f->xrun = (f->opt->mmc) ? XRUN_SYNC : XRUN_IGNORE;
1084: f->bufsz = f->dev->bufsz;
1085: f->round = f->dev->round;
1086: f->slot = ctl_slotnew(f->dev->midi, p->who,
1087: &ctl_sockops, f,
1088: f->opt->mmc);
1089: if (f->slot < 0)
1090: return 0;
1.18 ratchov 1091: f->pstate = SOCK_INIT;
1.17 ratchov 1092: return 1;
1093: }
1094:
1.1 ratchov 1095: /*
1.20 ratchov 1096: * Execute message in f->rmsg and change the state accordingly; return 1
1.1 ratchov 1097: * on success, and 0 on failure, in which case the socket is destroyed.
1098: */
1099: int
1100: sock_execmsg(struct sock *f)
1101: {
1102: struct amsg *m = &f->rmsg;
1.42 ratchov 1103: struct abuf *obuf;
1.1 ratchov 1104:
1105: switch (m->cmd) {
1106: case AMSG_DATA:
1.37 ratchov 1107: #ifdef DEBUG
1108: if (debug_level >= 4) {
1109: sock_dbg(f);
1110: dbg_puts(": DATA message\n");
1111: }
1112: #endif
1.42 ratchov 1113: if (f->pstate != SOCK_RUN && f->pstate != SOCK_START &&
1114: f->pstate != SOCK_READY) {
1.37 ratchov 1115: #ifdef DEBUG
1116: if (debug_level >= 1) {
1117: sock_dbg(f);
1118: dbg_puts(": DATA, bad state\n");
1119: }
1120: #endif
1.8 ratchov 1121: aproc_del(f->pipe.file.rproc);
1122: return 0;
1123: }
1.51 ratchov 1124: if (!(f->mode & MODE_PLAY)) {
1.37 ratchov 1125: #ifdef DEBUG
1126: if (debug_level >= 1) {
1127: sock_dbg(f);
1128: dbg_puts(": DATA not allowed in record-only mode\n");
1129: }
1130: #endif
1.1 ratchov 1131: aproc_del(f->pipe.file.rproc);
1132: return 0;
1133: }
1.45 ratchov 1134: obuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.42 ratchov 1135: if (f->pstate == SOCK_START && !ABUF_WOK(obuf)) {
1.37 ratchov 1136: #ifdef DEBUG
1137: if (debug_level >= 1) {
1138: sock_dbg(f);
1139: dbg_puts(": DATA client violates flow control\n");
1140: }
1141: #endif
1.34 ratchov 1142: aproc_del(f->pipe.file.rproc);
1143: return 0;
1144: }
1.42 ratchov 1145: if (m->u.data.size % obuf->bpf != 0) {
1146: #ifdef DEBUG
1147: if (debug_level >= 1) {
1148: sock_dbg(f);
1149: dbg_puts(": unaligned data chunk\n");
1150: }
1151: #endif
1152: aproc_del(f->pipe.file.rproc);
1153: return 0;
1154: }
1.1 ratchov 1155: f->rstate = SOCK_RDATA;
1.42 ratchov 1156: f->rtodo = m->u.data.size / obuf->bpf;
1157: #ifdef DEBUG
1158: if (f->rtodo > f->rmax && debug_level >= 2) {
1159: sock_dbg(f);
1160: dbg_puts(": received past current position, rtodo = ");
1161: dbg_putu(f->rtodo);
1162: dbg_puts(", rmax = ");
1163: dbg_putu(f->rmax);
1164: dbg_puts("\n");
1165: aproc_del(f->pipe.file.rproc);
1166: return 0;
1167: }
1168: #endif
1169: f->rmax -= 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.48 ratchov 1225: ctl_slotstart(f->dev->midi, 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);
1232: m->cmd = AMSG_ACK;
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);
1278: m->cmd = 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;
1286: m->u.par.rate = f->rpar.rate;
1287: m->u.par.pchan = f->rpar.cmax - f->rpar.cmin + 1;
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;
1295: m->u.par.rate = f->wpar.rate;
1296: m->u.par.rchan = f->wpar.cmax - f->wpar.cmin + 1;
1297: }
1.10 ratchov 1298: m->u.par.appbufsz = f->bufsz;
1.12 ratchov 1299: m->u.par.bufsz =
1.48 ratchov 1300: f->bufsz + (f->dev->bufsz / f->dev->round) * f->round;
1.1 ratchov 1301: m->u.par.round = f->round;
1302: f->rstate = SOCK_RRET;
1303: f->rtodo = sizeof(struct amsg);
1304: break;
1305: case AMSG_GETCAP:
1.37 ratchov 1306: #ifdef DEBUG
1307: if (debug_level >= 3) {
1308: sock_dbg(f);
1309: dbg_puts(": GETCAP message\n");
1310: }
1311: #endif
1.1 ratchov 1312: if (f->pstate != SOCK_INIT) {
1.37 ratchov 1313: #ifdef DEBUG
1314: if (debug_level >= 1) {
1315: sock_dbg(f);
1316: dbg_puts(": GETCAP, bad state\n");
1317: }
1318: #endif
1.1 ratchov 1319: aproc_del(f->pipe.file.rproc);
1320: return 0;
1321: }
1322: AMSG_INIT(m);
1323: m->cmd = AMSG_GETCAP;
1.48 ratchov 1324: m->u.cap.rate = f->dev->rate;
1.42 ratchov 1325: m->u.cap.pchan = (f->opt->mode & MODE_PLAY) ?
1.19 ratchov 1326: (f->opt->rpar.cmax - f->opt->rpar.cmin + 1) : 0;
1.42 ratchov 1327: m->u.cap.rchan = (f->opt->mode & (MODE_PLAY | MODE_REC)) ?
1.19 ratchov 1328: (f->opt->wpar.cmax - f->opt->wpar.cmin + 1) : 0;
1.1 ratchov 1329: m->u.cap.bits = sizeof(short) * 8;
1330: m->u.cap.bps = sizeof(short);
1331: f->rstate = SOCK_RRET;
1332: f->rtodo = sizeof(struct amsg);
1.3 ratchov 1333: break;
1334: case AMSG_SETVOL:
1.37 ratchov 1335: #ifdef DEBUG
1336: if (debug_level >= 3) {
1337: sock_dbg(f);
1338: dbg_puts(": SETVOL message\n");
1339: }
1340: #endif
1.42 ratchov 1341: if (f->pstate != SOCK_RUN && f->pstate != SOCK_START &&
1342: f->pstate != SOCK_INIT && f->pstate != SOCK_READY) {
1.37 ratchov 1343: #ifdef DEBUG
1344: if (debug_level >= 1) {
1345: sock_dbg(f);
1346: dbg_puts(": SETVOL, bad state\n");
1347: }
1348: #endif
1.3 ratchov 1349: aproc_del(f->pipe.file.rproc);
1350: return 0;
1351: }
1352: if (m->u.vol.ctl > MIDI_MAXCTL) {
1.37 ratchov 1353: #ifdef DEBUG
1354: if (debug_level >= 1) {
1355: sock_dbg(f);
1356: dbg_puts(": SETVOL, volume out of range\n");
1357: }
1358: #endif
1.3 ratchov 1359: aproc_del(f->pipe.file.rproc);
1360: return 0;
1361: }
1.25 ratchov 1362: sock_setvol(f, m->u.vol.ctl);
1.34 ratchov 1363: if (f->slot >= 0)
1.48 ratchov 1364: ctl_slotvol(f->dev->midi, f->slot, m->u.vol.ctl);
1.3 ratchov 1365: f->rtodo = sizeof(struct amsg);
1366: f->rstate = SOCK_RMSG;
1.17 ratchov 1367: break;
1368: case AMSG_HELLO:
1.37 ratchov 1369: #ifdef DEBUG
1370: if (debug_level >= 3) {
1371: sock_dbg(f);
1372: dbg_puts(": HELLO message\n");
1373: }
1374: #endif
1.18 ratchov 1375: if (f->pstate != SOCK_HELLO) {
1.37 ratchov 1376: #ifdef DEBUG
1377: if (debug_level >= 1) {
1378: sock_dbg(f);
1379: dbg_puts(": HELLO, bad state\n");
1380: }
1381: #endif
1.17 ratchov 1382: aproc_del(f->pipe.file.rproc);
1383: return 0;
1384: }
1385: if (!sock_hello(f)) {
1386: aproc_del(f->pipe.file.rproc);
1387: return 0;
1388: }
1389: AMSG_INIT(m);
1390: m->cmd = AMSG_ACK;
1391: f->rstate = SOCK_RRET;
1392: f->rtodo = sizeof(struct amsg);
1.1 ratchov 1393: break;
1.28 ratchov 1394: case AMSG_BYE:
1.37 ratchov 1395: #ifdef DEBUG
1396: if (debug_level >= 3) {
1397: sock_dbg(f);
1398: dbg_puts(": BYE message\n");
1399: }
1400: #endif
1.29 ratchov 1401: if (f->pstate != SOCK_INIT) {
1.37 ratchov 1402: #ifdef DEBUG
1403: if (debug_level >= 1) {
1404: sock_dbg(f);
1405: dbg_puts(": BYE, bad state\n");
1406: }
1407: #endif
1.29 ratchov 1408: }
1.28 ratchov 1409: aproc_del(f->pipe.file.rproc);
1410: return 0;
1.1 ratchov 1411: default:
1.37 ratchov 1412: #ifdef DEBUG
1413: if (debug_level >= 1) {
1414: sock_dbg(f);
1415: dbg_puts(": unknown command in message\n");
1416: }
1417: #endif
1.1 ratchov 1418: aproc_del(f->pipe.file.rproc);
1419: return 0;
1420: }
1421: if (f->rstate == SOCK_RRET) {
1422: if (f->wstate != SOCK_WIDLE ||
1423: !sock_wmsg(f, &f->rmsg, &f->rtodo))
1424: return 0;
1.37 ratchov 1425: #ifdef DEBUG
1426: if (debug_level >= 3) {
1427: sock_dbg(f);
1428: dbg_puts(": RRET done\n");
1429: }
1430: #endif
1.51 ratchov 1431: if (f->pstate == SOCK_MIDI && (f->mode & MODE_MIDIOUT)) {
1.19 ratchov 1432: f->rstate = SOCK_RDATA;
1433: f->rtodo = 0;
1434: } else {
1435: f->rstate = SOCK_RMSG;
1436: f->rtodo = sizeof(struct amsg);
1437: }
1.1 ratchov 1438: }
1439: return 1;
1440: }
1441:
1442: /*
1.20 ratchov 1443: * Create a new data/pos message.
1.1 ratchov 1444: */
1445: int
1446: sock_buildmsg(struct sock *f)
1447: {
1448: struct aproc *p;
1449: struct abuf *ibuf;
1.42 ratchov 1450: unsigned size, max;
1.12 ratchov 1451:
1.19 ratchov 1452: if (f->pstate == SOCK_MIDI) {
1.37 ratchov 1453: #ifdef DEBUG
1454: if (debug_level >= 3) {
1455: sock_dbg(f);
1456: dbg_puts(": switching to MIDI mode\n");
1457: }
1458: #endif
1.19 ratchov 1459: f->wstate = SOCK_WDATA;
1460: f->wtodo = 0;
1461: return 1;
1462: }
1463:
1.1 ratchov 1464: /*
1.49 ratchov 1465: * Send initial position
1466: */
1467: if (f->startpending) {
1468: #ifdef DEBUG
1469: if (debug_level >= 4) {
1470: sock_dbg(f);
1471: dbg_puts(": building POS message, pos = ");
1472: dbg_puti(f->startpos);
1473: dbg_puts("\n");
1474: }
1475: #endif
1476: AMSG_INIT(&f->wmsg);
1477: f->wmsg.cmd = AMSG_POS;
1478: f->wmsg.u.ts.delta = f->startpos;
1.50 ratchov 1479: f->rmax += f->startpos;
1.49 ratchov 1480: f->wtodo = sizeof(struct amsg);
1481: f->wstate = SOCK_WMSG;
1482: f->startpending = 0;
1483: return 1;
1484: }
1485:
1486: /*
1.20 ratchov 1487: * If pos changed, build a MOVE message.
1.1 ratchov 1488: */
1.49 ratchov 1489: if (f->tickpending) {
1.37 ratchov 1490: #ifdef DEBUG
1491: if (debug_level >= 4) {
1492: sock_dbg(f);
1.49 ratchov 1493: dbg_puts(": building MOVE message, delta = ");
1.37 ratchov 1494: dbg_puti(f->delta);
1495: dbg_puts("\n");
1496: }
1497: #endif
1.42 ratchov 1498: f->wmax += f->delta;
1.49 ratchov 1499: f->rmax += f->delta;
1.1 ratchov 1500: AMSG_INIT(&f->wmsg);
1501: f->wmsg.cmd = AMSG_MOVE;
1.14 ratchov 1502: f->wmsg.u.ts.delta = f->delta;
1.1 ratchov 1503: f->wtodo = sizeof(struct amsg);
1504: f->wstate = SOCK_WMSG;
1.14 ratchov 1505: f->delta = 0;
1506: f->tickpending = 0;
1.25 ratchov 1507: return 1;
1508: }
1509:
1510: /*
1511: * if volume changed build a SETVOL message
1512: */
1.27 ratchov 1513: if (f->pstate >= SOCK_START && f->vol != f->lastvol) {
1.37 ratchov 1514: #ifdef DEBUG
1515: if (debug_level >= 4) {
1516: sock_dbg(f);
1517: dbg_puts(": building SETVOL message, vol = ");
1518: dbg_puti(f->vol);
1519: dbg_puts("\n");
1520: }
1521: #endif
1.25 ratchov 1522: AMSG_INIT(&f->wmsg);
1523: f->wmsg.cmd = AMSG_SETVOL;
1524: f->wmsg.u.vol.ctl = f->vol;
1525: f->wtodo = sizeof(struct amsg);
1526: f->wstate = SOCK_WMSG;
1527: f->lastvol = f->vol;
1.1 ratchov 1528: return 1;
1529: }
1530:
1531: /*
1.20 ratchov 1532: * If data available, build a DATA message.
1.1 ratchov 1533: */
1534: p = f->pipe.file.wproc;
1.45 ratchov 1535: ibuf = LIST_FIRST(&p->ins);
1.1 ratchov 1536: if (ibuf && ABUF_ROK(ibuf)) {
1.42 ratchov 1537: #ifdef DEBUG
1538: if (ibuf->used > f->wmax && debug_level >= 3) {
1539: sock_dbg(f);
1.46 ratchov 1540: dbg_puts(": attempt to send past current position: used = ");
1541: dbg_putu(ibuf->used);
1542: dbg_puts(" wmax = ");
1543: dbg_putu(f->wmax);
1544: dbg_puts("\n");
1.42 ratchov 1545: }
1546: #endif
1547: max = AMSG_DATAMAX / ibuf->bpf;
1548: size = ibuf->used;
1.39 ratchov 1549: if (size > f->walign)
1550: size = f->walign;
1.42 ratchov 1551: if (size > f->wmax)
1552: size = f->wmax;
1553: if (size > max)
1554: size = max;
1555: if (size == 0)
1556: return 0;
1.39 ratchov 1557: f->walign -= size;
1.42 ratchov 1558: f->wmax -= size;
1.39 ratchov 1559: if (f->walign == 0)
1.42 ratchov 1560: f->walign = f->round;
1.1 ratchov 1561: AMSG_INIT(&f->wmsg);
1562: f->wmsg.cmd = AMSG_DATA;
1.42 ratchov 1563: f->wmsg.u.data.size = size * ibuf->bpf;
1.1 ratchov 1564: f->wtodo = sizeof(struct amsg);
1565: f->wstate = SOCK_WMSG;
1566: return 1;
1567: }
1.37 ratchov 1568: #ifdef DEBUG
1569: if (debug_level >= 4) {
1570: sock_dbg(f);
1571: dbg_puts(": no messages to build anymore, idling...\n");
1572: }
1573: #endif
1.1 ratchov 1574: f->wstate = SOCK_WIDLE;
1575: return 0;
1576: }
1577:
1578: /*
1.20 ratchov 1579: * Read from the socket file descriptor, fill input buffer and update
1.1 ratchov 1580: * the state. Return 1 if at least one message or 1 data byte was
1581: * processed, 0 if something blocked.
1582: */
1583: int
1584: sock_read(struct sock *f)
1585: {
1.37 ratchov 1586: #ifdef DEBUG
1587: if (debug_level >= 4) {
1588: sock_dbg(f);
1.39 ratchov 1589: dbg_puts(": reading ");
1.37 ratchov 1590: dbg_putu(f->rtodo);
1.39 ratchov 1591: dbg_puts(" todo\n");
1.37 ratchov 1592: }
1593: #endif
1.1 ratchov 1594: switch (f->rstate) {
1595: case SOCK_RMSG:
1596: if (!sock_rmsg(f))
1597: return 0;
1598: if (!sock_execmsg(f))
1599: return 0;
1600: break;
1601: case SOCK_RDATA:
1602: if (!sock_rdata(f))
1603: return 0;
1.19 ratchov 1604: if (f->pstate != SOCK_MIDI && f->rtodo == 0) {
1.1 ratchov 1605: f->rstate = SOCK_RMSG;
1606: f->rtodo = sizeof(struct amsg);
1607: }
1.35 ratchov 1608: /*
1.42 ratchov 1609: * XXX: sock_attach() may not start if there's not enough
1.52 ! ratchov 1610: * samples queued, if so ctl_slotstart() will trigger
1.42 ratchov 1611: * other streams, but this one won't start.
1.35 ratchov 1612: */
1.48 ratchov 1613: if (f->pstate == SOCK_READY && ctl_slotstart(f->dev->midi, f->slot))
1.1 ratchov 1614: (void)sock_attach(f, 0);
1615: break;
1616: case SOCK_RRET:
1.37 ratchov 1617: #ifdef DEBUG
1618: if (debug_level >= 4) {
1619: sock_dbg(f);
1620: dbg_puts(": blocked by pending RRET message\n");
1621: }
1622: #endif
1.1 ratchov 1623: return 0;
1624: }
1625: return 1;
1626: }
1627:
1628: /*
1.20 ratchov 1629: * Process messages to return.
1.1 ratchov 1630: */
1631: int
1632: sock_return(struct sock *f)
1633: {
1634: struct aproc *rp;
1635:
1636: while (f->rstate == SOCK_RRET) {
1637: if (!sock_wmsg(f, &f->rmsg, &f->rtodo))
1638: return 0;
1.37 ratchov 1639: #ifdef DEBUG
1640: if (debug_level >= 4) {
1641: sock_dbg(f);
1642: dbg_puts(": sent RRET message\n");
1643: }
1644: #endif
1.51 ratchov 1645: if (f->pstate == SOCK_MIDI && (f->mode & MODE_MIDIOUT)) {
1.19 ratchov 1646: f->rstate = SOCK_RDATA;
1647: f->rtodo = 0;
1648: } else {
1649: f->rstate = SOCK_RMSG;
1650: f->rtodo = sizeof(struct amsg);
1651: }
1652: if (f->pipe.file.state & FILE_RINUSE)
1653: break;
1654: f->pipe.file.state |= FILE_RINUSE;
1.1 ratchov 1655: for (;;) {
1656: /*
1657: * in() may trigger rsock_done and destroy the
1.20 ratchov 1658: * wsock.
1.1 ratchov 1659: */
1660: rp = f->pipe.file.rproc;
1661: if (!rp || !rp->ops->in(rp, NULL))
1662: break;
1663: }
1.19 ratchov 1664: f->pipe.file.state &= ~FILE_RINUSE;
1.1 ratchov 1665: if (f->pipe.file.wproc == NULL)
1666: return 0;
1667: }
1668: return 1;
1669: }
1670:
1671: /*
1.20 ratchov 1672: * Write messages and data on the socket file descriptor. Return 1 if
1.1 ratchov 1673: * at least one message or one data byte was processed, 0 if something
1674: * blocked.
1675: */
1676: int
1677: sock_write(struct sock *f)
1678: {
1.37 ratchov 1679: #ifdef DEBUG
1680: if (debug_level >= 4) {
1681: sock_dbg(f);
1.39 ratchov 1682: dbg_puts(": writing ");
1.37 ratchov 1683: dbg_putu(f->wtodo);
1.39 ratchov 1684: dbg_puts(" todo\n");
1.37 ratchov 1685: }
1686: #endif
1.1 ratchov 1687: switch (f->wstate) {
1688: case SOCK_WMSG:
1689: if (!sock_wmsg(f, &f->wmsg, &f->wtodo))
1690: return 0;
1691: if (f->wmsg.cmd != AMSG_DATA) {
1692: f->wstate = SOCK_WIDLE;
1693: f->wtodo = 0xdeadbeef;
1694: break;
1695: }
1.42 ratchov 1696: /*
1697: * XXX: why not set f->wtodo in sock_wmsg() ?
1698: */
1.1 ratchov 1699: f->wstate = SOCK_WDATA;
1.42 ratchov 1700: f->wtodo = f->wmsg.u.data.size /
1.45 ratchov 1701: LIST_FIRST(&f->pipe.file.wproc->ins)->bpf;
1.1 ratchov 1702: /* PASSTHROUGH */
1703: case SOCK_WDATA:
1704: if (!sock_wdata(f))
1705: return 0;
1.19 ratchov 1706: if (f->pstate == SOCK_MIDI || f->wtodo > 0)
1.1 ratchov 1707: break;
1708: f->wstate = SOCK_WIDLE;
1709: f->wtodo = 0xdeadbeef;
1.42 ratchov 1710: if (f->pstate == SOCK_STOP)
1711: sock_freebuf(f);
1.1 ratchov 1712: /* PASSTHROUGH */
1713: case SOCK_WIDLE:
1714: if (!sock_return(f))
1715: return 0;
1716: if (!sock_buildmsg(f))
1717: return 0;
1718: break;
1.37 ratchov 1719: #ifdef DEBUG
1720: default:
1721: sock_dbg(f);
1722: dbg_puts(": bad writing end state\n");
1723: dbg_panic();
1724: #endif
1.1 ratchov 1725: }
1726: return 1;
1727: }