xref: /openbsd-src/lib/libsndio/mio.c (revision 4c1e55dc91edd6e69ccc60ce855900fbc12cf34f)
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