xref: /netbsd-src/tests/lib/libossaudio/t_ossaudio.c (revision 7424242ff3b32704375257eccfd8d7cefb35a470)
1d00c08ecSnia /*-
2d00c08ecSnia  * Copyright (c) 2020 The NetBSD Foundation, Inc.
3d00c08ecSnia  * All rights reserved.
4d00c08ecSnia  *
5d00c08ecSnia  * This code is derived from software contributed to The NetBSD Foundation
6d00c08ecSnia  * by Nia Alarie.
7d00c08ecSnia  *
8d00c08ecSnia  * Redistribution and use in source and binary forms, with or without
9d00c08ecSnia  * modification, are permitted provided that the following conditions
10d00c08ecSnia  * are met:
11d00c08ecSnia  * 1. Redistributions of source code must retain the above copyright
12d00c08ecSnia  *    notice, this list of conditions and the following disclaimer.
13d00c08ecSnia  * 2. Redistributions in binary form must reproduce the above copyright
14d00c08ecSnia  *    notice, this list of conditions and the following disclaimer in the
15d00c08ecSnia  *    documentation and/or other materials provided with the distribution.
16d00c08ecSnia  *
17d00c08ecSnia  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18d00c08ecSnia  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19d00c08ecSnia  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20d00c08ecSnia  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21d00c08ecSnia  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22d00c08ecSnia  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23d00c08ecSnia  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24d00c08ecSnia  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25d00c08ecSnia  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26d00c08ecSnia  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27d00c08ecSnia  * POSSIBILITY OF SUCH DAMAGE.
28d00c08ecSnia  */
29d00c08ecSnia 
30d00c08ecSnia #include <sys/audioio.h>
31d00c08ecSnia #include <soundcard.h>
32d00c08ecSnia #include <fcntl.h>
33d00c08ecSnia #include <stdbool.h>
34d00c08ecSnia #include <stdio.h>
35d00c08ecSnia #include <math.h>
36d00c08ecSnia #include <atf-c.h>
37d00c08ecSnia 
38d00c08ecSnia ATF_TC(oss_dsp_init);
ATF_TC_HEAD(oss_dsp_init,tc)39d00c08ecSnia ATF_TC_HEAD(oss_dsp_init, tc)
40d00c08ecSnia {
41d00c08ecSnia 	atf_tc_set_md_var(tc, "descr", "Tests dsp init ioctls");
42d00c08ecSnia }
43d00c08ecSnia 
ATF_TC_BODY(oss_dsp_init,tc)44d00c08ecSnia ATF_TC_BODY(oss_dsp_init, tc)
45d00c08ecSnia {
46d00c08ecSnia 	struct audio_info hwinfo;
47d00c08ecSnia 	struct audio_info info;
48d00c08ecSnia 	int fd, channels, fmt, rate;
49d00c08ecSnia 
50d00c08ecSnia 	if ((fd = open("/dev/audio", O_WRONLY)) == -1)
51d00c08ecSnia 		atf_tc_skip("Audio device unavailable for playback");
52d00c08ecSnia 
53d00c08ecSnia 	if (ioctl(fd, AUDIO_GETFORMAT, &hwinfo) < 0) {
54a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETFORMAT failed");
55d00c08ecSnia 		close(fd);
56d00c08ecSnia 	}
57d00c08ecSnia 
58d00c08ecSnia 	/* Verify SNDCTL_DSP_CHANNELS sets the device to mono. */
59d00c08ecSnia 
60d00c08ecSnia 	channels = 1;
61d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) < 0)
62a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_CHANNELS (1) failed");
63d00c08ecSnia 	ATF_REQUIRE_EQ(channels, 1);
64d00c08ecSnia 
65d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
66a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
67d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.channels, 1);
68d00c08ecSnia 
69d00c08ecSnia 	/* Verify SNDCTL_DSP_CHANNELS sets the device to stereo. */
70d00c08ecSnia 
71d00c08ecSnia 	channels = 2;
72d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) < 0)
73a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_CHANNELS (2) failed");
74d00c08ecSnia 	ATF_REQUIRE_EQ(channels, 2);
75d00c08ecSnia 
76d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
77a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
78d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.channels, 2);
79d00c08ecSnia 
80d00c08ecSnia 	/*
81d00c08ecSnia 	 * Verify an invalid argument to SNDCTL_DSP_CHANNELS leaves the device
82d00c08ecSnia 	 * at the hardware channel count.
83d00c08ecSnia 	 */
84d00c08ecSnia 
85d00c08ecSnia 	channels = 0;
86d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) < 0)
87a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_CHANNELS (0) failed");
88d00c08ecSnia 	ATF_REQUIRE_EQ(channels, (int)hwinfo.play.channels);
89d00c08ecSnia 
90d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
91a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
92d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.channels, hwinfo.play.channels);
93d00c08ecSnia 
94d00c08ecSnia 	/*
95d00c08ecSnia 	 * SNDCTL_DSP_STEREO is an older alternative to SNDCTL_DSP_CHANNELS
96d00c08ecSnia 	 * that simply takes a boolean argument.
97d00c08ecSnia 	 */
98d00c08ecSnia 
99d00c08ecSnia 	/* Set the device to mono with SNDCTL_DSP_STEREO = 0 */
100d00c08ecSnia 
101d00c08ecSnia 	channels = 0;
102d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_STEREO, &channels) < 0)
103a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_STEREO (0) failed");
104d00c08ecSnia 	ATF_REQUIRE_EQ(channels, 0);
105d00c08ecSnia 
106d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
107a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
108d00c08ecSnia 
109d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.channels, 1);
110d00c08ecSnia 
111d00c08ecSnia 	/* Set the device to stereo with SNDCTL_DSP_STEREO = 1 */
112d00c08ecSnia 
113d00c08ecSnia 	channels = 1;
114d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_STEREO, &channels) < 0)
115a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_STEREO (1) failed");
116d00c08ecSnia 	ATF_REQUIRE_EQ(channels, 1);
117d00c08ecSnia 
118d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
119a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
120d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.channels, 2);
121d00c08ecSnia 
122d00c08ecSnia 	/* Verify SNDCTL_DSP_SETFMT works with common audio formats */
123d00c08ecSnia 
124d00c08ecSnia 	fmt = AFMT_MU_LAW;
125d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
126a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SETFMT (AFMT_MU_LAW) failed");
127d00c08ecSnia 	ATF_REQUIRE_EQ(fmt, AFMT_MU_LAW);
128d00c08ecSnia 
129d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
130a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
131d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.encoding, AUDIO_ENCODING_ULAW);
132d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.precision, 8);
133d00c08ecSnia 
134d00c08ecSnia 	fmt = AFMT_A_LAW;
135d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
136a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SETFMT (AFMT_A_LAW) failed");
137d00c08ecSnia 	ATF_REQUIRE_EQ(fmt, AFMT_A_LAW);
138d00c08ecSnia 
139d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
140a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
141d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.encoding, AUDIO_ENCODING_ALAW);
142d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.precision, 8);
143d00c08ecSnia 
144d00c08ecSnia 	fmt = AFMT_S16_LE;
145d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
146a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SETFMT (AFMT_S16_LE) failed");
147d00c08ecSnia 	ATF_REQUIRE_EQ(fmt, AFMT_S16_LE);
148d00c08ecSnia 
149d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
150a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
151d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.encoding, AUDIO_ENCODING_SLINEAR_LE);
152d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.precision, 16);
153d00c08ecSnia 
154d00c08ecSnia 	fmt = AFMT_S16_BE;
155d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
156a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SETFMT (AFMT_S16_BE) failed");
157d00c08ecSnia 	ATF_REQUIRE_EQ(fmt, AFMT_S16_BE);
158d00c08ecSnia 
159d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
160a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
161d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.encoding, AUDIO_ENCODING_SLINEAR_BE);
162d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.precision, 16);
163d00c08ecSnia 
164d00c08ecSnia 	fmt = AFMT_U16_LE;
165d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
166a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SETFMT (AFMT_U16_LE) failed");
167d00c08ecSnia 	ATF_REQUIRE_EQ(fmt, AFMT_U16_LE);
168d00c08ecSnia 
169d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
170a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
171d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.encoding, AUDIO_ENCODING_ULINEAR_LE);
172d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.precision, 16);
173d00c08ecSnia 
174d00c08ecSnia 	fmt = AFMT_U16_BE;
175d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
176a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SETFMT (AFMT_U16_BE) failed");
177d00c08ecSnia 	ATF_REQUIRE_EQ(fmt, AFMT_U16_BE);
178d00c08ecSnia 
179d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
180a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
181d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.encoding, AUDIO_ENCODING_ULINEAR_BE);
182d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.precision, 16);
183d00c08ecSnia 
184d00c08ecSnia 	fmt = AFMT_S32_LE;
185d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
186a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SETFMT (AFMT_S32_LE) failed");
187d00c08ecSnia 	ATF_REQUIRE_EQ(fmt, AFMT_S32_LE);
188d00c08ecSnia 
189d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
190a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
191d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.encoding, AUDIO_ENCODING_SLINEAR_LE);
192d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.precision, 32);
193d00c08ecSnia 
194d00c08ecSnia 	/* Verify some supported sample rates. */
195d00c08ecSnia 
196d00c08ecSnia 	rate = 8000;
197d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SPEED, &rate) < 0)
198a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SPEED (8000) failed");
199d00c08ecSnia 
200d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
201a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
202d00c08ecSnia 	ATF_REQUIRE_EQ(rate, (int)info.play.sample_rate);
203d00c08ecSnia 
204d00c08ecSnia 	rate = 32000;
205d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SPEED, &rate) < 0)
206a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SPEED (32000) failed");
207d00c08ecSnia 
208d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
209a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
210d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.sample_rate, 32000);
211d00c08ecSnia 	ATF_REQUIRE_EQ(rate, (int)info.play.sample_rate);
212d00c08ecSnia 
213d00c08ecSnia 	rate = 44100;
214d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SPEED, &rate) < 0)
215a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SPEED (44100) failed");
216d00c08ecSnia 
217d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
218a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
219d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.sample_rate, 44100);
220d00c08ecSnia 	ATF_REQUIRE_EQ(rate, (int)info.play.sample_rate);
221d00c08ecSnia 
222d00c08ecSnia 	rate = 48000;
223d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SPEED, &rate) < 0)
224a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SPEED (48000) failed");
225d00c08ecSnia 
226d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
227a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
228d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.sample_rate, 48000);
229d00c08ecSnia 	ATF_REQUIRE_EQ(rate, (int)info.play.sample_rate);
230d00c08ecSnia 
231d00c08ecSnia 	rate = 96000;
232d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SPEED, &rate) < 0)
233a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SPEED (96000) failed");
234d00c08ecSnia 
235d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
236a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
237d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.sample_rate, 96000);
238d00c08ecSnia 	ATF_REQUIRE_EQ(rate, (int)info.play.sample_rate);
239d00c08ecSnia 
240d00c08ecSnia 	rate = 192000;
241d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SPEED, &rate) < 0)
242a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SPEED (192000) failed");
243d00c08ecSnia 
244d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
245a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
246d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.sample_rate, 192000);
247d00c08ecSnia 	ATF_REQUIRE_EQ(rate, (int)info.play.sample_rate);
248d00c08ecSnia 
249d00c08ecSnia 	/*
250d00c08ecSnia 	 * and some unsupported sample rates... "best effort"
251d00c08ecSnia 	 */
252d00c08ecSnia 
253*7424242fSandvar 	/* closest supported rate is 1000 */
254d00c08ecSnia 	rate = 900;
255d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SPEED, &rate) < 0)
256a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SPEED (900) failed");
257d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
258a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
259d00c08ecSnia 	ATF_REQUIRE((fabs(900.0 - info.play.sample_rate) / 900.0) < 0.2);
260d00c08ecSnia 	ATF_REQUIRE_EQ(rate, (int)info.play.sample_rate);
261d00c08ecSnia 
262*7424242fSandvar 	/* closest supported rate is 192000 */
263d00c08ecSnia 	rate = 197000;
264d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SPEED, &rate) < 0)
265a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SPEED (197000) failed");
266d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
267a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
268d00c08ecSnia 	ATF_REQUIRE((fabs(197000.0 - info.play.sample_rate) / 197000.0) < 0.2);
269d00c08ecSnia 	ATF_REQUIRE_EQ(rate, (int)info.play.sample_rate);
270d00c08ecSnia 
271d00c08ecSnia 	/* 0 should return the hardware rate. */
272d00c08ecSnia 
273d00c08ecSnia 	rate = 0;
274d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SPEED, &rate) < 0)
275a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SPEED (0) failed");
276d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
277a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
278d00c08ecSnia 	ATF_REQUIRE_EQ(hwinfo.play.sample_rate, info.play.sample_rate);
279d00c08ecSnia 
280d00c08ecSnia 	close(fd);
281d00c08ecSnia }
282d00c08ecSnia 
283d00c08ecSnia ATF_TC(oss_dsp_trigger_read);
ATF_TC_HEAD(oss_dsp_trigger_read,tc)284d00c08ecSnia ATF_TC_HEAD(oss_dsp_trigger_read, tc)
285d00c08ecSnia {
286d00c08ecSnia 	atf_tc_set_md_var(tc, "descr", "Tests SNDCTL_DSP_SETTRIGGER correctly "
287d00c08ecSnia 	    "changes the recording pause state");
288d00c08ecSnia }
289d00c08ecSnia 
ATF_TC_BODY(oss_dsp_trigger_read,tc)290d00c08ecSnia ATF_TC_BODY(oss_dsp_trigger_read, tc)
291d00c08ecSnia {
292d00c08ecSnia 	struct audio_info info;
293d00c08ecSnia 	int fd, bits;
294d00c08ecSnia 
2952e0ec785Sgson #if defined(__sparc__)
2962e0ec785Sgson 	atf_tc_skip("PR port-sparc/55876");
2972e0ec785Sgson #endif
2982e0ec785Sgson 
299d00c08ecSnia 	if ((fd = open("/dev/audio", O_RDONLY)) == -1)
300d00c08ecSnia 		atf_tc_skip("Audio device unavailable for recording");
301d00c08ecSnia 
302d00c08ecSnia 	/* pause everything ... */
303d00c08ecSnia 
304d00c08ecSnia 	bits = 0;
305d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SETTRIGGER, &bits) < 0)
306a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SETTRIGGER (0) failed");
307d00c08ecSnia 
308d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_GETTRIGGER, &bits) < 0)
309a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_GETTRIGGER failed");
310d00c08ecSnia 	ATF_REQUIRE_EQ(bits, 0);
311d00c08ecSnia 
312d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
313a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
314d00c08ecSnia 
315d00c08ecSnia 	ATF_REQUIRE_EQ(info.record.pause, 1);
316d00c08ecSnia 
317d00c08ecSnia 	/* unpause everything ... */
318d00c08ecSnia 
319d00c08ecSnia 	bits = PCM_ENABLE_INPUT;
320d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SETTRIGGER, &bits) < 0)
321a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SETTRIGGER "
322a26ac9a7Snia 		    "(PCM_ENABLE_INPUT) failed");
323d00c08ecSnia 
324d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_GETTRIGGER, &bits) < 0)
325a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_GETTRIGGER failed");
326d00c08ecSnia 	ATF_REQUIRE_EQ(bits, PCM_ENABLE_INPUT);
327d00c08ecSnia 
328d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
329a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
330d00c08ecSnia 
331d00c08ecSnia 	ATF_REQUIRE_EQ(info.record.pause, 0);
332d00c08ecSnia 
333d00c08ecSnia 	close(fd);
334d00c08ecSnia }
335d00c08ecSnia 
336d00c08ecSnia ATF_TC(oss_dsp_trigger_write);
ATF_TC_HEAD(oss_dsp_trigger_write,tc)337d00c08ecSnia ATF_TC_HEAD(oss_dsp_trigger_write, tc)
338d00c08ecSnia {
339d00c08ecSnia 	atf_tc_set_md_var(tc, "descr", "Tests SNDCTL_DSP_SETTRIGGER correctly "
340d00c08ecSnia 	    "changes the playback pause state");
341d00c08ecSnia }
342d00c08ecSnia 
ATF_TC_BODY(oss_dsp_trigger_write,tc)343d00c08ecSnia ATF_TC_BODY(oss_dsp_trigger_write, tc)
344d00c08ecSnia {
345d00c08ecSnia 	struct audio_info info;
346d00c08ecSnia 	int fd, bits;
347d00c08ecSnia 
348d00c08ecSnia 	if ((fd = open("/dev/audio", O_WRONLY)) == -1)
349d00c08ecSnia 		atf_tc_skip("Audio device unavailable for playback");
350d00c08ecSnia 
351d00c08ecSnia 	/* pause everything ... */
352d00c08ecSnia 
353d00c08ecSnia 	bits = 0;
354d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SETTRIGGER, &bits) < 0)
355a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SETTRIGGER (0) failed");
356d00c08ecSnia 
357d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_GETTRIGGER, &bits) < 0)
358a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_GETTRIGGER failed");
359d00c08ecSnia 	ATF_REQUIRE_EQ(bits, 0);
360d00c08ecSnia 
361d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
362a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
363d00c08ecSnia 
364d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.pause, 1);
365d00c08ecSnia 
366d00c08ecSnia 	/* unpause everything ... */
367d00c08ecSnia 
368d00c08ecSnia 	bits = PCM_ENABLE_OUTPUT;
369d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_SETTRIGGER, &bits) < 0)
370a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_SETTRIGGER "
371a26ac9a7Snia 		    "(PCM_ENABLE_OUTPUT) failed");
372d00c08ecSnia 
373d00c08ecSnia 	if (ioctl(fd, SNDCTL_DSP_GETTRIGGER, &bits) < 0)
374a26ac9a7Snia 		atf_tc_fail("ioctl SNDCTL_DSP_GETTRIGGER failed");
375d00c08ecSnia 	ATF_REQUIRE_EQ(bits, PCM_ENABLE_OUTPUT);
376d00c08ecSnia 
377d00c08ecSnia 	if (ioctl(fd, AUDIO_GETBUFINFO, &info) < 0)
378a26ac9a7Snia 		atf_tc_fail("ioctl AUDIO_GETBUFINFO failed");
379d00c08ecSnia 
380d00c08ecSnia 	ATF_REQUIRE_EQ(info.play.pause, 0);
381d00c08ecSnia 
382d00c08ecSnia 	close(fd);
383d00c08ecSnia }
384d00c08ecSnia 
385d00c08ecSnia ATF_TC(oss_dsp_caps);
ATF_TC_HEAD(oss_dsp_caps,tc)386d00c08ecSnia ATF_TC_HEAD(oss_dsp_caps, tc)
387d00c08ecSnia {
388a26ac9a7Snia 	atf_tc_set_md_var(tc, "descr", "Verifies that OSS device capabilities "
389a26ac9a7Snia 	    "are the same as native capabilities");
390d00c08ecSnia }
391d00c08ecSnia 
ATF_TC_BODY(oss_dsp_caps,tc)392d00c08ecSnia ATF_TC_BODY(oss_dsp_caps, tc)
393d00c08ecSnia {
394d00c08ecSnia 	unsigned i;
395d00c08ecSnia 	char dev[16];
396d00c08ecSnia 	bool dev_tested = false;
397d00c08ecSnia 	int fd;
398d00c08ecSnia 	int caps, props, fmts;
399d00c08ecSnia 
400d00c08ecSnia 	for (i = 0; i < 16; ++i) {
401d00c08ecSnia 		(void)snprintf(dev, sizeof(dev), "/dev/audio%u", i);
402d00c08ecSnia 
403d00c08ecSnia 		if ((fd = open(dev, O_WRONLY)) == -1) {
404d00c08ecSnia 			if ((fd = open(dev, O_RDONLY)) == -1)
405d00c08ecSnia 				break;
406d00c08ecSnia 		}
407d00c08ecSnia 
408d00c08ecSnia 		if (ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) < 0)
409a26ac9a7Snia 			atf_tc_fail("ioctl SNDCTL_DSP_GETCAPS failed");
410d00c08ecSnia 
411d00c08ecSnia 		if (ioctl(fd, AUDIO_GETPROPS, &props) < 0)
412a26ac9a7Snia 			atf_tc_fail("ioctl AUDIO_GETPROPS failed");
413d00c08ecSnia 
414d00c08ecSnia 		ATF_REQUIRE(!(caps & DSP_CAP_DUPLEX) ==
415d00c08ecSnia 		    !(props & AUDIO_PROP_FULLDUPLEX));
416d00c08ecSnia 
417d00c08ecSnia 		ATF_REQUIRE(!(caps & DSP_CAP_MMAP) ==
418d00c08ecSnia 		    !(props & AUDIO_PROP_MMAP));
419d00c08ecSnia 
420d00c08ecSnia 		ATF_REQUIRE(!(caps & DSP_CAP_INPUT) ==
421d00c08ecSnia 		    !(props & AUDIO_PROP_CAPTURE));
422d00c08ecSnia 
423d00c08ecSnia 		ATF_REQUIRE(!(caps & DSP_CAP_OUTPUT) ==
424d00c08ecSnia 		    !(props & AUDIO_PROP_PLAYBACK));
425d00c08ecSnia 
426d00c08ecSnia 		/* Trigger is always supported in this implementation. */
427d00c08ecSnia 		ATF_REQUIRE(caps & DSP_CAP_TRIGGER);
428d00c08ecSnia 
429d00c08ecSnia 		if (ioctl(fd, SNDCTL_DSP_GETFMTS, &fmts) < 0)
430a26ac9a7Snia 			atf_tc_fail("ioctl SNDCTL_DSP_GETFMTS failed");
431d00c08ecSnia 
432d00c08ecSnia 		/* All supported by the kernel mixer. */
433d00c08ecSnia 		ATF_REQUIRE(fmts & AFMT_MU_LAW);
434d00c08ecSnia 		ATF_REQUIRE(fmts & AFMT_A_LAW);
435d00c08ecSnia 		ATF_REQUIRE(fmts & AFMT_S8);
436d00c08ecSnia 		ATF_REQUIRE(fmts & AFMT_U8);
437d00c08ecSnia 		ATF_REQUIRE(fmts & AFMT_S16_LE);
438d00c08ecSnia 		ATF_REQUIRE(fmts & AFMT_S16_BE);
439d00c08ecSnia 		ATF_REQUIRE(fmts & AFMT_U16_LE);
440d00c08ecSnia 		ATF_REQUIRE(fmts & AFMT_U16_BE);
441d00c08ecSnia 		ATF_REQUIRE(fmts & AFMT_S32_LE);
442d00c08ecSnia 		ATF_REQUIRE(fmts & AFMT_S32_BE);
443d00c08ecSnia 
444d00c08ecSnia 		/* Sanity test... */
445d00c08ecSnia 		ATF_REQUIRE_EQ(fmts & AFMT_MPEG, 0);
446d00c08ecSnia 
447d00c08ecSnia 		close(fd);
448d00c08ecSnia 
449d00c08ecSnia 		dev_tested = true;
450d00c08ecSnia 	}
451d00c08ecSnia 
452d00c08ecSnia 	if (!dev_tested)
453d00c08ecSnia 		atf_tc_skip("No testable audio device available");
454d00c08ecSnia }
455d00c08ecSnia 
ATF_TP_ADD_TCS(tp)456d00c08ecSnia ATF_TP_ADD_TCS(tp)
457d00c08ecSnia {
458d00c08ecSnia 	ATF_TP_ADD_TC(tp, oss_dsp_init);
459d00c08ecSnia 	ATF_TP_ADD_TC(tp, oss_dsp_caps);
460d00c08ecSnia 	ATF_TP_ADD_TC(tp, oss_dsp_trigger_read);
461d00c08ecSnia 	ATF_TP_ADD_TC(tp, oss_dsp_trigger_write);
462d00c08ecSnia 
463d00c08ecSnia 	return atf_no_error();
464d00c08ecSnia }
465d00c08ecSnia 
466