Annotation of src/usr.bin/sndiod/sock.c, Revision 1.11
1.11 ! ratchov 1: /* $OpenBSD: sock.c,v 1.10 2014/03/05 20:04:21 ratchov Exp $ */
1.1 ratchov 2: /*
3: * Copyright (c) 2008-2012 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: #include <sys/types.h>
18: #include <netinet/in.h>
19: #include <errno.h>
20: #include <poll.h>
21: #include <stdio.h>
22: #include <stdlib.h>
23: #include <string.h>
24: #include <unistd.h>
25:
26: #include "abuf.h"
27: #include "defs.h"
28: #include "dev.h"
29: #include "file.h"
30: #include "midi.h"
31: #include "opt.h"
32: #include "sock.h"
33: #include "utils.h"
34:
1.7 ratchov 35: void sock_log(struct sock *);
1.1 ratchov 36: void sock_close(struct sock *);
37: void sock_slot_fill(void *);
38: void sock_slot_flush(void *);
39: void sock_slot_eof(void *);
1.7 ratchov 40: void sock_slot_onmove(void *, int);
41: void sock_slot_onvol(void *, unsigned int);
42: void sock_midi_imsg(void *, unsigned char *, int);
43: void sock_midi_omsg(void *, unsigned char *, int);
44: void sock_midi_fill(void *, int);
45: struct sock *sock_new(int);
1.1 ratchov 46: void sock_exit(void *);
1.7 ratchov 47: int sock_fdwrite(struct sock *, void *, int);
48: int sock_fdread(struct sock *, void *, int);
49: int sock_rmsg(struct sock *);
50: int sock_wmsg(struct sock *);
51: int sock_rdata(struct sock *);
52: int sock_wdata(struct sock *);
53: int sock_setpar(struct sock *);
54: int sock_auth(struct sock *);
55: int sock_hello(struct sock *);
56: int sock_execmsg(struct sock *);
57: int sock_buildmsg(struct sock *);
58: int sock_read(struct sock *);
59: int sock_write(struct sock *);
60: int sock_pollfd(void *, struct pollfd *);
61: int sock_revents(void *, struct pollfd *);
62: void sock_in(void *);
63: void sock_out(void *);
64: void sock_hup(void *);
1.1 ratchov 65:
66: struct fileops sock_fileops = {
67: "sock",
68: sock_pollfd,
69: sock_revents,
70: sock_in,
71: sock_out,
72: sock_hup
73: };
74:
75: struct slotops sock_slotops = {
76: sock_slot_onmove,
77: sock_slot_onvol,
78: sock_slot_fill,
79: sock_slot_flush,
80: sock_slot_eof,
81: sock_exit
82: };
83:
84: struct midiops sock_midiops = {
85: sock_midi_imsg,
86: sock_midi_omsg,
87: sock_midi_fill,
88: sock_exit
89: };
90:
91: struct sock *sock_list = NULL;
92: unsigned int sock_sesrefs = 0; /* connections to the session */
93: uint8_t sock_sescookie[AMSG_COOKIELEN]; /* owner of the session */
94:
95: void
96: sock_log(struct sock *f)
97: {
98: #ifdef DEBUG
99: static char *rstates[] = { "ridl", "rmsg", "rdat", "rret" };
100: static char *wstates[] = { "widl", "wmsg", "wdat" };
101: #endif
102: if (f->slot)
103: slot_log(f->slot);
104: else if (f->midi)
105: midi_log(f->midi);
106: else
107: log_puts("sock");
108: #ifdef DEBUG
109: if (log_level >= 3) {
110: log_puts(",");
111: log_puts(rstates[f->rstate]);
112: log_puts(",");
113: log_puts(wstates[f->wstate]);
114: }
115: #endif
116: }
117:
118: void
119: sock_close(struct sock *f)
120: {
121: struct sock **pf;
122:
123: for (pf = &sock_list; *pf != f; pf = &(*pf)->next) {
124: #ifdef DEBUG
125: if (*pf == NULL) {
126: log_puts("sock_close: not on list\n");
127: panic();
128: }
129: #endif
130: }
131: *pf = f->next;
132:
133: #ifdef DEBUG
134: if (log_level >= 3) {
135: sock_log(f);
136: log_puts(": closing\n");
137: }
138: #endif
139: if (f->pstate > SOCK_AUTH)
140: sock_sesrefs--;
141: if (f->slot) {
142: slot_del(f->slot);
143: f->slot = NULL;
144: }
145: if (f->midi) {
146: midi_del(f->midi);
147: f->midi = NULL;
148: }
1.3 ratchov 149: if (f->port) {
150: port_unref(f->port);
151: f->port = NULL;
152: }
1.1 ratchov 153: file_del(f->file);
154: close(f->fd);
155: xfree(f);
156: }
157:
158: void
159: sock_slot_fill(void *arg)
160: {
161: struct sock *f = arg;
162: struct slot *s = f->slot;
163:
164: f->fillpending += s->round;
165: #ifdef DEBUG
166: if (log_level >= 4) {
167: sock_log(f);
168: log_puts(": fill, rmax -> ");
169: log_puti(f->rmax);
170: log_puts(", pending -> ");
171: log_puti(f->fillpending);
172: log_puts("\n");
173: }
174: #endif
175: }
176:
177: void
178: sock_slot_flush(void *arg)
179: {
180: struct sock *f = arg;
181: struct slot *s = f->slot;
182:
183: f->wmax += s->round * s->sub.bpf;
184: #ifdef DEBUG
185: if (log_level >= 4) {
186: sock_log(f);
187: log_puts(": flush, wmax -> ");
188: log_puti(f->wmax);
189: log_puts("\n");
190: }
191: #endif
192: }
193:
194: void
195: sock_slot_eof(void *arg)
196: {
197: struct sock *f = arg;
198:
199: #ifdef DEBUG
200: if (log_level >= 3) {
201: sock_log(f);
202: log_puts(": stopped\n");
203: }
204: #endif
205: f->stoppending = 1;
206: }
207:
208: void
209: sock_slot_onmove(void *arg, int delta)
210: {
211: struct sock *f = (struct sock *)arg;
212: struct slot *s = f->slot;
213:
214: #ifdef DEBUG
215: if (log_level >= 4) {
216: sock_log(f);
217: log_puts(": onmove: delta -> ");
218: log_puti(s->delta);
219: log_puts("\n");
220: }
221: #endif
222: if (s->pstate != SOCK_START)
223: return;
224: f->tickpending++;
225: }
226:
227: void
228: sock_slot_onvol(void *arg, unsigned int delta)
229: {
230: struct sock *f = (struct sock *)arg;
231: struct slot *s = f->slot;
232:
233: #ifdef DEBUG
234: if (log_level >= 4) {
235: sock_log(f);
236: log_puts(": onvol: vol -> ");
237: log_puti(s->vol);
238: log_puts("\n");
239: }
240: #endif
241: if (s->pstate != SOCK_START)
242: return;
243: }
244:
245: void
246: sock_midi_imsg(void *arg, unsigned char *msg, int size)
247: {
248: struct sock *f = arg;
249:
250: midi_send(f->midi, msg, size);
251: }
252:
253: void
254: sock_midi_omsg(void *arg, unsigned char *msg, int size)
255: {
256: struct sock *f = arg;
257:
258: midi_out(f->midi, msg, size);
259: }
260:
261: void
262: sock_midi_fill(void *arg, int count)
263: {
264: struct sock *f = arg;
265:
266: f->fillpending += count;
267: }
268:
269: struct sock *
270: sock_new(int fd)
271: {
272: struct sock *f;
273:
274: f = xmalloc(sizeof(struct sock));
275: f->pstate = SOCK_AUTH;
276: f->opt = NULL;
277: f->slot = NULL;
278: f->midi = NULL;
279: f->tickpending = 0;
280: f->fillpending = 0;
281: f->stoppending = 0;
282: f->wstate = SOCK_WIDLE;
283: f->wtodo = 0xdeadbeef;
284: f->rstate = SOCK_RMSG;
285: f->rtodo = sizeof(struct amsg);
286: f->wmax = f->rmax = 0;
287: f->lastvol = -1;
288: f->file = file_new(&sock_fileops, f, "sock", 1);
289: f->fd = fd;
290: if (f->file == NULL) {
291: xfree(f);
292: return NULL;
293: }
294: f->next = sock_list;
295: sock_list = f;
296: return f;
297: }
298:
299: void
300: sock_exit(void *arg)
301: {
302: struct sock *f = (struct sock *)arg;
303:
304: #ifdef DEBUG
305: if (log_level >= 3) {
306: sock_log(f);
307: log_puts(": exit\n");
308: }
309: #endif
310: sock_close(f);
311: }
312:
313: /*
314: * write on the socke fd and handle errors
315: */
316: int
317: sock_fdwrite(struct sock *f, void *data, int count)
318: {
319: int n;
320:
321: n = write(f->fd, data, count);
322: if (n < 0) {
323: #ifdef DEBUG
324: if (errno == EFAULT) {
325: log_puts("sock_fdwrite: fault\n");
326: panic();
327: }
328: #endif
329: if (errno != EAGAIN) {
330: if (log_level >= 1) {
331: sock_log(f);
332: log_puts(": write filed, errno = ");
333: log_puti(errno);
334: log_puts("\n");
335: }
336: sock_close(f);
337: } else {
338: #ifdef DEBUG
339: if (log_level >= 4) {
340: sock_log(f);
341: log_puts(": write blocked\n");
342: }
343: #endif
344: }
345: return 0;
346: }
347: if (n == 0) {
348: sock_close(f);
349: return 0;
350: }
351: return n;
352: }
353:
354: /*
355: * read from the socke fd and handle errors
356: */
357: int
358: sock_fdread(struct sock *f, void *data, int count)
359: {
360: int n;
361:
362: n = read(f->fd, data, count);
363: if (n < 0) {
364: #ifdef DEBUG
365: if (errno == EFAULT) {
366: log_puts("sock_fdread: fault\n");
367: panic();
368: }
369: #endif
370: if (errno != EAGAIN) {
371: if (log_level >= 1) {
372: sock_log(f);
373: log_puts(": read failed, errno = ");
374: log_puti(errno);
375: log_puts("\n");
376: }
377: sock_close(f);
378: } else {
379: #ifdef DEBUG
380: if (log_level >= 4) {
381: sock_log(f);
382: log_puts(": read blocked\n");
383: }
384: #endif
385: }
386: return 0;
387: }
388: if (n == 0) {
389: sock_close(f);
390: return 0;
391: }
392: return n;
393: }
394:
395: /*
396: * read the next message into f->rmsg, return 1 on success
397: */
398: int
399: sock_rmsg(struct sock *f)
400: {
401: int n;
402: char *data;
403:
404: #ifdef DEBUG
405: if (f->rtodo == 0) {
406: sock_log(f);
407: log_puts(": sock_rmsg: nothing to read\n");
408: panic();
409: }
410: #endif
411: data = (char *)&f->rmsg + sizeof(struct amsg) - f->rtodo;
412: n = sock_fdread(f, data, f->rtodo);
413: if (n == 0)
414: return 0;
415: if (n < f->rtodo) {
416: f->rtodo -= n;
417: return 0;
418: }
419: f->rtodo = 0;
420: #ifdef DEBUG
421: if (log_level >= 4) {
422: sock_log(f);
423: log_puts(": read full message\n");
424: }
425: #endif
426: return 1;
427: }
428:
429: /*
430: * write the message in f->rmsg, return 1 on success
431: */
432: int
433: sock_wmsg(struct sock *f)
434: {
435: int n;
436: char *data;
437:
438: #ifdef DEBUG
439: if (f->wtodo == 0) {
440: sock_log(f);
441: log_puts(": sock_wmsg: already written\n");
442: }
443: #endif
444: data = (char *)&f->wmsg + sizeof(struct amsg) - f->wtodo;
445: n = sock_fdwrite(f, data, f->wtodo);
446: if (n == 0)
447: return 0;
448: if (n < f->wtodo) {
449: f->wtodo -= n;
450: return 0;
451: }
452: f->wtodo = 0;
453: #ifdef DEBUG
454: if (log_level >= 4) {
455: sock_log(f);
456: log_puts(": wrote full message\n");
457: }
458: #endif
459: return 1;
460: }
461:
462: /*
463: * read data into the slot/midi ring buffer
464: */
465: int
466: sock_rdata(struct sock *f)
467: {
1.2 ratchov 468: unsigned char midibuf[MIDI_BUFSZ];
1.1 ratchov 469: unsigned char *data;
470: int n, count;
471:
472: #ifdef DEBUG
473: if (f->rtodo == 0) {
474: sock_log(f);
475: log_puts(": data block already read\n");
476: panic();
477: }
478: #endif
479: while (f->rtodo > 0) {
1.2 ratchov 480: if (f->slot)
481: data = abuf_wgetblk(&f->slot->mix.buf, &count);
482: else {
483: data = midibuf;
484: count = MIDI_BUFSZ;
485: }
1.1 ratchov 486: if (count > f->rtodo)
487: count = f->rtodo;
488: n = sock_fdread(f, data, count);
489: if (n == 0)
490: return 0;
491: f->rtodo -= n;
1.2 ratchov 492: if (f->slot)
493: abuf_wcommit(&f->slot->mix.buf, n);
494: else
495: midi_in(f->midi, midibuf, n);
1.1 ratchov 496: }
497: #ifdef DEBUG
498: if (log_level >= 4) {
499: sock_log(f);
500: log_puts(": read complete block\n");
501: }
502: #endif
503: if (f->slot)
504: slot_write(f->slot);
505: return 1;
506: }
507:
508: /*
509: * read data into the slot/midi ring buffer
510: */
511: int
512: sock_wdata(struct sock *f)
513: {
514: static unsigned char dummy[AMSG_DATAMAX];
515: unsigned char *data = NULL;
516: struct abuf *buf = NULL;
517: int n, count;
518:
519: #ifdef DEBUG
520: if (f->wtodo == 0) {
521: sock_log(f);
522: log_puts(": attempted to write zero-sized data block\n");
523: panic();
524: }
525: #endif
526: if (f->pstate == SOCK_STOP) {
527: while (f->wtodo > 0) {
528: n = sock_fdwrite(f, dummy, f->wtodo);
529: if (n == 0)
530: return 0;
531: f->wtodo -= n;
532: }
533: #ifdef DEBUG
534: if (log_level >= 4) {
535: sock_log(f);
536: log_puts(": zero-filled remaining block\n");
537: }
538: #endif
539: return 1;
540: }
541: if (f->slot)
542: buf = &f->slot->sub.buf;
543: else
544: buf = &f->midi->obuf;
545: while (f->wtodo > 0) {
546: data = abuf_rgetblk(buf, &count);
547: if (count > f->wtodo)
548: count = f->wtodo;
549: n = sock_fdwrite(f, data, count);
550: if (n == 0)
551: return 0;
552: f->wtodo -= n;
553: abuf_rdiscard(buf, n);
554: }
555: if (f->slot)
556: slot_read(f->slot);
557: if (f->midi)
558: midi_fill(f->midi);
559: #ifdef DEBUG
560: if (log_level >= 4) {
561: sock_log(f);
562: log_puts(": wrote complete block\n");
563: }
564: #endif
565: return 1;
566: }
567:
568: int
569: sock_setpar(struct sock *f)
570: {
571: struct slot *s = f->slot;
572: struct dev *d = s->dev;
573: struct amsg_par *p = &f->rmsg.u.par;
1.9 ratchov 574: unsigned int min, max;
575: uint32_t rate, appbufsz;
576: uint16_t pchan, rchan;
1.1 ratchov 577:
578: rchan = ntohs(p->rchan);
579: pchan = ntohs(p->pchan);
580: appbufsz = ntohl(p->appbufsz);
581: rate = ntohl(p->rate);
582:
583: if (AMSG_ISSET(p->bits)) {
584: if (p->bits < BITS_MIN || p->bits > BITS_MAX) {
585: #ifdef DEBUG
586: if (log_level >= 1) {
587: sock_log(f);
588: log_puts(": ");
589: log_putu(p->bits);
590: log_puts(": bits out of bounds\n");
591: }
592: #endif
593: return 0;
594: }
595: if (AMSG_ISSET(p->bps)) {
596: if (p->bps < ((p->bits + 7) / 8) || p->bps > 4) {
597: #ifdef DEBUG
598: if (log_level >= 1) {
599: sock_log(f);
600: log_puts(": ");
601: log_putu(p->bps);
602: log_puts(": wrong bytes per sample\n");
603: }
604: #endif
605: return 0;
606: }
607: } else
608: p->bps = APARAMS_BPS(p->bits);
609: s->par.bits = p->bits;
610: s->par.bps = p->bps;
611: }
612: if (AMSG_ISSET(p->sig))
613: s->par.sig = p->sig ? 1 : 0;
614: if (AMSG_ISSET(p->le))
615: s->par.le = p->le ? 1 : 0;
616: if (AMSG_ISSET(p->msb))
617: s->par.msb = p->msb ? 1 : 0;
618: if (AMSG_ISSET(rchan) && (s->mode & MODE_RECMASK)) {
619: if (rchan < 1)
620: rchan = 1;
621: if (rchan > NCHAN_MAX)
622: rchan = NCHAN_MAX;
623: s->sub.slot_cmin = f->opt->rmin;
624: s->sub.slot_cmax = f->opt->rmin + rchan - 1;
625: s->sub.dev_cmin = f->opt->rmin;
626: s->sub.dev_cmax = f->opt->rmax;
627: #ifdef DEBUG
628: if (log_level >= 3) {
629: sock_log(f);
630: log_puts(": recording channels ");
1.6 ratchov 631: log_putu(s->sub.dev_cmin);
632: log_puts(":");
633: log_putu(s->sub.dev_cmax);
634: log_puts(" -> ");
1.1 ratchov 635: log_putu(s->sub.slot_cmin);
636: log_puts(":");
637: log_putu(s->sub.slot_cmax);
638: log_puts("\n");
639: }
640: #endif
641: }
642: if (AMSG_ISSET(pchan) && (s->mode & MODE_PLAY)) {
643: if (pchan < 1)
644: pchan = 1;
645: if (pchan > NCHAN_MAX)
646: pchan = NCHAN_MAX;
647: s->mix.slot_cmin = f->opt->pmin;
648: s->mix.slot_cmax = f->opt->pmin + pchan - 1;
649: s->mix.dev_cmin = f->opt->pmin;
650: s->mix.dev_cmax = f->opt->pmax;
651: #ifdef DEBUG
652: if (log_level >= 3) {
653: sock_log(f);
654: log_puts(": playback channels ");
655: log_putu(s->mix.slot_cmin);
656: log_puts(":");
657: log_putu(s->mix.slot_cmax);
658: log_puts(" -> ");
659: log_putu(s->mix.dev_cmin);
660: log_puts(":");
661: log_putu(s->mix.dev_cmax);
662: log_puts("\n");
663: }
664: #endif
665: }
666: if (AMSG_ISSET(rate)) {
667: if (rate < RATE_MIN)
668: rate = RATE_MIN;
669: if (rate > RATE_MAX)
670: rate = RATE_MAX;
671: s->round = dev_roundof(d, rate);
672: s->rate = rate;
673: if (!AMSG_ISSET(appbufsz)) {
674: appbufsz = d->bufsz / d->round * s->round;
675: #ifdef DEBUG
676: if (log_level >= 3) {
677: sock_log(f);
678: log_puts(": ");
679: log_putu(appbufsz);
680: log_puts(" frame buffer\n");
681: }
682: #endif
683: }
684: #ifdef DEBUG
685: if (log_level >= 3) {
686: sock_log(f);
687: log_puts(": ");
688: log_putu(rate);
689: log_puts("Hz sample rate, ");
690: log_putu(s->round);
691: log_puts(" frame blocks\n");
692: }
693: #endif
694: }
695: if (AMSG_ISSET(p->xrun)) {
696: if (p->xrun != XRUN_IGNORE &&
697: p->xrun != XRUN_SYNC &&
698: p->xrun != XRUN_ERROR) {
699: #ifdef DEBUG
700: if (log_level >= 1) {
701: sock_log(f);
702: log_puts(": ");
703: log_putx(p->xrun);
704: log_puts(": bad xrun policy\n");
705: }
706: #endif
707: return 0;
708: }
709: s->xrun = p->xrun;
710: if (f->opt->mmc && s->xrun == XRUN_IGNORE)
711: s->xrun = XRUN_SYNC;
712: #ifdef DEBUG
713: if (log_level >= 3) {
714: sock_log(f);
715: log_puts(": 0x");
716: log_putx(s->xrun);
717: log_puts(" xrun policy\n");
718: }
719: #endif
720: }
721: if (AMSG_ISSET(appbufsz)) {
722: rate = s->rate;
723: min = 1;
724: max = 1 + rate / d->round;
725: min *= s->round;
726: max *= s->round;
1.8 ratchov 727: appbufsz += s->round / 2;
1.1 ratchov 728: appbufsz -= appbufsz % s->round;
729: if (appbufsz < min)
730: appbufsz = min;
731: if (appbufsz > max)
732: appbufsz = max;
733: s->appbufsz = appbufsz;
734: #ifdef DEBUG
735: if (log_level >= 3) {
736: sock_log(f);
737: log_puts(": ");
738: log_putu(s->appbufsz);
739: log_puts(" frame buffer\n");
740: }
741: #endif
742: }
743: return 1;
744: }
745:
746: int
747: sock_auth(struct sock *f)
748: {
749: struct amsg_auth *p = &f->rmsg.u.auth;
750:
751: if (sock_sesrefs == 0) {
752: /* start a new session */
753: memcpy(sock_sescookie, p->cookie, AMSG_COOKIELEN);
754: } else if (memcmp(sock_sescookie, p->cookie, AMSG_COOKIELEN) != 0) {
755: /* another session is active, drop connection */
756: return 0;
757: }
758: sock_sesrefs++;
759: f->pstate = SOCK_HELLO;
760: return 1;
761: }
762:
763: int
764: sock_hello(struct sock *f)
765: {
766: struct amsg_hello *p = &f->rmsg.u.hello;
767: struct slot *s;
768: struct port *c;
769: struct dev *d;
770: unsigned int mode;
771:
772: mode = ntohs(p->mode);
773: #ifdef DEBUG
774: if (log_level >= 3) {
775: sock_log(f);
776: log_puts(": hello from <");
777: log_puts(p->who);
778: log_puts(">, mode = ");
779: log_putx(mode);
780: log_puts(", ver ");
781: log_putu(p->version);
782: log_puts("\n");
783: }
784: #endif
785: if (p->version != AMSG_VERSION) {
786: if (log_level >= 1) {
787: sock_log(f);
788: log_puts(": ");
789: log_putu(p->version);
790: log_puts(": unsupported protocol version\n");
791: }
792: return 0;
793: }
794: switch (mode) {
795: case MODE_MIDIIN:
796: case MODE_MIDIOUT:
797: case MODE_MIDIOUT | MODE_MIDIIN:
798: case MODE_REC:
799: case MODE_PLAY:
800: case MODE_PLAY | MODE_REC:
801: break;
802: default:
803: #ifdef DEBUG
804: if (log_level >= 1) {
805: sock_log(f);
806: log_puts(": ");
807: log_putx(mode);
808: log_puts(": unsupported mode\n");
809: }
810: #endif
811: return 0;
812: }
813: f->pstate = SOCK_INIT;
1.5 ratchov 814: f->port = NULL;
1.1 ratchov 815: if (mode & MODE_MIDIMASK) {
816: f->slot = NULL;
817: f->midi = midi_new(&sock_midiops, f, mode);
818: if (f->midi == NULL)
819: return 0;
820: /* XXX: add 'devtype' to libsndio */
821: if (p->devnum < 16) {
822: d = dev_bynum(p->devnum);
823: if (d == NULL)
824: return 0;
825: midi_tag(f->midi, p->devnum);
826: } else if (p->devnum < 32) {
827: midi_tag(f->midi, p->devnum);
828: } else if (p->devnum < 48) {
829: c = port_bynum(p->devnum - 32);
1.3 ratchov 830: if (c == NULL || !port_ref(c))
1.1 ratchov 831: return 0;
1.3 ratchov 832: f->port = c;
1.2 ratchov 833: midi_link(f->midi, c->midi);
1.1 ratchov 834: } else
835: return 0;
836: return 1;
837: }
838: f->opt = opt_byname(p->opt, p->devnum);
839: if (f->opt == NULL)
840: return 0;
841: #ifdef DEBUG
842: if (log_level >= 3) {
843: sock_log(f);
844: log_puts(": using ");
845: dev_log(f->opt->dev);
846: log_puts(".");
847: log_puts(f->opt->name);
848: log_puts(", mode = ");
849: log_putx(mode);
850: log_puts("\n");
851: }
852: #endif
853: if ((mode & MODE_REC) && (f->opt->mode & MODE_MON)) {
854: mode |= MODE_MON;
855: mode &= ~MODE_REC;
856: }
857: if ((mode & f->opt->mode) != mode) {
858: if (log_level >= 1) {
859: sock_log(f);
860: log_puts(": requested mode not allowed\n");
861: }
862: return 0;
863: }
864: s = slot_new(f->opt->dev, p->who, &sock_slotops, f, mode);
865: if (s == NULL)
866: return 0;
867: f->midi = NULL;
868: if (s->mode & MODE_PLAY) {
1.6 ratchov 869: s->mix.slot_cmin = s->mix.dev_cmin = f->opt->pmin;
870: s->mix.slot_cmax = s->mix.dev_cmax = f->opt->pmax;
1.1 ratchov 871: }
872: if (s->mode & MODE_RECMASK) {
1.6 ratchov 873: s->sub.slot_cmin = s->sub.dev_cmin = f->opt->rmin;
874: s->sub.slot_cmax = s->sub.dev_cmax = f->opt->rmax;
1.1 ratchov 875: }
876: if (f->opt->mmc) {
877: s->xrun = XRUN_SYNC;
878: s->tstate = MMC_STOP;
879: } else {
880: s->xrun = XRUN_IGNORE;
881: s->tstate = MMC_OFF;
882: }
883: s->mix.maxweight = f->opt->maxweight;
884: s->dup = f->opt->dup;
885: f->slot = s;
886: return 1;
887: }
888:
889: /*
890: * execute the message in f->rmsg, return 1 on success
891: */
892: int
893: sock_execmsg(struct sock *f)
894: {
895: struct slot *s = f->slot;
896: struct amsg *m = &f->rmsg;
897: unsigned char *data;
898: int size, ctl;
899:
900: switch (ntohl(m->cmd)) {
901: case AMSG_DATA:
902: #ifdef DEBUG
903: if (log_level >= 4) {
904: sock_log(f);
905: log_puts(": DATA message\n");
906: }
907: #endif
908: if (s != NULL && f->pstate != SOCK_START) {
909: #ifdef DEBUG
910: if (log_level >= 1) {
911: sock_log(f);
912: log_puts(": DATA, wrong state\n");
913: }
914: #endif
915: sock_close(f);
916: return 0;
917: }
918: if ((f->slot && !(f->slot->mode & MODE_PLAY)) ||
919: (f->midi && !(f->midi->mode & MODE_MIDIOUT))) {
920: #ifdef DEBUG
921: if (log_level >= 1) {
922: sock_log(f);
923: log_puts(": DATA, input-only mode\n");
924: }
925: #endif
926: sock_close(f);
927: return 0;
928: }
929: size = ntohl(m->u.data.size);
930: if (size <= 0) {
931: #ifdef DEBUG
932: if (log_level >= 1) {
933: sock_log(f);
934: log_puts(": zero size payload\n");
935: }
936: #endif
937: sock_close(f);
938: return 0;
939: }
940: if (s != NULL && size % s->mix.bpf != 0) {
941: #ifdef DEBUG
942: if (log_level >= 1) {
943: sock_log(f);
944: log_puts(": not aligned to frame\n");
945: }
946: #endif
947: sock_close(f);
948: return 0;
949: }
950: if (s != NULL && size > f->ralign) {
951: #ifdef DEBUG
952: if (log_level >= 1) {
953: sock_log(f);
954: log_puts(": size = ");
955: log_puti(size);
956: log_puts(": ralign = ");
957: log_puti(f->ralign);
958: log_puts(": not aligned to block\n");
959: }
960: #endif
961: sock_close(f);
962: return 0;
963: }
964: f->rstate = SOCK_RDATA;
965: f->rsize = f->rtodo = size;
966: if (s != NULL) {
967: f->ralign -= size;
968: if (f->ralign == 0)
969: f->ralign = s->round * s->mix.bpf;
970: }
971: if (f->rtodo > f->rmax) {
972: #ifdef DEBUG
973: if (log_level >= 1) {
974: sock_log(f);
975: log_puts(": unexpected data, size = ");
976: log_putu(size);
977: log_puts(", rmax = ");
978: log_putu(f->rmax);
979: log_puts("\n");
980: }
981: #endif
982: sock_close(f);
983: return 0;
984: }
985: f->rmax -= f->rtodo;
986: if (f->rtodo == 0) {
987: #ifdef DEBUG
988: if (log_level >= 1) {
989: sock_log(f);
990: log_puts(": zero-length data chunk\n");
991: }
992: #endif
993: sock_close(f);
994: return 0;
995: }
996: break;
997: case AMSG_START:
998: #ifdef DEBUG
999: if (log_level >= 3) {
1000: sock_log(f);
1001: log_puts(": START message\n");
1002: }
1003: #endif
1004: if (f->pstate != SOCK_INIT) {
1005: #ifdef DEBUG
1006: if (log_level >= 1) {
1007: sock_log(f);
1008: log_puts(": START, wrong state\n");
1009: }
1010: #endif
1011: sock_close(f);
1012: return 0;
1013: }
1014: f->tickpending = 0;
1015: f->stoppending = 0;
1016: slot_start(s);
1017: if (s->mode & MODE_PLAY) {
1018: f->fillpending = s->appbufsz;
1019: f->ralign = s->round * s->mix.bpf;
1020: f->rmax = 0;
1021: }
1022: if (s->mode & MODE_RECMASK) {
1023: f->walign = s->round * s->sub.bpf;
1024: f->wmax = 0;
1025: }
1026: f->pstate = SOCK_START;
1027: f->rstate = SOCK_RMSG;
1028: f->rtodo = sizeof(struct amsg);
1029: if (log_level >= 2) {
1030: slot_log(f->slot);
1031: log_puts(": ");
1032: log_putu(s->rate);
1033: log_puts("Hz, ");
1034: aparams_log(&s->par);
1035: if (s->mode & MODE_PLAY) {
1036: log_puts(", play ");
1037: log_puti(s->mix.slot_cmin);
1038: log_puts(":");
1039: log_puti(s->mix.slot_cmax);
1040: }
1041: if (s->mode & MODE_RECMASK) {
1042: log_puts(", rec ");
1043: log_puti(s->sub.slot_cmin);
1044: log_puts(":");
1045: log_puti(s->sub.slot_cmax);
1046: }
1047: log_puts(", ");
1048: log_putu(s->appbufsz / s->round);
1049: log_puts(" blocks of ");
1050: log_putu(s->round);
1051: log_puts(" frames\n");
1052: }
1053: break;
1054: case AMSG_STOP:
1055: #ifdef DEBUG
1056: if (log_level >= 3) {
1057: sock_log(f);
1058: log_puts(": STOP message\n");
1059: }
1060: #endif
1061: if (f->pstate != SOCK_START) {
1062: #ifdef DEBUG
1063: if (log_level >= 1) {
1064: sock_log(f);
1065: log_puts(": STOP, wrong state\n");
1066: }
1067: #endif
1068: sock_close(f);
1069: return 0;
1070: }
1071: f->rmax = 0;
1072: if (!(s->mode & MODE_PLAY))
1073: f->stoppending = 1;
1074: f->pstate = SOCK_STOP;
1075: f->rstate = SOCK_RMSG;
1076: f->rtodo = sizeof(struct amsg);
1077: if (s->mode & MODE_PLAY) {
1078: if (f->ralign < s->round * s->mix.bpf) {
1079: data = abuf_wgetblk(&s->mix.buf, &size);
1080: #ifdef DEBUG
1081: if (size < f->ralign) {
1082: sock_log(f);
1083: log_puts(": unaligned stop, size = ");
1084: log_putu(size);
1085: log_puts(", ralign = ");
1086: log_putu(f->ralign);
1087: log_puts("\n");
1088: panic();
1089: }
1090: #endif
1091: memset(data, 0, f->ralign);
1092: abuf_wcommit(&s->mix.buf, f->ralign);
1093: f->ralign = s->round * s->mix.bpf;
1094: }
1095: }
1096: slot_stop(s);
1097: break;
1098: case AMSG_SETPAR:
1099: #ifdef DEBUG
1100: if (log_level >= 3) {
1101: sock_log(f);
1102: log_puts(": SETPAR message\n");
1103: }
1104: #endif
1105: if (f->pstate != SOCK_INIT) {
1106: #ifdef DEBUG
1107: if (log_level >= 1) {
1108: sock_log(f);
1109: log_puts(": SETPAR, wrong state\n");
1110: }
1111: #endif
1112: sock_close(f);
1113: return 0;
1114: }
1115: if (!sock_setpar(f)) {
1116: sock_close(f);
1117: return 0;
1118: }
1119: f->rtodo = sizeof(struct amsg);
1120: f->rstate = SOCK_RMSG;
1121: break;
1122: case AMSG_GETPAR:
1123: #ifdef DEBUG
1124: if (log_level >= 3) {
1125: sock_log(f);
1126: log_puts(": GETPAR message\n");
1127: }
1128: #endif
1129: if (f->pstate != SOCK_INIT) {
1130: #ifdef DEBUG
1131: if (log_level >= 1) {
1132: sock_log(f);
1133: log_puts(": GETPAR, wrong state\n");
1134: }
1135: #endif
1136: sock_close(f);
1137: return 0;
1138: }
1139: AMSG_INIT(m);
1140: m->cmd = htonl(AMSG_GETPAR);
1141: m->u.par.legacy_mode = s->mode;
1142: m->u.par.bits = s->par.bits;
1143: m->u.par.bps = s->par.bps;
1144: m->u.par.sig = s->par.sig;
1145: m->u.par.le = s->par.le;
1146: m->u.par.msb = s->par.msb;
1147: if (s->mode & MODE_PLAY) {
1148: m->u.par.pchan = htons(s->mix.slot_cmax -
1149: s->mix.slot_cmin + 1);
1150: }
1151: if (s->mode & MODE_RECMASK) {
1152: m->u.par.rchan = htons(s->sub.slot_cmax -
1153: s->sub.slot_cmin + 1);
1154: }
1155: m->u.par.rate = htonl(s->rate);
1156: m->u.par.appbufsz = htonl(s->appbufsz);
1157: m->u.par.bufsz = htonl(SLOT_BUFSZ(s));
1158: m->u.par.round = htonl(s->round);
1159: f->rstate = SOCK_RRET;
1160: f->rtodo = sizeof(struct amsg);
1161: break;
1162: case AMSG_SETVOL:
1163: #ifdef DEBUG
1164: if (log_level >= 3) {
1165: sock_log(f);
1166: log_puts(": SETVOL message\n");
1167: }
1168: #endif
1169: if (f->pstate < SOCK_INIT) {
1170: #ifdef DEBUG
1171: if (log_level >= 1) {
1172: sock_log(f);
1173: log_puts(": SETVOL, wrong state\n");
1174: }
1175: #endif
1176: sock_close(f);
1177: return 0;
1178: }
1179: ctl = ntohl(m->u.vol.ctl);
1180: if (ctl > MIDI_MAXCTL) {
1181: #ifdef DEBUG
1182: if (log_level >= 1) {
1183: sock_log(f);
1184: log_puts(": SETVOL, volume out of range\n");
1185: }
1186: #endif
1187: sock_close(f);
1188: return 0;
1189: }
1190: f->rtodo = sizeof(struct amsg);
1191: f->rstate = SOCK_RMSG;
1192: f->lastvol = ctl; /* dont trigger feedback message */
1193: dev_midi_vol(s->dev, s);
1194: slot_setvol(s, ctl);
1195: break;
1196: case AMSG_AUTH:
1197: #ifdef DEBUG
1198: if (log_level >= 3) {
1199: sock_log(f);
1200: log_puts(": AUTH message\n");
1201: }
1202: #endif
1203: if (f->pstate != SOCK_AUTH) {
1204: #ifdef DEBUG
1205: if (log_level >= 1) {
1206: sock_log(f);
1207: log_puts(": AUTH, wrong state\n");
1208: }
1209: #endif
1210: sock_close(f);
1211: return 0;
1212: }
1213: if (!sock_auth(f)) {
1214: sock_close(f);
1215: return 0;
1216: }
1217: f->rstate = SOCK_RMSG;
1218: f->rtodo = sizeof(struct amsg);
1219: break;
1220: case AMSG_HELLO:
1221: #ifdef DEBUG
1222: if (log_level >= 3) {
1223: sock_log(f);
1224: log_puts(": HELLO message\n");
1225: }
1226: #endif
1227: if (f->pstate != SOCK_HELLO) {
1228: #ifdef DEBUG
1229: if (log_level >= 1) {
1230: sock_log(f);
1231: log_puts(": HELLO, wrong state\n");
1232: }
1233: #endif
1234: sock_close(f);
1235: return 0;
1236: }
1237: if (!sock_hello(f)) {
1238: sock_close(f);
1239: return 0;
1240: }
1241: AMSG_INIT(m);
1242: m->cmd = htonl(AMSG_ACK);
1243: f->rstate = SOCK_RRET;
1244: f->rtodo = sizeof(struct amsg);
1245: break;
1246: case AMSG_BYE:
1247: #ifdef DEBUG
1248: if (log_level >= 3) {
1249: sock_log(f);
1250: log_puts(": BYE message\n");
1251: }
1252: #endif
1253: if (s != NULL && f->pstate != SOCK_INIT) {
1254: #ifdef DEBUG
1255: if (log_level >= 1) {
1256: sock_log(f);
1257: log_puts(": BYE, wrong state\n");
1258: }
1259: #endif
1260: }
1261: sock_close(f);
1262: return 0;
1263: default:
1264: #ifdef DEBUG
1265: if (log_level >= 1) {
1266: sock_log(f);
1267: log_puts(": unknown command in message\n");
1268: }
1269: #endif
1270: sock_close(f);
1271: return 0;
1272: }
1273: return 1;
1274: }
1275:
1276: /*
1277: * build a message in f->wmsg, return 1 on success and 0 if
1278: * there's nothing to do. Assume f->wstate is SOCK_WIDLE
1279: */
1280: int
1281: sock_buildmsg(struct sock *f)
1282: {
1283: unsigned int size;
1284:
1285: /*
1286: * If pos changed (or initial tick), build a MOVE message.
1287: */
1288: if (f->tickpending) {
1289: #ifdef DEBUG
1290: if (log_level >= 4) {
1291: sock_log(f);
1292: log_puts(": building MOVE message, delta = ");
1293: log_puti(f->slot->delta);
1294: log_puts("\n");
1295: }
1296: #endif
1297: AMSG_INIT(&f->wmsg);
1298: f->wmsg.cmd = htonl(AMSG_MOVE);
1299: f->wmsg.u.ts.delta = htonl(f->slot->delta);
1300: f->wtodo = sizeof(struct amsg);
1301: f->wstate = SOCK_WMSG;
1302: f->tickpending = 0;
1303: /*
1304: * XXX: use tickpending as accumulator rather than
1305: * slot->delta
1306: */
1307: f->slot->delta = 0;
1308: return 1;
1309: }
1310:
1311: if (f->fillpending > 0) {
1312: AMSG_INIT(&f->wmsg);
1313: f->wmsg.cmd = htonl(AMSG_FLOWCTL);
1314: f->wmsg.u.ts.delta = htonl(f->fillpending);
1315: size = f->fillpending;
1316: if (f->slot)
1317: size *= f->slot->mix.bpf;
1318: f->rmax += size;
1319: #ifdef DEBUG
1320: if (log_level >= 4) {
1321: sock_log(f);
1322: log_puts(": building FLOWCTL message, count = ");
1323: log_puti(f->fillpending);
1324: log_puts(", rmax -> ");
1325: log_puti(f->rmax);
1326: log_puts("\n");
1327: }
1328: #endif
1329: f->wtodo = sizeof(struct amsg);
1330: f->wstate = SOCK_WMSG;
1331: f->fillpending = 0;
1332: return 1;
1333: }
1334:
1335: /*
1336: * if volume changed build a SETVOL message
1337: */
1338: if (f->pstate >= SOCK_START && f->slot->vol != f->lastvol) {
1339: #ifdef DEBUG
1340: if (log_level >= 3) {
1341: sock_log(f);
1342: log_puts(": building SETVOL message, vol = ");
1343: log_puti(f->slot->vol);
1344: log_puts("\n");
1345: }
1346: #endif
1347: AMSG_INIT(&f->wmsg);
1348: f->wmsg.cmd = htonl(AMSG_SETVOL);
1349: f->wmsg.u.vol.ctl = htonl(f->slot->vol);
1350: f->wtodo = sizeof(struct amsg);
1351: f->wstate = SOCK_WMSG;
1352: f->lastvol = f->slot->vol;
1353: return 1;
1354: }
1355:
1356: if (f->midi != NULL && f->midi->obuf.used > 0) {
1357: size = f->midi->obuf.used;
1358: if (size > AMSG_DATAMAX)
1359: size = AMSG_DATAMAX;
1360: AMSG_INIT(&f->wmsg);
1361: f->wmsg.cmd = htonl(AMSG_DATA);
1362: f->wmsg.u.data.size = htonl(size);
1363: f->wtodo = sizeof(struct amsg);
1364: f->wstate = SOCK_WMSG;
1365: return 1;
1366: }
1367:
1368: /*
1369: * If data available, build a DATA message.
1370: */
1.10 ratchov 1371: if (f->slot != NULL && f->wmax > 0 && f->slot->sub.buf.used > 0) {
1.1 ratchov 1372: size = f->slot->sub.buf.used;
1373: if (size > AMSG_DATAMAX)
1374: size = AMSG_DATAMAX;
1375: if (size > f->walign)
1376: size = f->walign;
1377: if (size > f->wmax)
1378: size = f->wmax;
1379: size -= size % f->slot->sub.bpf;
1380: #ifdef DEBUG
1381: if (size == 0) {
1382: sock_log(f);
1383: log_puts(": sock_buildmsg size == 0\n");
1384: panic();
1385: }
1386: #endif
1387: f->walign -= size;
1388: f->wmax -= size;
1389: if (f->walign == 0)
1390: f->walign = f->slot->round * f->slot->sub.bpf;
1391: #ifdef DEBUG
1392: if (log_level >= 4) {
1393: sock_log(f);
1394: log_puts(": building audio DATA message, size = ");
1395: log_puti(size);
1396: log_puts("\n");
1397: }
1398: #endif
1399: AMSG_INIT(&f->wmsg);
1400: f->wmsg.cmd = htonl(AMSG_DATA);
1401: f->wmsg.u.data.size = htonl(size);
1402: f->wtodo = sizeof(struct amsg);
1403: f->wstate = SOCK_WMSG;
1404: return 1;
1405: }
1406:
1407: if (f->stoppending) {
1408: #ifdef DEBUG
1409: if (log_level >= 3) {
1410: sock_log(f);
1411: log_puts(": building STOP message\n");
1412: }
1413: #endif
1414: f->stoppending = 0;
1415: f->pstate = SOCK_INIT;
1416: AMSG_INIT(&f->wmsg);
1417: f->wmsg.cmd = htonl(AMSG_STOP);
1418: f->wtodo = sizeof(struct amsg);
1419: f->wstate = SOCK_WMSG;
1420: return 1;
1421: }
1422: #ifdef DEBUG
1423: if (log_level >= 4) {
1424: sock_log(f);
1425: log_puts(": no messages to build anymore, idling...\n");
1426: }
1427: #endif
1428: f->wstate = SOCK_WIDLE;
1429: return 0;
1430: }
1431:
1432: /*
1433: * iteration of the socket reader loop, return 1 on success
1434: */
1435: int
1436: sock_read(struct sock *f)
1437: {
1438: #ifdef DEBUG
1439: if (log_level >= 4) {
1440: sock_log(f);
1441: log_puts(": reading ");
1442: log_putu(f->rtodo);
1443: log_puts(" todo\n");
1444: }
1445: #endif
1446: switch (f->rstate) {
1447: case SOCK_RIDLE:
1448: return 0;
1449: case SOCK_RMSG:
1450: if (!sock_rmsg(f))
1451: return 0;
1452: if (!sock_execmsg(f))
1453: return 0;
1454: break;
1455: case SOCK_RDATA:
1456: if (!sock_rdata(f))
1457: return 0;
1458: f->rstate = SOCK_RMSG;
1459: f->rtodo = sizeof(struct amsg);
1460: break;
1461: case SOCK_RRET:
1462: if (f->wstate != SOCK_WIDLE) {
1463: #ifdef DEBUG
1464: if (log_level >= 4) {
1465: sock_log(f);
1466: log_puts(": can't reply, write-end blocked\n");
1467: }
1468: #endif
1469: return 0;
1470: }
1471: f->wmsg = f->rmsg;
1472: f->wstate = SOCK_WMSG;
1473: f->wtodo = sizeof(struct amsg);
1474: f->rstate = SOCK_RMSG;
1475: f->rtodo = sizeof(struct amsg);
1476: #ifdef DEBUG
1477: if (log_level >= 4) {
1478: sock_log(f);
1479: log_puts(": copied RRET message\n");
1480: }
1481: #endif
1482: }
1483: return 1;
1484: }
1485:
1486: /*
1487: * iteration of the socket writer loop, return 1 on success
1488: */
1489: int
1490: sock_write(struct sock *f)
1491: {
1492: #ifdef DEBUG
1493: if (log_level >= 4) {
1494: sock_log(f);
1495: log_puts(": writing");
1496: if (f->wstate != SOCK_WIDLE) {
1497: log_puts(" todo = ");
1498: log_putu(f->wtodo);
1499: }
1500: log_puts("\n");
1501: }
1502: #endif
1503: switch (f->wstate) {
1504: case SOCK_WMSG:
1505: if (!sock_wmsg(f))
1506: return 0;
1507: if (ntohl(f->wmsg.cmd) != AMSG_DATA) {
1508: f->wstate = SOCK_WIDLE;
1509: f->wtodo = 0xdeadbeef;
1510: break;
1511: }
1512: f->wstate = SOCK_WDATA;
1513: f->wsize = f->wtodo = ntohl(f->wmsg.u.data.size);
1514: /* PASSTHROUGH */
1515: case SOCK_WDATA:
1516: if (!sock_wdata(f))
1517: return 0;
1518: if (f->wtodo > 0)
1519: break;
1520: f->wstate = SOCK_WIDLE;
1521: f->wtodo = 0xdeadbeef;
1522: if (f->pstate == SOCK_STOP) {
1523: f->pstate = SOCK_INIT;
1524: f->wmax = 0;
1525: #ifdef DEBUG
1526: if (log_level >= 4) {
1527: sock_log(f);
1528: log_puts(": drained, moved to INIT state\n");
1529: }
1530: #endif
1531: }
1532: /* PASSTHROUGH */
1533: case SOCK_WIDLE:
1534: if (f->rstate == SOCK_RRET) {
1535: f->wmsg = f->rmsg;
1536: f->wstate = SOCK_WMSG;
1537: f->wtodo = sizeof(struct amsg);
1538: f->rstate = SOCK_RMSG;
1539: f->rtodo = sizeof(struct amsg);
1540: #ifdef DEBUG
1541: if (log_level >= 4) {
1542: sock_log(f);
1543: log_puts(": copied RRET message\n");
1544: }
1545: #endif
1546: } else {
1547: if (!sock_buildmsg(f))
1548: return 0;
1549: }
1550: break;
1551: #ifdef DEBUG
1552: default:
1553: sock_log(f);
1554: log_puts(": bad writing end state\n");
1555: panic();
1556: #endif
1557: }
1558: return 1;
1559: }
1560:
1561: int
1562: sock_pollfd(void *arg, struct pollfd *pfd)
1563: {
1564: struct sock *f = arg;
1565: int events = 0;
1566:
1567: /*
1568: * feedback counters, clock ticks and alike may have changed,
1569: * prepare a message to trigger writes
1570: *
1571: * XXX: doing this at the beginning of the cycle is not optimal,
1572: * because state is changed at the end of the read cycle, and
1573: * thus counters, ret message and alike are generated then.
1574: */
1575: if (f->wstate == SOCK_WIDLE && f->rstate != SOCK_RRET)
1576: sock_buildmsg(f);
1577:
1578: if (f->rstate == SOCK_RMSG ||
1579: f->rstate == SOCK_RDATA)
1580: events |= POLLIN;
1581: if (f->rstate == SOCK_RRET ||
1582: f->wstate == SOCK_WMSG ||
1583: f->wstate == SOCK_WDATA)
1584: events |= POLLOUT;
1585: pfd->fd = f->fd;
1586: pfd->events = events;
1587: return 1;
1588: }
1589:
1590: int
1591: sock_revents(void *arg, struct pollfd *pfd)
1592: {
1593: return pfd->revents;
1594: }
1595:
1596: void
1597: sock_in(void *arg)
1598: {
1599: struct sock *f = arg;
1600:
1601: while (sock_read(f))
1602: ;
1603: }
1604:
1605: void
1606: sock_out(void *arg)
1607: {
1608: struct sock *f = arg;
1609:
1610: while (sock_write(f))
1611: ;
1612: }
1613:
1614: void
1615: sock_hup(void *arg)
1616: {
1617: struct sock *f = arg;
1618:
1619: sock_close(f);
1620: }