GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libsndio/mio.c Lines: 0 94 0.0 %
Date: 2017-11-13 Branches: 0 92 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: mio.c,v 1.20 2015/11/22 12:01:23 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/types.h>
19
#include <sys/time.h>
20
#include <sys/stat.h>
21
22
#include <errno.h>
23
#include <fcntl.h>
24
#include <poll.h>
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <string.h>
28
#include <unistd.h>
29
30
#include "debug.h"
31
#include "mio_priv.h"
32
33
struct mio_hdl *
34
mio_open(const char *str, unsigned int mode, int nbio)
35
{
36
	static char portany[] = MIO_PORTANY;
37
	struct mio_hdl *hdl;
38
39
#ifdef DEBUG
40
	_sndio_debug_init();
41
#endif
42
	if ((mode & (MIO_OUT | MIO_IN)) == 0)
43
		return NULL;
44
	if (str == NULL) /* backward compat */
45
		str = portany;
46
	if (strcmp(str, portany) == 0 && !issetugid()) {
47
		str = getenv("MIDIDEVICE");
48
		if (str == NULL)
49
			str = portany;
50
	}
51
	if (strcmp(str, portany) == 0) {
52
		hdl = _mio_aucat_open("midithru/0", mode, nbio);
53
		if (hdl != NULL)
54
			return hdl;
55
		return _mio_rmidi_open("rmidi/0", mode, nbio);
56
	}
57
	if (_sndio_parsetype(str, "snd") ||
58
	    _sndio_parsetype(str, "midithru") ||
59
	    _sndio_parsetype(str, "midi"))
60
		return _mio_aucat_open(str, mode, nbio);
61
	if (_sndio_parsetype(str, "rmidi"))
62
		return _mio_rmidi_open(str, mode, nbio);
63
	DPRINTF("mio_open: %s: unknown device type\n", str);
64
	return NULL;
65
}
66
67
void
68
_mio_create(struct mio_hdl *hdl, struct mio_ops *ops,
69
    unsigned int mode, int nbio)
70
{
71
	hdl->ops = ops;
72
	hdl->mode = mode;
73
	hdl->nbio = nbio;
74
	hdl->eof = 0;
75
}
76
77
void
78
mio_close(struct mio_hdl *hdl)
79
{
80
	hdl->ops->close(hdl);
81
}
82
83
static int
84
mio_psleep(struct mio_hdl *hdl, int event)
85
{
86
	struct pollfd pfd[MIO_MAXNFDS];
87
	int revents;
88
	int nfds;
89
90
	nfds = mio_nfds(hdl);
91
	if (nfds > MIO_MAXNFDS) {
92
		DPRINTF("mio_psleep: %d: too many descriptors\n", nfds);
93
		hdl->eof = 1;
94
		return 0;
95
	}
96
	for (;;) {
97
		nfds = mio_pollfd(hdl, pfd, event);
98
		while (poll(pfd, nfds, -1) < 0) {
99
			if (errno == EINTR)
100
				continue;
101
			DPERROR("mio_psleep: poll");
102
			hdl->eof = 1;
103
			return 0;
104
		}
105
		revents = mio_revents(hdl, pfd);
106
		if (revents & POLLHUP) {
107
			DPRINTF("mio_psleep: hang-up\n");
108
			return 0;
109
		}
110
		if (revents & event)
111
			break;
112
	}
113
	return 1;
114
}
115
116
size_t
117
mio_read(struct mio_hdl *hdl, void *buf, size_t len)
118
{
119
	unsigned int n;
120
	char *data = buf;
121
	size_t todo = len;
122
123
	if (hdl->eof) {
124
		DPRINTF("mio_read: eof\n");
125
		return 0;
126
	}
127
	if (!(hdl->mode & MIO_IN)) {
128
		DPRINTF("mio_read: not input device\n");
129
		hdl->eof = 1;
130
		return 0;
131
	}
132
	if (len == 0) {
133
		DPRINTF("mio_read: zero length read ignored\n");
134
		return 0;
135
	}
136
	while (todo > 0) {
137
		n = hdl->ops->read(hdl, data, todo);
138
		if (n == 0 && hdl->eof)
139
			break;
140
		data += n;
141
		todo -= n;
142
		if (n > 0 || hdl->nbio)
143
			break;
144
		if (!mio_psleep(hdl, POLLIN))
145
			break;
146
	}
147
	return len - todo;
148
}
149
150
size_t
151
mio_write(struct mio_hdl *hdl, const void *buf, size_t len)
152
{
153
	unsigned int n;
154
	const unsigned char *data = buf;
155
	size_t todo = len;
156
157
	if (hdl->eof) {
158
		DPRINTF("mio_write: eof\n");
159
		return 0;
160
	}
161
	if (!(hdl->mode & MIO_OUT)) {
162
		DPRINTF("mio_write: not output device\n");
163
		hdl->eof = 1;
164
		return 0;
165
	}
166
	if (len == 0) {
167
		DPRINTF("mio_write: zero length write ignored\n");
168
		return 0;
169
	}
170
	if (todo == 0) {
171
		DPRINTF("mio_write: zero length write ignored\n");
172
		return 0;
173
	}
174
	while (todo > 0) {
175
		n = hdl->ops->write(hdl, data, todo);
176
		if (n == 0) {
177
			if (hdl->nbio || hdl->eof)
178
				break;
179
			if (!mio_psleep(hdl, POLLOUT))
180
				break;
181
			continue;
182
		}
183
		data += n;
184
		todo -= n;
185
	}
186
	return len - todo;
187
}
188
189
int
190
mio_nfds(struct mio_hdl *hdl)
191
{
192
	return hdl->ops->nfds(hdl);
193
}
194
195
int
196
mio_pollfd(struct mio_hdl *hdl, struct pollfd *pfd, int events)
197
{
198
	if (hdl->eof)
199
		return 0;
200
	return hdl->ops->pollfd(hdl, pfd, events);
201
}
202
203
int
204
mio_revents(struct mio_hdl *hdl, struct pollfd *pfd)
205
{
206
	if (hdl->eof)
207
		return POLLHUP;
208
	return hdl->ops->revents(hdl, pfd);
209
}
210
211
int
212
mio_eof(struct mio_hdl *hdl)
213
{
214
	return hdl->eof;
215
}