1 /* $OpenBSD: mio.c,v 1.14 2012/04/11 06:05:43 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 struct mio_hdl *hdl; 38 const char *p; 39 40 #ifdef DEBUG 41 sndio_debug_init(); 42 #endif 43 if ((mode & (MIO_OUT | MIO_IN)) == 0) 44 return NULL; 45 if (str == NULL && !issetugid()) 46 str = getenv("MIDIDEVICE"); 47 if (str == NULL) { 48 hdl = mio_aucat_open("/0", mode, nbio, 1); 49 if (hdl != NULL) 50 return hdl; 51 return mio_rmidi_open("/0", mode, nbio); 52 } 53 if ((p = sndio_parsetype(str, "snd")) != NULL || 54 (p = sndio_parsetype(str, "aucat")) != NULL) 55 return mio_aucat_open(p, mode, nbio, 0); 56 if ((p = sndio_parsetype(str, "midithru")) != NULL) 57 return mio_aucat_open(p, mode, nbio, 1); 58 if ((p = sndio_parsetype(str, "rmidi")) != NULL) 59 return mio_rmidi_open(p, mode, nbio); 60 DPRINTF("mio_open: %s: unknown device type\n", str); 61 return NULL; 62 } 63 64 void 65 mio_create(struct mio_hdl *hdl, struct mio_ops *ops, 66 unsigned int mode, int nbio) 67 { 68 hdl->ops = ops; 69 hdl->mode = mode; 70 hdl->nbio = nbio; 71 hdl->eof = 0; 72 } 73 74 void 75 mio_close(struct mio_hdl *hdl) 76 { 77 hdl->ops->close(hdl); 78 } 79 80 size_t 81 mio_read(struct mio_hdl *hdl, void *buf, size_t len) 82 { 83 if (hdl->eof) { 84 DPRINTF("mio_read: eof\n"); 85 return 0; 86 } 87 if (!(hdl->mode & MIO_IN)) { 88 DPRINTF("mio_read: not input device\n"); 89 hdl->eof = 1; 90 return 0; 91 } 92 if (len == 0) { 93 DPRINTF("mio_read: zero length read ignored\n"); 94 return 0; 95 } 96 return hdl->ops->read(hdl, buf, len); 97 } 98 99 size_t 100 mio_write(struct mio_hdl *hdl, const void *buf, size_t len) 101 { 102 if (hdl->eof) { 103 DPRINTF("mio_write: eof\n"); 104 return 0; 105 } 106 if (!(hdl->mode & MIO_OUT)) { 107 DPRINTF("mio_write: not output device\n"); 108 hdl->eof = 1; 109 return 0; 110 } 111 if (len == 0) { 112 DPRINTF("mio_write: zero length write ignored\n"); 113 return 0; 114 } 115 return hdl->ops->write(hdl, buf, len); 116 } 117 118 int 119 mio_nfds(struct mio_hdl *hdl) 120 { 121 return 1; 122 } 123 124 int 125 mio_pollfd(struct mio_hdl *hdl, struct pollfd *pfd, int events) 126 { 127 if (hdl->eof) 128 return 0; 129 return hdl->ops->pollfd(hdl, pfd, events); 130 } 131 132 int 133 mio_revents(struct mio_hdl *hdl, struct pollfd *pfd) 134 { 135 if (hdl->eof) 136 return POLLHUP; 137 return hdl->ops->revents(hdl, pfd); 138 } 139 140 int 141 mio_eof(struct mio_hdl *hdl) 142 { 143 return hdl->eof; 144 } 145