xref: /openbsd/usr.bin/sndiod/miofile.c (revision 36355b88)
1 /*	$OpenBSD: miofile.c,v 1.9 2021/11/01 14:43:25 ratchov Exp $	*/
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"
27 #include "fdpass.h"
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 
48 int
port_mio_open(struct port * p)49 port_mio_open(struct port *p)
50 {
51 	p->mio.hdl = fdpass_mio_open(p->num, p->midi->mode);
52 	if (p->mio.hdl == NULL)
53 		return 0;
54 	p->mio.file = file_new(&port_mio_ops, p, "port", mio_nfds(p->mio.hdl));
55 	return 1;
56 }
57 
58 void
port_mio_close(struct port * p)59 port_mio_close(struct port *p)
60 {
61 	file_del(p->mio.file);
62 	mio_close(p->mio.hdl);
63 }
64 
65 int
port_mio_pollfd(void * addr,struct pollfd * pfd)66 port_mio_pollfd(void *addr, struct pollfd *pfd)
67 {
68 	struct port *p = addr;
69 	struct midi *ep = p->midi;
70 	int events = 0;
71 
72 	if (ep->mode & MODE_MIDIIN)
73 		events |= POLLIN;
74 	if ((ep->mode & MODE_MIDIOUT) && ep->obuf.used > 0)
75 		events |= POLLOUT;
76 	return mio_pollfd(p->mio.hdl, pfd, events);
77 }
78 
79 int
port_mio_revents(void * addr,struct pollfd * pfd)80 port_mio_revents(void *addr, struct pollfd *pfd)
81 {
82 	struct port *p = addr;
83 
84 	return mio_revents(p->mio.hdl, pfd);
85 }
86 
87 void
port_mio_in(void * arg)88 port_mio_in(void *arg)
89 {
90 	unsigned char data[MIDI_BUFSZ];
91 	struct port *p = arg;
92 	struct midi *ep = p->midi;
93 	int n;
94 
95 	for (;;) {
96 		n = mio_read(p->mio.hdl, data, MIDI_BUFSZ);
97 		if (n == 0)
98 			break;
99 		midi_in(ep, data, n);
100 	}
101 }
102 
103 void
port_mio_out(void * arg)104 port_mio_out(void *arg)
105 {
106 	struct port *p = arg;
107 	struct midi *ep = p->midi;
108 	unsigned char *data;
109 	int n, count;
110 
111 	for (;;) {
112 		data = abuf_rgetblk(&ep->obuf, &count);
113 		if (count == 0)
114 			break;
115 		n = mio_write(p->mio.hdl, data, count);
116 		if (n == 0)
117 			break;
118 		abuf_rdiscard(&ep->obuf, n);
119 		if (n < count)
120 			break;
121 	}
122 	if (p->state == PORT_DRAIN && ep->obuf.used == 0)
123 		port_close(p);
124 	midi_fill(ep);
125 }
126 
127 void
port_mio_hup(void * arg)128 port_mio_hup(void *arg)
129 {
130 	struct port *p = arg;
131 
132 	port_migrate(p);
133 	midi_abort(p->midi);
134 	if (p->state != PORT_CFG)
135 		port_close(p);
136 }
137