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