Annotation of src/usr.bin/sndiod/miofile.c, Revision 1.6
1.6 ! ratchov 1: /* $OpenBSD: miofile.c,v 1.5 2019/09/21 04:42:46 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:
18: #include <sys/types.h>
19: #include <sys/time.h>
20:
21: #include <poll.h>
22: #include <stdio.h>
23: #include <stdlib.h>
24: #include <string.h>
25: #include <sndio.h>
26: #include "defs.h"
1.4 ratchov 27: #include "fdpass.h"
1.1 ratchov 28: #include "file.h"
29: #include "midi.h"
30: #include "miofile.h"
31: #include "utils.h"
32:
33: int port_mio_pollfd(void *, struct pollfd *);
34: int port_mio_revents(void *, struct pollfd *);
35: void port_mio_in(void *);
36: void port_mio_out(void *);
37: void port_mio_hup(void *);
38:
39: struct fileops port_mio_ops = {
40: "mio",
41: port_mio_pollfd,
42: port_mio_revents,
43: port_mio_in,
44: port_mio_out,
45: port_mio_hup
46: };
47:
1.6 ! ratchov 48: /*
! 49: * open the port using one of the provided paths
! 50: */
! 51: static struct mio_hdl *
! 52: port_mio_openlist(struct port *c, unsigned int mode)
! 53: {
! 54: struct mio_hdl *hdl;
! 55: struct name *n;
! 56: int idx;
! 57:
! 58: idx = 0;
! 59: n = c->path_list;
! 60: while (1) {
! 61: if (n == NULL)
! 62: break;
! 63: hdl = fdpass_mio_open(c->num, idx, mode);
! 64: if (hdl != NULL) {
! 65: if (log_level >= 2) {
! 66: port_log(c);
! 67: log_puts(": using ");
! 68: log_puts(n->str);
! 69: log_puts("\n");
! 70: }
! 71: return hdl;
! 72: }
! 73: n = n->next;
! 74: idx++;
! 75: }
! 76: return NULL;
! 77: }
! 78:
1.1 ratchov 79: int
80: port_mio_open(struct port *p)
81: {
1.6 ! ratchov 82: p->mio.hdl = port_mio_openlist(p, p->midi->mode);
1.1 ratchov 83: if (p->mio.hdl == NULL)
84: return 0;
1.5 ratchov 85: p->mio.file = file_new(&port_mio_ops, p, "port", mio_nfds(p->mio.hdl));
86: return 1;
87: }
88:
89: /*
90: * Open an alternate port. Upon success, close the old port
91: * and continue using the new one.
92: */
93: int
94: port_mio_reopen(struct port *p)
95: {
96: struct mio_hdl *hdl;
97:
1.6 ! ratchov 98: hdl = port_mio_openlist(p, p->midi->mode);
1.5 ratchov 99: if (hdl == NULL) {
100: if (log_level >= 1) {
101: port_log(p);
102: log_puts(": couldn't open an alternate port\n");
103: }
104: return 0;
105: }
106:
107: /* close unused device */
108: file_del(p->mio.file);
109: mio_close(p->mio.hdl);
110:
111: p->mio.hdl = hdl;
112: p->mio.file = file_new(&port_mio_ops, p, "port", mio_nfds(hdl));
1.1 ratchov 113: return 1;
114: }
115:
116: void
117: port_mio_close(struct port *p)
118: {
119: file_del(p->mio.file);
120: mio_close(p->mio.hdl);
121: }
122:
123: int
124: port_mio_pollfd(void *addr, struct pollfd *pfd)
125: {
126: struct port *p = addr;
127: struct midi *ep = p->midi;
128: int events = 0;
129:
1.2 ratchov 130: if (ep->mode & MODE_MIDIIN)
1.1 ratchov 131: events |= POLLIN;
132: if ((ep->mode & MODE_MIDIOUT) && ep->obuf.used > 0)
133: events |= POLLOUT;
134: return mio_pollfd(p->mio.hdl, pfd, events);
135: }
136:
137: int
138: port_mio_revents(void *addr, struct pollfd *pfd)
139: {
140: struct port *p = addr;
141:
142: return mio_revents(p->mio.hdl, pfd);
143: }
144:
145: void
146: port_mio_in(void *arg)
147: {
1.2 ratchov 148: unsigned char data[MIDI_BUFSZ];
1.1 ratchov 149: struct port *p = arg;
150: struct midi *ep = p->midi;
1.2 ratchov 151: int n;
1.1 ratchov 152:
153: for (;;) {
1.2 ratchov 154: n = mio_read(p->mio.hdl, data, MIDI_BUFSZ);
1.1 ratchov 155: if (n == 0)
156: break;
1.2 ratchov 157: midi_in(ep, data, n);
1.1 ratchov 158: }
159: }
160:
161: void
162: port_mio_out(void *arg)
163: {
164: struct port *p = arg;
165: struct midi *ep = p->midi;
166: unsigned char *data;
167: int n, count;
168:
169: for (;;) {
170: data = abuf_rgetblk(&ep->obuf, &count);
171: if (count == 0)
172: break;
173: n = mio_write(p->mio.hdl, data, count);
174: if (n == 0)
175: break;
176: abuf_rdiscard(&ep->obuf, n);
177: if (n < count)
178: break;
179: }
1.3 ratchov 180: if (p->state == PORT_DRAIN && ep->obuf.used == 0)
181: port_close(p);
1.2 ratchov 182: midi_fill(ep);
1.1 ratchov 183: }
184:
185: void
186: port_mio_hup(void *arg)
187: {
188: struct port *p = arg;
189:
1.5 ratchov 190: if (!port_reopen(p))
191: port_close(p);
1.1 ratchov 192: }