Implement mmap support with STORE and RETRIEVE notifications
[ossp.git] / osstest.c
blob53c3edcfb029b2c177356711e32a148a33faccc0
1 /* Simple oss testsuite
3 * Copyright (C) 2009 Maarten Lankhorst <m.b.lankhorst@gmail.com>
5 * This file is released under the GPLv2.
6 */
8 #include <sys/types.h>
9 #include <sys/soundcard.h>
10 #include <sys/stat.h>
11 #include <sys/ioctl.h>
12 #include <stdio.h>
13 #include <stdarg.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <errno.h>
17 #include <string.h>
18 #include <poll.h>
19 #include <sys/mman.h>
20 #include <stdlib.h>
22 #define MIXERDEV "/dev/mixer"
23 #define DSPDEV "/dev/dsp"
25 /* Test macros */
27 static int errors, success;
28 static int report_success = 1;
30 #define ok(a, b, c...) do { \
31 if (!(a)) { \
32 fprintf(stderr, "%s@%d test failed (%s): " b "\n", __func__, __LINE__, #a, ##c); \
33 ++errors; \
34 } else { \
35 if (report_success) \
36 printf("%s@%d test succeeded (%s)\n", __func__, __LINE__, #a); \
37 ++success; \
38 } } while (0)
40 static int mixerfd, dspfd;
42 static int reopen(int blocking)
44 close(dspfd);
45 if (!blocking)
46 blocking = O_NDELAY;
47 else
48 blocking = 0;
49 dspfd = open(DSPDEV, O_RDWR|blocking);
50 return dspfd;
53 static void test_ro(int fd)
55 int ret;
56 char buf[1024];
57 struct audio_buf_info abi;
58 memset(buf, 0, sizeof(buf));
60 ret = read(fd, buf, sizeof(buf));
61 ok(ret >= 0, "%s", strerror(errno));
63 ret = write(fd, buf, sizeof(buf));
64 ok(ret < 0, "read %d bytes", ret);
66 ret = ioctl(fd, SNDCTL_DSP_GETISPACE, &abi);
67 ok(ret >= 0, "%s", strerror(errno));
69 ret = ioctl(fd, SNDCTL_DSP_GETOSPACE, &abi);
70 ok(ret < 0, "%s", strerror(errno));
71 if (ret < 0)
72 ok(errno == EINVAL, "Invalid errno: %s", strerror(errno));
75 static void test_wo(int fd)
77 int ret;
78 char buf[1024];
79 struct audio_buf_info abi;
80 memset(buf, 0, sizeof(buf));
82 ret = read(fd, buf, sizeof(buf));
83 ok(ret < 0, "read %d bytes", ret);
85 ret = write(fd, buf, sizeof(buf));
86 ok(ret >= 0, "%s", strerror(errno));
88 ret = ioctl(fd, SNDCTL_DSP_GETISPACE, &abi);
89 ok(ret < 0, "%s", strerror(errno));
90 if (ret < 0)
91 ok(errno == EINVAL, "Invalid errno: %s", strerror(errno));
93 ret = ioctl(fd, SNDCTL_DSP_GETOSPACE, &abi);
94 ok(ret >= 0, "%s", strerror(errno));
97 static void test_rw(int fd)
99 int ret;
100 char buf[1024];
101 struct audio_buf_info abi;
102 memset(buf, 0, sizeof(buf));
104 ret = read(fd, buf, sizeof(buf));
105 ok(ret >= 0, "%s", strerror(errno));
107 ret = write(fd, buf, sizeof(buf));
108 ok(ret >= 0, "%s", strerror(errno));
110 ret = ioctl(fd, SNDCTL_DSP_GETISPACE, &abi);
111 ok(ret >= 0, "%s", strerror(errno));
113 ret = ioctl(fd, SNDCTL_DSP_GETOSPACE, &abi);
114 ok(ret >= 0, "%s", strerror(errno));
117 static void test_open(void)
119 int ro_fd, rw_fd, wo_fd;
121 mixerfd = open(MIXERDEV, O_RDONLY|O_NDELAY);
122 ok(mixerfd >= 0, "%s", strerror(errno));
125 /* In order to make this work it has to be serialized
126 * alsa's kernel emulation can only have device open once
127 * so do some specific smokescreen tests here
128 * and then open dsp for testing
130 ro_fd = open(DSPDEV, O_RDONLY);
131 ok(ro_fd >= 0, "%s", strerror(errno));
133 if (ro_fd >= 0)
134 test_ro(ro_fd);
136 close(ro_fd);
138 wo_fd = open(DSPDEV, O_WRONLY);
139 ok(wo_fd >= 0, "%s", strerror(errno));
141 if (wo_fd >= 0)
142 test_wo(wo_fd);
144 close(wo_fd);
146 rw_fd = open(DSPDEV, O_RDWR);
147 ok(rw_fd >= 0, "%s", strerror(errno));
149 if (rw_fd >= 0)
150 test_rw(rw_fd);
152 dspfd = rw_fd;
155 static void test_mixer(void)
157 int ret;
158 struct mixer_info info;
159 memset(&info, 0, sizeof(info));
161 ret = ioctl(mixerfd, SOUND_MIXER_INFO, &info);
162 ok(ret >= 0, "%s", strerror(errno));
163 if (ret >= 0) {
164 printf("Mixer id: %s\n", info.id);
165 printf("Name: %s\n", info.name);
169 static void test_trigger(int fd)
171 int ret, i;
173 ret = ioctl(fd, SNDCTL_DSP_GETTRIGGER, &i);
174 ok(ret == 0, "Returned error %s", strerror(errno));
175 ok(i == (PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT), "i is set to %d", i);
177 i = 0;
178 ret = ioctl(fd, SNDCTL_DSP_SETTRIGGER, &i);
179 ok(ret == 0, "Returned error %s", strerror(errno));
180 ok(i == 0, "Wrong i returned");
182 i = PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT;
183 ret = ioctl(fd, SNDCTL_DSP_SETTRIGGER, &i);
184 ok(ret == 0, "Returned error %s", strerror(errno));
185 ok(i == (PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT), "i has value %d", i);
187 ret = ioctl(fd, SNDCTL_DSP_POST, NULL);
188 ok(ret == 0, "Returned error %s", strerror(errno));
191 static void test_mmap(int fd)
193 char *area;
194 int ret;
195 char buf[24];
197 area = mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
198 ok(area != MAP_FAILED, "Failed to map: %s\n", strerror(errno));
200 if (area == MAP_FAILED)
201 return;
203 ret = write(fd, &buf, sizeof(buf));
204 ok(ret == -1, "write after mmap returned %i\n", ret);
205 if (ret == -1)
206 ok(errno == ENXIO, "Error returned is %s\n", strerror(errno));
208 munmap(area, 8192);
211 static void test_notify(int fd)
213 struct audio_buf_info bi;
214 char *bytes = NULL;
215 int ret, written;
216 struct pollfd pfd = { fd, POLLOUT };
217 int rounds = 20;
219 ioctl(fd, SNDCTL_DSP_GETOSPACE, &bi);
221 bytes = calloc(1, bi.fragsize);
222 written = 0;
223 ok(0, "Fragsize: %i, bytes: %i\n", bi.fragsize, bi.bytes);
224 while (written + bi.fragsize - 1 < bi.bytes)
226 ret = write(fd, bytes, bi.fragsize);
227 ok(ret == bi.fragsize, "Returned: %i instead of %i\n",
228 ret, bi.fragsize);
229 if (ret > 0)
230 written += ret;
233 while (rounds--)
235 ret = poll(&pfd, 1, -1);
236 ok(ret > 0, "Poll returned %i\n", ret);
237 if (ret < 0)
238 break;
239 ret = write(fd, bytes, bi.fragsize);
240 if (ret < 0) ret = -errno;
241 ok(ret == bi.fragsize, "Returned: %i instead of %i\n",
242 ret, bi.fragsize);
246 int main()
248 test_open();
249 if (mixerfd >= 0)
250 test_mixer();
252 if (reopen(1) >= 0)
253 test_trigger(dspfd);
255 if (reopen(0) >= 0)
256 test_notify(dspfd);
258 if (reopen(1) >= 0)
259 test_mmap(dspfd);
261 close(mixerfd);
262 close(dspfd);
263 printf("Tests: %d errors %d success\n", errors, success);
264 return errors > 127 ? 127 : errors;