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