1 /* $OpenBSD: miofile.c,v 1.4 2015/12/20 11:38:33 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 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, p->path, mio_nfds(p->mio.hdl)); 55 return 1; 56 } 57 58 void 59 port_mio_close(struct port *p) 60 { 61 file_del(p->mio.file); 62 mio_close(p->mio.hdl); 63 } 64 65 int 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 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 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 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 128 port_mio_hup(void *arg) 129 { 130 struct port *p = arg; 131 132 port_close(p); 133 } 134