1 /* $OpenBSD: miofile.c,v 1.3 2012/11/30 22:26:34 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 "file.h" 28 #include "midi.h" 29 #include "miofile.h" 30 #include "utils.h" 31 32 int port_mio_pollfd(void *, struct pollfd *); 33 int port_mio_revents(void *, struct pollfd *); 34 void port_mio_in(void *); 35 void port_mio_out(void *); 36 void port_mio_hup(void *); 37 38 struct fileops port_mio_ops = { 39 "mio", 40 port_mio_pollfd, 41 port_mio_revents, 42 port_mio_in, 43 port_mio_out, 44 port_mio_hup 45 }; 46 47 int 48 port_mio_open(struct port *p) 49 { 50 p->mio.hdl = mio_open(p->path, p->midi->mode, 1); 51 if (p->mio.hdl == NULL) 52 return 0; 53 p->mio.file = file_new(&port_mio_ops, p, p->path, mio_nfds(p->mio.hdl)); 54 return 1; 55 } 56 57 void 58 port_mio_close(struct port *p) 59 { 60 file_del(p->mio.file); 61 mio_close(p->mio.hdl); 62 } 63 64 int 65 port_mio_pollfd(void *addr, struct pollfd *pfd) 66 { 67 struct port *p = addr; 68 struct midi *ep = p->midi; 69 int events = 0; 70 71 if (ep->mode & MODE_MIDIIN) 72 events |= POLLIN; 73 if ((ep->mode & MODE_MIDIOUT) && ep->obuf.used > 0) 74 events |= POLLOUT; 75 return mio_pollfd(p->mio.hdl, pfd, events); 76 } 77 78 int 79 port_mio_revents(void *addr, struct pollfd *pfd) 80 { 81 struct port *p = addr; 82 83 return mio_revents(p->mio.hdl, pfd); 84 } 85 86 void 87 port_mio_in(void *arg) 88 { 89 unsigned char data[MIDI_BUFSZ]; 90 struct port *p = arg; 91 struct midi *ep = p->midi; 92 int n; 93 94 for (;;) { 95 n = mio_read(p->mio.hdl, data, MIDI_BUFSZ); 96 if (n == 0) 97 break; 98 midi_in(ep, data, n); 99 } 100 } 101 102 void 103 port_mio_out(void *arg) 104 { 105 struct port *p = arg; 106 struct midi *ep = p->midi; 107 unsigned char *data; 108 int n, count; 109 110 for (;;) { 111 data = abuf_rgetblk(&ep->obuf, &count); 112 if (count == 0) 113 break; 114 n = mio_write(p->mio.hdl, data, count); 115 if (n == 0) 116 break; 117 abuf_rdiscard(&ep->obuf, n); 118 if (n < count) 119 break; 120 } 121 if (p->state == PORT_DRAIN && ep->obuf.used == 0) 122 port_close(p); 123 midi_fill(ep); 124 } 125 126 void 127 port_mio_hup(void *arg) 128 { 129 struct port *p = arg; 130 131 port_close(p); 132 } 133