1 /* $OpenBSD: mio.c,v 1.15 2012/05/23 19:25:11 ratchov Exp $ */ 2 /* 3 * Copyright (c) 2008 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/param.h> 19 #include <sys/types.h> 20 #include <sys/time.h> 21 #include <sys/stat.h> 22 23 #include <errno.h> 24 #include <fcntl.h> 25 #include <poll.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <unistd.h> 30 31 #include "debug.h" 32 #include "mio_priv.h" 33 34 struct mio_hdl * 35 mio_open(const char *str, unsigned int mode, int nbio) 36 { 37 static char portany[] = MIO_PORTANY; 38 struct mio_hdl *hdl; 39 const char *p; 40 41 #ifdef DEBUG 42 sndio_debug_init(); 43 #endif 44 if ((mode & (MIO_OUT | MIO_IN)) == 0) 45 return NULL; 46 if (str == NULL) /* backward compat */ 47 str = portany; 48 if (strcmp(str, portany) == 0 && !issetugid()) { 49 str = getenv("MIDIDEVICE"); 50 if (str == NULL) 51 str = portany; 52 } 53 if (strcmp(str, portany) == 0) { 54 hdl = mio_aucat_open("/0", mode, nbio, 1); 55 if (hdl != NULL) 56 return hdl; 57 return mio_rmidi_open("/0", mode, nbio); 58 } 59 if ((p = sndio_parsetype(str, "snd")) != NULL || 60 (p = sndio_parsetype(str, "aucat")) != NULL) 61 return mio_aucat_open(p, mode, nbio, 0); 62 if ((p = sndio_parsetype(str, "midithru")) != NULL) 63 return mio_aucat_open(p, mode, nbio, 1); 64 if ((p = sndio_parsetype(str, "rmidi")) != NULL) 65 return mio_rmidi_open(p, mode, nbio); 66 DPRINTF("mio_open: %s: unknown device type\n", str); 67 return NULL; 68 } 69 70 void 71 mio_create(struct mio_hdl *hdl, struct mio_ops *ops, 72 unsigned int mode, int nbio) 73 { 74 hdl->ops = ops; 75 hdl->mode = mode; 76 hdl->nbio = nbio; 77 hdl->eof = 0; 78 } 79 80 void 81 mio_close(struct mio_hdl *hdl) 82 { 83 hdl->ops->close(hdl); 84 } 85 86 size_t 87 mio_read(struct mio_hdl *hdl, void *buf, size_t len) 88 { 89 if (hdl->eof) { 90 DPRINTF("mio_read: eof\n"); 91 return 0; 92 } 93 if (!(hdl->mode & MIO_IN)) { 94 DPRINTF("mio_read: not input device\n"); 95 hdl->eof = 1; 96 return 0; 97 } 98 if (len == 0) { 99 DPRINTF("mio_read: zero length read ignored\n"); 100 return 0; 101 } 102 return hdl->ops->read(hdl, buf, len); 103 } 104 105 size_t 106 mio_write(struct mio_hdl *hdl, const void *buf, size_t len) 107 { 108 if (hdl->eof) { 109 DPRINTF("mio_write: eof\n"); 110 return 0; 111 } 112 if (!(hdl->mode & MIO_OUT)) { 113 DPRINTF("mio_write: not output device\n"); 114 hdl->eof = 1; 115 return 0; 116 } 117 if (len == 0) { 118 DPRINTF("mio_write: zero length write ignored\n"); 119 return 0; 120 } 121 return hdl->ops->write(hdl, buf, len); 122 } 123 124 int 125 mio_nfds(struct mio_hdl *hdl) 126 { 127 return 1; 128 } 129 130 int 131 mio_pollfd(struct mio_hdl *hdl, struct pollfd *pfd, int events) 132 { 133 if (hdl->eof) 134 return 0; 135 return hdl->ops->pollfd(hdl, pfd, events); 136 } 137 138 int 139 mio_revents(struct mio_hdl *hdl, struct pollfd *pfd) 140 { 141 if (hdl->eof) 142 return POLLHUP; 143 return hdl->ops->revents(hdl, pfd); 144 } 145 146 int 147 mio_eof(struct mio_hdl *hdl) 148 { 149 return hdl->eof; 150 } 151