xref: /openbsd-src/usr.bin/sndiod/miofile.c (revision 36355b8814c2d1777fba59123746164a289c5acb)
1*36355b88Sratchov /*	$OpenBSD: miofile.c,v 1.9 2021/11/01 14:43:25 ratchov Exp $	*/
287bc9f6aSratchov /*
387bc9f6aSratchov  * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
487bc9f6aSratchov  *
587bc9f6aSratchov  * Permission to use, copy, modify, and distribute this software for any
687bc9f6aSratchov  * purpose with or without fee is hereby granted, provided that the above
787bc9f6aSratchov  * copyright notice and this permission notice appear in all copies.
887bc9f6aSratchov  *
987bc9f6aSratchov  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1087bc9f6aSratchov  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1187bc9f6aSratchov  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1287bc9f6aSratchov  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1387bc9f6aSratchov  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1487bc9f6aSratchov  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1587bc9f6aSratchov  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1687bc9f6aSratchov  */
1787bc9f6aSratchov 
1887bc9f6aSratchov #include <sys/types.h>
1987bc9f6aSratchov #include <sys/time.h>
2087bc9f6aSratchov 
2187bc9f6aSratchov #include <poll.h>
2287bc9f6aSratchov #include <stdio.h>
2387bc9f6aSratchov #include <stdlib.h>
2487bc9f6aSratchov #include <string.h>
2587bc9f6aSratchov #include <sndio.h>
2687bc9f6aSratchov #include "defs.h"
27395f8c55Sratchov #include "fdpass.h"
2887bc9f6aSratchov #include "file.h"
2987bc9f6aSratchov #include "midi.h"
3087bc9f6aSratchov #include "miofile.h"
3187bc9f6aSratchov #include "utils.h"
3287bc9f6aSratchov 
3387bc9f6aSratchov int  port_mio_pollfd(void *, struct pollfd *);
3487bc9f6aSratchov int  port_mio_revents(void *, struct pollfd *);
3587bc9f6aSratchov void port_mio_in(void *);
3687bc9f6aSratchov void port_mio_out(void *);
3787bc9f6aSratchov void port_mio_hup(void *);
3887bc9f6aSratchov 
3987bc9f6aSratchov struct fileops port_mio_ops = {
4087bc9f6aSratchov 	"mio",
4187bc9f6aSratchov 	port_mio_pollfd,
4287bc9f6aSratchov 	port_mio_revents,
4387bc9f6aSratchov 	port_mio_in,
4487bc9f6aSratchov 	port_mio_out,
4587bc9f6aSratchov 	port_mio_hup
4687bc9f6aSratchov };
4787bc9f6aSratchov 
4887bc9f6aSratchov int
port_mio_open(struct port * p)4987bc9f6aSratchov port_mio_open(struct port *p)
5087bc9f6aSratchov {
51*36355b88Sratchov 	p->mio.hdl = fdpass_mio_open(p->num, p->midi->mode);
5287bc9f6aSratchov 	if (p->mio.hdl == NULL)
5387bc9f6aSratchov 		return 0;
54731605d7Sratchov 	p->mio.file = file_new(&port_mio_ops, p, "port", mio_nfds(p->mio.hdl));
55731605d7Sratchov 	return 1;
56731605d7Sratchov }
57731605d7Sratchov 
5887bc9f6aSratchov void
port_mio_close(struct port * p)5987bc9f6aSratchov port_mio_close(struct port *p)
6087bc9f6aSratchov {
6187bc9f6aSratchov 	file_del(p->mio.file);
6287bc9f6aSratchov 	mio_close(p->mio.hdl);
6387bc9f6aSratchov }
6487bc9f6aSratchov 
6587bc9f6aSratchov int
port_mio_pollfd(void * addr,struct pollfd * pfd)6687bc9f6aSratchov port_mio_pollfd(void *addr, struct pollfd *pfd)
6787bc9f6aSratchov {
6887bc9f6aSratchov 	struct port *p = addr;
6987bc9f6aSratchov 	struct midi *ep = p->midi;
7087bc9f6aSratchov 	int events = 0;
7187bc9f6aSratchov 
7207826207Sratchov 	if (ep->mode & MODE_MIDIIN)
7387bc9f6aSratchov 		events |= POLLIN;
7487bc9f6aSratchov 	if ((ep->mode & MODE_MIDIOUT) && ep->obuf.used > 0)
7587bc9f6aSratchov 		events |= POLLOUT;
7687bc9f6aSratchov 	return mio_pollfd(p->mio.hdl, pfd, events);
7787bc9f6aSratchov }
7887bc9f6aSratchov 
7987bc9f6aSratchov int
port_mio_revents(void * addr,struct pollfd * pfd)8087bc9f6aSratchov port_mio_revents(void *addr, struct pollfd *pfd)
8187bc9f6aSratchov {
8287bc9f6aSratchov 	struct port *p = addr;
8387bc9f6aSratchov 
8487bc9f6aSratchov 	return mio_revents(p->mio.hdl, pfd);
8587bc9f6aSratchov }
8687bc9f6aSratchov 
8787bc9f6aSratchov void
port_mio_in(void * arg)8887bc9f6aSratchov port_mio_in(void *arg)
8987bc9f6aSratchov {
9007826207Sratchov 	unsigned char data[MIDI_BUFSZ];
9187bc9f6aSratchov 	struct port *p = arg;
9287bc9f6aSratchov 	struct midi *ep = p->midi;
9307826207Sratchov 	int n;
9487bc9f6aSratchov 
9587bc9f6aSratchov 	for (;;) {
9607826207Sratchov 		n = mio_read(p->mio.hdl, data, MIDI_BUFSZ);
9787bc9f6aSratchov 		if (n == 0)
9887bc9f6aSratchov 			break;
9907826207Sratchov 		midi_in(ep, data, n);
10087bc9f6aSratchov 	}
10187bc9f6aSratchov }
10287bc9f6aSratchov 
10387bc9f6aSratchov void
port_mio_out(void * arg)10487bc9f6aSratchov port_mio_out(void *arg)
10587bc9f6aSratchov {
10687bc9f6aSratchov 	struct port *p = arg;
10787bc9f6aSratchov 	struct midi *ep = p->midi;
10887bc9f6aSratchov 	unsigned char *data;
10987bc9f6aSratchov 	int n, count;
11087bc9f6aSratchov 
11187bc9f6aSratchov 	for (;;) {
11287bc9f6aSratchov 		data = abuf_rgetblk(&ep->obuf, &count);
11387bc9f6aSratchov 		if (count == 0)
11487bc9f6aSratchov 			break;
11587bc9f6aSratchov 		n = mio_write(p->mio.hdl, data, count);
11687bc9f6aSratchov 		if (n == 0)
11787bc9f6aSratchov 			break;
11887bc9f6aSratchov 		abuf_rdiscard(&ep->obuf, n);
11987bc9f6aSratchov 		if (n < count)
12087bc9f6aSratchov 			break;
12187bc9f6aSratchov 	}
1221e00c562Sratchov 	if (p->state == PORT_DRAIN && ep->obuf.used == 0)
1231e00c562Sratchov 		port_close(p);
12407826207Sratchov 	midi_fill(ep);
12587bc9f6aSratchov }
12687bc9f6aSratchov 
12787bc9f6aSratchov void
port_mio_hup(void * arg)12887bc9f6aSratchov port_mio_hup(void *arg)
12987bc9f6aSratchov {
13087bc9f6aSratchov 	struct port *p = arg;
13187bc9f6aSratchov 
132*36355b88Sratchov 	port_migrate(p);
133f7f6d88aSratchov 	midi_abort(p->midi);
134f7f6d88aSratchov 	if (p->state != PORT_CFG)
135f7f6d88aSratchov 		port_close(p);
136f7f6d88aSratchov }
137