xref: /netbsd/tests/dev/audio/audiotest.c (revision 393145cf)
1 /*	$NetBSD: audiotest.c,v 1.30 2023/06/24 05:27:13 msaitoh Exp $	*/
2 
3 /*
4  * Copyright (C) 2019 Tetsuya Isaki. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 __RCSID("$NetBSD: audiotest.c,v 1.30 2023/06/24 05:27:13 msaitoh Exp $");
30 
31 #include <errno.h>
32 #include <fcntl.h>
33 #define __STDC_FORMAT_MACROS	/* for PRIx64 */
34 #include <inttypes.h>
35 #include <pthread.h>
36 #include <stdarg.h>
37 #include <stdbool.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42 #include <util.h>
43 #include <sys/audioio.h>
44 #include <sys/event.h>
45 #include <sys/ioctl.h>
46 #include <sys/mman.h>
47 #include <sys/poll.h>
48 #include <sys/sysctl.h>
49 #include <sys/time.h>
50 #include <sys/wait.h>
51 #if !defined(NO_RUMP)
52 #include <rump/rump.h>
53 #include <rump/rump_syscalls.h>
54 #endif
55 
56 /* this internal driver option is not exported to userland */
57 #define AUDIO_SUPPORT_LINEAR24
58 
59 #if !defined(AUDIO_ENCODING_SLINEAR_NE)
60 #if BYTE_ORDER == LITTLE_ENDIAN
61 #define AUDIO_ENCODING_SLINEAR_NE AUDIO_ENCODING_SLINEAR_LE
62 #define AUDIO_ENCODING_ULINEAR_NE AUDIO_ENCODING_ULINEAR_LE
63 #define AUDIO_ENCODING_SLINEAR_OE AUDIO_ENCODING_SLINEAR_BE
64 #define AUDIO_ENCODING_ULINEAR_OE AUDIO_ENCODING_ULINEAR_BE
65 #else
66 #define AUDIO_ENCODING_SLINEAR_NE AUDIO_ENCODING_SLINEAR_BE
67 #define AUDIO_ENCODING_ULINEAR_NE AUDIO_ENCODING_ULINEAR_BE
68 #define AUDIO_ENCODING_SLINEAR_OE AUDIO_ENCODING_SLINEAR_LE
69 #define AUDIO_ENCODING_ULINEAR_OE AUDIO_ENCODING_ULINEAR_LE
70 #endif
71 #endif
72 
73 struct testentry {
74 	const char *name;
75 	void (*func)(void);
76 };
77 
78 void usage(void) __dead;
79 void xp_err(int, int, const char *, ...) __printflike(3, 4) __dead;
80 void xp_errx(int, int, const char *, ...) __printflike(3, 4) __dead;
81 bool match(const char *, const char *);
82 void xxx_close_wait(void);
83 int mixer_get_outputs_master(int);
84 void do_test(int);
85 int rump_or_open(const char *, int);
86 int rump_or_write(int, const void *, size_t);
87 int rump_or_read(int, void *, size_t);
88 int rump_or_ioctl(int, u_long, void *);
89 int rump_or_close(int);
90 int rump_or_fcntl(int, int, ...);
91 int rump_or_poll(struct pollfd *, nfds_t, int);
92 int rump_or_kqueue(void);
93 int rump_or_kevent(int, const struct kevent *, size_t,
94 	struct kevent *, size_t, const struct timespec *);
95 int hw_canplay(void);
96 int hw_canrec(void);
97 int hw_bidir(void);
98 int hw_fulldup(void);
99 void init(int);
100 void *consumer_thread(void *);
101 void cleanup_audiofd(void);
102 void TEST(const char *, ...) __printflike(1, 2);
103 bool xp_fail(int, const char *, ...) __printflike(2, 3);
104 void xp_skip(int, const char *, ...) __printflike(2, 3);
105 bool xp_eq(int, int, int, const char *);
106 bool xp_eq_str(int, const char *, const char *, const char *);
107 bool xp_ne(int, int, int, const char *);
108 bool xp_if(int, bool, const char *);
109 bool xp_sys_eq(int, int, int, const char *);
110 bool xp_sys_ok(int, int, const char *);
111 bool xp_sys_ng(int, int, int, const char *);
112 bool xp_sys_ptr(int, int, void *, const char *);
113 int debug_open(int, const char *, int);
114 int debug_write(int, int, const void *, size_t);
115 int debug_read(int, int, void *, size_t);
116 int debug_ioctl(int, int, u_long, const char *, void *, const char *, ...)
117 	__printflike(6, 7);
118 int debug_fcntl(int, int, int, const char *, ...) __printflike(4, 5);
119 int debug_close(int, int);
120 void *debug_mmap(int, void *, size_t, int, int, int, off_t);
121 int debug_munmap(int, void *, int);
122 const char *event_tostr(int);
123 int debug_poll(int, struct pollfd *, int, int);
124 int debug_kqueue(int);
125 int debug_kevent_set(int, int, const struct kevent *, size_t);
126 int debug_kevent_poll(int, int, struct kevent *, size_t,
127 	const struct timespec *);
128 void debug_kev(int, const char *, const struct kevent *);
129 uid_t debug_getuid(int);
130 int debug_seteuid(int, uid_t);
131 int debug_sysctlbyname(int, const char *, void *, size_t *, const void *,
132 	size_t);
133 
134 int openable_mode(void);
135 int mode2aumode(int);
136 int mode2play(int);
137 int mode2rec(int);
138 void reset_after_mmap(void);
139 
140 /* from audio.c */
141 static const char *encoding_names[] __unused = {
142 	"none",
143 	AudioEmulaw,
144 	AudioEalaw,
145 	"pcm16",
146 	"pcm8",
147 	AudioEadpcm,
148 	AudioEslinear_le,
149 	AudioEslinear_be,
150 	AudioEulinear_le,
151 	AudioEulinear_be,
152 	AudioEslinear,
153 	AudioEulinear,
154 	AudioEmpeg_l1_stream,
155 	AudioEmpeg_l1_packets,
156 	AudioEmpeg_l1_system,
157 	AudioEmpeg_l2_stream,
158 	AudioEmpeg_l2_packets,
159 	AudioEmpeg_l2_system,
160 	AudioEac3,
161 };
162 
163 int debug;
164 int props;
165 int hwfull;
166 int netbsd;
167 bool opt_atf;
168 char testname[64];
169 int testcount;
170 int failcount;
171 int skipcount;
172 int unit;
173 bool use_rump;
174 bool use_pad;
175 bool exact_match;
176 int padfd;
177 int maxfd;
178 pthread_t th;
179 char devicename[16];	/* "audioN" */
180 char devaudio[16];	/* "/dev/audioN" */
181 char devsound[16];	/* "/dev/soundN" */
182 char devaudioctl[16];	/* "/dev/audioctlN" */
183 char devmixer[16];	/* "/dev/mixerN" */
184 extern struct testentry testtable[];
185 
186 void
usage(void)187 usage(void)
188 {
189 	fprintf(stderr, "usage:\t%s [<options>] [<testname>...]\n",
190 	    getprogname());
191 	fprintf(stderr, "\t-A        : make output suitable for ATF\n");
192 	fprintf(stderr, "\t-a        : Test all\n");
193 	fprintf(stderr, "\t-d        : Increase debug level\n");
194 	fprintf(stderr, "\t-e        : Use exact match for testnames "
195 	    "(default is forward match)\n");
196 	fprintf(stderr, "\t-l        : List all tests\n");
197 	fprintf(stderr, "\t-p        : Open pad\n");
198 #if !defined(NO_RUMP)
199 	fprintf(stderr, "\t-R        : Use rump (implies -p)\n");
200 #endif
201 	fprintf(stderr, "\t-u <unit> : Use audio<unit> (default:0)\n");
202 	exit(1);
203 }
204 
205 /* Customized err(3) */
206 void
xp_err(int code,int line,const char * fmt,...)207 xp_err(int code, int line, const char *fmt, ...)
208 {
209 	va_list ap;
210 	int backup_errno;
211 
212 	backup_errno = errno;
213 	printf("%s %d: ", (opt_atf ? "Line" : " ERROR:"), line);
214 	va_start(ap, fmt);
215 	vprintf(fmt, ap);
216 	va_end(ap);
217 	printf(": %s\n", strerror(backup_errno));
218 
219 	exit(code);
220 }
221 
222 /* Customized errx(3) */
223 void
xp_errx(int code,int line,const char * fmt,...)224 xp_errx(int code, int line, const char *fmt, ...)
225 {
226 	va_list ap;
227 
228 	printf("%s %d: ", (opt_atf ? "Line" : " ERROR:"), line);
229 	va_start(ap, fmt);
230 	vprintf(fmt, ap);
231 	va_end(ap);
232 	printf("\n");
233 
234 	exit(code);
235 }
236 
237 int
main(int argc,char * argv[])238 main(int argc, char *argv[])
239 {
240 	int i;
241 	int j;
242 	int c;
243 	enum {
244 		CMD_TEST,
245 		CMD_ALL,
246 		CMD_LIST,
247 	} cmd;
248 	bool found;
249 
250 	props = -1;
251 	hwfull = 0;
252 	unit = 0;
253 	cmd = CMD_TEST;
254 	use_pad = false;
255 	padfd = -1;
256 	exact_match = false;
257 
258 	while ((c = getopt(argc, argv, "AadelpRu:")) != -1) {
259 		switch (c) {
260 		case 'A':
261 			opt_atf = true;
262 			break;
263 		case 'a':
264 			cmd = CMD_ALL;
265 			break;
266 		case 'd':
267 			debug++;
268 			break;
269 		case 'e':
270 			exact_match = true;
271 			break;
272 		case 'l':
273 			cmd = CMD_LIST;
274 			break;
275 		case 'p':
276 			use_pad = true;
277 			break;
278 		case 'R':
279 #if !defined(NO_RUMP)
280 			use_rump = true;
281 			use_pad = true;
282 #else
283 			usage();
284 #endif
285 			break;
286 		case 'u':
287 			unit = atoi(optarg);
288 			break;
289 		default:
290 			usage();
291 		}
292 	}
293 	argc -= optind;
294 	argv += optind;
295 
296 	if (cmd == CMD_LIST) {
297 		/* List all */
298 		for (i = 0; testtable[i].name != NULL; i++)
299 			printf("%s\n", testtable[i].name);
300 		return 0;
301 	}
302 
303 	init(unit);
304 
305 	if (cmd == CMD_ALL) {
306 		/* Test all */
307 		if (argc > 0)
308 			usage();
309 		for (i = 0; testtable[i].name != NULL; i++)
310 			do_test(i);
311 	} else {
312 		/* Test only matched */
313 		if (argc == 0)
314 			usage();
315 
316 		found = false;
317 		for (j = 0; j < argc; j++) {
318 			for (i = 0; testtable[i].name != NULL; i++) {
319 				if (match(argv[j], testtable[i].name)) {
320 					do_test(i);
321 					found = true;
322 				}
323 			}
324 		}
325 		if (!found) {
326 			printf("test not found\n");
327 			exit(1);
328 		}
329 	}
330 
331 	if (opt_atf == false) {
332 		printf("Result: %d tests, %d success",
333 		    testcount,
334 		    testcount - failcount - skipcount);
335 		if (failcount > 0)
336 			printf(", %d failed", failcount);
337 		if (skipcount > 0)
338 			printf(", %d skipped", skipcount);
339 		printf("\n");
340 	}
341 
342 	if (skipcount > 0)
343 		return 2;
344 	if (failcount > 0)
345 		return 1;
346 
347 	return 0;
348 }
349 
350 bool
match(const char * arg,const char * name)351 match(const char *arg, const char *name)
352 {
353 	if (exact_match) {
354 		/* Exact match */
355 		if (strcmp(arg, name) == 0)
356 			return true;
357 	} else {
358 		/* Forward match */
359 		if (strncmp(arg, name, strlen(arg)) == 0)
360 			return true;
361 	}
362 	return false;
363 }
364 
365 /*
366  * XXX
367  * Some hardware drivers (e.g. hdafg(4)) require a little "rest" between
368  * close(2) and re-open(2).
369  * audio(4) uses hw_if->close() to tell the hardware to close.  However,
370  * there is no agreement to wait for completion between MI and MD layer.
371  * audio(4) immediately shifts the "closed" state, and that is, the next
372  * open() will be acceptable immediately in audio layer.  But the real
373  * hardware may not have been closed actually at that point.
374  * It's troublesome issue but should be fixed...
375  *
376  * However, the most frequently used pad(4) (for ATF tests) doesn't have
377  * such problem, so avoids it to reduce time.
378  */
379 void
xxx_close_wait(void)380 xxx_close_wait(void)
381 {
382 
383 	if (!use_pad)
384 		usleep(500 * 1000);
385 }
386 
387 void
do_test(int testnumber)388 do_test(int testnumber)
389 {
390 	/* Sentinel */
391 	strlcpy(testname, "<NoName>", sizeof(testname));
392 	/* Do test */
393 	testtable[testnumber].func();
394 
395 	cleanup_audiofd();
396 	xxx_close_wait();
397 }
398 
399 /*
400  * system call wrappers for rump.
401  */
402 
403 /* open(2) or rump_sys_open(3) */
404 int
rump_or_open(const char * filename,int flag)405 rump_or_open(const char *filename, int flag)
406 {
407 	int r;
408 
409 #if !defined(NO_RUMP)
410 	if (use_rump)
411 		r = rump_sys_open(filename, flag);
412 	else
413 #endif
414 		r = open(filename, flag);
415 
416 	if (r > maxfd)
417 		maxfd = r;
418 	return r;
419 }
420 
421 /* write(2) or rump_sys_write(3) */
422 int
rump_or_write(int fd,const void * buf,size_t len)423 rump_or_write(int fd, const void *buf, size_t len)
424 {
425 	int r;
426 
427 #if !defined(NO_RUMP)
428 	if (use_rump)
429 		r = rump_sys_write(fd, buf, len);
430 	else
431 #endif
432 		r = write(fd, buf, len);
433 	return r;
434 }
435 
436 /* read(2) or rump_sys_read(3) */
437 int
rump_or_read(int fd,void * buf,size_t len)438 rump_or_read(int fd, void *buf, size_t len)
439 {
440 	int r;
441 
442 #if !defined(NO_RUMP)
443 	if (use_rump)
444 		r = rump_sys_read(fd, buf, len);
445 	else
446 #endif
447 		r = read(fd, buf, len);
448 	return r;
449 }
450 
451 /* ioctl(2) or rump_sys_ioctl(3) */
452 int
rump_or_ioctl(int fd,u_long cmd,void * arg)453 rump_or_ioctl(int fd, u_long cmd, void *arg)
454 {
455 	int r;
456 
457 #if !defined(NO_RUMP)
458 	if (use_rump)
459 		r = rump_sys_ioctl(fd, cmd, arg);
460 	else
461 #endif
462 		r = ioctl(fd, cmd, arg);
463 	return r;
464 }
465 
466 /* close(2) or rump_sys_close(3) */
467 int
rump_or_close(int fd)468 rump_or_close(int fd)
469 {
470 	int r;
471 
472 #if !defined(NO_RUMP)
473 	if (use_rump)
474 		r = rump_sys_close(fd);
475 	else
476 #endif
477 		r = close(fd);
478 
479 	/* maxfd-1 may not valid fd but no matter */
480 	if (fd == maxfd)
481 		maxfd--;
482 	return r;
483 }
484 
485 /* fcntl(2) or rump_sys_fcntl(3) */
486 /* XXX Supported only with no arguments for now */
487 int
rump_or_fcntl(int fd,int cmd,...)488 rump_or_fcntl(int fd, int cmd, ...)
489 {
490 	int r;
491 
492 #if !defined(NO_RUMP)
493 	if (use_rump)
494 		r = rump_sys_fcntl(fd, cmd);
495 	else
496 #endif
497 		r = fcntl(fd, cmd);
498 	return r;
499 }
500 
501 /* poll(2) or rump_sys_poll(3) */
502 int
rump_or_poll(struct pollfd * fds,nfds_t nfds,int timeout)503 rump_or_poll(struct pollfd *fds, nfds_t nfds, int timeout)
504 {
505 	int r;
506 
507 #if !defined(NO_RUMP)
508 	if (use_rump)
509 		r = rump_sys_poll(fds, nfds, timeout);
510 	else
511 #endif
512 		r = poll(fds, nfds, timeout);
513 	return r;
514 }
515 
516 /* kqueue(2) or rump_sys_kqueue(3) */
517 int
rump_or_kqueue(void)518 rump_or_kqueue(void)
519 {
520 	int r;
521 
522 #if !defined(NO_RUMP)
523 	if (use_rump)
524 		r = rump_sys_kqueue();
525 	else
526 #endif
527 		r = kqueue();
528 	return r;
529 }
530 
531 /* kevent(2) or rump_sys_kevent(3) */
532 int
rump_or_kevent(int kq,const struct kevent * chlist,size_t nch,struct kevent * evlist,size_t nev,const struct timespec * timeout)533 rump_or_kevent(int kq, const struct kevent *chlist, size_t nch,
534 	struct kevent *evlist, size_t nev,
535 	const struct timespec *timeout)
536 {
537 	int r;
538 
539 #if !defined(NO_RUMP)
540 	if (use_rump)
541 		r = rump_sys_kevent(kq, chlist, nch, evlist, nev, timeout);
542 	else
543 #endif
544 		r = kevent(kq, chlist, nch, evlist, nev, timeout);
545 	return r;
546 }
547 
548 int
hw_canplay(void)549 hw_canplay(void)
550 {
551 	return (props & AUDIO_PROP_PLAYBACK) ? 1 : 0;
552 }
553 
554 int
hw_canrec(void)555 hw_canrec(void)
556 {
557 	return (props & AUDIO_PROP_CAPTURE) ? 1 : 0;
558 }
559 
560 int
hw_bidir(void)561 hw_bidir(void)
562 {
563 	return hw_canplay() & hw_canrec();
564 }
565 
566 int
hw_fulldup(void)567 hw_fulldup(void)
568 {
569 	return (props & AUDIO_PROP_FULLDUPLEX) ? 1 : 0;
570 }
571 
572 #define DPRINTF(fmt...) do {	\
573 	if (debug)		\
574 		printf(fmt);	\
575 } while (0)
576 
577 #define DPRINTFF(line, fmt...) do {		\
578 	if (debug) {				\
579 		printf("  > %d: ", line);	\
580 		DPRINTF(fmt);			\
581 		fflush(stdout);			\
582 	}					\
583 } while (0)
584 
585 #define DRESULT(r) do {				\
586 	int backup_errno = errno;		\
587 	if (r == -1) {				\
588 		DPRINTF(" = %d, err#%d %s\n",	\
589 		    r, backup_errno,		\
590 		    strerror(backup_errno));	\
591 	} else {				\
592 		DPRINTF(" = %d\n", r);		\
593 	}					\
594 	errno = backup_errno;			\
595 	return r;				\
596 } while (0)
597 
598 /* pointer variants for mmap */
599 #define DRESULT_PTR(r) do {			\
600 	int backup_errno = errno;		\
601 	if (r == (void *)-1) {			\
602 		DPRINTF(" = -1, err#%d %s\n",	\
603 		    backup_errno,		\
604 		    strerror(backup_errno));	\
605 	} else {				\
606 		DPRINTF(" = %p\n", r);		\
607 	}					\
608 	errno = backup_errno;			\
609 	return r;				\
610 } while (0)
611 
612 
613 /*
614  * requnit <  0: Use auto by pad (not implemented).
615  * requnit >= 0: Use audio<requnit>.
616  */
617 void
init(int requnit)618 init(int requnit)
619 {
620 	struct audio_device devinfo;
621 	size_t len;
622 	int rel;
623 	int fd;
624 	int r;
625 
626 	/* XXX */
627 	atexit(cleanup_audiofd);
628 
629 	if (requnit < 0) {
630 		xp_errx(1, __LINE__, "requnit < 0 not implemented.");
631 	} else {
632 		unit = requnit;
633 	}
634 
635 	/* Set device name */
636 	snprintf(devicename, sizeof(devicename), "audio%d", unit);
637 	snprintf(devaudio, sizeof(devaudio), "/dev/audio%d", unit);
638 	snprintf(devsound, sizeof(devsound), "/dev/sound%d", unit);
639 	snprintf(devaudioctl, sizeof(devaudioctl), "/dev/audioctl%d", unit);
640 	snprintf(devmixer, sizeof(devmixer), "/dev/mixer%d", unit);
641 
642 	/*
643 	 * version
644 	 * audio2 is merged in 8.99.39.
645 	 */
646 	len = sizeof(rel);
647 	r = sysctlbyname("kern.osrevision", &rel, &len, NULL, 0);
648 	if (r == -1)
649 		xp_err(1, __LINE__, "sysctl kern.osrevision");
650 	netbsd = rel / 100000000;
651 	if (rel >=  899003900)
652 		netbsd = 9;
653 
654 #if !defined(NO_RUMP)
655 	if (use_rump) {
656 		DPRINTF("  use rump\n");
657 		rump_init();
658 	}
659 #endif
660 
661 	/*
662 	 * Open pad device before all accesses (including /dev/audioctl).
663 	 */
664 	if (use_pad) {
665 		padfd = rump_or_open("/dev/pad0", O_RDONLY);
666 		if (padfd == -1)
667 			xp_err(1, __LINE__, "rump_or_open");
668 
669 		/* Create consumer thread */
670 		pthread_create(&th, NULL, consumer_thread, NULL);
671 		/* Set this thread's name */
672 		pthread_setname_np(pthread_self(), "main", NULL);
673 	}
674 
675 	/*
676 	 * Get device properties, etc.
677 	 */
678 	fd = rump_or_open(devaudioctl, O_RDONLY);
679 	if (fd == -1)
680 		xp_err(1, __LINE__, "open %s", devaudioctl);
681 	r = rump_or_ioctl(fd, AUDIO_GETPROPS, &props);
682 	if (r == -1)
683 		xp_err(1, __LINE__, "AUDIO_GETPROPS");
684 	r = rump_or_ioctl(fd, AUDIO_GETDEV, &devinfo);
685 	if (r == -1)
686 		xp_err(1, __LINE__, "AUDIO_GETDEV");
687 	rump_or_close(fd);
688 
689 	if (debug) {
690 		printf("  device = %s, %s, %s\n",
691 		    devinfo.name, devinfo.version, devinfo.config);
692 		printf("  hw props =");
693 		if (hw_canplay())
694 			printf(" playback");
695 		if (hw_canrec())
696 			printf(" capture");
697 		if (hw_fulldup())
698 			printf(" fullduplex");
699 		printf("\n");
700 	}
701 
702 }
703 
704 /* Consumer thread used by pad */
705 void *
consumer_thread(void * arg)706 consumer_thread(void *arg)
707 {
708 	char buf[1024];
709 	int r;
710 
711 	pthread_setname_np(pthread_self(), "consumer", NULL);
712 	pthread_detach(pthread_self());
713 
714 	/* throw away data anyway */
715 	for (;;) {
716 		r = read(padfd, buf, sizeof(buf));
717 		if (r < 1)
718 			break;
719 	}
720 
721 	pthread_exit(NULL);
722 }
723 
724 /*
725  * XXX
726  * Closing pad descriptor before audio descriptor causes panic (PR kern/54427).
727  * To avoid this, close non-pad descriptor first using atexit(3) for now.
728  * This is just a workaround and this function should be removed.
729  */
cleanup_audiofd()730 void cleanup_audiofd()
731 {
732 	int fd;
733 
734 	for (fd = 3; fd <= maxfd; fd++) {
735 		if (fd != padfd)
736 			close(fd);
737 	}
738 	maxfd = 3;
739 }
740 
741 /*
742  * Support functions
743  */
744 
745 /* Set testname */
746 void
TEST(const char * name,...)747 TEST(const char *name, ...)
748 {
749 	va_list ap;
750 
751 	va_start(ap, name);
752 	vsnprintf(testname, sizeof(testname), name, ap);
753 	va_end(ap);
754 	if (opt_atf == false) {
755 		printf("%s\n", testname);
756 		fflush(stdout);
757 	}
758 }
759 
760 /*
761  * XP_FAIL() should be called when this test fails.
762  * If caller already count up testcount, call xp_fail() instead.
763  */
764 #define XP_FAIL(fmt...)	do {	\
765 	testcount++;	\
766 	xp_fail(__LINE__, fmt);	\
767 } while (0)
xp_fail(int line,const char * fmt,...)768 bool xp_fail(int line, const char *fmt, ...)
769 {
770 	va_list ap;
771 
772 	printf("%s %d: ", (opt_atf ? "Line" : " FAIL:"), line);
773 	va_start(ap, fmt);
774 	vprintf(fmt, ap);
775 	va_end(ap);
776 	printf("\n");
777 	fflush(stdout);
778 	failcount++;
779 
780 	return false;
781 }
782 
783 /*
784  * XP_SKIP() should be called when you want to skip this test.
785  * If caller already count up testcount, call xp_skip() instead.
786  */
787 #define XP_SKIP(fmt...)	do { \
788 	testcount++;	\
789 	xp_skip(__LINE__, fmt);	\
790 } while (0)
xp_skip(int line,const char * fmt,...)791 void xp_skip(int line, const char *fmt, ...)
792 {
793 	va_list ap;
794 
795 	printf("%s %d: ", (opt_atf ? "Line" : " SKIP:"), line);
796 	va_start(ap, fmt);
797 	vprintf(fmt, ap);
798 	va_end(ap);
799 	printf("\n");
800 	fflush(stdout);
801 	skipcount++;
802 }
803 
804 #define XP_EQ(exp, act)	xp_eq(__LINE__, exp, act, #act)
xp_eq(int line,int exp,int act,const char * varname)805 bool xp_eq(int line, int exp, int act, const char *varname)
806 {
807 	bool r = true;
808 
809 	testcount++;
810 	if (exp != act) {
811 		r = xp_fail(line, "%s expects %d but %d", varname, exp, act);
812 	}
813 	return r;
814 }
815 #define XP_EQ_STR(exp, act) xp_eq_str(__LINE__, exp, act, #act)
xp_eq_str(int line,const char * exp,const char * act,const char * varname)816 bool xp_eq_str(int line, const char *exp, const char *act, const char *varname)
817 {
818 	bool r = true;
819 
820 	testcount++;
821 	if (strcmp(exp, act) != 0) {
822 		r = xp_fail(line, "%s expects \"%s\" but \"%s\"",
823 		    varname, exp, act);
824 	}
825 	return r;
826 }
827 
828 #define XP_NE(exp, act)	xp_ne(__LINE__, exp, act, #act)
xp_ne(int line,int exp,int act,const char * varname)829 bool xp_ne(int line, int exp, int act, const char *varname)
830 {
831 	bool r = true;
832 
833 	testcount++;
834 	if (exp == act) {
835 		r = xp_fail(line, "%s expects != %d but %d", varname, exp, act);
836 	}
837 	return r;
838 }
839 
840 /* This expects that result is expressed in expr. */
841 /* GCC extension */
842 #define XP_IF(expr) xp_if(__LINE__, (expr), #expr)
xp_if(int line,bool expr,const char * exprname)843 bool xp_if(int line, bool expr, const char *exprname)
844 {
845 	bool r = true;
846 	testcount++;
847 	if (!expr) {
848 		r = xp_fail(__LINE__, "(%s) is expected but not met", exprname);
849 	}
850 	return r;
851 }
852 
853 /* This expects that the system call returns 'exp'. */
854 #define XP_SYS_EQ(exp, act)	xp_sys_eq(__LINE__, exp, act, #act)
xp_sys_eq(int line,int exp,int act,const char * varname)855 bool xp_sys_eq(int line, int exp, int act, const char *varname)
856 {
857 	bool r = true;
858 
859 	testcount++;
860 	if (act == -1) {
861 		r = xp_fail(line, "%s expects %d but -1,err#%d(%s)",
862 		    varname, exp, errno, strerror(errno));
863 	} else {
864 		r = xp_eq(line, exp, act, varname);
865 	}
866 	return r;
867 }
868 
869 /*
870  * This expects that system call succeeds.
871  * This is useful when you expect the system call succeeds but don't know
872  * the expected return value, such as open(2).
873  */
874 #define XP_SYS_OK(act)	xp_sys_ok(__LINE__, act, #act)
xp_sys_ok(int line,int act,const char * varname)875 bool xp_sys_ok(int line, int act, const char *varname)
876 {
877 	bool r = true;
878 
879 	testcount++;
880 	if (act == -1) {
881 		r = xp_fail(line, "%s expects success but -1,err#%d(%s)",
882 		    varname, errno, strerror(errno));
883 	}
884 	return r;
885 }
886 
887 /* This expects that the system call fails with 'experrno'. */
888 #define XP_SYS_NG(experrno, act) xp_sys_ng(__LINE__, experrno, act, #act)
xp_sys_ng(int line,int experrno,int act,const char * varname)889 bool xp_sys_ng(int line, int experrno, int act, const char *varname)
890 {
891 	bool r = true;
892 
893 	testcount++;
894 	if (act != -1) {
895 		r = xp_fail(line, "%s expects -1,err#%d but %d",
896 		    varname, experrno, act);
897 	} else if (experrno != errno) {
898 		char acterrbuf[100];
899 		int acterrno = errno;
900 		strlcpy(acterrbuf, strerror(acterrno), sizeof(acterrbuf));
901 		r = xp_fail(line, "%s expects -1,err#%d(%s) but -1,err#%d(%s)",
902 		    varname, experrno, strerror(experrno),
903 		    acterrno, acterrbuf);
904 	}
905 	return r;
906 }
907 
908 /*
909  * When exp == 0, this expects that the system call succeeds with returned
910  * pointer is not -1.
911  * When exp != 0, this expects that the system call fails with returned
912  * pointer is -1 and its errno is exp.
913  * It's only for mmap().
914  */
915 #define XP_SYS_PTR(exp, act) xp_sys_ptr(__LINE__, exp, act, #act)
xp_sys_ptr(int line,int exp,void * act,const char * varname)916 bool xp_sys_ptr(int line, int exp, void *act, const char *varname)
917 {
918 	char errbuf[256];
919 	int actual_errno;
920 	bool r = true;
921 
922 	testcount++;
923 	if (exp == 0) {
924 		/* expects to succeed */
925 		if (act == (void *)-1) {
926 			r = xp_fail(line,
927 			    "%s expects success but -1,err#%d(%s)",
928 			    varname, errno, strerror(errno));
929 		}
930 	} else {
931 		/* expects to fail */
932 		if (act != (void *)-1) {
933 			r = xp_fail(line,
934 			    "%s expects -1,err#%d(%s) but success",
935 			    varname, exp, strerror(exp));
936 		} else if (exp != errno) {
937 			actual_errno = errno;
938 			strerror_r(actual_errno, errbuf, sizeof(errbuf));
939 			r = xp_fail(line,
940 			    "%s expects -1,err#%d(%s) but -1,err#%d(%s)",
941 			    varname, exp, strerror(exp), actual_errno, errbuf);
942 		}
943 	}
944 	return r;
945 }
946 
947 
948 /*
949  * REQUIRED_* return immediately if condition does not meet.
950  */
951 #define REQUIRED_EQ(e, a) do { if (!XP_EQ(e, a)) return; } while (0)
952 #define REQUIRED_NE(e, a) do { if (!XP_NE(e, a)) return; } while (0)
953 #define REQUIRED_IF(expr) do { if (!XP_IF(expr)) return; } while (0)
954 #define REQUIRED_SYS_EQ(e, a) do { if (!XP_SYS_EQ(e, a)) return; } while (0)
955 #define REQUIRED_SYS_OK(a)    do { if (!XP_SYS_OK(a))    return; } while (0)
956 
957 
958 static const char *openmode_str[] = {
959 	"O_RDONLY",
960 	"O_WRONLY",
961 	"O_RDWR",
962 };
963 
964 
965 /*
966  * All system calls in following tests should be called with these macros.
967  */
968 
969 #define OPEN(name, mode)	\
970 	debug_open(__LINE__, name, mode)
debug_open(int line,const char * name,int mode)971 int debug_open(int line, const char *name, int mode)
972 {
973 	char modestr[32];
974 	int n;
975 
976 	if ((mode & 3) != 3) {
977 		n = snprintf(modestr, sizeof(modestr), "%s",
978 		    openmode_str[mode & 3]);
979 	} else {
980 		n = snprintf(modestr, sizeof(modestr), "%d", mode & 3);
981 	}
982 	if ((mode & O_NONBLOCK))
983 		n += snprintf(modestr + n, sizeof(modestr) - n, "|O_NONBLOCK");
984 
985 	DPRINTFF(line, "open(\"%s\", %s)", name, modestr);
986 	int r = rump_or_open(name, mode);
987 	DRESULT(r);
988 }
989 
990 #define WRITE(fd, addr, len)	\
991 	debug_write(__LINE__, fd, addr, len)
debug_write(int line,int fd,const void * addr,size_t len)992 int debug_write(int line, int fd, const void *addr, size_t len)
993 {
994 	DPRINTFF(line, "write(%d, %p, %zd)", fd, addr, len);
995 	int r = rump_or_write(fd, addr, len);
996 	DRESULT(r);
997 }
998 
999 #define READ(fd, addr, len)	\
1000 	debug_read(__LINE__, fd, addr, len)
debug_read(int line,int fd,void * addr,size_t len)1001 int debug_read(int line, int fd, void *addr, size_t len)
1002 {
1003 	DPRINTFF(line, "read(%d, %p, %zd)", fd, addr, len);
1004 	int r = rump_or_read(fd, addr, len);
1005 	DRESULT(r);
1006 }
1007 
1008 /*
1009  * addrstr is the comment for debug message.
1010  *   int onoff = 0;
1011  *   ioctl(fd, SWITCH, onoff); -> IOCTL(fd, SWITCH, onoff, "off");
1012  */
1013 #define IOCTL(fd, name, addr, addrfmt...)	\
1014 	debug_ioctl(__LINE__, fd, name, #name, addr, addrfmt)
debug_ioctl(int line,int fd,u_long name,const char * namestr,void * addr,const char * addrfmt,...)1015 int debug_ioctl(int line, int fd, u_long name, const char *namestr,
1016 	void *addr, const char *addrfmt, ...)
1017 {
1018 	char addrbuf[100];
1019 	va_list ap;
1020 
1021 	va_start(ap, addrfmt);
1022 	vsnprintf(addrbuf, sizeof(addrbuf), addrfmt, ap);
1023 	va_end(ap);
1024 	DPRINTFF(line, "ioctl(%d, %s, %s)", fd, namestr, addrbuf);
1025 	int r = rump_or_ioctl(fd, name, addr);
1026 	DRESULT(r);
1027 }
1028 
1029 #define FCNTL(fd, name...)	\
1030 	debug_fcntl(__LINE__, fd, name, #name)
debug_fcntl(int line,int fd,int name,const char * namestr,...)1031 int debug_fcntl(int line, int fd, int name, const char *namestr, ...)
1032 {
1033 	int r;
1034 
1035 	switch (name) {
1036 	 case F_GETFL:	/* no arguments */
1037 		DPRINTFF(line, "fcntl(%d, %s)", fd, namestr);
1038 		r = rump_or_fcntl(fd, name);
1039 		break;
1040 	 default:
1041 		__unreachable();
1042 	}
1043 	DRESULT(r);
1044 	return r;
1045 }
1046 
1047 #define CLOSE(fd)	\
1048 	debug_close(__LINE__, fd)
debug_close(int line,int fd)1049 int debug_close(int line, int fd)
1050 {
1051 	DPRINTFF(line, "close(%d)", fd);
1052 	int r = rump_or_close(fd);
1053 	DRESULT(r);
1054 }
1055 
1056 #define MMAP(ptr, len, prot, flags, fd, offset)	\
1057 	debug_mmap(__LINE__, ptr, len, prot, flags, fd, offset)
debug_mmap(int line,void * ptr,size_t len,int prot,int flags,int fd,off_t offset)1058 void *debug_mmap(int line, void *ptr, size_t len, int prot, int flags, int fd,
1059 	off_t offset)
1060 {
1061 	char protbuf[256];
1062 	char flagbuf[256];
1063 	int n;
1064 
1065 #define ADDFLAG(buf, var, name)	do {				\
1066 	if (((var) & (name)))					\
1067 		n = strlcat(buf, "|" #name, sizeof(buf));	\
1068 		var &= ~(name);					\
1069 } while (0)
1070 
1071 	n = 0;
1072 	protbuf[n] = '\0';
1073 	if (prot == 0) {
1074 		strlcpy(protbuf, "|PROT_NONE", sizeof(protbuf));
1075 	} else {
1076 		ADDFLAG(protbuf, prot, PROT_EXEC);
1077 		ADDFLAG(protbuf, prot, PROT_WRITE);
1078 		ADDFLAG(protbuf, prot, PROT_READ);
1079 		if (prot != 0) {
1080 			snprintf(protbuf + n, sizeof(protbuf) - n,
1081 			    "|prot=0x%x", prot);
1082 		}
1083 	}
1084 
1085 	n = 0;
1086 	flagbuf[n] = '\0';
1087 	if (flags == 0) {
1088 		strlcpy(flagbuf, "|MAP_FILE", sizeof(flagbuf));
1089 	} else {
1090 		ADDFLAG(flagbuf, flags, MAP_SHARED);
1091 		ADDFLAG(flagbuf, flags, MAP_PRIVATE);
1092 		ADDFLAG(flagbuf, flags, MAP_FIXED);
1093 		ADDFLAG(flagbuf, flags, MAP_INHERIT);
1094 		ADDFLAG(flagbuf, flags, MAP_HASSEMAPHORE);
1095 		ADDFLAG(flagbuf, flags, MAP_TRYFIXED);
1096 		ADDFLAG(flagbuf, flags, MAP_WIRED);
1097 		ADDFLAG(flagbuf, flags, MAP_ANON);
1098 		if (flags != 0) {
1099 			n += snprintf(flagbuf + n, sizeof(flagbuf) - n,
1100 			    "|flag=0x%x", flags);
1101 		}
1102 	}
1103 
1104 	DPRINTFF(line, "mmap(%p, %zd, %s, %s, %d, %jd)",
1105 	    ptr, len, protbuf + 1, flagbuf + 1, fd, offset);
1106 	void *r = mmap(ptr, len, prot, flags, fd, offset);
1107 	DRESULT_PTR(r);
1108 }
1109 
1110 #define MUNMAP(ptr, len)	\
1111 	debug_munmap(__LINE__, ptr, len)
debug_munmap(int line,void * ptr,int len)1112 int debug_munmap(int line, void *ptr, int len)
1113 {
1114 #if !defined(NO_RUMP)
1115 	if (use_rump)
1116 		xp_errx(1, __LINE__, "rump doesn't support munmap");
1117 #endif
1118 	DPRINTFF(line, "munmap(%p, %d)", ptr, len);
1119 	int r = munmap(ptr, len);
1120 	DRESULT(r);
1121 }
1122 
1123 const char *
event_tostr(int events)1124 event_tostr(int events)
1125 {
1126 	static char buf[64];
1127 
1128 	snprintb(buf, sizeof(buf),
1129 	    "\177\020" \
1130 	    "b\10WRBAND\0" \
1131 	    "b\7RDBAND\0" "b\6RDNORM\0" "b\5NVAL\0" "b\4HUP\0" \
1132 	    "b\3ERR\0" "b\2OUT\0" "b\1PRI\0" "b\0IN\0",
1133 	    events);
1134 	return buf;
1135 }
1136 
1137 #define POLL(pfd, nfd, timeout)	\
1138 	debug_poll(__LINE__, pfd, nfd, timeout)
debug_poll(int line,struct pollfd * pfd,int nfd,int timeout)1139 int debug_poll(int line, struct pollfd *pfd, int nfd, int timeout)
1140 {
1141 	char buf[256];
1142 	int n = 0;
1143 	buf[n] = '\0';
1144 	for (int i = 0; i < nfd; i++) {
1145 		n += snprintf(buf + n, sizeof(buf) - n, "{fd=%d,events=%s}",
1146 		    pfd[i].fd, event_tostr(pfd[i].events));
1147 	}
1148 	DPRINTFF(line, "poll(%s, %d, %d)", buf, nfd, timeout);
1149 	int r = rump_or_poll(pfd, nfd, timeout);
1150 	DRESULT(r);
1151 }
1152 
1153 #define KQUEUE()	\
1154 	debug_kqueue(__LINE__)
debug_kqueue(int line)1155 int debug_kqueue(int line)
1156 {
1157 	DPRINTFF(line, "kqueue()");
1158 	int r = rump_or_kqueue();
1159 	DRESULT(r);
1160 }
1161 
1162 #define KEVENT_SET(kq, kev, nev)	\
1163 	debug_kevent_set(__LINE__, kq, kev, nev)
debug_kevent_set(int line,int kq,const struct kevent * kev,size_t nev)1164 int debug_kevent_set(int line, int kq, const struct kevent *kev, size_t nev)
1165 {
1166 	DPRINTFF(line, "kevent_set(%d, %p, %zd)", kq, kev, nev);
1167 	int r = rump_or_kevent(kq, kev, nev, NULL, 0, NULL);
1168 	DRESULT(r);
1169 }
1170 
1171 #define KEVENT_POLL(kq, kev, nev, ts) \
1172 	debug_kevent_poll(__LINE__, kq, kev, nev, ts)
debug_kevent_poll(int line,int kq,struct kevent * kev,size_t nev,const struct timespec * ts)1173 int debug_kevent_poll(int line, int kq, struct kevent *kev, size_t nev,
1174 	const struct timespec *ts)
1175 {
1176 	char tsbuf[32];
1177 
1178 	if (ts == NULL) {
1179 		snprintf(tsbuf, sizeof(tsbuf), "NULL");
1180 	} else if (ts->tv_sec == 0 && ts->tv_nsec == 0) {
1181 		snprintf(tsbuf, sizeof(tsbuf), "0.0");
1182 	} else {
1183 		snprintf(tsbuf, sizeof(tsbuf), "%d.%09ld",
1184 			(int)ts->tv_sec, ts->tv_nsec);
1185 	}
1186 	DPRINTFF(line, "kevent_poll(%d, %p, %zd, %s)", kq, kev, nev, tsbuf);
1187 	int r = rump_or_kevent(kq, NULL, 0, kev, nev, ts);
1188 	DRESULT(r);
1189 }
1190 
1191 #define DEBUG_KEV(name, kev)	\
1192 	debug_kev(__LINE__, name, kev)
debug_kev(int line,const char * name,const struct kevent * kev)1193 void debug_kev(int line, const char *name, const struct kevent *kev)
1194 {
1195 	char flagbuf[256];
1196 	const char *filterbuf;
1197 	uint32_t v;
1198 	int n;
1199 
1200 	n = 0;
1201 	flagbuf[n] = '\0';
1202 	if (kev->flags == 0) {
1203 		strcpy(flagbuf, "|0?");
1204 	} else {
1205 		v = kev->flags;
1206 		ADDFLAG(flagbuf, v, EV_ADD);
1207 		if (v != 0)
1208 			snprintf(flagbuf + n, sizeof(flagbuf)-n, "|0x%x", v);
1209 	}
1210 
1211 	switch (kev->filter) {
1212 	 case EVFILT_READ:	filterbuf = "EVFILT_READ";	break;
1213 	 case EVFILT_WRITE:	filterbuf = "EVFILT_WRITE";	break;
1214 	 default:		filterbuf = "EVFILT_?";		break;
1215 	}
1216 
1217 	DPRINTFF(line,
1218 	    "%s={id:%d,%s,%s,fflags:0x%x,data:0x%" PRIx64 ",udata:0x%x}\n",
1219 	    name,
1220 	    (int)kev->ident,
1221 	    flagbuf + 1,
1222 	    filterbuf,
1223 	    kev->fflags,
1224 	    kev->data,
1225 	    (int)(intptr_t)kev->udata);
1226 }
1227 
1228 /* XXX rump? */
1229 #define GETUID()	\
1230 	debug_getuid(__LINE__)
debug_getuid(int line)1231 uid_t debug_getuid(int line)
1232 {
1233 	DPRINTFF(line, "getuid");
1234 	uid_t r = getuid();
1235 	/* getuid() never fails */
1236 	DPRINTF(" = %u\n", r);
1237 	return r;
1238 }
1239 
1240 /* XXX rump? */
1241 #define SETEUID(id)	\
1242 	debug_seteuid(__LINE__, id)
debug_seteuid(int line,uid_t id)1243 int debug_seteuid(int line, uid_t id)
1244 {
1245 	DPRINTFF(line, "seteuid(%d)", (int)id);
1246 	int r = seteuid(id);
1247 	DRESULT(r);
1248 }
1249 
1250 #define SYSCTLBYNAME(name, oldp, oldlenp, newp, newlen)	\
1251 	debug_sysctlbyname(__LINE__, name, oldp, oldlenp, newp, newlen)
debug_sysctlbyname(int line,const char * name,void * oldp,size_t * oldlenp,const void * newp,size_t newlen)1252 int debug_sysctlbyname(int line, const char *name, void *oldp, size_t *oldlenp,
1253 	const void *newp, size_t newlen)
1254 {
1255 	DPRINTFF(line, "sysctlbyname(\"%s\")", name);
1256 	int r = sysctlbyname(name, oldp, oldlenp, newp, newlen);
1257 	DRESULT(r);
1258 }
1259 
1260 
1261 /* Return openable mode on this hardware property */
1262 int
openable_mode(void)1263 openable_mode(void)
1264 {
1265 	if (hw_bidir())
1266 		return O_RDWR;
1267 	if (hw_canplay())
1268 		return O_WRONLY;
1269 	else
1270 		return O_RDONLY;
1271 }
1272 
1273 int mode2aumode_full[] = {
1274 	                                AUMODE_RECORD,	/* O_RDONLY */
1275 	AUMODE_PLAY | AUMODE_PLAY_ALL,			/* O_WRONLY */
1276 	AUMODE_PLAY | AUMODE_PLAY_ALL | AUMODE_RECORD,	/* O_RDWR   */
1277 };
1278 
1279 /* Convert openmode(O_*) to AUMODE_*, with hardware property */
1280 int
mode2aumode(int mode)1281 mode2aumode(int mode)
1282 {
1283 	int aumode;
1284 
1285 	aumode = mode2aumode_full[mode];
1286 	if (hw_canplay() == 0)
1287 		aumode &= ~(AUMODE_PLAY | AUMODE_PLAY_ALL);
1288 	if (hw_canrec() == 0)
1289 		aumode &= ~AUMODE_RECORD;
1290 
1291 	if (netbsd >= 9) {
1292 		/* half-duplex treats O_RDWR as O_WRONLY */
1293 		if (mode == O_RDWR && hw_bidir() && hw_fulldup() == 0)
1294 			aumode &= ~AUMODE_RECORD;
1295 	}
1296 
1297 	return aumode;
1298 }
1299 
1300 /* Is this mode + hardware playable? */
1301 int
mode2play(int mode)1302 mode2play(int mode)
1303 {
1304 	int aumode;
1305 
1306 	aumode = mode2aumode(mode);
1307 	return ((aumode & AUMODE_PLAY)) ? 1 : 0;
1308 }
1309 
1310 /* Is this mode + hardware recordable? */
1311 int
mode2rec(int mode)1312 mode2rec(int mode)
1313 {
1314 	int aumode;
1315 
1316 	aumode = mode2aumode(mode);
1317 	return ((aumode & AUMODE_RECORD)) ? 1 : 0;
1318 }
1319 
1320 /*
1321  * On NetBSD7, open() after-closing-mmap fails due to a bug.
1322  * It happens once every two times like flip-flop, so the workaround is
1323  * to open it again.
1324  */
1325 void
reset_after_mmap(void)1326 reset_after_mmap(void)
1327 {
1328 	int fd;
1329 
1330 	if (netbsd < 8) {
1331 		fd = OPEN(devaudio, O_WRONLY);
1332 		if (fd != -1)
1333 			CLOSE(fd);
1334 	}
1335 }
1336 
1337 /*
1338  * Lookup "outputs.master" and return its mixer device index.
1339  * It may not be strict but I'm not sure.
1340  */
1341 int
mixer_get_outputs_master(int mixerfd)1342 mixer_get_outputs_master(int mixerfd)
1343 {
1344 	const char * const typename[] = { "CLASS", "ENUM", "SET", "VALUE" };
1345 	mixer_devinfo_t di;
1346 	int class_outputs;
1347 	int i;
1348 	int r;
1349 
1350 	class_outputs = -1;
1351 	for (i = 0; ; i++) {
1352 		memset(&di, 0, sizeof(di));
1353 		di.index = i;
1354 		r = IOCTL(mixerfd, AUDIO_MIXER_DEVINFO, &di, "index=%d", i);
1355 		if (r < 0)
1356 			break;
1357 		DPRINTF("  > type=%s(%d) mixer_class=%d name=%s\n",
1358 		    (0 <= di.type && di.type <= 3) ? typename[di.type] : "",
1359 		    di.type, di.mixer_class, di.label.name);
1360 		if (di.type == AUDIO_MIXER_CLASS &&
1361 		    strcmp(di.label.name, "outputs") == 0) {
1362 			class_outputs = di.mixer_class;
1363 			DPRINTF("  > class_output=%d\n", class_outputs);
1364 			continue;
1365 		}
1366 		if (di.type == AUDIO_MIXER_VALUE &&
1367 		    di.mixer_class == class_outputs &&
1368 		    strcmp(di.label.name, "master") == 0) {
1369 			return i;
1370 		}
1371 	}
1372 	/* Not found */
1373 	return -1;
1374 }
1375 
1376 /*
1377  * Tests
1378  */
1379 
1380 void test_open_mode(int);
1381 void test_open(const char *, int);
1382 void test_open_simul(int, int);
1383 void try_open_multiuser(bool);
1384 void test_open_multiuser(bool);
1385 void test_rdwr_fallback(int, bool, bool);
1386 void test_rdwr_two(int, int);
1387 void test_mmap_mode(int, int);
1388 void test_mmap_len(size_t, off_t, int);
1389 void test_poll_mode(int, int, int);
1390 void test_poll_in_open(const char *);
1391 void test_kqueue_mode(int, int, int);
1392 volatile int sigio_caught;
1393 void signal_FIOASYNC(int);
1394 void test_AUDIO_SETFD_xxONLY(int);
1395 void test_AUDIO_SETINFO_mode(int, int, int, int);
1396 void test_AUDIO_SETINFO_params_set(int, int, int);
1397 void test_AUDIO_SETINFO_pause(int, int, int);
1398 int getenc_make_table(int, int[][5]);
1399 void xp_getenc(int[][5], int, int, int, struct audio_prinfo *);
1400 void getenc_check_encodings(int, int[][5]);
1401 void test_AUDIO_ERROR(int);
1402 void test_AUDIO_GETIOFFS_one(int);
1403 void test_AUDIO_GETOOFFS_one(int);
1404 void test_AUDIO_GETOOFFS_wrap(int);
1405 void test_AUDIO_GETOOFFS_flush(int);
1406 void test_AUDIO_GETOOFFS_set(int);
1407 void test_audioctl_open_1(int, int);
1408 void test_audioctl_open_2(int, int);
1409 void try_audioctl_open_multiuser(const char *, const char *);
1410 void test_audioctl_open_multiuser(bool, const char *, const char *);
1411 void test_audioctl_rw(int);
1412 
1413 #define DEF(name) \
1414 	void test__ ## name (void); \
1415 	void test__ ## name (void)
1416 
1417 /*
1418  * Whether it can be open()ed with specified mode.
1419  */
1420 void
test_open_mode(int mode)1421 test_open_mode(int mode)
1422 {
1423 	int fd;
1424 	int r;
1425 
1426 	TEST("open_mode_%s", openmode_str[mode] + 2);
1427 
1428 	fd = OPEN(devaudio, mode);
1429 	if (mode2aumode(mode) != 0) {
1430 		XP_SYS_OK(fd);
1431 	} else {
1432 		XP_SYS_NG(ENXIO, fd);
1433 	}
1434 
1435 	if (fd >= 0) {
1436 		r = CLOSE(fd);
1437 		XP_SYS_EQ(0, r);
1438 	}
1439 }
DEF(open_mode_RDONLY)1440 DEF(open_mode_RDONLY)	{ test_open_mode(O_RDONLY); }
DEF(open_mode_WRONLY)1441 DEF(open_mode_WRONLY)	{ test_open_mode(O_WRONLY); }
DEF(open_mode_RDWR)1442 DEF(open_mode_RDWR)	{ test_open_mode(O_RDWR);   }
1443 
1444 /*
1445  * Check the initial parameters and stickiness.
1446  * /dev/audio
1447  *	The initial parameters are always the same whenever you open.
1448  * /dev/sound and /dev/audioctl
1449  *	The initial parameters are inherited from the last /dev/sound or
1450  *	/dev/audio.
1451  */
1452 void
test_open(const char * devname,int mode)1453 test_open(const char *devname, int mode)
1454 {
1455 	struct audio_info ai;
1456 	struct audio_info ai0;
1457 	char devfile[16];
1458 	int fd;
1459 	int r;
1460 	int can_play;
1461 	int can_rec;
1462 	int exp_mode;
1463 	int exp_encoding;
1464 	int exp_precision;
1465 	int exp_channels;
1466 	int exp_sample_rate;
1467 	int exp_pause;
1468 	int exp_popen;
1469 	int exp_ropen;
1470 
1471 	TEST("open_%s_%s", devname, openmode_str[mode] + 2);
1472 
1473 	snprintf(devfile, sizeof(devfile), "/dev/%s%d", devname, unit);
1474 	can_play = mode2play(mode);
1475 	can_rec  = mode2rec(mode);
1476 	if (strcmp(devname, "audioctl") != 0) {
1477 		if (can_play + can_rec == 0) {
1478 			/* Check whether it cannot be opened */
1479 			fd = OPEN(devaudio, mode);
1480 			XP_SYS_NG(ENXIO, fd);
1481 			return;
1482 		}
1483 	}
1484 
1485 	/* /dev/audio is always initialized */
1486 	if (strcmp(devname, "audio") == 0) {
1487 		exp_encoding = AUDIO_ENCODING_ULAW;
1488 		exp_precision = 8;
1489 		exp_channels = 1;
1490 		exp_sample_rate = 8000;
1491 		exp_pause = 0;
1492 	} else {
1493 		exp_encoding = AUDIO_ENCODING_SLINEAR_LE;
1494 		exp_precision = 16;
1495 		exp_channels = 2;
1496 		exp_sample_rate = 11025;
1497 		exp_pause = 1;
1498 	}
1499 
1500 	/* /dev/audioctl is always "not opened" */
1501 	if (strcmp(devname, "audioctl") == 0) {
1502 		exp_mode = 0;
1503 		exp_popen = 0;
1504 		exp_ropen = 0;
1505 	} else {
1506 		exp_mode = mode2aumode(mode);
1507 		exp_popen = can_play;
1508 		exp_ropen = can_rec;
1509 	}
1510 
1511 
1512 	/*
1513 	 * At first, initialize the sticky parameters both of play and rec.
1514 	 * This uses /dev/audio to verify /dev/audio.  It's not good way but
1515 	 * I don't have better one...
1516 	 */
1517 	fd = OPEN(devaudio, openable_mode());
1518 	REQUIRED_SYS_OK(fd);
1519 	r = CLOSE(fd);
1520 	REQUIRED_SYS_EQ(0, r);
1521 
1522 	/*
1523 	 * Open target device and check the initial parameters
1524 	 * At this moment, all devices are initialized by default.
1525 	 */
1526 	fd = OPEN(devfile, mode);
1527 	REQUIRED_SYS_OK(fd);
1528 	memset(&ai, 0, sizeof(ai));
1529 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
1530 	REQUIRED_SYS_EQ(0, r);
1531 
1532 	XP_NE(0, ai.blocksize);
1533 		/* hiwat/lowat */
1534 	XP_EQ(exp_mode, ai.mode);
1535 	/* ai.play */
1536 	XP_EQ(8000, ai.play.sample_rate);
1537 	XP_EQ(1, ai.play.channels);
1538 	XP_EQ(8, ai.play.precision);
1539 	XP_EQ(AUDIO_ENCODING_ULAW, ai.play.encoding);
1540 		/* gain */
1541 		/* port */
1542 	XP_EQ(0, ai.play.seek);
1543 		/* avail_ports */
1544 	XP_NE(0, ai.play.buffer_size);
1545 	XP_EQ(0, ai.play.samples);
1546 	XP_EQ(0, ai.play.eof);
1547 	XP_EQ(0, ai.play.pause);
1548 	XP_EQ(0, ai.play.error);
1549 	XP_EQ(0, ai.play.waiting);
1550 		/* balance */
1551 	XP_EQ(exp_popen, ai.play.open);
1552 	XP_EQ(0, ai.play.active);
1553 	/* ai.record */
1554 	XP_EQ(8000, ai.record.sample_rate);
1555 	XP_EQ(1, ai.record.channels);
1556 	XP_EQ(8, ai.record.precision);
1557 	XP_EQ(AUDIO_ENCODING_ULAW, ai.record.encoding);
1558 		/* gain */
1559 		/* port */
1560 	XP_EQ(0, ai.record.seek);
1561 		/* avail_ports */
1562 	XP_NE(0, ai.record.buffer_size);
1563 	XP_EQ(0, ai.record.samples);
1564 	XP_EQ(0, ai.record.eof);
1565 	XP_EQ(0, ai.record.pause);
1566 	XP_EQ(0, ai.record.error);
1567 	XP_EQ(0, ai.record.waiting);
1568 		/* balance */
1569 	XP_EQ(exp_ropen, ai.record.open);
1570 	if (netbsd < 9 && strcmp(devname, "sound") == 0) {
1571 		/*
1572 		 * On NetBSD7/8, it doesn't seem to start recording on open
1573 		 * for /dev/sound.  It should be a bug.
1574 		 */
1575 		XP_EQ(0, ai.record.active);
1576 	} else {
1577 		XP_EQ(exp_ropen, ai.record.active);
1578 	}
1579 	/* Save it */
1580 	ai0 = ai;
1581 
1582 	/*
1583 	 * Change much as possible
1584 	 */
1585 	AUDIO_INITINFO(&ai);
1586 	ai.mode = ai0.mode ^ AUMODE_PLAY_ALL;
1587 	ai.play.sample_rate = 11025;
1588 	ai.play.channels = 2;
1589 	ai.play.precision = 16;
1590 	ai.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
1591 	ai.play.pause = 1;
1592 	ai.record.sample_rate = 11025;
1593 	ai.record.channels = 2;
1594 	ai.record.precision = 16;
1595 	ai.record.encoding = AUDIO_ENCODING_SLINEAR_LE;
1596 	ai.record.pause = 1;
1597 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "ai");
1598 	REQUIRED_SYS_EQ(0, r);
1599 	r = CLOSE(fd);
1600 	REQUIRED_SYS_EQ(0, r);
1601 
1602 	/*
1603 	 * Open the same target device again and check
1604 	 */
1605 	fd = OPEN(devfile, mode);
1606 	REQUIRED_SYS_OK(fd);
1607 	memset(&ai, 0, sizeof(ai));
1608 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
1609 	REQUIRED_SYS_EQ(0, r);
1610 
1611 	XP_NE(0, ai.blocksize);
1612 		/* hiwat/lowat */
1613 	if (netbsd < 8) {
1614 		/*
1615 		 * On NetBSD7, the behavior when changing ai.mode on
1616 		 * /dev/audioctl can not be explained yet but I won't
1617 		 * verify it more over.
1618 		 */
1619 	} else {
1620 		/* On NetBSD9, changing mode never affects other fds */
1621 		XP_EQ(exp_mode, ai.mode);
1622 	}
1623 	/* ai.play */
1624 	XP_EQ(exp_sample_rate, ai.play.sample_rate);
1625 	XP_EQ(exp_channels, ai.play.channels);
1626 	XP_EQ(exp_precision, ai.play.precision);
1627 	XP_EQ(exp_encoding, ai.play.encoding);
1628 		/* gain */
1629 		/* port */
1630 	XP_EQ(0, ai.play.seek);
1631 		/* avail_ports */
1632 	XP_NE(0, ai.play.buffer_size);
1633 	XP_EQ(0, ai.play.samples);
1634 	XP_EQ(0, ai.play.eof);
1635 	XP_EQ(exp_pause, ai.play.pause);
1636 	XP_EQ(0, ai.play.error);
1637 	XP_EQ(0, ai.play.waiting);
1638 		/* balance */
1639 	XP_EQ(exp_popen, ai.play.open);
1640 	XP_EQ(0, ai.play.active);
1641 	/* ai.record */
1642 	XP_EQ(exp_sample_rate, ai.record.sample_rate);
1643 	XP_EQ(exp_channels, ai.record.channels);
1644 	XP_EQ(exp_precision, ai.record.precision);
1645 	XP_EQ(exp_encoding, ai.record.encoding);
1646 		/* gain */
1647 		/* port */
1648 	XP_EQ(0, ai.record.seek);
1649 		/* avail_ports */
1650 	XP_NE(0, ai.record.buffer_size);
1651 	XP_EQ(0, ai.record.samples);
1652 	XP_EQ(0, ai.record.eof);
1653 	XP_EQ(exp_pause, ai.record.pause);
1654 	XP_EQ(0, ai.record.error);
1655 	XP_EQ(0, ai.record.waiting);
1656 		/* balance */
1657 	XP_EQ(exp_ropen, ai.record.open);
1658 	if (netbsd < 9 && strcmp(devname, "sound") == 0) {
1659 		/*
1660 		 * On NetBSD7/8, it doesn't seem to start recording on open
1661 		 * for /dev/sound.  It should be a bug.
1662 		 */
1663 		XP_EQ(0, ai.record.active);
1664 	} else {
1665 		XP_EQ(exp_ropen, ai.record.active);
1666 	}
1667 
1668 	r = CLOSE(fd);
1669 	REQUIRED_SYS_EQ(0, r);
1670 }
DEF(open_audio_RDONLY)1671 DEF(open_audio_RDONLY)		{ test_open("audio", O_RDONLY); }
DEF(open_audio_WRONLY)1672 DEF(open_audio_WRONLY)		{ test_open("audio", O_WRONLY); }
DEF(open_audio_RDWR)1673 DEF(open_audio_RDWR)		{ test_open("audio", O_RDWR);   }
DEF(open_sound_RDONLY)1674 DEF(open_sound_RDONLY)		{ test_open("sound", O_RDONLY); }
DEF(open_sound_WRONLY)1675 DEF(open_sound_WRONLY)		{ test_open("sound", O_WRONLY); }
DEF(open_sound_RDWR)1676 DEF(open_sound_RDWR)		{ test_open("sound", O_RDWR);   }
DEF(open_audioctl_RDONLY)1677 DEF(open_audioctl_RDONLY)	{ test_open("audioctl", O_RDONLY); }
DEF(open_audioctl_WRONLY)1678 DEF(open_audioctl_WRONLY)	{ test_open("audioctl", O_WRONLY); }
DEF(open_audioctl_RDWR)1679 DEF(open_audioctl_RDWR)		{ test_open("audioctl", O_RDWR);   }
1680 
1681 /*
1682  * Open (1) /dev/sound -> (2) /dev/audio -> (3) /dev/sound,
1683  * Both of /dev/audio and /dev/sound share the sticky parameters,
1684  * /dev/sound inherits and use it but /dev/audio initialize and use it.
1685  * So 2nd audio descriptor affects 3rd sound descriptor.
1686  */
DEF(open_sound_sticky)1687 DEF(open_sound_sticky)
1688 {
1689 	struct audio_info ai;
1690 	int fd;
1691 	int r;
1692 	int openmode;
1693 
1694 	TEST("open_sound_sticky");
1695 
1696 	openmode = openable_mode();
1697 
1698 	/* First, open /dev/sound and change encoding as a delegate */
1699 	fd = OPEN(devsound, openmode);
1700 	REQUIRED_SYS_OK(fd);
1701 	AUDIO_INITINFO(&ai);
1702 	ai.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
1703 	ai.record.encoding = AUDIO_ENCODING_SLINEAR_LE;
1704 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "");
1705 	REQUIRED_SYS_EQ(0, r);
1706 	r = CLOSE(fd);
1707 	REQUIRED_SYS_EQ(0, r);
1708 
1709 	/* Next, open /dev/audio.  It makes the encoding mulaw */
1710 	fd = OPEN(devaudio, openmode);
1711 	REQUIRED_SYS_OK(fd);
1712 	r = CLOSE(fd);
1713 	REQUIRED_SYS_EQ(0, r);
1714 
1715 	/* And then, open /dev/sound again */
1716 	fd = OPEN(devsound, openmode);
1717 	REQUIRED_SYS_OK(fd);
1718 	memset(&ai, 0, sizeof(ai));
1719 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
1720 	REQUIRED_SYS_EQ(0, r);
1721 	XP_EQ(AUDIO_ENCODING_ULAW, ai.play.encoding);
1722 	XP_EQ(AUDIO_ENCODING_ULAW, ai.record.encoding);
1723 	r = CLOSE(fd);
1724 	REQUIRED_SYS_EQ(0, r);
1725 }
1726 
1727 /*
1728  * /dev/audioctl has stickiness like /dev/sound.
1729  */
DEF(open_audioctl_sticky)1730 DEF(open_audioctl_sticky)
1731 {
1732 	struct audio_info ai;
1733 	int fd;
1734 	int r;
1735 	int openmode;
1736 
1737 	TEST("open_audioctl_sticky");
1738 
1739 	openmode = openable_mode();
1740 
1741 	/* First, open /dev/audio and change encoding */
1742 	fd = OPEN(devaudio, openmode);
1743 	REQUIRED_SYS_OK(fd);
1744 	AUDIO_INITINFO(&ai);
1745 	ai.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
1746 	ai.play.precision = 16;
1747 	ai.record.encoding = AUDIO_ENCODING_SLINEAR_LE;
1748 	ai.record.precision = 16;
1749 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "SLINEAR_LE");
1750 	REQUIRED_SYS_EQ(0, r);
1751 	r = CLOSE(fd);
1752 	REQUIRED_SYS_EQ(0, r);
1753 
1754 	/* Next, open /dev/audioctl.  It should be affected */
1755 	fd = OPEN(devaudioctl, openmode);
1756 	REQUIRED_SYS_OK(fd);
1757 	memset(&ai, 0, sizeof(ai));
1758 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
1759 	REQUIRED_SYS_EQ(0, r);
1760 	XP_EQ(AUDIO_ENCODING_SLINEAR_LE, ai.play.encoding);
1761 	XP_EQ(16, ai.play.precision);
1762 	XP_EQ(AUDIO_ENCODING_SLINEAR_LE, ai.record.encoding);
1763 	XP_EQ(16, ai.record.precision);
1764 
1765 	/* Then, change /dev/audioctl */
1766 	AUDIO_INITINFO(&ai);
1767 	ai.play.encoding = AUDIO_ENCODING_ULAW;
1768 	ai.play.precision = 8;
1769 	ai.record.encoding = AUDIO_ENCODING_ULAW;
1770 	ai.record.precision = 8;
1771 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "ULAW");
1772 	REQUIRED_SYS_EQ(0, r);
1773 	r = CLOSE(fd);
1774 	REQUIRED_SYS_EQ(0, r);
1775 
1776 	/* Finally, open /dev/sound.  It also should be affected  */
1777 	fd = OPEN(devsound, openmode);
1778 	REQUIRED_SYS_OK(fd);
1779 	memset(&ai, 0, sizeof(ai));
1780 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
1781 	REQUIRED_SYS_EQ(0, r);
1782 	XP_EQ(AUDIO_ENCODING_ULAW, ai.play.encoding);
1783 	XP_EQ(8, ai.play.precision);
1784 	XP_EQ(AUDIO_ENCODING_ULAW, ai.record.encoding);
1785 	XP_EQ(8, ai.record.precision);
1786 	r = CLOSE(fd);
1787 	REQUIRED_SYS_EQ(0, r);
1788 }
1789 
1790 /*
1791  * Open two descriptors simultaneously.
1792  */
1793 void
test_open_simul(int mode0,int mode1)1794 test_open_simul(int mode0, int mode1)
1795 {
1796 	struct audio_info ai;
1797 	int fd0, fd1;
1798 	int i;
1799 	int r;
1800 	int actmode;
1801 #define AUMODE_BOTH (AUMODE_PLAY | AUMODE_RECORD)
1802 	struct {
1803 		int mode0;
1804 		int mode1;
1805 	} expfulltable[] = {
1806 		/* expected fd0		expected fd1 (-errno expects error) */
1807 		{ AUMODE_RECORD,	AUMODE_RECORD },	// REC, REC
1808 		{ AUMODE_RECORD,	AUMODE_PLAY },		// REC, PLAY
1809 		{ AUMODE_RECORD,	AUMODE_BOTH },		// REC, BOTH
1810 		{ AUMODE_PLAY,		AUMODE_RECORD },	// PLAY, REC
1811 		{ AUMODE_PLAY,		AUMODE_PLAY },		// PLAY, PLAY
1812 		{ AUMODE_PLAY,		AUMODE_BOTH },		// PLAY, BOTH
1813 		{ AUMODE_BOTH,		AUMODE_RECORD },	// BOTH, REC
1814 		{ AUMODE_BOTH,		AUMODE_PLAY },		// BOTH, PLAY
1815 		{ AUMODE_BOTH,		AUMODE_BOTH },		// BOTH, BOTH
1816 	},
1817 	exphalftable[] = {
1818 		/* expected fd0		expected fd1 (-errno expects error) */
1819 		{ AUMODE_RECORD,	AUMODE_RECORD },	// REC, REC
1820 		{ AUMODE_RECORD,	-ENODEV },		// REC, PLAY
1821 		{ AUMODE_RECORD,	-ENODEV },		// REC, BOTH
1822 		{ AUMODE_PLAY,		-ENODEV },		// PLAY, REC
1823 		{ AUMODE_PLAY,		AUMODE_PLAY },		// PLAY, PLAY
1824 		{ AUMODE_PLAY,		AUMODE_PLAY },		// PLAY, BOTH
1825 		{ AUMODE_PLAY,		-ENODEV },		// BOTH, REC
1826 		{ AUMODE_PLAY,		AUMODE_PLAY },		// BOTH, PLAY
1827 		{ AUMODE_PLAY,		AUMODE_PLAY },		// BOTH, BOTH
1828 	}, *exptable;
1829 
1830 	/* The expected values are different in half-duplex or full-duplex */
1831 	if (hw_fulldup()) {
1832 		exptable = expfulltable;
1833 	} else {
1834 		exptable = exphalftable;
1835 	}
1836 
1837 	TEST("open_simul_%s_%s",
1838 	    openmode_str[mode0] + 2,
1839 	    openmode_str[mode1] + 2);
1840 
1841 	if (netbsd < 8) {
1842 		XP_SKIP("Multiple open is not supported");
1843 		return;
1844 	}
1845 
1846 	if (mode2aumode(mode0) == 0 || mode2aumode(mode1) == 0) {
1847 		XP_SKIP("Operation not allowed on this hardware property");
1848 		return;
1849 	}
1850 
1851 	i = mode0 * 3 + mode1;
1852 
1853 	/* Open first one */
1854 	fd0 = OPEN(devaudio, mode0);
1855 	REQUIRED_SYS_OK(fd0);
1856 	r = IOCTL(fd0, AUDIO_GETBUFINFO, &ai, "");
1857 	REQUIRED_SYS_EQ(0, r);
1858 	actmode = ai.mode & AUMODE_BOTH;
1859 	XP_EQ(exptable[i].mode0, actmode);
1860 
1861 	/* Open second one */
1862 	fd1 = OPEN(devaudio, mode1);
1863 	if (exptable[i].mode1 >= 0) {
1864 		/* Case to expect to be able to open */
1865 		REQUIRED_SYS_OK(fd1);
1866 		r = IOCTL(fd1, AUDIO_GETBUFINFO, &ai, "");
1867 		XP_SYS_EQ(0, r);
1868 		if (r == 0) {
1869 			actmode = ai.mode & AUMODE_BOTH;
1870 			XP_EQ(exptable[i].mode1, actmode);
1871 		}
1872 	} else {
1873 		/* Case to expect not to be able to open */
1874 		XP_SYS_NG(ENODEV, fd1);
1875 		if (fd1 == -1) {
1876 			XP_EQ(-exptable[i].mode1, errno);
1877 		} else {
1878 			r = IOCTL(fd1, AUDIO_GETBUFINFO, &ai, "");
1879 			XP_SYS_EQ(0, r);
1880 			if (r == 0) {
1881 				actmode = ai.mode & AUMODE_BOTH;
1882 				XP_FAIL("expects error but %d", actmode);
1883 			}
1884 		}
1885 	}
1886 
1887 	if (fd1 >= 0) {
1888 		r = CLOSE(fd1);
1889 		XP_SYS_EQ(0, r);
1890 	}
1891 
1892 	r = CLOSE(fd0);
1893 	XP_SYS_EQ(0, r);
1894 }
DEF(open_simul_RDONLY_RDONLY)1895 DEF(open_simul_RDONLY_RDONLY)	{ test_open_simul(O_RDONLY, O_RDONLY);	}
DEF(open_simul_RDONLY_WRONLY)1896 DEF(open_simul_RDONLY_WRONLY)	{ test_open_simul(O_RDONLY, O_WRONLY);	}
DEF(open_simul_RDONLY_RDWR)1897 DEF(open_simul_RDONLY_RDWR)	{ test_open_simul(O_RDONLY, O_RDWR);	}
DEF(open_simul_WRONLY_RDONLY)1898 DEF(open_simul_WRONLY_RDONLY)	{ test_open_simul(O_WRONLY, O_RDONLY);	}
DEF(open_simul_WRONLY_WRONLY)1899 DEF(open_simul_WRONLY_WRONLY)	{ test_open_simul(O_WRONLY, O_WRONLY);	}
DEF(open_simul_WRONLY_RDWR)1900 DEF(open_simul_WRONLY_RDWR)	{ test_open_simul(O_WRONLY, O_RDWR);	}
DEF(open_simul_RDWR_RDONLY)1901 DEF(open_simul_RDWR_RDONLY)	{ test_open_simul(O_RDWR, O_RDONLY);	}
DEF(open_simul_RDWR_WRONLY)1902 DEF(open_simul_RDWR_WRONLY)	{ test_open_simul(O_RDWR, O_WRONLY);	}
DEF(open_simul_RDWR_RDWR)1903 DEF(open_simul_RDWR_RDWR)	{ test_open_simul(O_RDWR, O_RDWR);	}
1904 
1905 /*
1906  * /dev/audio can be opened by other user who opens /dev/audio.
1907  */
1908 void
try_open_multiuser(bool multiuser)1909 try_open_multiuser(bool multiuser)
1910 {
1911 	int fd0;
1912 	int fd1;
1913 	int r;
1914 	uid_t ouid;
1915 
1916 	/*
1917 	 * Test1: Open as root first and then unprivileged user.
1918 	 */
1919 
1920 	/* At first, open as root */
1921 	fd0 = OPEN(devaudio, openable_mode());
1922 	REQUIRED_SYS_OK(fd0);
1923 
1924 	ouid = GETUID();
1925 	r = SETEUID(1);
1926 	REQUIRED_SYS_EQ(0, r);
1927 
1928 	/* Then, open as unprivileged user */
1929 	fd1 = OPEN(devaudio, openable_mode());
1930 	if (multiuser) {
1931 		/* If multiuser, another user also can open */
1932 		XP_SYS_OK(fd1);
1933 	} else {
1934 		/* If not multiuser, another user cannot open */
1935 		XP_SYS_NG(EPERM, fd1);
1936 	}
1937 	if (fd1 != -1) {
1938 		r = CLOSE(fd1);
1939 		XP_SYS_EQ(0, r);
1940 	}
1941 
1942 	r = SETEUID(ouid);
1943 	REQUIRED_SYS_EQ(0, r);
1944 
1945 	r = CLOSE(fd0);
1946 	XP_SYS_EQ(0, r);
1947 
1948 	/*
1949 	 * Test2: Open as unprivileged user first and then root.
1950 	 */
1951 
1952 	/* At first, open as unprivileged user */
1953 	ouid = GETUID();
1954 	r = SETEUID(1);
1955 	REQUIRED_SYS_EQ(0, r);
1956 
1957 	fd0 = OPEN(devaudio, openable_mode());
1958 	REQUIRED_SYS_OK(fd0);
1959 
1960 	/* Then open as root */
1961 	r = SETEUID(ouid);
1962 	REQUIRED_SYS_EQ(0, r);
1963 
1964 	/* root always can open */
1965 	fd1 = OPEN(devaudio, openable_mode());
1966 	XP_SYS_OK(fd1);
1967 	if (fd1 != -1) {
1968 		r = CLOSE(fd1);
1969 		XP_SYS_EQ(0, r);
1970 	}
1971 
1972 	/* Close first one as unprivileged user */
1973 	r = SETEUID(1);
1974 	REQUIRED_SYS_EQ(0, r);
1975 	r = CLOSE(fd0);
1976 	XP_SYS_EQ(0, r);
1977 	r = SETEUID(ouid);
1978 	REQUIRED_SYS_EQ(0, r);
1979 }
1980 /*
1981  * This is a wrapper for open_multiuser.
1982  * XXX XP_* macros are not compatible with on-error-goto, we need try-catch...
1983  */
1984 void
test_open_multiuser(bool multiuser)1985 test_open_multiuser(bool multiuser)
1986 {
1987 	char mibname[32];
1988 	bool oldval;
1989 	size_t oldlen;
1990 	int r;
1991 
1992 	TEST("open_multiuser_%d", multiuser);
1993 	if (netbsd < 8) {
1994 		XP_SKIP("Multiple open is not supported");
1995 		return;
1996 	}
1997 	if (netbsd < 9) {
1998 		/* NetBSD8 has no way (difficult) to determine device name */
1999 		XP_SKIP("NetBSD8 cannot determine device name");
2000 		return;
2001 	}
2002 	if (geteuid() != 0) {
2003 		XP_SKIP("Must be run as a privileged user");
2004 		return;
2005 	}
2006 
2007 	/* Get current multiuser mode (and save it) */
2008 	snprintf(mibname, sizeof(mibname), "hw.%s.multiuser", devicename);
2009 	oldlen = sizeof(oldval);
2010 	r = SYSCTLBYNAME(mibname, &oldval, &oldlen, NULL, 0);
2011 	REQUIRED_SYS_EQ(0, r);
2012 	DPRINTF("  > multiuser=%d\n", oldval);
2013 
2014 	/* Change if necessary */
2015 	if (oldval != multiuser) {
2016 		r = SYSCTLBYNAME(mibname, NULL, NULL, &multiuser,
2017 		    sizeof(multiuser));
2018 		REQUIRED_SYS_EQ(0, r);
2019 		DPRINTF("  > new multiuser=%d\n", multiuser);
2020 	}
2021 
2022 	/* Do test */
2023 	try_open_multiuser(multiuser);
2024 
2025 	/* Restore multiuser mode */
2026 	if (oldval != multiuser) {
2027 		DPRINTF("  > restore multiuser to %d\n", oldval);
2028 		r = SYSCTLBYNAME(mibname, NULL, NULL, &oldval, sizeof(oldval));
2029 		REQUIRED_SYS_EQ(0, r);
2030 	}
2031 }
DEF(open_multiuser_0)2032 DEF(open_multiuser_0)	{ test_open_multiuser(false); }
DEF(open_multiuser_1)2033 DEF(open_multiuser_1)	{ test_open_multiuser(true); }
2034 
2035 /*
2036  * Normal playback (with PLAY_ALL).
2037  * It does not verify real playback data.
2038  */
DEF(write_PLAY_ALL)2039 DEF(write_PLAY_ALL)
2040 {
2041 	char buf[8000];
2042 	int fd;
2043 	int r;
2044 
2045 	TEST("write_PLAY_ALL");
2046 
2047 	fd = OPEN(devaudio, O_WRONLY);
2048 	if (hw_canplay()) {
2049 		REQUIRED_SYS_OK(fd);
2050 	} else {
2051 		XP_SYS_NG(ENXIO, fd);
2052 		return;
2053 	}
2054 
2055 	/* mulaw 1sec silence */
2056 	memset(buf, 0xff, sizeof(buf));
2057 	r = WRITE(fd, buf, sizeof(buf));
2058 	XP_SYS_EQ(sizeof(buf), r);
2059 
2060 	r = CLOSE(fd);
2061 	XP_SYS_EQ(0, r);
2062 }
2063 
2064 /*
2065  * Normal playback (without PLAY_ALL).
2066  * It does not verify real playback data.
2067  */
DEF(write_PLAY)2068 DEF(write_PLAY)
2069 {
2070 	struct audio_info ai;
2071 	char *wav;
2072 	int wavsize;
2073 	int totalsize;
2074 	int fd;
2075 	int r;
2076 
2077 	TEST("write_PLAY");
2078 
2079 	fd = OPEN(devaudio, O_WRONLY);
2080 	if (hw_canplay()) {
2081 		REQUIRED_SYS_OK(fd);
2082 	} else {
2083 		XP_SYS_NG(ENXIO, fd);
2084 		return;
2085 	}
2086 
2087 	/* Drop PLAY_ALL */
2088 	AUDIO_INITINFO(&ai);
2089 	ai.mode = AUMODE_PLAY;
2090 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "mode");
2091 	REQUIRED_SYS_EQ(0, r);
2092 
2093 	/* Check mode and get blocksize */
2094 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
2095 	REQUIRED_SYS_EQ(0, r);
2096 	XP_EQ(AUMODE_PLAY, ai.mode);
2097 
2098 	wavsize = ai.blocksize;
2099 	wav = (char *)malloc(wavsize);
2100 	REQUIRED_IF(wav != NULL);
2101 	memset(wav, 0xff, wavsize);
2102 
2103 	/* Write blocks until 1sec */
2104 	for (totalsize = 0; totalsize < 8000; ) {
2105 		r = WRITE(fd, wav, wavsize);
2106 		XP_SYS_EQ(wavsize, r);
2107 		if (r == -1)
2108 			break;	/* XXX */
2109 		totalsize += r;
2110 	}
2111 
2112 	/* XXX What should I test it? */
2113 	/* Check ai.play.error */
2114 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
2115 	REQUIRED_SYS_EQ(0, r);
2116 	XP_EQ(0, ai.play.error);
2117 
2118 	/* Playback data is no longer necessary */
2119 	r = IOCTL(fd, AUDIO_FLUSH, NULL, "");
2120 	REQUIRED_SYS_EQ(0, r);
2121 
2122 	r = CLOSE(fd);
2123 	REQUIRED_SYS_EQ(0, r);
2124 
2125 	free(wav);
2126 }
2127 
2128 /*
2129  * Normal recording.
2130  * It does not verify real recorded data.
2131  */
DEF(read)2132 DEF(read)
2133 {
2134 	char buf[8000];
2135 	int fd;
2136 	int r;
2137 
2138 	TEST("read");
2139 
2140 	fd = OPEN(devaudio, O_RDONLY);
2141 	if (hw_canrec()) {
2142 		REQUIRED_SYS_OK(fd);
2143 	} else {
2144 		XP_SYS_NG(ENXIO, fd);
2145 		return;
2146 	}
2147 
2148 	/* mulaw 1sec */
2149 	r = READ(fd, buf, sizeof(buf));
2150 	XP_SYS_EQ(sizeof(buf), r);
2151 
2152 	r = CLOSE(fd);
2153 	XP_SYS_EQ(0, r);
2154 }
2155 
2156 /*
2157  * Repeat open-write-close cycle.
2158  */
DEF(rept_write)2159 DEF(rept_write)
2160 {
2161 	struct timeval start, end, result;
2162 	double res;
2163 	char buf[8000];	/* 1sec in 8bit-mulaw,1ch,8000Hz */
2164 	int fd;
2165 	int r;
2166 	int n;
2167 
2168 	TEST("rept_write");
2169 
2170 	if (hw_canplay() == 0) {
2171 		XP_SKIP("This test is only for playable device");
2172 		return;
2173 	}
2174 
2175 	/* XXX It may timeout on some hardware driver. */
2176 	XP_SKIP("not yet");
2177 	return;
2178 
2179 	memset(buf, 0xff, sizeof(buf));
2180 	n = 3;
2181 	gettimeofday(&start, NULL);
2182 	for (int i = 0; i < n; i++) {
2183 		fd = OPEN(devaudio, O_WRONLY);
2184 		REQUIRED_SYS_OK(fd);
2185 
2186 		r = WRITE(fd, buf, sizeof(buf));
2187 		XP_SYS_EQ(sizeof(buf), r);
2188 
2189 		r = CLOSE(fd);
2190 		XP_SYS_EQ(0, r);
2191 	}
2192 	gettimeofday(&end, NULL);
2193 	timersub(&end, &start, &result);
2194 	res = (double)result.tv_sec + (double)result.tv_usec / 1000000;
2195 	/* Make judgement but not too strict */
2196 	if (res >= n * 1.5) {
2197 		XP_FAIL("expects %d sec but %4.1f sec", n, res);
2198 		return;
2199 	}
2200 }
2201 
2202 /*
2203  * Repeat open-read-close cycle.
2204  */
DEF(rept_read)2205 DEF(rept_read)
2206 {
2207 	struct timeval start, end, result;
2208 	double res;
2209 	char buf[8000];	/* 1sec in 8bit-mulaw,1ch,8000Hz */
2210 	int fd;
2211 	int r;
2212 	int n;
2213 
2214 	TEST("rept_read");
2215 
2216 	if (hw_canrec() == 0) {
2217 		XP_SKIP("This test is only for recordable device");
2218 		return;
2219 	}
2220 
2221 	/* XXX It may timeout on some hardware driver. */
2222 	XP_SKIP("not yet");
2223 	return;
2224 
2225 	n = 3;
2226 	gettimeofday(&start, NULL);
2227 	for (int i = 0; i < n; i++) {
2228 		fd = OPEN(devaudio, O_RDONLY);
2229 		REQUIRED_SYS_OK(fd);
2230 
2231 		r = READ(fd, buf, sizeof(buf));
2232 		XP_SYS_EQ(sizeof(buf), r);
2233 
2234 		r = CLOSE(fd);
2235 		XP_SYS_EQ(0, r);
2236 	}
2237 	gettimeofday(&end, NULL);
2238 	timersub(&end, &start, &result);
2239 	res = (double)result.tv_sec + (double)result.tv_usec / 1000000;
2240 	/* Make judgement but not too strict */
2241 	if (res >= n * 1.5) {
2242 		XP_FAIL("expects %d sec but %4.1f sec", n, res);
2243 		return;
2244 	}
2245 }
2246 
2247 /*
2248  * Opening with O_RDWR on half-duplex hardware falls back to O_WRONLY.
2249  * expwrite: expected to be able to play.
2250  * expread : expected to be able to record.
2251  */
2252 void
test_rdwr_fallback(int openmode,bool expwrite,bool expread)2253 test_rdwr_fallback(int openmode, bool expwrite, bool expread)
2254 {
2255 	struct audio_info ai;
2256 	char buf[10];
2257 	int fd;
2258 	int r;
2259 
2260 	TEST("rdwr_fallback_%s", openmode_str[openmode] + 2);
2261 
2262 	if (hw_bidir() == 0) {
2263 		XP_SKIP("This test is only for bi-directional device");
2264 		return;
2265 	}
2266 
2267 	AUDIO_INITINFO(&ai);
2268 	ai.play.pause = 1;
2269 	ai.record.pause = 1;
2270 
2271 	fd = OPEN(devaudio, openmode);
2272 	REQUIRED_SYS_OK(fd);
2273 
2274 	/* Set pause not to play noise */
2275 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause");
2276 	REQUIRED_SYS_EQ(0, r);
2277 
2278 	memset(buf, 0xff, sizeof(buf));
2279 	r = WRITE(fd, buf, sizeof(buf));
2280 	if (expwrite) {
2281 		XP_SYS_EQ(sizeof(buf), r);
2282 	} else {
2283 		XP_SYS_NG(EBADF, r);
2284 	}
2285 
2286 	r = READ(fd, buf, 0);
2287 	if (expread) {
2288 		XP_SYS_EQ(0, r);
2289 	} else {
2290 		XP_SYS_NG(EBADF, r);
2291 	}
2292 
2293 	r = CLOSE(fd);
2294 	REQUIRED_SYS_EQ(0, r);
2295 }
DEF(rdwr_fallback_RDONLY)2296 DEF(rdwr_fallback_RDONLY) { test_rdwr_fallback(O_RDONLY, false, true); }
DEF(rdwr_fallback_WRONLY)2297 DEF(rdwr_fallback_WRONLY) { test_rdwr_fallback(O_WRONLY, true, false); }
DEF(rdwr_fallback_RDWR)2298 DEF(rdwr_fallback_RDWR) {
2299 	bool expread;
2300 	/*
2301 	 * On NetBSD7, O_RDWR on half-duplex is accepted. It's possible to
2302 	 * read and write if they don't occur at the same time.
2303 	 * On NetBSD9, O_RDWR on half-duplex falls back O_WRONLY.
2304 	 */
2305 	if (netbsd < 8) {
2306 		expread = true;
2307 	} else {
2308 		expread = hw_fulldup() ? true : false;
2309 	}
2310 	test_rdwr_fallback(O_RDWR, true, expread);
2311 }
2312 
2313 /*
2314  * On full-duplex hardware, the second descriptor's readability/writability
2315  * does not depend on the first descriptor's open mode.
2316  * On half-duplex hardware, it depends on the first descriptor's open mode.
2317  */
2318 void
test_rdwr_two(int mode0,int mode1)2319 test_rdwr_two(int mode0, int mode1)
2320 {
2321 	struct audio_info ai;
2322 	char wbuf[100];	/* 1/80sec in 8bit-mulaw,1ch,8000Hz */
2323 	char rbuf[100];	/* 1/80sec in 8bit-mulaw,1ch,8000Hz */
2324 	bool canopen;
2325 	bool canwrite;
2326 	bool canread;
2327 	int fd0;
2328 	int fd1;
2329 	int r;
2330 	struct {
2331 		bool canopen;
2332 		bool canwrite;
2333 		bool canread;
2334 	} exptable_full[] = {
2335 	/*	open write read	   1st, 2nd mode */
2336 		{ 1, 0, 1 },	/* REC, REC */
2337 		{ 1, 1, 0 },	/* REC, PLAY */
2338 		{ 1, 1, 1 },	/* REC, BOTH */
2339 		{ 1, 0, 1 },	/* PLAY, REC */
2340 		{ 1, 1, 0 },	/* PLAY, PLAY */
2341 		{ 1, 1, 1 },	/* PLAY, BOTH */
2342 		{ 1, 0, 1 },	/* BOTH, REC */
2343 		{ 1, 1, 0 },	/* BOTH, PLAY */
2344 		{ 1, 1, 1 },	/* BOTH, BOTH */
2345 	},
2346 	exptable_half[] = {
2347 		{ 1, 0, 1 },	/* REC, REC */
2348 		{ 0, 0, 0 },	/* REC, PLAY */
2349 		{ 0, 0, 0 },	/* REC, BOTH */
2350 		{ 0, 0, 0 },	/* PLAY, REC */
2351 		{ 1, 1, 0 },	/* PLAY, PLAY */
2352 		{ 1, 1, 0 },	/* PLAY, BOTH */
2353 		{ 0, 0, 0 },	/* BOTH, REC */
2354 		{ 1, 1, 0 },	/* BOTH, PLAY */
2355 		{ 0, 0, 0 },	/* BOTH, BOTH */
2356 	}, *exptable;
2357 
2358 	TEST("rdwr_two_%s_%s",
2359 	    openmode_str[mode0] + 2,
2360 	    openmode_str[mode1] + 2);
2361 
2362 	if (netbsd < 8) {
2363 		XP_SKIP("Multiple open is not supported");
2364 		return;
2365 	}
2366 	if (hw_bidir() == 0) {
2367 		XP_SKIP("This test is only for bi-directional device");
2368 		return;
2369 	}
2370 
2371 	exptable = hw_fulldup() ? exptable_full : exptable_half;
2372 
2373 	canopen  = exptable[mode0 * 3 + mode1].canopen;
2374 	canwrite = exptable[mode0 * 3 + mode1].canwrite;
2375 	canread  = exptable[mode0 * 3 + mode1].canread;
2376 
2377 	if (!canopen) {
2378 		XP_SKIP("This combination is not openable on half-duplex");
2379 		return;
2380 	}
2381 
2382 	fd0 = OPEN(devaudio, mode0);
2383 	REQUIRED_SYS_OK(fd0);
2384 
2385 	fd1 = OPEN(devaudio, mode1);
2386 	REQUIRED_SYS_OK(fd1);
2387 
2388 	/* Silent data to make no sound */
2389 	memset(&wbuf, 0xff, sizeof(wbuf));
2390 	/* Pause to make no sound */
2391 	AUDIO_INITINFO(&ai);
2392 	ai.play.pause = 1;
2393 	r = IOCTL(fd0, AUDIO_SETINFO, &ai, "pause");
2394 	XP_SYS_EQ(0, r);
2395 
2396 	/* write(fd1) */
2397 	r = WRITE(fd1, wbuf, sizeof(wbuf));
2398 	if (canwrite) {
2399 		XP_SYS_EQ(100, r);
2400 	} else {
2401 		XP_SYS_NG(EBADF, r);
2402 	}
2403 
2404 	/* read(fd1) */
2405 	r = READ(fd1, rbuf, sizeof(rbuf));
2406 	if (canread) {
2407 		XP_SYS_EQ(100, r);
2408 	} else {
2409 		XP_SYS_NG(EBADF, r);
2410 	}
2411 
2412 	r = CLOSE(fd0);
2413 	XP_SYS_EQ(0, r);
2414 	r = CLOSE(fd1);
2415 	XP_SYS_EQ(0, r);
2416 }
DEF(rdwr_two_RDONLY_RDONLY)2417 DEF(rdwr_two_RDONLY_RDONLY)	{ test_rdwr_two(O_RDONLY, O_RDONLY);	}
DEF(rdwr_two_RDONLY_WRONLY)2418 DEF(rdwr_two_RDONLY_WRONLY)	{ test_rdwr_two(O_RDONLY, O_WRONLY);	}
DEF(rdwr_two_RDONLY_RDWR)2419 DEF(rdwr_two_RDONLY_RDWR)	{ test_rdwr_two(O_RDONLY, O_RDWR);	}
DEF(rdwr_two_WRONLY_RDONLY)2420 DEF(rdwr_two_WRONLY_RDONLY)	{ test_rdwr_two(O_WRONLY, O_RDONLY);	}
DEF(rdwr_two_WRONLY_WRONLY)2421 DEF(rdwr_two_WRONLY_WRONLY)	{ test_rdwr_two(O_WRONLY, O_WRONLY);	}
DEF(rdwr_two_WRONLY_RDWR)2422 DEF(rdwr_two_WRONLY_RDWR)	{ test_rdwr_two(O_WRONLY, O_RDWR);	}
DEF(rdwr_two_RDWR_RDONLY)2423 DEF(rdwr_two_RDWR_RDONLY)	{ test_rdwr_two(O_RDWR, O_RDONLY);	}
DEF(rdwr_two_RDWR_WRONLY)2424 DEF(rdwr_two_RDWR_WRONLY)	{ test_rdwr_two(O_RDWR, O_WRONLY);	}
DEF(rdwr_two_RDWR_RDWR)2425 DEF(rdwr_two_RDWR_RDWR)		{ test_rdwr_two(O_RDWR, O_RDWR);	}
2426 
2427 /*
2428  * Read and write different descriptors simultaneously.
2429  * Only on full-duplex.
2430  */
DEF(rdwr_simul)2431 DEF(rdwr_simul)
2432 {
2433 	char wbuf[1000];	/* 1/8sec in mulaw,1ch,8kHz */
2434 	char rbuf[1000];
2435 	int fd0;
2436 	int fd1;
2437 	int r;
2438 	int status;
2439 	pid_t pid;
2440 
2441 	TEST("rdwr_simul");
2442 	if (netbsd < 8) {
2443 		XP_SKIP("Multiple open is not supported");
2444 		return;
2445 	}
2446 	if (!hw_fulldup()) {
2447 		XP_SKIP("This test is only for full-duplex device");
2448 		return;
2449 	}
2450 
2451 	/* Silence data to make no sound */
2452 	memset(wbuf, 0xff, sizeof(wbuf));
2453 
2454 	fd0 = OPEN(devaudio, O_WRONLY);
2455 	REQUIRED_SYS_OK(fd0);
2456 	fd1 = OPEN(devaudio, O_RDONLY);
2457 	REQUIRED_SYS_OK(fd1);
2458 
2459 	fflush(stdout);
2460 	fflush(stderr);
2461 	pid = fork();
2462 	if (pid == -1)
2463 		xp_err(1, __LINE__, "fork");
2464 
2465 	if (pid == 0) {
2466 		/* child (read) */
2467 		for (int i = 0; i < 10; i++) {
2468 			r = READ(fd1, rbuf, sizeof(rbuf));
2469 			if (r == -1)
2470 				xp_err(1, __LINE__, "read(i=%d)", i);
2471 		}
2472 		exit(0);
2473 	} else {
2474 		/* parent (write) */
2475 		for (int i = 0; i < 10; i++) {
2476 			r = WRITE(fd0, wbuf, sizeof(wbuf));
2477 			if (r == -1)
2478 				xp_err(1, __LINE__, "write(i=%d)", i);
2479 		}
2480 		waitpid(pid, &status, 0);
2481 	}
2482 
2483 	CLOSE(fd0);
2484 	CLOSE(fd1);
2485 	/* If you reach here, consider as success */
2486 	XP_EQ(0, 0);
2487 }
2488 
2489 /*
2490  * DRAIN should work even on incomplete data left.
2491  */
DEF(drain_incomplete)2492 DEF(drain_incomplete)
2493 {
2494 	struct audio_info ai;
2495 	int r;
2496 	int fd;
2497 
2498 	TEST("drain_incomplete");
2499 
2500 	if (hw_canplay() == 0) {
2501 		XP_SKIP("This test is only for playable device");
2502 		return;
2503 	}
2504 
2505 	fd = OPEN(devaudio, O_WRONLY);
2506 	REQUIRED_SYS_OK(fd);
2507 
2508 	AUDIO_INITINFO(&ai);
2509 	/* let precision > 8 */
2510 	ai.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
2511 	ai.play.precision = 16;
2512 	ai.mode = AUMODE_PLAY;
2513 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "");
2514 	REQUIRED_SYS_EQ(0, r);
2515 	/* Write one byte and then close */
2516 	r = WRITE(fd, &r, 1);
2517 	XP_SYS_EQ(1, r);
2518 	r = CLOSE(fd);
2519 	XP_SYS_EQ(0, r);
2520 }
2521 
2522 /*
2523  * DRAIN should work even in pause.
2524  */
DEF(drain_pause)2525 DEF(drain_pause)
2526 {
2527 	struct audio_info ai;
2528 	int r;
2529 	int fd;
2530 
2531 	TEST("drain_pause");
2532 
2533 	if (hw_canplay() == 0) {
2534 		XP_SKIP("This test is only for playable device");
2535 		return;
2536 	}
2537 
2538 	fd = OPEN(devaudio, O_WRONLY);
2539 	REQUIRED_SYS_OK(fd);
2540 
2541 	/* Set pause */
2542 	AUDIO_INITINFO(&ai);
2543 	ai.play.pause = 1;
2544 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "");
2545 	XP_SYS_EQ(0, r);
2546 	/* Write some data and then close */
2547 	r = WRITE(fd, &r, 4);
2548 	XP_SYS_EQ(4, r);
2549 	r = CLOSE(fd);
2550 	XP_SYS_EQ(0, r);
2551 }
2552 
2553 /*
2554  * DRAIN does not affect for record-only descriptor.
2555  */
DEF(drain_onrec)2556 DEF(drain_onrec)
2557 {
2558 	int fd;
2559 	int r;
2560 
2561 	TEST("drain_onrec");
2562 
2563 	if (hw_canrec() == 0) {
2564 		XP_SKIP("This test is only for recordable device");
2565 		return;
2566 	}
2567 
2568 	fd = OPEN(devaudio, O_RDONLY);
2569 	REQUIRED_SYS_OK(fd);
2570 
2571 	r = IOCTL(fd, AUDIO_DRAIN, NULL, "");
2572 	XP_SYS_EQ(0, r);
2573 
2574 	r = CLOSE(fd);
2575 	XP_SYS_EQ(0, r);
2576 }
2577 
2578 /*
2579  * Whether mmap() succeeds with specified parameter.
2580  */
2581 void
test_mmap_mode(int mode,int prot)2582 test_mmap_mode(int mode, int prot)
2583 {
2584 	char buf[10];
2585 	struct audio_info ai;
2586 	const char *protstr;
2587 	int expected;
2588 	int fd;
2589 	int r;
2590 	int len;
2591 	void *ptr;
2592 
2593 	if (prot == PROT_NONE) {
2594 		protstr = "NONE";
2595 	} else if (prot == PROT_READ) {
2596 		protstr = "READ";
2597 	} else if (prot == PROT_WRITE) {
2598 		protstr = "WRITE";
2599 	} else if (prot == (PROT_READ | PROT_WRITE)) {
2600 		protstr = "READWRITE";
2601 	} else {
2602 		xp_errx(1, __LINE__, "unknown prot %x\n", prot);
2603 	}
2604 	TEST("mmap_%s_%s", openmode_str[mode] + 2, protstr);
2605 	if ((props & AUDIO_PROP_MMAP) == 0) {
2606 		XP_SKIP("This test is only for mmap-able device");
2607 		return;
2608 	}
2609 	if (mode2aumode(mode) == 0) {
2610 		XP_SKIP("Operation not allowed on this hardware property");
2611 		return;
2612 	}
2613 #if !defined(NO_RUMP)
2614 	if (use_rump) {
2615 		XP_SKIP("rump doesn't support mmap");
2616 		return;
2617 	}
2618 #endif
2619 
2620 	/*
2621 	 * On NetBSD7 and 8, mmap() always succeeds regardless of open mode.
2622 	 * On NetBSD9, mmap() succeeds only for writable descriptor.
2623 	 */
2624 	expected = mode2play(mode);
2625 	if (netbsd < 9) {
2626 		expected = true;
2627 	}
2628 
2629 	fd = OPEN(devaudio, mode);
2630 	REQUIRED_SYS_OK(fd);
2631 
2632 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "get");
2633 	REQUIRED_SYS_EQ(0, r);
2634 
2635 	len = ai.play.buffer_size;
2636 
2637 	/* Make it pause */
2638 	AUDIO_INITINFO(&ai);
2639 	ai.play.pause = 1;
2640 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause");
2641 	REQUIRED_SYS_EQ(0, r);
2642 
2643 	ptr = MMAP(NULL, len, prot, MAP_FILE, fd, 0);
2644 	XP_SYS_PTR(expected ? 0 : EACCES, ptr);
2645 	if (expected) {
2646 		/* XXX Doing mmap(2) doesn't inhibit read(2) */
2647 		if (mode2rec(mode)) {
2648 			r = READ(fd, buf, 0);
2649 			XP_SYS_EQ(0, r);
2650 		}
2651 		/* Doing mmap(2) inhibits write(2) */
2652 		if (mode2play(mode)) {
2653 			/* NetBSD9 changes errno */
2654 			r = WRITE(fd, buf, 0);
2655 			if (netbsd < 9) {
2656 				XP_SYS_NG(EINVAL, r);
2657 			} else {
2658 				XP_SYS_NG(EPERM, r);
2659 			}
2660 		}
2661 	}
2662 	if (ptr != MAP_FAILED) {
2663 		r = MUNMAP(ptr, len);
2664 		XP_SYS_EQ(0, r);
2665 	}
2666 
2667 	/* Whether the pause is still valid */
2668 	if (mode2play(mode)) {
2669 		r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
2670 		XP_SYS_EQ(0, r);
2671 		XP_EQ(1, ai.play.pause);
2672 	}
2673 
2674 	r = CLOSE(fd);
2675 	XP_SYS_EQ(0, r);
2676 
2677 	reset_after_mmap();
2678 }
2679 #define PROT_READWRITE	(PROT_READ | PROT_WRITE)
DEF(mmap_mode_RDONLY_NONE)2680 DEF(mmap_mode_RDONLY_NONE)	{ test_mmap_mode(O_RDONLY, PROT_NONE); }
DEF(mmap_mode_RDONLY_READ)2681 DEF(mmap_mode_RDONLY_READ)	{ test_mmap_mode(O_RDONLY, PROT_READ); }
DEF(mmap_mode_RDONLY_WRITE)2682 DEF(mmap_mode_RDONLY_WRITE)	{ test_mmap_mode(O_RDONLY, PROT_WRITE); }
DEF(mmap_mode_RDONLY_READWRITE)2683 DEF(mmap_mode_RDONLY_READWRITE)	{ test_mmap_mode(O_RDONLY, PROT_READWRITE); }
DEF(mmap_mode_WRONLY_NONE)2684 DEF(mmap_mode_WRONLY_NONE)	{ test_mmap_mode(O_WRONLY, PROT_NONE); }
DEF(mmap_mode_WRONLY_READ)2685 DEF(mmap_mode_WRONLY_READ)	{ test_mmap_mode(O_WRONLY, PROT_READ); }
DEF(mmap_mode_WRONLY_WRITE)2686 DEF(mmap_mode_WRONLY_WRITE)	{ test_mmap_mode(O_WRONLY, PROT_WRITE); }
DEF(mmap_mode_WRONLY_READWRITE)2687 DEF(mmap_mode_WRONLY_READWRITE)	{ test_mmap_mode(O_WRONLY, PROT_READWRITE); }
DEF(mmap_mode_RDWR_NONE)2688 DEF(mmap_mode_RDWR_NONE)	{ test_mmap_mode(O_RDWR, PROT_NONE); }
DEF(mmap_mode_RDWR_READ)2689 DEF(mmap_mode_RDWR_READ)	{ test_mmap_mode(O_RDWR, PROT_READ); }
DEF(mmap_mode_RDWR_WRITE)2690 DEF(mmap_mode_RDWR_WRITE)	{ test_mmap_mode(O_RDWR, PROT_WRITE); }
DEF(mmap_mode_RDWR_READWRITE)2691 DEF(mmap_mode_RDWR_READWRITE)	{ test_mmap_mode(O_RDWR, PROT_READWRITE); }
2692 
2693 /*
2694  * Check mmap()'s length and offset.
2695  *
2696  * Actual len and offset cannot be determined before open.  So that,
2697  * pass pre-defined constant as argument, and convert it after open.
2698  */
2699 #define LS	(100)	/* lsize     */
2700 #define LS1	(101)	/* lsize + 1 */
2701 void
test_mmap_len(size_t len,off_t offset,int exp)2702 test_mmap_len(size_t len, off_t offset, int exp)
2703 {
2704 	struct audio_info ai;
2705 	int fd;
2706 	int r;
2707 	size_t plen;
2708 	void *ptr;
2709 	int bufsize;
2710 	int pagesize;
2711 	int lsize;
2712 
2713 	TEST("mmap_len(%zd, %jd, %d)", len, offset, exp);
2714 	if ((props & AUDIO_PROP_MMAP) == 0) {
2715 		XP_SKIP("This test is only for mmap-able device");
2716 		return;
2717 	}
2718 #if !defined(NO_RUMP)
2719 	if (use_rump) {
2720 		XP_SKIP("rump doesn't support mmap");
2721 		return;
2722 	}
2723 #endif
2724 
2725 	plen = sizeof(pagesize);
2726 	r = SYSCTLBYNAME("hw.pagesize", &pagesize, &plen, NULL, 0);
2727 	REQUIRED_SYS_EQ(0, r);
2728 
2729 	fd = OPEN(devaudio, O_WRONLY);
2730 	REQUIRED_SYS_OK(r);
2731 
2732 	/* Get buffer_size */
2733 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
2734 	REQUIRED_SYS_EQ(0, r);
2735 	bufsize = ai.play.buffer_size;
2736 
2737 	/*
2738 	 * XXX someone refers bufsize and another one does pagesize.
2739 	 * I'm not sure.
2740 	 */
2741 	lsize = roundup2(bufsize, pagesize);
2742 
2743 	/* Here, lsize can be assigned */
2744 	if (len == LS) {
2745 		len = lsize;
2746 	} else if (len == LS1) {
2747 		len = lsize + 1;
2748 	}
2749 	if (offset == LS) {
2750 		offset = lsize;
2751 	} else if (offset == LS1) {
2752 		offset = lsize + 1;
2753 	}
2754 
2755 	ptr = MMAP(NULL, len, PROT_WRITE, MAP_FILE, fd, offset);
2756 	if (exp == 0) {
2757 		XP_SYS_PTR(0, ptr);
2758 	} else {
2759 		/* NetBSD8 introduces EOVERFLOW */
2760 		if (netbsd < 8 && exp == EOVERFLOW)
2761 			exp = EINVAL;
2762 		XP_SYS_PTR(exp, ptr);
2763 	}
2764 
2765 	if (ptr != MAP_FAILED) {
2766 		r = MUNMAP(ptr, len);
2767 		XP_SYS_EQ(0, r);
2768 	}
2769 
2770 	r = CLOSE(fd);
2771 	XP_SYS_EQ(0, r);
2772 
2773 	reset_after_mmap();
2774 }
2775 #define f(l, o, e)	test_mmap_len(l, o, e)
DEF(mmap_len_0)2776 DEF(mmap_len_0)	{ f(0,   0,   0); }		/* len is 0 */
DEF(mmap_len_1)2777 DEF(mmap_len_1)	{ f(1,   0,   0); }		/* len is smaller than lsize */
DEF(mmap_len_2)2778 DEF(mmap_len_2)	{ f(LS,  0,   0); }		/* len is the same as lsize */
DEF(mmap_len_3)2779 DEF(mmap_len_3)	{ f(LS1, 0,   EOVERFLOW); }	/* len is larger */
DEF(mmap_len_4)2780 DEF(mmap_len_4)	{ f(0,   -1,  EINVAL); }	/* offset is negative */
DEF(mmap_len_5)2781 DEF(mmap_len_5)	{ f(0,   LS,  0); }		/* pointless param but ok */
DEF(mmap_len_6)2782 DEF(mmap_len_6)	{ f(0,   LS1, EOVERFLOW); }	/* exceed */
DEF(mmap_len_7)2783 DEF(mmap_len_7)	{ f(1,   LS,  EOVERFLOW); }	/* exceed */
2784 /*
2785  * When you treat the offset as 32bit, offset will be 0 and thus it
2786  * incorrectly succeeds.
2787  */
DEF(mmap_len_8)2788 DEF(mmap_len_8)	{ f(LS, 1ULL << 32, EOVERFLOW); }
2789 #undef f
2790 
2791 /*
2792  * mmap() the same descriptor twice.
2793  */
DEF(mmap_twice)2794 DEF(mmap_twice)
2795 {
2796 	struct audio_info ai;
2797 	int fd;
2798 	int r;
2799 	int len;
2800 	void *ptr1;
2801 	void *ptr2;
2802 
2803 	TEST("mmap_twice");
2804 	if ((props & AUDIO_PROP_MMAP) == 0) {
2805 		XP_SKIP("This test is only for mmap-able device");
2806 		return;
2807 	}
2808 #if !defined(NO_RUMP)
2809 	if (use_rump) {
2810 		XP_SKIP("rump doesn't support mmap");
2811 		return;
2812 	}
2813 #endif
2814 
2815 	fd = OPEN(devaudio, O_WRONLY);
2816 	REQUIRED_SYS_OK(fd);
2817 
2818 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "get");
2819 	REQUIRED_SYS_EQ(0, r);
2820 	len = ai.play.buffer_size;
2821 
2822 	ptr1 = MMAP(NULL, len, PROT_WRITE, MAP_FILE, fd, 0);
2823 	XP_SYS_PTR(0, ptr1);
2824 
2825 	/* XXX I'm not sure this sucess is intended.  Anyway I follow it */
2826 	ptr2 = MMAP(NULL, len, PROT_WRITE, MAP_FILE, fd, 0);
2827 	XP_SYS_PTR(0, ptr2);
2828 
2829 	if (ptr2 != MAP_FAILED) {
2830 		r = MUNMAP(ptr2, len);
2831 		XP_SYS_EQ(0, r);
2832 	}
2833 	if (ptr1 != MAP_FAILED) {
2834 		r = MUNMAP(ptr1, len);
2835 		XP_SYS_EQ(0, r);
2836 	}
2837 
2838 	r = CLOSE(fd);
2839 	XP_SYS_EQ(0, r);
2840 
2841 	reset_after_mmap();
2842 }
2843 
2844 /*
2845  * mmap() different descriptors.
2846  */
DEF(mmap_multi)2847 DEF(mmap_multi)
2848 {
2849 	struct audio_info ai;
2850 	int fd0;
2851 	int fd1;
2852 	int r;
2853 	int len;
2854 	void *ptr0;
2855 	void *ptr1;
2856 
2857 	TEST("mmap_multi");
2858 	if (netbsd < 8) {
2859 		XP_SKIP("Multiple open is not supported");
2860 		return;
2861 	}
2862 	if ((props & AUDIO_PROP_MMAP) == 0) {
2863 		XP_SKIP("This test is only for mmap-able device");
2864 		return;
2865 	}
2866 #if !defined(NO_RUMP)
2867 	if (use_rump) {
2868 		XP_SKIP("rump doesn't support mmap");
2869 		return;
2870 	}
2871 #endif
2872 
2873 	fd0 = OPEN(devaudio, O_WRONLY);
2874 	REQUIRED_SYS_OK(fd0);
2875 
2876 	r = IOCTL(fd0, AUDIO_GETBUFINFO, &ai, "get");
2877 	REQUIRED_SYS_EQ(0, r);
2878 	len = ai.play.buffer_size;
2879 
2880 	fd1 = OPEN(devaudio, O_WRONLY);
2881 	REQUIRED_SYS_OK(fd1);
2882 
2883 	ptr0 = MMAP(NULL, len, PROT_WRITE, MAP_FILE, fd0, 0);
2884 	XP_SYS_PTR(0, ptr0);
2885 
2886 	ptr1 = MMAP(NULL, len,  PROT_WRITE, MAP_FILE, fd1, 0);
2887 	XP_SYS_PTR(0, ptr1);
2888 
2889 	if (ptr0 != MAP_FAILED) {
2890 		r = MUNMAP(ptr1, len);
2891 		XP_SYS_EQ(0, r);
2892 	}
2893 
2894 	r = CLOSE(fd1);
2895 	XP_SYS_EQ(0, r);
2896 
2897 	if (ptr1 != MAP_FAILED) {
2898 		r = MUNMAP(ptr0, len);
2899 		XP_SYS_EQ(0, r);
2900 	}
2901 
2902 	r = CLOSE(fd0);
2903 	XP_SYS_EQ(0, r);
2904 
2905 	reset_after_mmap();
2906 }
2907 
2908 #define IN	POLLIN
2909 #define OUT	POLLOUT
2910 /*
2911  * Whether poll() succeeds with specified mode.
2912  */
2913 void
test_poll_mode(int mode,int events,int expected_revents)2914 test_poll_mode(int mode, int events, int expected_revents)
2915 {
2916 	struct pollfd pfd;
2917 	const char *events_str;
2918 	int fd;
2919 	int r;
2920 	int expected_r;
2921 
2922 	if (events == IN) {
2923 		events_str = "IN";
2924 	} else if (events == OUT) {
2925 		events_str = "OUT";
2926 	} else if (events == (IN | OUT)) {
2927 		events_str = "INOUT";
2928 	} else {
2929 		events_str = "?";
2930 	}
2931 	TEST("poll_mode_%s_%s", openmode_str[mode] + 2, events_str);
2932 	if (mode2aumode(mode) == 0) {
2933 		XP_SKIP("Operation not allowed on this hardware property");
2934 		return;
2935 	}
2936 
2937 	expected_r = (expected_revents != 0) ? 1 : 0;
2938 
2939 	fd = OPEN(devaudio, mode);
2940 	REQUIRED_SYS_OK(fd);
2941 
2942 	/* Wait a bit to be recorded. */
2943 	usleep(100 * 1000);
2944 
2945 	memset(&pfd, 0, sizeof(pfd));
2946 	pfd.fd = fd;
2947 	pfd.events = events;
2948 
2949 	r = POLL(&pfd, 1, 100);
2950 	/* It's a bit complicated..  */
2951 	if (r < 0 || r > 1) {
2952 		/*
2953 		 * Check these two cases first:
2954 		 * - system call fails.
2955 		 * - poll() with one nfds returns >1.  It's strange.
2956 		 */
2957 		XP_SYS_EQ(expected_r, r);
2958 	} else {
2959 		/*
2960 		 * Otherwise, poll() returned 0 or 1.
2961 		 */
2962 		DPRINTF("  > pfd.revents=%s\n", event_tostr(pfd.revents));
2963 
2964 		/* NetBSD7,8 have several strange behavior.  It must be bug. */
2965 
2966 		XP_SYS_EQ(expected_r, r);
2967 		XP_EQ(expected_revents, pfd.revents);
2968 	}
2969 	r = CLOSE(fd);
2970 	XP_SYS_EQ(0, r);
2971 }
DEF(poll_mode_RDONLY_IN)2972 DEF(poll_mode_RDONLY_IN)	{ test_poll_mode(O_RDONLY, IN,     IN); }
DEF(poll_mode_RDONLY_OUT)2973 DEF(poll_mode_RDONLY_OUT)	{ test_poll_mode(O_RDONLY, OUT,    0); }
DEF(poll_mode_RDONLY_INOUT)2974 DEF(poll_mode_RDONLY_INOUT)	{ test_poll_mode(O_RDONLY, IN|OUT, IN); }
DEF(poll_mode_WRONLY_IN)2975 DEF(poll_mode_WRONLY_IN)	{ test_poll_mode(O_WRONLY, IN,     0); }
DEF(poll_mode_WRONLY_OUT)2976 DEF(poll_mode_WRONLY_OUT)	{ test_poll_mode(O_WRONLY, OUT,	   OUT); }
DEF(poll_mode_WRONLY_INOUT)2977 DEF(poll_mode_WRONLY_INOUT)	{ test_poll_mode(O_WRONLY, IN|OUT, OUT); }
DEF(poll_mode_RDWR_IN)2978 DEF(poll_mode_RDWR_IN)		{
2979 	/* On half-duplex, O_RDWR is the same as O_WRONLY. */
2980 	if (hw_fulldup()) test_poll_mode(O_RDWR,   IN,     IN);
2981 	else		  test_poll_mode(O_RDWR,   IN,     0);
2982 }
DEF(poll_mode_RDWR_OUT)2983 DEF(poll_mode_RDWR_OUT)		{ test_poll_mode(O_RDWR,   OUT,	   OUT); }
DEF(poll_mode_RDWR_INOUT)2984 DEF(poll_mode_RDWR_INOUT)	{
2985 	/* On half-duplex, O_RDWR is the same as O_WRONLY. */
2986 	if (hw_fulldup()) test_poll_mode(O_RDWR,   IN|OUT, IN|OUT);
2987 	else		  test_poll_mode(O_RDWR,   IN|OUT,    OUT);
2988 }
2989 
2990 /*
2991  * Poll(OUT) when buffer is empty.
2992  */
DEF(poll_out_empty)2993 DEF(poll_out_empty)
2994 {
2995 	struct pollfd pfd;
2996 	int fd;
2997 	int r;
2998 
2999 	TEST("poll_out_empty");
3000 
3001 	fd = OPEN(devaudio, O_WRONLY);
3002 	REQUIRED_SYS_OK(fd);
3003 
3004 	memset(&pfd, 0, sizeof(pfd));
3005 	pfd.fd = fd;
3006 	pfd.events = POLLOUT;
3007 
3008 	/* Check when empty.  It should succeed even if timeout == 0 */
3009 	r = POLL(&pfd, 1, 0);
3010 	XP_SYS_EQ(1, r);
3011 	XP_EQ(POLLOUT, pfd.revents);
3012 
3013 	r = CLOSE(fd);
3014 	XP_SYS_EQ(0, r);
3015 }
3016 
3017 /*
3018  * Poll(OUT) when buffer is full.
3019  */
DEF(poll_out_full)3020 DEF(poll_out_full)
3021 {
3022 	struct audio_info ai;
3023 	struct pollfd pfd;
3024 	int fd;
3025 	int r;
3026 	char *buf;
3027 	int buflen;
3028 
3029 	TEST("poll_out_full");
3030 
3031 	fd = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3032 	REQUIRED_SYS_OK(fd);
3033 
3034 	/* Pause */
3035 	AUDIO_INITINFO(&ai);
3036 	ai.play.pause = 1;
3037 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "");
3038 	XP_SYS_EQ(0, r);
3039 
3040 	/* Get buffer size */
3041 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3042 	XP_SYS_EQ(0, r);
3043 
3044 	/* Write until full */
3045 	buflen = ai.play.buffer_size;
3046 	buf = (char *)malloc(buflen);
3047 	REQUIRED_IF(buf != NULL);
3048 	memset(buf, 0xff, buflen);
3049 	do {
3050 		r = WRITE(fd, buf, buflen);
3051 	} while (r == buflen);
3052 	if (r == -1) {
3053 		XP_SYS_NG(EAGAIN, r);
3054 	}
3055 
3056 	/* Do poll */
3057 	memset(&pfd, 0, sizeof(pfd));
3058 	pfd.fd = fd;
3059 	pfd.events = POLLOUT;
3060 	r = POLL(&pfd, 1, 0);
3061 	XP_SYS_EQ(0, r);
3062 	XP_EQ(0, pfd.revents);
3063 
3064 	r = CLOSE(fd);
3065 	XP_SYS_EQ(0, r);
3066 	free(buf);
3067 }
3068 
3069 /*
3070  * Poll(OUT) when buffer is full but hiwat sets lower than full.
3071  */
DEF(poll_out_hiwat)3072 DEF(poll_out_hiwat)
3073 {
3074 	struct audio_info ai;
3075 	struct pollfd pfd;
3076 	int fd;
3077 	int r;
3078 	char *buf;
3079 	int buflen;
3080 	int newhiwat;
3081 
3082 	TEST("poll_out_hiwat");
3083 
3084 	fd = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3085 	REQUIRED_SYS_OK(fd);
3086 
3087 	/* Get buffer size and hiwat */
3088 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3089 	XP_SYS_EQ(0, r);
3090 	/* Change hiwat some different value */
3091 	newhiwat = ai.lowat;
3092 
3093 	/* Set pause and hiwat */
3094 	AUDIO_INITINFO(&ai);
3095 	ai.play.pause = 1;
3096 	ai.hiwat = newhiwat;
3097 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause=1;hiwat");
3098 	XP_SYS_EQ(0, r);
3099 
3100 	/* Get the set hiwat again */
3101 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3102 	XP_SYS_EQ(0, r);
3103 
3104 	/* Write until full */
3105 	buflen = ai.blocksize * ai.hiwat;
3106 	buf = (char *)malloc(buflen);
3107 	REQUIRED_IF(buf != NULL);
3108 	memset(buf, 0xff, buflen);
3109 	do {
3110 		r = WRITE(fd, buf, buflen);
3111 	} while (r == buflen);
3112 	if (r == -1) {
3113 		XP_SYS_NG(EAGAIN, r);
3114 	}
3115 
3116 	/* Do poll */
3117 	memset(&pfd, 0, sizeof(pfd));
3118 	pfd.fd = fd;
3119 	pfd.events = POLLOUT;
3120 	r = POLL(&pfd, 1, 0);
3121 	XP_SYS_EQ(0, r);
3122 	XP_EQ(0, pfd.revents);
3123 
3124 	r = CLOSE(fd);
3125 	XP_SYS_EQ(0, r);
3126 	free(buf);
3127 }
3128 
3129 /*
3130  * Unpause from buffer full, POLLOUT should raise.
3131  * XXX poll(2) on NetBSD7 is really incomplete and weird.  I don't test it.
3132  */
DEF(poll_out_unpause)3133 DEF(poll_out_unpause)
3134 {
3135 	struct audio_info ai;
3136 	struct pollfd pfd;
3137 	int fd;
3138 	int r;
3139 	char *buf;
3140 	int buflen;
3141 	u_int blocksize;
3142 	int hiwat;
3143 	int lowat;
3144 
3145 	TEST("poll_out_unpause");
3146 	if (netbsd < 8) {
3147 		XP_SKIP("NetBSD7's poll() is too incomplete to test.");
3148 		return;
3149 	}
3150 
3151 	/* Non-blocking open */
3152 	fd = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3153 	REQUIRED_SYS_OK(fd);
3154 
3155 	/* Adjust block size and hiwat/lowat to make the test time 1sec */
3156 	blocksize = 1000;	/* 1/8 sec in mulaw,1ch,8000Hz */
3157 	hiwat = 12;		/* 1.5sec */
3158 	lowat = 4;		/* 0.5sec */
3159 	AUDIO_INITINFO(&ai);
3160 	ai.blocksize = blocksize;
3161 	ai.hiwat = hiwat;
3162 	ai.lowat = lowat;
3163 	/* and also set encoding */
3164 	/*
3165 	 * XXX NetBSD7 has different results depending on whether the input
3166 	 * encoding is emulated (AUDIO_ENCODINGFLAG_EMULATED) or not.  It's
3167 	 * not easy to ensure this situation on all hardware environment.
3168 	 * On NetBSD9, the result is the same regardless of input encoding.
3169 	 */
3170 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "blocksize=%d", blocksize);
3171 	XP_SYS_EQ(0, r);
3172 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3173 	if (ai.blocksize != blocksize) {
3174 		/*
3175 		 * NetBSD9 can not change the blocksize.  Then,
3176 		 * adjust using hiwat/lowat.
3177 		 */
3178 		blocksize = ai.blocksize;
3179 		hiwat = howmany(8000 * 1.5, blocksize);
3180 		lowat = howmany(8000 * 0.5, blocksize);
3181 	}
3182 	/* Anyway, set the parameters */
3183 	AUDIO_INITINFO(&ai);
3184 	ai.blocksize = blocksize;
3185 	ai.hiwat = hiwat;
3186 	ai.lowat = lowat;
3187 	ai.play.pause = 1;
3188 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause=1");
3189 	XP_SYS_EQ(0, r);
3190 
3191 	/* Get the set parameters again */
3192 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3193 	XP_SYS_EQ(0, r);
3194 
3195 	/* Write until full */
3196 	buflen = ai.blocksize * ai.hiwat;
3197 	buf = (char *)malloc(buflen);
3198 	REQUIRED_IF(buf != NULL);
3199 	memset(buf, 0xff, buflen);
3200 	do {
3201 		r = WRITE(fd, buf, buflen);
3202 	} while (r == buflen);
3203 	if (r == -1) {
3204 		XP_SYS_NG(EAGAIN, r);
3205 	}
3206 
3207 	/* At this time, POLLOUT should not be set because buffer is full */
3208 	memset(&pfd, 0, sizeof(pfd));
3209 	pfd.fd = fd;
3210 	pfd.events = POLLOUT;
3211 	r = POLL(&pfd, 1, 0);
3212 	XP_SYS_EQ(0, r);
3213 	XP_EQ(0, pfd.revents);
3214 
3215 	/* Unpause */
3216 	AUDIO_INITINFO(&ai);
3217 	ai.play.pause = 0;
3218 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause=0");
3219 	XP_SYS_EQ(0, r);
3220 
3221 	/*
3222 	 * When unpause occurs:
3223 	 * - NetBSD7 (emul=0) -> the buffer remains.
3224 	 * - NetBSD7 (emul=1) -> the buffer is cleared.
3225 	 * - NetBSD8          -> the buffer remains.
3226 	 * - NetBSD9          -> the buffer remains.
3227 	 */
3228 
3229 	/* Check poll() up to 2sec */
3230 	pfd.revents = 0;
3231 	r = POLL(&pfd, 1, 2000);
3232 	XP_SYS_EQ(1, r);
3233 	XP_EQ(POLLOUT, pfd.revents);
3234 
3235 	/*
3236 	 * Since POLLOUT is set, it should be writable.
3237 	 * But at this time, no all buffer may be writable.
3238 	 */
3239 	r = WRITE(fd, buf, buflen);
3240 	XP_SYS_OK(r);
3241 
3242 	/* Flush it because there is no need to play it */
3243 	r = IOCTL(fd, AUDIO_FLUSH, NULL, "");
3244 	XP_SYS_EQ(0, r);
3245 
3246 	r = CLOSE(fd);
3247 	XP_SYS_EQ(0, r);
3248 	free(buf);
3249 }
3250 
3251 /*
3252  * poll(2) must not be affected by playback of other descriptors.
3253  */
DEF(poll_out_simul)3254 DEF(poll_out_simul)
3255 {
3256 	struct audio_info ai;
3257 	struct pollfd pfd[2];
3258 	int fd[2];
3259 	int r;
3260 	char *buf;
3261 	u_int blocksize;
3262 	int hiwat;
3263 	int lowat;
3264 	int buflen;
3265 	int time;
3266 
3267 	TEST("poll_out_simul");
3268 	if (netbsd < 8) {
3269 		XP_SKIP("Multiple open is not supported");
3270 		return;
3271 	}
3272 
3273 	/* Make sure that it's not affected by descriptor order */
3274 	for (int i = 0; i < 2; i++) {
3275 		int a = i;
3276 		int b = 1 - i;
3277 
3278 		fd[0] = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3279 		REQUIRED_SYS_OK(fd[0]);
3280 		fd[1] = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3281 		REQUIRED_SYS_OK(fd[1]);
3282 
3283 		/*
3284 		 * Adjust block size and hiwat/lowat.
3285 		 * I want to choice suitable blocksize (if possible).
3286 		 */
3287 		blocksize = 1000;	/* 1/8 sec in mulaw,1ch,8000Hz */
3288 		hiwat = 12;		/* 1.5sec */
3289 		lowat = 4;		/* 0.5sec */
3290 		AUDIO_INITINFO(&ai);
3291 		ai.blocksize = blocksize;
3292 		ai.hiwat = hiwat;
3293 		ai.lowat = lowat;
3294 		r = IOCTL(fd[0], AUDIO_SETINFO, &ai, "blocksize=1000");
3295 		XP_SYS_EQ(0, r);
3296 		r = IOCTL(fd[0], AUDIO_GETBUFINFO, &ai, "read back blocksize");
3297 		if (ai.blocksize != blocksize) {
3298 			/*
3299 			 * NetBSD9 can not change the blocksize.  Then,
3300 			 * adjust using hiwat/lowat.
3301 			 */
3302 			blocksize = ai.blocksize;
3303 			hiwat = howmany(8000 * 1.5, blocksize);
3304 			lowat = howmany(8000 * 0.5, blocksize);
3305 		}
3306 		/* Anyway, set the parameters */
3307 		AUDIO_INITINFO(&ai);
3308 		ai.blocksize = blocksize;
3309 		ai.hiwat = hiwat;
3310 		ai.lowat = lowat;
3311 		/* Pause fdA */
3312 		ai.play.pause = 1;
3313 		r = IOCTL(fd[a], AUDIO_SETINFO, &ai, "pause=1");
3314 		XP_SYS_EQ(0, r);
3315 		/* Unpause fdB */
3316 		ai.play.pause = 0;
3317 		r = IOCTL(fd[b], AUDIO_SETINFO, &ai, "pause=0");
3318 		XP_SYS_EQ(0, r);
3319 
3320 		/* Get again. XXX two individual ioctls are correct */
3321 		r = IOCTL(fd[0], AUDIO_GETBUFINFO, &ai, "");
3322 		XP_SYS_EQ(0, r);
3323 		DPRINTF("  > blocksize=%d lowat=%d hiwat=%d\n",
3324 			ai.blocksize, ai.lowat, ai.hiwat);
3325 
3326 		/* Enough long time than the playback time */
3327 		time = (ai.hiwat - ai.lowat) * blocksize / 8;  /*[msec]*/
3328 		time *= 2;
3329 
3330 		/* Write fdA full */
3331 		buflen = blocksize * ai.lowat;
3332 		buf = (char *)malloc(buflen);
3333 		REQUIRED_IF(buf != NULL);
3334 		memset(buf, 0xff, buflen);
3335 		do {
3336 			r = WRITE(fd[a], buf, buflen);
3337 		} while (r == buflen);
3338 		if (r == -1) {
3339 			XP_SYS_NG(EAGAIN, r);
3340 		}
3341 
3342 		/* POLLOUT should not be set, because fdA is buffer full */
3343 		memset(pfd, 0, sizeof(pfd));
3344 		pfd[0].fd = fd[a];
3345 		pfd[0].events = POLLOUT;
3346 		r = POLL(pfd, 1, 0);
3347 		XP_SYS_EQ(0, r);
3348 		XP_EQ(0, pfd[0].revents);
3349 
3350 		/* Write fdB at least lowat */
3351 		r = WRITE(fd[b], buf, buflen);
3352 		XP_SYS_EQ(buflen, r);
3353 		r = WRITE(fd[b], buf, buflen);
3354 		if (r == -1) {
3355 			XP_SYS_NG(EAGAIN, r);
3356 		}
3357 
3358 		/* Only fdB should become POLLOUT */
3359 		memset(pfd, 0, sizeof(pfd));
3360 		pfd[0].fd = fd[0];
3361 		pfd[0].events = POLLOUT;
3362 		pfd[1].fd = fd[1];
3363 		pfd[1].events = POLLOUT;
3364 		r = POLL(pfd, 2, time);
3365 		XP_SYS_EQ(1, r);
3366 		if (r != -1) {
3367 			XP_EQ(0, pfd[a].revents);
3368 			XP_EQ(POLLOUT, pfd[b].revents);
3369 		}
3370 
3371 		/* Drop the rest */
3372 		r = IOCTL(fd[0], AUDIO_FLUSH, NULL, "");
3373 		XP_SYS_EQ(0, r);
3374 		r = IOCTL(fd[1], AUDIO_FLUSH, NULL, "");
3375 		XP_SYS_EQ(0, r);
3376 
3377 		r = CLOSE(fd[0]);
3378 		XP_SYS_EQ(0, r);
3379 		r = CLOSE(fd[1]);
3380 		XP_SYS_EQ(0, r);
3381 		free(buf);
3382 
3383 		xxx_close_wait();
3384 	}
3385 }
3386 
3387 /*
3388  * Open with READ mode starts recording immediately.
3389  * Of course, audioctl doesn't start.
3390  */
3391 void
test_poll_in_open(const char * devname)3392 test_poll_in_open(const char *devname)
3393 {
3394 	struct audio_info ai;
3395 	struct pollfd pfd;
3396 	char buf[4096];
3397 	char devfile[16];
3398 	int fd;
3399 	int r;
3400 	bool is_audioctl;
3401 
3402 	TEST("poll_in_open_%s", devname);
3403 	if (hw_canrec() == 0) {
3404 		XP_SKIP("This test is only for recordable device");
3405 		return;
3406 	}
3407 
3408 	snprintf(devfile, sizeof(devfile), "/dev/%s%d", devname, unit);
3409 	is_audioctl = (strcmp(devname, "audioctl") == 0);
3410 
3411 	fd = OPEN(devfile, O_RDONLY);
3412 	REQUIRED_SYS_OK(fd);
3413 
3414 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3415 	REQUIRED_SYS_EQ(0, r);
3416 	if (is_audioctl) {
3417 		/* opening /dev/audioctl doesn't start recording. */
3418 		XP_EQ(0, ai.record.active);
3419 	} else {
3420 		/* opening /dev/{audio,sound} starts recording. */
3421 		/*
3422 		 * On NetBSD7/8, opening /dev/sound doesn't start recording.
3423 		 * It must be a bug.
3424 		 */
3425 		XP_EQ(1, ai.record.active);
3426 	}
3427 
3428 	memset(&pfd, 0, sizeof(pfd));
3429 	pfd.fd = fd;
3430 	pfd.events = POLLIN;
3431 	r = POLL(&pfd, 1, 1000);
3432 	if (is_audioctl) {
3433 		/*
3434 		 * poll-ing /dev/audioctl always fails.
3435 		 * XXX Returning error instead of timeout should be better(?).
3436 		 */
3437 		REQUIRED_SYS_EQ(0, r);
3438 	} else {
3439 		/*
3440 		 * poll-ing /dev/{audio,sound} will succeed when recorded
3441 		 * data is arrived.
3442 		 */
3443 		/*
3444 		 * On NetBSD7/8, opening /dev/sound doesn't start recording.
3445 		 * It must be a bug.
3446 		 */
3447 		REQUIRED_SYS_EQ(1, r);
3448 
3449 		/* In this case, read() should succeed. */
3450 		r = READ(fd, buf, sizeof(buf));
3451 		XP_SYS_OK(r);
3452 		XP_NE(0, r);
3453 	}
3454 
3455 	r = CLOSE(fd);
3456 	XP_SYS_EQ(0, r);
3457 }
DEF(poll_in_open_audio)3458 DEF(poll_in_open_audio)		{ test_poll_in_open("audio"); }
DEF(poll_in_open_sound)3459 DEF(poll_in_open_sound)		{ test_poll_in_open("sound"); }
DEF(poll_in_open_audioctl)3460 DEF(poll_in_open_audioctl)	{ test_poll_in_open("audioctl"); }
3461 
3462 /*
3463  * poll(2) must not be affected by other recording descriptors even if
3464  * playback descriptor waits with POLLIN (though it's not normal usage).
3465  * In other words, two POLLIN must not interfere.
3466  */
DEF(poll_in_simul)3467 DEF(poll_in_simul)
3468 {
3469 	struct audio_info ai;
3470 	struct pollfd pfd;
3471 	int fd[2];
3472 	int r;
3473 	char *buf;
3474 	int blocksize;
3475 
3476 	TEST("poll_in_simul");
3477 	if (netbsd < 8) {
3478 		XP_SKIP("Multiple open is not supported");
3479 		return;
3480 	}
3481 	if (hw_fulldup() == 0) {
3482 		XP_SKIP("This test is only for full-duplex device");
3483 		return;
3484 	}
3485 
3486 	int play = 0;
3487 	int rec = 1;
3488 
3489 	fd[play] = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3490 	REQUIRED_SYS_OK(fd[play]);
3491 	fd[rec] = OPEN(devaudio, O_RDONLY);
3492 	REQUIRED_SYS_OK(fd[rec]);
3493 
3494 	/* Get block size */
3495 	r = IOCTL(fd[rec], AUDIO_GETBUFINFO, &ai, "");
3496 	XP_SYS_EQ(0, r);
3497 	blocksize = ai.blocksize;
3498 
3499 	buf = (char *)malloc(blocksize);
3500 	REQUIRED_IF(buf != NULL);
3501 
3502 	/*
3503 	 * At first, make sure the playback one doesn't return POLLIN.
3504 	 */
3505 	memset(&pfd, 0, sizeof(pfd));
3506 	pfd.fd = fd[play];
3507 	pfd.events = POLLIN;
3508 	r = POLL(&pfd, 1, 0);
3509 	if (r == 0 && pfd.revents == 0) {
3510 		XP_SYS_EQ(0, r);
3511 		XP_EQ(0, pfd.revents);
3512 	} else {
3513 		XP_FAIL("play fd returns POLLIN");
3514 		goto abort;
3515 	}
3516 
3517 	/* Start recording */
3518 	r = READ(fd[rec], buf, blocksize);
3519 	XP_SYS_EQ(blocksize, r);
3520 
3521 	/* Poll()ing playback descriptor with POLLIN should not raise */
3522 	r = POLL(&pfd, 1, 1000);
3523 	XP_SYS_EQ(0, r);
3524 	XP_EQ(0, pfd.revents);
3525 
3526 	/* Poll()ing recording descriptor with POLLIN should raise */
3527 	pfd.fd = fd[rec];
3528 	r = POLL(&pfd, 1, 0);
3529 	XP_SYS_EQ(1, r);
3530 	XP_EQ(POLLIN, pfd.revents);
3531 
3532 abort:
3533 	r = CLOSE(fd[play]);
3534 	XP_SYS_EQ(0, r);
3535 	r = CLOSE(fd[rec]);
3536 	XP_SYS_EQ(0, r);
3537 	free(buf);
3538 }
3539 
3540 /*
3541  * Whether kqueue() succeeds with specified mode.
3542  */
3543 void
test_kqueue_mode(int openmode,int filt,int expected)3544 test_kqueue_mode(int openmode, int filt, int expected)
3545 {
3546 	struct kevent kev;
3547 	struct timespec ts;
3548 	int fd;
3549 	int kq;
3550 	int r;
3551 
3552 	TEST("kqueue_mode_%s_%s",
3553 	    openmode_str[openmode] + 2,
3554 	    (filt == EVFILT_READ) ? "READ" : "WRITE");
3555 	if (mode2aumode(openmode) == 0) {
3556 		XP_SKIP("Operation not allowed on this hardware property");
3557 		return;
3558 	}
3559 
3560 	ts.tv_sec = 0;
3561 	ts.tv_nsec = 100 * 1000 * 1000;	// 100msec
3562 
3563 	kq = KQUEUE();
3564 	XP_SYS_OK(kq);
3565 
3566 	fd = OPEN(devaudio, openmode);
3567 	REQUIRED_SYS_OK(fd);
3568 
3569 	/*
3570 	 * Check whether the specified filter can be set.
3571 	 * Any filters can always be set, even if pointless combination.
3572 	 * For example, EVFILT_READ can be set on O_WRONLY descriptor
3573 	 * though it will never raise.
3574 	 * I will not mention about good or bad of this behavior here.
3575 	 */
3576 	EV_SET(&kev, fd, filt, EV_ADD, 0, 0, 0);
3577 	r = KEVENT_SET(kq, &kev, 1);
3578 	XP_SYS_EQ(0, r);
3579 
3580 	if (r == 0) {
3581 		/* If the filter can be set, try kevent(poll) */
3582 		r = KEVENT_POLL(kq, &kev, 1, &ts);
3583 		XP_SYS_EQ(expected, r);
3584 
3585 		/* Delete it */
3586 		EV_SET(&kev, fd, filt, EV_DELETE, 0, 0, 0);
3587 		r = KEVENT_SET(kq, &kev, 1);
3588 		XP_SYS_EQ(0, r);
3589 	}
3590 
3591 	r = CLOSE(fd);
3592 	XP_SYS_EQ(0, r);
3593 	r = CLOSE(kq);
3594 	XP_SYS_EQ(0, r);
3595 }
DEF(kqueue_mode_RDONLY_READ)3596 DEF(kqueue_mode_RDONLY_READ) {
3597 	/* Should raise */
3598 	test_kqueue_mode(O_RDONLY, EVFILT_READ, 1);
3599 }
DEF(kqueue_mode_RDONLY_WRITE)3600 DEF(kqueue_mode_RDONLY_WRITE) {
3601 	/* Should never raise (NetBSD7 has bugs) */
3602 	int expected = (netbsd < 8) ? 1 : 0;
3603 	test_kqueue_mode(O_RDONLY, EVFILT_WRITE, expected);
3604 }
DEF(kqueue_mode_WRONLY_READ)3605 DEF(kqueue_mode_WRONLY_READ) {
3606 	/* Should never raise */
3607 	test_kqueue_mode(O_WRONLY, EVFILT_READ, 0);
3608 }
DEF(kqueue_mode_WRONLY_WRITE)3609 DEF(kqueue_mode_WRONLY_WRITE) {
3610 	/* Should raise */
3611 	test_kqueue_mode(O_WRONLY, EVFILT_WRITE, 1);
3612 }
DEF(kqueue_mode_RDWR_READ)3613 DEF(kqueue_mode_RDWR_READ) {
3614 	/* Should raise on fulldup but not on halfdup, on NetBSD9 */
3615 	int expected = hw_fulldup() ? 1 : 0;
3616 	test_kqueue_mode(O_RDWR, EVFILT_READ, expected);
3617 }
DEF(kqueue_mode_RDWR_WRITE)3618 DEF(kqueue_mode_RDWR_WRITE) {
3619 	/* Should raise */
3620 	test_kqueue_mode(O_RDWR, EVFILT_WRITE, 1);
3621 }
3622 
3623 /*
3624  * kqueue(2) when buffer is empty.
3625  */
DEF(kqueue_empty)3626 DEF(kqueue_empty)
3627 {
3628 	struct audio_info ai;
3629 	struct kevent kev;
3630 	struct timespec ts;
3631 	int kq;
3632 	int fd;
3633 	int r;
3634 
3635 	TEST("kqueue_empty");
3636 
3637 	fd = OPEN(devaudio, O_WRONLY);
3638 	REQUIRED_SYS_OK(fd);
3639 
3640 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3641 	XP_SYS_EQ(0, r);
3642 
3643 	kq = KQUEUE();
3644 	XP_SYS_OK(kq);
3645 
3646 	EV_SET(&kev, fd, EV_ADD, EVFILT_WRITE, 0, 0, 0);
3647 	r = KEVENT_SET(kq, &kev, 1);
3648 	XP_SYS_EQ(0, r);
3649 
3650 	/* When the buffer is empty, it should succeed even if timeout == 0 */
3651 	memset(&ts, 0, sizeof(ts));
3652 	r = KEVENT_POLL(kq, &kev, 1, &ts);
3653 	XP_SYS_EQ(1, r);
3654 	XP_EQ(fd, kev.ident);
3655 	/*
3656 	 * XXX According to kqueue(2) manpage, returned kev.data contains
3657 	 * "the amount of space remaining in the write buffer".
3658 	 * NetBSD7 returns buffer_size.  Shouldn't it be blocksize * hiwat?
3659 	 */
3660 	/* XP_EQ(ai.blocksize * ai.hiwat, kev.data); */
3661 	XP_EQ(ai.play.buffer_size, kev.data);
3662 
3663 	r = CLOSE(fd);
3664 	XP_SYS_EQ(0, r);
3665 	r = CLOSE(kq);
3666 	XP_SYS_EQ(0, r);
3667 }
3668 
3669 /*
3670  * kqueue(2) when buffer is full.
3671  */
DEF(kqueue_full)3672 DEF(kqueue_full)
3673 {
3674 	struct audio_info ai;
3675 	struct kevent kev;
3676 	struct timespec ts;
3677 	int kq;
3678 	int fd;
3679 	int r;
3680 	char *buf;
3681 	int buflen;
3682 
3683 	TEST("kqueue_full");
3684 
3685 	fd = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3686 	REQUIRED_SYS_OK(fd);
3687 
3688 	/* Pause */
3689 	AUDIO_INITINFO(&ai);
3690 	ai.play.pause = 1;
3691 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "");
3692 	XP_SYS_EQ(0, r);
3693 
3694 	/* Get buffer size */
3695 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3696 	XP_SYS_EQ(0, r);
3697 
3698 	/* Write until full */
3699 	buflen = ai.play.buffer_size;
3700 	buf = (char *)malloc(buflen);
3701 	REQUIRED_IF(buf != NULL);
3702 	memset(buf, 0xff, buflen);
3703 	do {
3704 		r = WRITE(fd, buf, buflen);
3705 	} while (r == buflen);
3706 	if (r == -1) {
3707 		XP_SYS_NG(EAGAIN, r);
3708 	}
3709 
3710 	kq = KQUEUE();
3711 	XP_SYS_OK(kq);
3712 
3713 	EV_SET(&kev, fd, EV_ADD, EVFILT_WRITE, 0, 0, 0);
3714 	r = KEVENT_SET(kq, &kev, 1);
3715 	XP_SYS_EQ(0, r);
3716 
3717 	/* kevent() should not raise */
3718 	ts.tv_sec = 0;
3719 	ts.tv_nsec = 100L * 1000 * 1000;	/* 100msec */
3720 	r = KEVENT_POLL(kq, &kev, 1, &ts);
3721 	XP_SYS_EQ(0, r);
3722 	if (r > 0) {
3723 		XP_EQ(fd, kev.ident);
3724 		XP_EQ(0, kev.data);
3725 	}
3726 
3727 	r = CLOSE(fd);
3728 	XP_SYS_EQ(0, r);
3729 	r = CLOSE(kq);
3730 	XP_SYS_EQ(0, r);
3731 	free(buf);
3732 }
3733 
3734 /*
3735  * kqueue(2) when buffer is full but hiwat sets lower than full.
3736  */
DEF(kqueue_hiwat)3737 DEF(kqueue_hiwat)
3738 {
3739 	struct audio_info ai;
3740 	struct kevent kev;
3741 	struct timespec ts;
3742 	int kq;
3743 	int fd;
3744 	int r;
3745 	char *buf;
3746 	int buflen;
3747 	int newhiwat;
3748 
3749 	TEST("kqueue_hiwat");
3750 
3751 	fd = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3752 	REQUIRED_SYS_OK(fd);
3753 
3754 	/* Get buffer size and hiwat */
3755 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "hiwat");
3756 	XP_SYS_EQ(0, r);
3757 	/* Change hiwat some different value */
3758 	newhiwat = ai.hiwat - 1;
3759 
3760 	/* Set pause and hiwat */
3761 	AUDIO_INITINFO(&ai);
3762 	ai.play.pause = 1;
3763 	ai.hiwat = newhiwat;
3764 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause=1;hiwat");
3765 	XP_SYS_EQ(0, r);
3766 
3767 	/* Get the set parameters again */
3768 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3769 	XP_SYS_EQ(0, r);
3770 	XP_EQ(1, ai.play.pause);
3771 	XP_EQ(newhiwat, ai.hiwat);
3772 
3773 	/* Write until full */
3774 	buflen = ai.blocksize * ai.hiwat;
3775 	buf = (char *)malloc(buflen);
3776 	REQUIRED_IF(buf != NULL);
3777 	memset(buf, 0xff, buflen);
3778 	do {
3779 		r = WRITE(fd, buf, buflen);
3780 	} while (r == buflen);
3781 	if (r == -1) {
3782 		XP_SYS_NG(EAGAIN, r);
3783 	}
3784 
3785 	kq = KQUEUE();
3786 	XP_SYS_OK(kq);
3787 
3788 	EV_SET(&kev, fd, EV_ADD, EVFILT_WRITE, 0, 0, 0);
3789 	r = KEVENT_SET(kq, &kev, 1);
3790 	XP_SYS_EQ(0, r);
3791 
3792 	/* Should not raise because it's not possible to write */
3793 	ts.tv_sec = 0;
3794 	ts.tv_nsec = 100L * 1000 * 1000;	/* 100msec */
3795 	r = KEVENT_POLL(kq, &kev, 1, &ts);
3796 	if (r > 0)
3797 		DEBUG_KEV("kev", &kev);
3798 	XP_SYS_EQ(0, r);
3799 
3800 	r = CLOSE(fd);
3801 	XP_SYS_EQ(0, r);
3802 	r = CLOSE(kq);
3803 	XP_SYS_EQ(0, r);
3804 	free(buf);
3805 }
3806 
3807 /*
3808  * Unpause from buffer full, kevent() should raise.
3809  */
DEF(kqueue_unpause)3810 DEF(kqueue_unpause)
3811 {
3812 	struct audio_info ai;
3813 	struct kevent kev;
3814 	struct timespec ts;
3815 	int fd;
3816 	int r;
3817 	int kq;
3818 	char *buf;
3819 	int buflen;
3820 	u_int blocksize;
3821 	int hiwat;
3822 	int lowat;
3823 
3824 	TEST("kqueue_unpause");
3825 
3826 	/* Non-blocking open */
3827 	fd = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3828 	REQUIRED_SYS_OK(fd);
3829 
3830 	/* Adjust block size and hiwat/lowat to make the test time 1sec */
3831 	blocksize = 1000;	/* 1/8 sec in mulaw,1ch,8000Hz */
3832 	hiwat = 12;		/* 1.5sec */
3833 	lowat = 4;		/* 0.5sec */
3834 	AUDIO_INITINFO(&ai);
3835 	ai.blocksize = blocksize;
3836 	ai.hiwat = hiwat;
3837 	ai.lowat = lowat;
3838 	/* and also set encoding */
3839 	/*
3840 	 * XXX NetBSD7 has different results depending on whether the input
3841 	 * encoding is emulated (AUDIO_ENCODINGFLAG_EMULATED) or not.  It's
3842 	 * not easy to ensure this situation on all hardware environment.
3843 	 * On NetBSD9, the result is the same regardless of input encoding.
3844 	 */
3845 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "blocksize=%d", blocksize);
3846 	XP_SYS_EQ(0, r);
3847 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3848 	if (ai.blocksize != blocksize) {
3849 		/*
3850 		 * NetBSD9 can not change the blocksize.  Then,
3851 		 * adjust using hiwat/lowat.
3852 		 */
3853 		blocksize = ai.blocksize;
3854 		hiwat = howmany(8000 * 1.5, blocksize);
3855 		lowat = howmany(8000 * 0.5, blocksize);
3856 	}
3857 	/* Anyway, set the parameters */
3858 	AUDIO_INITINFO(&ai);
3859 	ai.blocksize = blocksize;
3860 	ai.hiwat = hiwat;
3861 	ai.lowat = lowat;
3862 	ai.play.pause = 1;
3863 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause=1");
3864 	XP_SYS_EQ(0, r);
3865 
3866 	/* Get the set parameters again */
3867 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3868 	XP_SYS_EQ(0, r);
3869 	DPRINTF("  > blocksize=%d hiwat=%d lowat=%d buffer_size=%d\n",
3870 	    ai.blocksize, ai.hiwat, ai.lowat, ai.play.buffer_size);
3871 
3872 	/* Write until full */
3873 	buflen = ai.blocksize * ai.hiwat;
3874 	buf = (char *)malloc(buflen);
3875 	REQUIRED_IF(buf != NULL);
3876 	memset(buf, 0xff, buflen);
3877 	do {
3878 		r = WRITE(fd, buf, buflen);
3879 	} while (r == buflen);
3880 	if (r == -1) {
3881 		XP_SYS_NG(EAGAIN, r);
3882 	}
3883 
3884 	kq = KQUEUE();
3885 	XP_SYS_OK(kq);
3886 
3887 	EV_SET(&kev, fd, EV_ADD, EVFILT_WRITE, 0, 0, 0);
3888 	r = KEVENT_SET(kq, &kev, 1);
3889 	XP_SYS_EQ(0, r);
3890 
3891 	/* Unpause */
3892 	AUDIO_INITINFO(&ai);
3893 	ai.play.pause = 0;
3894 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause=0");
3895 	XP_SYS_EQ(0, r);
3896 
3897 	/* Check kevent() up to 2sec */
3898 	ts.tv_sec = 2;
3899 	ts.tv_nsec = 0;
3900 	r = KEVENT_POLL(kq, &kev, 1, &ts);
3901 	if (r >= 1)
3902 		DEBUG_KEV("kev", &kev);
3903 	if (netbsd < 8) {
3904 		/*
3905 		 * NetBSD7 with EMULATED_FLAG unset has bugs.  Unpausing
3906 		 * unintentionally clears buffer (and therefore it becomes
3907 		 * writable) but it doesn't raise EVFILT_WRITE.
3908 		 */
3909 	} else {
3910 		XP_SYS_EQ(1, r);
3911 	}
3912 
3913 	/* Flush it because there is no need to play it */
3914 	r = IOCTL(fd, AUDIO_FLUSH, NULL, "");
3915 	XP_SYS_EQ(0, r);
3916 
3917 	r = CLOSE(fd);
3918 	XP_SYS_EQ(0, r);
3919 	r = CLOSE(kq);
3920 	XP_SYS_EQ(0, r);
3921 	free(buf);
3922 }
3923 
3924 /*
3925  * kevent(2) must not be affected by other audio descriptors.
3926  */
DEF(kqueue_simul)3927 DEF(kqueue_simul)
3928 {
3929 	struct audio_info ai;
3930 	struct audio_info ai2;
3931 	struct kevent kev[2];
3932 	struct timespec ts;
3933 	int fd[2];
3934 	int r;
3935 	int kq;
3936 	u_int blocksize;
3937 	int hiwat;
3938 	int lowat;
3939 	char *buf;
3940 	int buflen;
3941 
3942 	TEST("kqueue_simul");
3943 	if (netbsd < 8) {
3944 		XP_SKIP("Multiple open is not supported");
3945 		return;
3946 	}
3947 
3948 	memset(&ts, 0, sizeof(ts));
3949 
3950 	/* Make sure that it's not affected by descriptor order */
3951 	for (int i = 0; i < 2; i++) {
3952 		int a = i;
3953 		int b = 1 - i;
3954 
3955 		fd[0] = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3956 		REQUIRED_SYS_OK(fd[0]);
3957 		fd[1] = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3958 		REQUIRED_SYS_OK(fd[1]);
3959 
3960 		/*
3961 		 * Adjust block size and hiwat/lowat.
3962 		 * I want to choice suitable blocksize (if possible).
3963 		 */
3964 		blocksize = 1000;	/* 1/8 sec in mulaw,1ch,8000Hz */
3965 		hiwat = 12;		/* 1.5sec */
3966 		lowat = 4;		/* 0.5sec */
3967 		AUDIO_INITINFO(&ai);
3968 		ai.blocksize = blocksize;
3969 		ai.hiwat = hiwat;
3970 		ai.lowat = lowat;
3971 		r = IOCTL(fd[0], AUDIO_SETINFO, &ai, "blocksize=1000");
3972 		XP_SYS_EQ(0, r);
3973 		r = IOCTL(fd[0], AUDIO_GETBUFINFO, &ai, "read back blocksize");
3974 		if (ai.blocksize != blocksize) {
3975 			/*
3976 			 * NetBSD9 can not change the blocksize.  Then,
3977 			 * adjust using hiwat/lowat.
3978 			 */
3979 			blocksize = ai.blocksize;
3980 			hiwat = howmany(8000 * 1.5, blocksize);
3981 			lowat = howmany(8000 * 0.5, blocksize);
3982 		}
3983 		/* Anyway, set the parameters to both */
3984 		AUDIO_INITINFO(&ai);
3985 		ai.blocksize = blocksize;
3986 		ai.hiwat = hiwat;
3987 		ai.lowat = lowat;
3988 		ai.play.pause = 1;
3989 		r = IOCTL(fd[a], AUDIO_SETINFO, &ai, "pause=1");
3990 		XP_SYS_EQ(0, r);
3991 		r = IOCTL(fd[b], AUDIO_SETINFO, &ai, "pause=1");
3992 		XP_SYS_EQ(0, r);
3993 
3994 		/* Write both until full */
3995 		buflen = ai.blocksize * ai.hiwat;
3996 		buf = (char *)malloc(buflen);
3997 		REQUIRED_IF(buf != NULL);
3998 		memset(buf, 0xff, buflen);
3999 		/* Write fdA */
4000 		do {
4001 			r = WRITE(fd[a], buf, buflen);
4002 		} while (r == buflen);
4003 		if (r == -1) {
4004 			XP_SYS_NG(EAGAIN, r);
4005 		}
4006 		/* Write fdB */
4007 		do {
4008 			r = WRITE(fd[b], buf, buflen);
4009 		} while (r == buflen);
4010 		if (r == -1) {
4011 			XP_SYS_NG(EAGAIN, r);
4012 		}
4013 
4014 		/* Get fdB's initial seek for later */
4015 		r = IOCTL(fd[b], AUDIO_GETBUFINFO, &ai2, "");
4016 		XP_SYS_EQ(0, r);
4017 
4018 		kq = KQUEUE();
4019 		XP_SYS_OK(kq);
4020 
4021 		/* Both aren't raised at this point */
4022 		EV_SET(&kev[0], fd[a], EV_ADD, EVFILT_WRITE, 0, 0, 0);
4023 		EV_SET(&kev[1], fd[b], EV_ADD, EVFILT_WRITE, 0, 0, 0);
4024 		r = KEVENT_SET(kq, kev, 2);
4025 		XP_SYS_EQ(0, r);
4026 
4027 		/* Unpause only fdA */
4028 		AUDIO_INITINFO(&ai);
4029 		ai.play.pause = 0;
4030 		r = IOCTL(fd[a], AUDIO_SETINFO, &ai, "pause=0");
4031 		XP_SYS_EQ(0, r);
4032 
4033 		/* kevent() up to 2sec */
4034 		ts.tv_sec = 2;
4035 		ts.tv_nsec = 0;
4036 		r = KEVENT_POLL(kq, &kev[0], 1, &ts);
4037 		if (r >= 1)
4038 			DEBUG_KEV("kev", &kev[0]);
4039 		/* fdA should raise */
4040 		XP_SYS_EQ(1, r);
4041 		XP_EQ(fd[a], kev[0].ident);
4042 
4043 		/* Make sure that fdB keeps whole data */
4044 		r = IOCTL(fd[b], AUDIO_GETBUFINFO, &ai, "");
4045 		XP_EQ(ai2.play.seek, ai.play.seek);
4046 
4047 		/* Flush it because there is no need to play it */
4048 		r = IOCTL(fd[0], AUDIO_FLUSH, NULL, "");
4049 		XP_SYS_EQ(0, r);
4050 		r = IOCTL(fd[1], AUDIO_FLUSH, NULL, "");
4051 		XP_SYS_EQ(0, r);
4052 
4053 		r = CLOSE(fd[0]);
4054 		XP_SYS_EQ(0, r);
4055 		r = CLOSE(fd[1]);
4056 		XP_SYS_EQ(0, r);
4057 		r = CLOSE(kq);
4058 		XP_SYS_EQ(0, r);
4059 		free(buf);
4060 
4061 		xxx_close_wait();
4062 	}
4063 }
4064 
4065 /* Shared data between threads for ioctl_while_write */
4066 struct ioctl_while_write_data {
4067 	int fd;
4068 	struct timeval start;
4069 	int terminated;
4070 };
4071 
4072 /* Test thread for ioctl_while_write */
4073 void *thread_ioctl_while_write(void *);
4074 void *
thread_ioctl_while_write(void * arg)4075 thread_ioctl_while_write(void *arg)
4076 {
4077 	struct ioctl_while_write_data *data = arg;
4078 	struct timeval now, res;
4079 	struct audio_info ai;
4080 	int r;
4081 
4082 	/* If 0.5 seconds have elapsed since writing, assume it's blocked */
4083 	do {
4084 		usleep(100);
4085 		gettimeofday(&now, NULL);
4086 		timersub(&now, &data->start, &res);
4087 	} while (res.tv_usec < 500000);
4088 
4089 	/* Then, do ioctl() */
4090 	r = IOCTL(data->fd, AUDIO_GETBUFINFO, &ai, "");
4091 	XP_SYS_EQ(0, r);
4092 
4093 	/* Terminate */
4094 	data->terminated = 1;
4095 
4096 	/* Resume write() by unpause */
4097 	AUDIO_INITINFO(&ai);
4098 	if (netbsd < 8) {
4099 		/*
4100 		 * XXX NetBSD7 has bugs and it cannot be unpaused.
4101 		 * However, it also has another bug and it clears buffer
4102 		 * when encoding is changed.  I use it. :-P
4103 		 */
4104 		ai.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
4105 	}
4106 	ai.play.pause = 0;
4107 	r = IOCTL(data->fd, AUDIO_SETINFO, &ai, "pause=0");
4108 	XP_SYS_EQ(0, r);
4109 
4110 	return NULL;
4111 }
4112 
4113 /*
4114  * ioctl(2) can be issued while write(2)-ing.
4115  */
DEF(ioctl_while_write)4116 DEF(ioctl_while_write)
4117 {
4118 	struct audio_info ai;
4119 	struct ioctl_while_write_data data0, *data;
4120 	char buf[8000];	/* 1sec in mulaw,1ch,8000Hz */
4121 	pthread_t tid;
4122 	int r;
4123 
4124 	TEST("ioctl_while_write");
4125 
4126 	data = &data0;
4127 	memset(data, 0, sizeof(*data));
4128 	memset(buf, 0xff, sizeof(buf));
4129 
4130 	data->fd = OPEN(devaudio, O_WRONLY);
4131 	REQUIRED_SYS_OK(data->fd);
4132 
4133 	/* Pause to block write(2)ing */
4134 	AUDIO_INITINFO(&ai);
4135 	ai.play.pause = 1;
4136 	r = IOCTL(data->fd, AUDIO_SETINFO, &ai, "pause=1");
4137 	XP_SYS_EQ(0, r);
4138 
4139 	gettimeofday(&data->start, NULL);
4140 
4141 	pthread_create(&tid, NULL, thread_ioctl_while_write, data);
4142 
4143 	/* Write until blocking */
4144 	for (;;) {
4145 		r = WRITE(data->fd, buf, sizeof(buf));
4146 		if (data->terminated)
4147 			break;
4148 		XP_SYS_EQ(sizeof(buf), r);
4149 
4150 		/* Update written time */
4151 		gettimeofday(&data->start, NULL);
4152 	}
4153 
4154 	pthread_join(tid, NULL);
4155 
4156 	/* Flush */
4157 	r = IOCTL(data->fd, AUDIO_FLUSH, NULL, "");
4158 	XP_SYS_EQ(0, r);
4159 	r = CLOSE(data->fd);
4160 	XP_SYS_EQ(0, r);
4161 }
4162 
4163 volatile int sigio_caught;
4164 void
signal_FIOASYNC(int signo)4165 signal_FIOASYNC(int signo)
4166 {
4167 	if (signo == SIGIO) {
4168 		sigio_caught = 1;
4169 		DPRINTF("  > %d: pid %d got SIGIO\n", __LINE__, (int)getpid());
4170 	}
4171 }
4172 
4173 /*
4174  * FIOASYNC between two descriptors should be split.
4175  */
DEF(FIOASYNC_reset)4176 DEF(FIOASYNC_reset)
4177 {
4178 	int fd0, fd1;
4179 	int r;
4180 	int val;
4181 
4182 	TEST("FIOASYNC_reset");
4183 	if (netbsd < 8) {
4184 		XP_SKIP("Multiple open is not supported");
4185 		return;
4186 	}
4187 
4188 	/* The first one opens */
4189 	fd0 = OPEN(devaudio, O_WRONLY);
4190 	REQUIRED_SYS_OK(fd0);
4191 
4192 	/* The second one opens, enables ASYNC, and closes */
4193 	fd1 = OPEN(devaudio, O_WRONLY);
4194 	REQUIRED_SYS_OK(fd1);
4195 	val = 1;
4196 	r = IOCTL(fd1, FIOASYNC, &val, "on");
4197 	XP_SYS_EQ(0, r);
4198 	r = CLOSE(fd1);
4199 	XP_SYS_EQ(0, r);
4200 
4201 	/* Again, the second one opens and enables ASYNC */
4202 	fd1 = OPEN(devaudio, O_WRONLY);
4203 	REQUIRED_SYS_OK(fd1);
4204 	val = 1;
4205 	r = IOCTL(fd1, FIOASYNC, &val, "on");
4206 	XP_SYS_EQ(0, r);	/* NetBSD8 fails */
4207 	r = CLOSE(fd1);
4208 	XP_SYS_EQ(0, r);
4209 	r = CLOSE(fd0);
4210 	XP_SYS_EQ(0, r);
4211 }
4212 
4213 /*
4214  * Whether SIGIO is emitted on playback.
4215  * XXX I don't understand conditions that NetBSD7 emits signal.
4216  */
DEF(FIOASYNC_play_signal)4217 DEF(FIOASYNC_play_signal)
4218 {
4219 	struct audio_info ai;
4220 	int r;
4221 	int fd;
4222 	int val;
4223 	char *data;
4224 	int i;
4225 
4226 	TEST("FIOASYNC_play_signal");
4227 	if (hw_canplay() == 0) {
4228 		XP_SKIP("This test is only for playable device");
4229 		return;
4230 	}
4231 
4232 	signal(SIGIO, signal_FIOASYNC);
4233 	sigio_caught = 0;
4234 
4235 	fd = OPEN(devaudio, O_WRONLY);
4236 	REQUIRED_SYS_OK(fd);
4237 
4238 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4239 	REQUIRED_SYS_EQ(0, r);
4240 	REQUIRED_IF(ai.blocksize != 0);
4241 	data = (char *)malloc(ai.blocksize);
4242 	REQUIRED_IF(data != NULL);
4243 	memset(data, 0xff, ai.blocksize);
4244 
4245 	val = 1;
4246 	r = IOCTL(fd, FIOASYNC, &val, "on");
4247 	XP_SYS_EQ(0, r);
4248 
4249 	r = WRITE(fd, data, ai.blocksize);
4250 	XP_SYS_EQ(ai.blocksize, r);
4251 
4252 	/* Waits signal until 1sec */
4253 	for (i = 0; i < 100 && sigio_caught == 0; i++) {
4254 		usleep(10000);
4255 	}
4256 	signal(SIGIO, SIG_IGN);
4257 	XP_EQ(1, sigio_caught);
4258 
4259 	r = CLOSE(fd);
4260 	XP_SYS_EQ(0, r);
4261 
4262 	free(data);
4263 	signal(SIGIO, SIG_IGN);
4264 	sigio_caught = 0;
4265 }
4266 
4267 /*
4268  * Whether SIGIO is emitted on recording.
4269  */
DEF(FIOASYNC_rec_signal)4270 DEF(FIOASYNC_rec_signal)
4271 {
4272 	char buf[10];
4273 	int r;
4274 	int fd;
4275 	int val;
4276 	int i;
4277 
4278 	TEST("FIOASYNC_rec_signal");
4279 	if (hw_canrec() == 0) {
4280 		XP_SKIP("This test is only for recordable device");
4281 		return;
4282 	}
4283 
4284 	signal(SIGIO, signal_FIOASYNC);
4285 	sigio_caught = 0;
4286 
4287 	fd = OPEN(devaudio, O_RDONLY);
4288 	REQUIRED_SYS_OK(fd);
4289 
4290 	val = 1;
4291 	r = IOCTL(fd, FIOASYNC, &val, "on");
4292 	XP_SYS_EQ(0, r);
4293 
4294 	r = READ(fd, buf, sizeof(buf));
4295 	XP_SYS_EQ(sizeof(buf), r);
4296 
4297 	/* Wait signal until 1sec */
4298 	for (i = 0; i < 100 && sigio_caught == 0; i++) {
4299 		usleep(10000);
4300 	}
4301 	signal(SIGIO, SIG_IGN);
4302 	XP_EQ(1, sigio_caught);
4303 
4304 	r = CLOSE(fd);
4305 	XP_SYS_EQ(0, r);
4306 
4307 	signal(SIGIO, SIG_IGN);
4308 	sigio_caught = 0;
4309 }
4310 
4311 /*
4312  * FIOASYNC doesn't affect other descriptor.
4313  * For simplify, test only for playback...
4314  */
DEF(FIOASYNC_multi)4315 DEF(FIOASYNC_multi)
4316 {
4317 	struct audio_info ai;
4318 	char *buf;
4319 	char pipebuf[1];
4320 	int r;
4321 	int i;
4322 	int fd1;
4323 	int fd2;
4324 	int pd[2];
4325 	int val;
4326 	pid_t pid;
4327 	int status;
4328 
4329 	TEST("FIOASYNC_multi");
4330 	if (netbsd < 8) {
4331 		XP_SKIP("Multiple open is not supported");
4332 		return;
4333 	}
4334 	if (hw_canplay() == 0) {
4335 		XP_SKIP("This test is only for playable device");
4336 		return;
4337 	}
4338 
4339 	/* Pipe used between parent and child */
4340 	r = pipe(pd);
4341 	REQUIRED_SYS_EQ(0, r);
4342 
4343 	fd1 = OPEN(devaudio, O_WRONLY);
4344 	REQUIRED_SYS_OK(fd1);
4345 	fd2 = OPEN(devaudio, O_WRONLY);
4346 	REQUIRED_SYS_OK(fd2);
4347 
4348 	/* Pause fd2 */
4349 	AUDIO_INITINFO(&ai);
4350 	ai.play.pause = 1;
4351 	r = IOCTL(fd2, AUDIO_SETINFO, &ai, "pause");
4352 	REQUIRED_SYS_EQ(0, r);
4353 
4354 	/* Fill both */
4355 	r = IOCTL(fd1, AUDIO_GETBUFINFO, &ai, "");
4356 	REQUIRED_SYS_EQ(0, r);
4357 	REQUIRED_IF(ai.blocksize != 0);
4358 	buf = (char *)malloc(ai.blocksize);
4359 	REQUIRED_IF(buf != NULL);
4360 	memset(buf, 0xff, ai.blocksize);
4361 	r = WRITE(fd1, buf, ai.blocksize);
4362 	XP_SYS_EQ(ai.blocksize, r);
4363 
4364 	sigio_caught = 0;
4365 	val = 1;
4366 
4367 	fflush(stdout);
4368 	fflush(stderr);
4369 	pid = fork();
4370 	if (pid == -1) {
4371 		REQUIRED_SYS_OK(pid);
4372 	}
4373 	if (pid == 0) {
4374 		/* Child */
4375 		close(fd1);
4376 
4377 		/* Child enables ASYNC on fd2 */
4378 		signal(SIGIO, signal_FIOASYNC);
4379 		r = IOCTL(fd2, FIOASYNC, &val, "on");
4380 		/* It cannot count errors because here is a child process */
4381 		/* XP_SYS_EQ(0, r); */
4382 
4383 		/*
4384 		 * Waits signal until 1sec.
4385 		 * But fd2 is paused so it should never raise.
4386 		 */
4387 		for (i = 0; i < 100 && sigio_caught == 0; i++) {
4388 			usleep(10000);
4389 		}
4390 		signal(SIGIO, SIG_IGN);
4391 		pipebuf[0] = sigio_caught;
4392 		/* This is not WRITE() macro here */
4393 		write(pd[1], pipebuf, sizeof(pipebuf));
4394 
4395 		/* XXX? */
4396 		close(fd2);
4397 		sleep(1);
4398 		exit(0);
4399 	} else {
4400 		/* Parent */
4401 		DPRINTF("  > fork() = %d\n", (int)pid);
4402 
4403 		/* Parent enables ASYNC on fd1 */
4404 		signal(SIGIO, signal_FIOASYNC);
4405 		r = IOCTL(fd1, FIOASYNC, &val, "on");
4406 		XP_SYS_EQ(0, r);
4407 
4408 		/* Waits signal until 1sec */
4409 		for (i = 0; i < 100 && sigio_caught == 0; i++) {
4410 			usleep(10000);
4411 		}
4412 		signal(SIGIO, SIG_IGN);
4413 		XP_EQ(1, sigio_caught);
4414 
4415 		/* Then read child's result from pipe */
4416 		r = read(pd[0], pipebuf, sizeof(pipebuf));
4417 		if (r != 1) {
4418 			XP_FAIL("reading from child failed");
4419 		}
4420 		DPRINTF("  > child's sigio_cauht = %d\n", pipebuf[0]);
4421 		XP_EQ(0, pipebuf[0]);
4422 
4423 		waitpid(pid, &status, 0);
4424 	}
4425 
4426 	r = CLOSE(fd1);
4427 	XP_SYS_EQ(0, r);
4428 	r = CLOSE(fd2);
4429 	XP_SYS_EQ(0, r);
4430 
4431 	signal(SIGIO, SIG_IGN);
4432 	sigio_caught = 0;
4433 	free(buf);
4434 }
4435 
4436 /*
4437  * Check AUDIO_WSEEK behavior.
4438  */
DEF(AUDIO_WSEEK)4439 DEF(AUDIO_WSEEK)
4440 {
4441 	char buf[4];
4442 	struct audio_info ai;
4443 	int r;
4444 	int fd;
4445 	u_long n;
4446 
4447 	TEST("AUDIO_WSEEK");
4448 
4449 	fd = OPEN(devaudio, O_WRONLY);
4450 	REQUIRED_SYS_OK(fd);
4451 
4452 	/* Pause to count sample data */
4453 	AUDIO_INITINFO(&ai);
4454 	ai.play.pause = 1;
4455 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause=1");
4456 	REQUIRED_SYS_EQ(0, r);
4457 
4458 	/* On the initial state, it should be 0 bytes */
4459 	n = 0;
4460 	r = IOCTL(fd, AUDIO_WSEEK, &n, "");
4461 	XP_SYS_EQ(0, r);
4462 	XP_EQ(0, n);
4463 
4464 	/* When writing 4 bytes, it should be 4 bytes */
4465 	memset(buf, 0xff, sizeof(buf));
4466 	r = WRITE(fd, buf, sizeof(buf));
4467 	REQUIRED_EQ(sizeof(buf), r);
4468 	r = IOCTL(fd, AUDIO_WSEEK, &n, "");
4469 	XP_SYS_EQ(0, r);
4470 	if (netbsd < 9) {
4471 		/*
4472 		 * On NetBSD7, it will return 0.
4473 		 * Perhaps, WSEEK returns the number of pustream bytes but
4474 		 * data has already advanced...
4475 		 */
4476 		XP_EQ(0, n);
4477 	} else {
4478 		/* Data less than one block remains here */
4479 		XP_EQ(4, n);
4480 	}
4481 
4482 	r = CLOSE(fd);
4483 	XP_SYS_EQ(0, r);
4484 }
4485 
4486 /*
4487  * Check AUDIO_SETFD behavior for O_*ONLY descriptor.
4488  * On NetBSD7, SETFD modify audio layer's state (and MD driver's state)
4489  * regardless of open mode.  GETFD obtains audio layer's duplex.
4490  * On NetBSD9, SETFD is obsoleted.  GETFD obtains hardware's duplex.
4491  */
4492 void
test_AUDIO_SETFD_xxONLY(int openmode)4493 test_AUDIO_SETFD_xxONLY(int openmode)
4494 {
4495 	struct audio_info ai;
4496 	int r;
4497 	int fd;
4498 	int n;
4499 
4500 	TEST("AUDIO_SETFD_%s", openmode_str[openmode] + 2);
4501 	if (openmode == O_RDONLY && hw_canrec() == 0) {
4502 		XP_SKIP("This test is for recordable device");
4503 		return;
4504 	}
4505 	if (openmode == O_WRONLY && hw_canplay() == 0) {
4506 		XP_SKIP("This test is for playable device");
4507 		return;
4508 	}
4509 
4510 	fd = OPEN(devaudio, openmode);
4511 	REQUIRED_SYS_OK(fd);
4512 
4513 	/*
4514 	 * Just after open(2),
4515 	 * - On NetBSD7, it's always half-duplex.
4516 	 * - On NetBSD9, it's the same as hardware one regardless of openmode.
4517 	 */
4518 	n = 0;
4519 	r = IOCTL(fd, AUDIO_GETFD, &n, "");
4520 	XP_SYS_EQ(0, r);
4521 	if (netbsd < 9) {
4522 		XP_EQ(0, n);
4523 	} else {
4524 		XP_EQ(hw_fulldup(), n);
4525 	}
4526 
4527 	/*
4528 	 * When trying to set to full-duplex,
4529 	 * - On NetBSD7, it will succeed if the hardware is full-duplex, or
4530 	 *   will fail if the hardware is half-duplex.
4531 	 * - On NetBSD9, it will always succeed but will not be modified.
4532 	 */
4533 	n = 1;
4534 	r = IOCTL(fd, AUDIO_SETFD, &n, "on");
4535 	if (netbsd < 8) {
4536 		if (hw_fulldup()) {
4537 			XP_SYS_EQ(0, r);
4538 		} else {
4539 			XP_SYS_NG(ENOTTY, r);
4540 		}
4541 	} else if (netbsd == 8) {
4542 		XP_FAIL("expected result is unknown");
4543 	} else {
4544 		XP_SYS_EQ(0, r);
4545 	}
4546 
4547 	/*
4548 	 * When obtain it,
4549 	 * - On NetBSD7, it will be 1 if the hardware is full-duplex or
4550 	 *   0 if half-duplex.
4551 	 * - On NetBSD9, it will never be changed because it's the hardware
4552 	 *   property.
4553 	 */
4554 	n = 0;
4555 	r = IOCTL(fd, AUDIO_GETFD, &n, "");
4556 	XP_SYS_EQ(0, r);
4557 	if (netbsd < 8) {
4558 		XP_EQ(hw_fulldup(), n);
4559 	} else if (netbsd == 8) {
4560 		XP_FAIL("expected result is unknown");
4561 	} else {
4562 		XP_EQ(hw_fulldup(), n);
4563 	}
4564 
4565 	/* Some track parameters like ai.*.open should not change */
4566 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4567 	XP_SYS_EQ(0, r);
4568 	XP_EQ(mode2play(openmode), ai.play.open);
4569 	XP_EQ(mode2rec(openmode), ai.record.open);
4570 
4571 	/*
4572 	 * When trying to set to half-duplex,
4573 	 * - On NetBSD7, it will succeed if the hardware is full-duplex, or
4574 	 *   it will succeed with nothing happens.
4575 	 * - On NetBSD9, it will always succeed but nothing happens.
4576 	 */
4577 	n = 0;
4578 	r = IOCTL(fd, AUDIO_SETFD, &n, "off");
4579 	XP_SYS_EQ(0, r);
4580 
4581 	/*
4582 	 * When obtain it again,
4583 	 * - On NetBSD7, it will be 0 if the hardware is full-duplex, or
4584 	 *   still 0 if half-duplex.
4585 	 * - On NetBSD9, it should not change.
4586 	 */
4587 	n = 0;
4588 	r = IOCTL(fd, AUDIO_GETFD, &n, "");
4589 	XP_SYS_EQ(0, r);
4590 	if (netbsd < 9) {
4591 		XP_EQ(0, n);
4592 	} else {
4593 		XP_EQ(hw_fulldup(), n);
4594 	}
4595 
4596 	/* Some track parameters like ai.*.open should not change */
4597 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4598 	XP_SYS_EQ(0, r);
4599 	XP_EQ(mode2play(openmode), ai.play.open);
4600 	XP_EQ(mode2rec(openmode), ai.record.open);
4601 
4602 	r = CLOSE(fd);
4603 	XP_SYS_EQ(0, r);
4604 }
DEF(AUDIO_SETFD_RDONLY)4605 DEF(AUDIO_SETFD_RDONLY)	{ test_AUDIO_SETFD_xxONLY(O_RDONLY); }
DEF(AUDIO_SETFD_WRONLY)4606 DEF(AUDIO_SETFD_WRONLY)	{ test_AUDIO_SETFD_xxONLY(O_WRONLY); }
4607 
4608 /*
4609  * Check AUDIO_SETFD behavior for O_RDWR descriptor.
4610  */
DEF(AUDIO_SETFD_RDWR)4611 DEF(AUDIO_SETFD_RDWR)
4612 {
4613 	struct audio_info ai;
4614 	int r;
4615 	int fd;
4616 	int n;
4617 
4618 	TEST("AUDIO_SETFD_RDWR");
4619 	if (!hw_fulldup()) {
4620 		XP_SKIP("This test is only for full-duplex device");
4621 		return;
4622 	}
4623 
4624 	fd = OPEN(devaudio, O_RDWR);
4625 	REQUIRED_SYS_OK(fd);
4626 
4627 	/*
4628 	 * - audio(4) manpage until NetBSD7 said "If a full-duplex capable
4629 	 *   audio device is opened for both reading and writing it will
4630 	 *   start in half-duplex play mode", but implementation doesn't
4631 	 *   seem to follow it.  It returns full-duplex.
4632 	 * - On NetBSD9, it should return full-duplex on full-duplex, or
4633 	 *   half-duplex on half-duplex.
4634 	 */
4635 	n = 0;
4636 	r = IOCTL(fd, AUDIO_GETFD, &n, "");
4637 	XP_SYS_EQ(0, r);
4638 	XP_EQ(hw_fulldup(), n);
4639 
4640 	/*
4641 	 * When trying to set to full-duplex,
4642 	 * - On NetBSD7, it will succeed with nothing happens if full-duplex,
4643 	 *   or will fail if half-duplex.
4644 	 * - On NetBSD9, it will always succeed with nothing happens.
4645 	 */
4646 	n = 1;
4647 	r = IOCTL(fd, AUDIO_SETFD, &n, "on");
4648 	if (netbsd < 9) {
4649 		if (hw_fulldup()) {
4650 			XP_SYS_EQ(0, r);
4651 		} else {
4652 			XP_SYS_NG(ENOTTY, r);
4653 		}
4654 	} else {
4655 		XP_SYS_EQ(0, r);
4656 	}
4657 
4658 	/* When obtains it, it returns half/full-duplex as is */
4659 	n = 0;
4660 	r = IOCTL(fd, AUDIO_GETFD, &n, "");
4661 	XP_SYS_EQ(0, r);
4662 	XP_EQ(hw_fulldup(), n);
4663 
4664 	/* Some track parameters like ai.*.open should not change */
4665 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4666 	XP_SYS_EQ(0, r);
4667 	XP_EQ(1, ai.play.open);
4668 	XP_EQ(mode2rec(O_RDWR), ai.record.open);
4669 
4670 	/*
4671 	 * When trying to set to half-duplex,
4672 	 * - On NetBSD7, it will succeed if the hardware is full-duplex, or
4673 	 *   it will succeed with nothing happens.
4674 	 * - On NetBSD9, it will always succeed but nothing happens.
4675 	 */
4676 	n = 0;
4677 	r = IOCTL(fd, AUDIO_SETFD, &n, "off");
4678 	if (netbsd < 8) {
4679 		XP_SYS_EQ(0, r);
4680 	} else if (netbsd == 8) {
4681 		XP_FAIL("expected result is unknown");
4682 	} else {
4683 		XP_SYS_EQ(0, r);
4684 	}
4685 
4686 	/*
4687 	 * When obtain it again,
4688 	 * - On NetBSD7, it will be 0 if the hardware is full-duplex, or
4689 	 *   still 0 if half-duplex.
4690 	 * - On NetBSD9, it should be 1 if the hardware is full-duplex, or
4691 	 *   0 if half-duplex.
4692 	 */
4693 	n = 0;
4694 	r = IOCTL(fd, AUDIO_GETFD, &n, "");
4695 	XP_SYS_EQ(0, r);
4696 	if (netbsd < 8) {
4697 		XP_EQ(0, n);
4698 	} else if (netbsd == 8) {
4699 		XP_FAIL("expected result is unknown");
4700 	} else {
4701 		XP_EQ(hw_fulldup(), n);
4702 	}
4703 
4704 	/* Some track parameters like ai.*.open should not change */
4705 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4706 	XP_SYS_EQ(0, r);
4707 	XP_EQ(1, ai.play.open);
4708 	XP_EQ(mode2rec(O_RDWR), ai.record.open);
4709 
4710 	r = CLOSE(fd);
4711 	XP_SYS_EQ(0, r);
4712 }
4713 
4714 /*
4715  * Check AUDIO_GETINFO.eof behavior.
4716  */
DEF(AUDIO_GETINFO_eof)4717 DEF(AUDIO_GETINFO_eof)
4718 {
4719 	struct audio_info ai;
4720 	char buf[4];
4721 	int r;
4722 	int fd, fd1;
4723 
4724 	TEST("AUDIO_GETINFO_eof");
4725 	if (hw_canplay() == 0) {
4726 		XP_SKIP("This test is for playable device");
4727 		return;
4728 	}
4729 
4730 	fd = OPEN(devaudio, O_RDWR);
4731 	REQUIRED_SYS_OK(fd);
4732 
4733 	/* Pause to make no sound */
4734 	AUDIO_INITINFO(&ai);
4735 	ai.play.pause = 1;
4736 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause");
4737 	REQUIRED_SYS_EQ(0, r);
4738 
4739 	/* It should be 0 initially */
4740 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4741 	XP_SYS_EQ(0, r);
4742 	XP_EQ(0, ai.play.eof);
4743 	XP_EQ(0, ai.record.eof);
4744 
4745 	/* Writing zero bytes should increment it */
4746 	r = WRITE(fd, &r, 0);
4747 	REQUIRED_SYS_OK(r);
4748 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4749 	XP_SYS_EQ(0, r);
4750 	XP_EQ(1, ai.play.eof);
4751 	XP_EQ(0, ai.record.eof);
4752 
4753 	/* Writing one ore more bytes should noto increment it */
4754 	memset(buf, 0xff, sizeof(buf));
4755 	r = WRITE(fd, buf, sizeof(buf));
4756 	REQUIRED_SYS_OK(r);
4757 	memset(&ai, 0, sizeof(ai));
4758 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4759 	XP_SYS_EQ(0, r);
4760 	XP_EQ(1, ai.play.eof);
4761 	XP_EQ(0, ai.record.eof);
4762 
4763 	/* Writing zero bytes again should increment it */
4764 	r = WRITE(fd, buf, 0);
4765 	REQUIRED_SYS_OK(r);
4766 	memset(&ai, 0, sizeof(ai));
4767 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4768 	XP_SYS_EQ(0, r);
4769 	XP_EQ(2, ai.play.eof);
4770 	XP_EQ(0, ai.record.eof);
4771 
4772 	/* Reading zero bytes should not increment it */
4773 	if (hw_fulldup()) {
4774 		r = READ(fd, buf, 0);
4775 		REQUIRED_SYS_OK(r);
4776 		memset(&ai, 0, sizeof(ai));
4777 		r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4778 		XP_SYS_EQ(0, r);
4779 		XP_EQ(2, ai.play.eof);
4780 		XP_EQ(0, ai.record.eof);
4781 	}
4782 
4783 	/* should not interfere with other descriptor */
4784 	if (netbsd >= 8) {
4785 		fd1 = OPEN(devaudio, O_RDWR);
4786 		REQUIRED_SYS_OK(fd1);
4787 		memset(&ai, 0, sizeof(ai));
4788 		r = IOCTL(fd1, AUDIO_GETBUFINFO, &ai, "");
4789 		XP_SYS_EQ(0, r);
4790 		XP_EQ(0, ai.play.eof);
4791 		XP_EQ(0, ai.record.eof);
4792 		r = CLOSE(fd1);
4793 		XP_SYS_EQ(0, r);
4794 	}
4795 
4796 	r = CLOSE(fd);
4797 	XP_SYS_EQ(0, r);
4798 
4799 	xxx_close_wait();
4800 
4801 	/* When reopen, it should reset the counter */
4802 	fd = OPEN(devaudio, O_RDWR);
4803 	REQUIRED_SYS_OK(fd);
4804 
4805 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4806 	XP_SYS_EQ(0, r);
4807 	XP_EQ(0, ai.play.eof);
4808 	XP_EQ(0, ai.record.eof);
4809 
4810 	r = CLOSE(fd);
4811 	XP_SYS_EQ(0, r);
4812 }
4813 
4814 /*
4815  * Check relationship between openmode and mode set by AUDIO_SETINFO.
4816  */
4817 void
test_AUDIO_SETINFO_mode(int openmode,int index,int setmode,int expected)4818 test_AUDIO_SETINFO_mode(int openmode, int index, int setmode, int expected)
4819 {
4820 	struct audio_info ai;
4821 	char buf[10];
4822 	int inimode;
4823 	int r;
4824 	int fd;
4825 	bool canwrite;
4826 	bool canread;
4827 
4828 	/* index was passed only for displaying here */
4829 	TEST("AUDIO_SETINFO_mode_%s_%d", openmode_str[openmode] + 2, index);
4830 	if (mode2aumode(openmode) == 0) {
4831 		XP_SKIP("Operation not allowed on this hardware property");
4832 		return;
4833 	}
4834 
4835 	inimode = mode2aumode(openmode);
4836 
4837 	fd = OPEN(devaudio, openmode);
4838 	REQUIRED_SYS_OK(fd);
4839 
4840 	/* When just after opening */
4841 	memset(&ai, 0, sizeof(ai));
4842 	r = IOCTL(fd, AUDIO_GETINFO, &ai, "");
4843 	REQUIRED_SYS_EQ(0, r);
4844 	XP_EQ(inimode, ai.mode);
4845 	XP_EQ(mode2play(openmode), ai.play.open);
4846 	XP_EQ(mode2rec(openmode),  ai.record.open);
4847 	XP_NE(0, ai.play.buffer_size);
4848 	XP_NE(0, ai.record.buffer_size);
4849 
4850 	/* Change mode (and pause here) */
4851 	ai.mode = setmode;
4852 	ai.play.pause = 1;
4853 	ai.record.pause = 1;
4854 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "mode");
4855 	XP_SYS_EQ(0, r);
4856 	if (r == 0) {
4857 		r = IOCTL(fd, AUDIO_GETINFO, &ai, "");
4858 		XP_SYS_EQ(0, r);
4859 		XP_EQ(expected, ai.mode);
4860 
4861 		/* It seems to keep the initial openmode regardless of mode */
4862 		XP_EQ(mode2play(openmode), ai.play.open);
4863 		XP_EQ(mode2rec(openmode), ai.record.open);
4864 		XP_NE(0, ai.play.buffer_size);
4865 		XP_NE(0, ai.record.buffer_size);
4866 	}
4867 
4868 	/*
4869 	 * On NetBSD7, whether writable depends openmode when open.
4870 	 * On NetBSD9, whether writable should depend inimode when open.
4871 	 * Modifying after open should not affect this mode.
4872 	 */
4873 	if (netbsd < 9) {
4874 		canwrite = (openmode != O_RDONLY);
4875 	} else {
4876 		canwrite = ((inimode & AUMODE_PLAY) != 0);
4877 	}
4878 	r = WRITE(fd, buf, 0);
4879 	if (canwrite) {
4880 		XP_SYS_EQ(0, r);
4881 	} else {
4882 		XP_SYS_NG(EBADF, r);
4883 	}
4884 
4885 	/*
4886 	 * On NetBSD7, whether readable depends openmode when open.
4887 	 * On NetBSD9, whether readable should depend inimode when open.
4888 	 * Modifying after open should not affect this mode.
4889 	 */
4890 	if (netbsd < 9) {
4891 		canread = (openmode != O_WRONLY);
4892 	} else {
4893 		canread = ((inimode & AUMODE_RECORD) != 0);
4894 	}
4895 	r = READ(fd, buf, 0);
4896 	if (canread) {
4897 		XP_SYS_EQ(0, r);
4898 	} else {
4899 		XP_SYS_NG(EBADF, r);
4900 	}
4901 
4902 	r = CLOSE(fd);
4903 	XP_SYS_EQ(0, r);
4904 }
4905 /*
4906  * XXX hmm... it's too complex
4907  */
4908 /* shortcut for table form */
4909 #define P	AUMODE_PLAY
4910 #define A	AUMODE_PLAY_ALL
4911 #define R	AUMODE_RECORD
4912 struct setinfo_mode_t {
4913 	int setmode;	/* mode used in SETINFO */
4914 	int expmode7;	/* expected mode on NetBSD7 */
4915 	int expmode9;	/* expected mode on NetBSD9 */
4916 };
4917 /*
4918  * The following tables show this operation on NetBSD7 is almost 'undefined'.
4919  * In contrast, NetBSD9 never changes mode by AUDIO_SETINFO except
4920  * AUMODE_PLAY_ALL.
4921  *
4922  * setmode == 0 and 8 are out of range and invalid input samples.
4923  * But NetBSD7 seems to accept it as is.
4924  */
4925 struct setinfo_mode_t table_SETINFO_mode_O_RDONLY[] = {
4926 	/* setmode	expmode7	expmode9 */
4927 	{     0,	     0,		 R    },
4928 	{     P,	     P,		 R    },
4929 	{   A  ,	   A|P,		 R    },
4930 	{   A|P,	   A|P,		 R    },
4931 	{ R    ,	 R    ,		 R    },
4932 	{ R|  P,	     P,		 R    },
4933 	{ R|A  ,	   A|P,		 R    },
4934 	{ R|A|P,	   A|P,		 R    },
4935 	{     8,	     8,		 R    },
4936 };
4937 struct setinfo_mode_t table_SETINFO_mode_O_WRONLY[] = {
4938 	/* setmode	expmode7	expmode9 */
4939 	{     0,	     0,		     P },
4940 	{     P,	     P,		     P },
4941 	{   A  ,	   A|P,		   A|P },
4942 	{   A|P,	   A|P,		   A|P },
4943 	{ R    ,	 R    ,		     P },
4944 	{ R|  P,	     P,		     P },
4945 	{ R|A  ,	   A|P,		   A|P },
4946 	{ R|A|P,	   A|P,		   A|P },
4947 	{     8,	     8,		     P },
4948 };
4949 #define f(openmode, index)	do {					\
4950 	struct setinfo_mode_t *table = table_SETINFO_mode_##openmode;	\
4951 	int setmode = table[index].setmode;				\
4952 	int expected = (netbsd < 9)					\
4953 	    ? table[index].expmode7					\
4954 	    : table[index].expmode9;					\
4955 	test_AUDIO_SETINFO_mode(openmode, index, setmode, expected);	\
4956 } while (0)
DEF(AUDIO_SETINFO_mode_RDONLY_0)4957 DEF(AUDIO_SETINFO_mode_RDONLY_0) { f(O_RDONLY, 0); }
DEF(AUDIO_SETINFO_mode_RDONLY_1)4958 DEF(AUDIO_SETINFO_mode_RDONLY_1) { f(O_RDONLY, 1); }
DEF(AUDIO_SETINFO_mode_RDONLY_2)4959 DEF(AUDIO_SETINFO_mode_RDONLY_2) { f(O_RDONLY, 2); }
DEF(AUDIO_SETINFO_mode_RDONLY_3)4960 DEF(AUDIO_SETINFO_mode_RDONLY_3) { f(O_RDONLY, 3); }
DEF(AUDIO_SETINFO_mode_RDONLY_4)4961 DEF(AUDIO_SETINFO_mode_RDONLY_4) { f(O_RDONLY, 4); }
DEF(AUDIO_SETINFO_mode_RDONLY_5)4962 DEF(AUDIO_SETINFO_mode_RDONLY_5) { f(O_RDONLY, 5); }
DEF(AUDIO_SETINFO_mode_RDONLY_6)4963 DEF(AUDIO_SETINFO_mode_RDONLY_6) { f(O_RDONLY, 6); }
DEF(AUDIO_SETINFO_mode_RDONLY_7)4964 DEF(AUDIO_SETINFO_mode_RDONLY_7) { f(O_RDONLY, 7); }
DEF(AUDIO_SETINFO_mode_RDONLY_8)4965 DEF(AUDIO_SETINFO_mode_RDONLY_8) { f(O_RDONLY, 8); }
DEF(AUDIO_SETINFO_mode_WRONLY_0)4966 DEF(AUDIO_SETINFO_mode_WRONLY_0) { f(O_WRONLY, 0); }
DEF(AUDIO_SETINFO_mode_WRONLY_1)4967 DEF(AUDIO_SETINFO_mode_WRONLY_1) { f(O_WRONLY, 1); }
DEF(AUDIO_SETINFO_mode_WRONLY_2)4968 DEF(AUDIO_SETINFO_mode_WRONLY_2) { f(O_WRONLY, 2); }
DEF(AUDIO_SETINFO_mode_WRONLY_3)4969 DEF(AUDIO_SETINFO_mode_WRONLY_3) { f(O_WRONLY, 3); }
DEF(AUDIO_SETINFO_mode_WRONLY_4)4970 DEF(AUDIO_SETINFO_mode_WRONLY_4) { f(O_WRONLY, 4); }
DEF(AUDIO_SETINFO_mode_WRONLY_5)4971 DEF(AUDIO_SETINFO_mode_WRONLY_5) { f(O_WRONLY, 5); }
DEF(AUDIO_SETINFO_mode_WRONLY_6)4972 DEF(AUDIO_SETINFO_mode_WRONLY_6) { f(O_WRONLY, 6); }
DEF(AUDIO_SETINFO_mode_WRONLY_7)4973 DEF(AUDIO_SETINFO_mode_WRONLY_7) { f(O_WRONLY, 7); }
DEF(AUDIO_SETINFO_mode_WRONLY_8)4974 DEF(AUDIO_SETINFO_mode_WRONLY_8) { f(O_WRONLY, 8); }
4975 #undef f
4976 /*
4977  * The following tables also show that NetBSD7's behavior is almost
4978  * 'undefined'.
4979  */
4980 struct setinfo_mode_t table_SETINFO_mode_O_RDWR_full[] = {
4981 	/* setmode	expmode7	expmode9 */
4982 	{     0,	    0,		R|  P },
4983 	{     P,	    P,		R|  P },
4984 	{   A  ,	  A|P,		R|A|P },
4985 	{   A|P,	  A|P,		R|A|P },
4986 	{ R    ,	R    ,		R|  P },
4987 	{ R|  P,	R|  P,		R|  P },
4988 	{ R|A  ,	R|A|P,		R|A|P },
4989 	{ R|A|P,	R|A|P,		R|A|P },
4990 	{     8,	    8,		R|  P },
4991 };
4992 struct setinfo_mode_t table_SETINFO_mode_O_RDWR_half[] = {
4993 	/* setmode	expmode7	expmode9 */
4994 	{     0,	    0,		    P },
4995 	{     P,	    P,		    P },
4996 	{   A  ,	  A|P,		  A|P },
4997 	{   A|P,	  A|P,		  A|P },
4998 	{ R    ,	R    ,		    P },
4999 	{ R|  P,	    P,		    P },
5000 	{ R|A  ,	  A|P,		  A|P },
5001 	{ R|A|P,	  A|P,		  A|P },
5002 	{     8,	    8,		    P },
5003 };
5004 #define f(index)	do {						\
5005 	struct setinfo_mode_t *table = (hw_fulldup())			\
5006 	    ? table_SETINFO_mode_O_RDWR_full				\
5007 	    : table_SETINFO_mode_O_RDWR_half;				\
5008 	int setmode = table[index].setmode;				\
5009 	int expected = (netbsd < 9)					\
5010 	    ? table[index].expmode7					\
5011 	    : table[index].expmode9;					\
5012 	test_AUDIO_SETINFO_mode(O_RDWR, index, setmode, expected);	\
5013 } while (0)
DEF(AUDIO_SETINFO_mode_RDWR_0)5014 DEF(AUDIO_SETINFO_mode_RDWR_0) { f(0); }
DEF(AUDIO_SETINFO_mode_RDWR_1)5015 DEF(AUDIO_SETINFO_mode_RDWR_1) { f(1); }
DEF(AUDIO_SETINFO_mode_RDWR_2)5016 DEF(AUDIO_SETINFO_mode_RDWR_2) { f(2); }
DEF(AUDIO_SETINFO_mode_RDWR_3)5017 DEF(AUDIO_SETINFO_mode_RDWR_3) { f(3); }
DEF(AUDIO_SETINFO_mode_RDWR_4)5018 DEF(AUDIO_SETINFO_mode_RDWR_4) { f(4); }
DEF(AUDIO_SETINFO_mode_RDWR_5)5019 DEF(AUDIO_SETINFO_mode_RDWR_5) { f(5); }
DEF(AUDIO_SETINFO_mode_RDWR_6)5020 DEF(AUDIO_SETINFO_mode_RDWR_6) { f(6); }
DEF(AUDIO_SETINFO_mode_RDWR_7)5021 DEF(AUDIO_SETINFO_mode_RDWR_7) { f(7); }
DEF(AUDIO_SETINFO_mode_RDWR_8)5022 DEF(AUDIO_SETINFO_mode_RDWR_8) { f(8); }
5023 #undef f
5024 #undef P
5025 #undef A
5026 #undef R
5027 
5028 /*
5029  * Check whether encoding params can be set.
5030  */
5031 void
test_AUDIO_SETINFO_params_set(int openmode,int aimode,int pause)5032 test_AUDIO_SETINFO_params_set(int openmode, int aimode, int pause)
5033 {
5034 	struct audio_info ai;
5035 	int r;
5036 	int fd;
5037 
5038 	/*
5039 	 * aimode is bool value that indicates whether to change ai.mode.
5040 	 * pause is bool value that indicates whether to change ai.*.pause.
5041 	 */
5042 
5043 	TEST("AUDIO_SETINFO_params_%s_%d_%d",
5044 	    openmode_str[openmode] + 2, aimode, pause);
5045 	if (mode2aumode(openmode) == 0) {
5046 		XP_SKIP("Operation not allowed on this hardware property");
5047 		return;
5048 	}
5049 
5050 	/* On half-duplex, O_RDWR is the same as O_WRONLY, so skip it */
5051 	if (!hw_fulldup() && openmode == O_RDWR) {
5052 		XP_SKIP("This is the same with O_WRONLY on half-duplex");
5053 		return;
5054 	}
5055 
5056 	fd = OPEN(devaudio, openmode);
5057 	REQUIRED_SYS_OK(fd);
5058 
5059 	AUDIO_INITINFO(&ai);
5060 	/*
5061 	 * It takes time and effort to check all parameters independently,
5062 	 * so that use sample_rate as a representative.
5063 	 */
5064 	ai.play.sample_rate = 11025;
5065 	ai.record.sample_rate = 11025;
5066 	if (aimode)
5067 		ai.mode = mode2aumode(openmode) & ~AUMODE_PLAY_ALL;
5068 	if (pause) {
5069 		ai.play.pause = 1;
5070 		ai.record.pause = 1;
5071 	}
5072 
5073 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "");
5074 	XP_SYS_EQ(0, r);
5075 
5076 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
5077 	XP_SYS_EQ(0, r);
5078 	int expmode = (aimode)
5079 	    ? (mode2aumode(openmode) & ~AUMODE_PLAY_ALL)
5080 	    : mode2aumode(openmode);
5081 	XP_EQ(expmode, ai.mode);
5082 	XP_EQ(11025, ai.play.sample_rate);
5083 	XP_EQ(pause, ai.play.pause);
5084 	XP_EQ(11025, ai.record.sample_rate);
5085 	XP_EQ(pause, ai.record.pause);
5086 
5087 	r = CLOSE(fd);
5088 	XP_SYS_EQ(0, r);
5089 }
5090 #define f(a,b,c) test_AUDIO_SETINFO_params_set(a, b, c)
DEF(AUDIO_SETINFO_params_set_RDONLY_0)5091 DEF(AUDIO_SETINFO_params_set_RDONLY_0)	{ f(O_RDONLY, 0, 0); }
DEF(AUDIO_SETINFO_params_set_RDONLY_1)5092 DEF(AUDIO_SETINFO_params_set_RDONLY_1)	{ f(O_RDONLY, 0, 1); }
5093 /* On RDONLY, ai.mode is not changeable
5094  *  AUDIO_SETINFO_params_set_RDONLY_2)	{ f(O_RDONLY, 1, 0); }
5095  *  AUDIO_SETINFO_params_set_RDONLY_3)	{ f(O_RDONLY, 1, 1); }
5096  */
DEF(AUDIO_SETINFO_params_set_WRONLY_0)5097 DEF(AUDIO_SETINFO_params_set_WRONLY_0)	{ f(O_WRONLY, 0, 0); }
DEF(AUDIO_SETINFO_params_set_WRONLY_1)5098 DEF(AUDIO_SETINFO_params_set_WRONLY_1)	{ f(O_WRONLY, 0, 1); }
DEF(AUDIO_SETINFO_params_set_WRONLY_2)5099 DEF(AUDIO_SETINFO_params_set_WRONLY_2)	{ f(O_WRONLY, 1, 0); }
DEF(AUDIO_SETINFO_params_set_WRONLY_3)5100 DEF(AUDIO_SETINFO_params_set_WRONLY_3)	{ f(O_WRONLY, 1, 1); }
DEF(AUDIO_SETINFO_params_set_RDWR_0)5101 DEF(AUDIO_SETINFO_params_set_RDWR_0)	{ f(O_RDWR, 0, 0); }
DEF(AUDIO_SETINFO_params_set_RDWR_1)5102 DEF(AUDIO_SETINFO_params_set_RDWR_1)	{ f(O_RDWR, 0, 1); }
DEF(AUDIO_SETINFO_params_set_RDWR_2)5103 DEF(AUDIO_SETINFO_params_set_RDWR_2)	{ f(O_RDWR, 1, 0); }
DEF(AUDIO_SETINFO_params_set_RDWR_3)5104 DEF(AUDIO_SETINFO_params_set_RDWR_3)	{ f(O_RDWR, 1, 1); }
5105 #undef f
5106 
5107 /*
5108  * AUDIO_SETINFO for existing track should not be interfered by other
5109  * descriptor.
5110  * AUDIO_SETINFO for non-existing track affects/is affected sticky parameters
5111  * for backward compatibility.
5112  */
DEF(AUDIO_SETINFO_params_simul)5113 DEF(AUDIO_SETINFO_params_simul)
5114 {
5115 	struct audio_info ai;
5116 	int fd0;
5117 	int fd1;
5118 	int r;
5119 
5120 	TEST("AUDIO_SETINFO_params_simul");
5121 	if (netbsd < 8) {
5122 		XP_SKIP("Multiple open is not supported");
5123 		return;
5124 	}
5125 	if (hw_canplay() == 0) {
5126 		XP_SKIP("This test is for playable device");
5127 		return;
5128 	}
5129 
5130 	/* Open the 1st one as playback only */
5131 	fd0 = OPEN(devaudio, O_WRONLY);
5132 	REQUIRED_SYS_OK(fd0);
5133 
5134 	/* Open the 2nd one as both of playback and recording */
5135 	fd1 = OPEN(devaudio, O_RDWR);
5136 	REQUIRED_SYS_OK(fd1);
5137 
5138 	/* Change some parameters of both track on the 2nd one */
5139 	AUDIO_INITINFO(&ai);
5140 	ai.play.sample_rate = 11025;
5141 	ai.record.sample_rate = 11025;
5142 	r = IOCTL(fd1, AUDIO_SETINFO, &ai, "");
5143 	XP_SYS_EQ(0, r);
5144 
5145 	/*
5146 	 * The 1st one doesn't have recording track so that only recording
5147 	 * parameter is affected by sticky parameter.
5148 	 */
5149 	memset(&ai, 0, sizeof(ai));
5150 	r = IOCTL(fd0, AUDIO_GETBUFINFO, &ai, "");
5151 	XP_SYS_EQ(0, r);
5152 	XP_EQ(8000, ai.play.sample_rate);
5153 	XP_EQ(11025, ai.record.sample_rate);
5154 
5155 	/* Next, change some parameters of both track on the 1st one */
5156 	AUDIO_INITINFO(&ai);
5157 	ai.play.sample_rate = 16000;
5158 	ai.record.sample_rate = 16000;
5159 	r = IOCTL(fd0, AUDIO_SETINFO, &ai, "");
5160 	XP_SYS_EQ(0, r);
5161 
5162 	/*
5163 	 * On full-duplex device, the 2nd one has both track so that
5164 	 * both track are not affected by sticky parameter.
5165 	 * Otherwise, the 2nd one has only playback track so that
5166 	 * playback track is not affected by sticky parameter.
5167 	 */
5168 	memset(&ai, 0, sizeof(ai));
5169 	r = IOCTL(fd1, AUDIO_GETBUFINFO, &ai, "");
5170 	XP_SYS_EQ(0, r);
5171 	XP_EQ(11025, ai.play.sample_rate);
5172 	if (hw_fulldup()) {
5173 		XP_EQ(11025, ai.record.sample_rate);
5174 	} else {
5175 		XP_EQ(16000, ai.record.sample_rate);
5176 	}
5177 
5178 	r = CLOSE(fd0);
5179 	XP_SYS_EQ(0, r);
5180 	r = CLOSE(fd1);
5181 	XP_SYS_EQ(0, r);
5182 }
5183 
5184 /*
5185  * AUDIO_SETINFO(encoding/precision) is tested in AUDIO_GETENC_range below.
5186  */
5187 
5188 /*
5189  * Check whether the number of channels can be set.
5190  */
DEF(AUDIO_SETINFO_channels)5191 DEF(AUDIO_SETINFO_channels)
5192 {
5193 	struct audio_info hwinfo;
5194 	struct audio_info ai;
5195 	int mode;
5196 	int r;
5197 	int fd;
5198 	int i;
5199 	unsigned int ch;
5200 	struct {
5201 		int ch;
5202 		bool expected;
5203 	} table[] = {
5204 		{  0,	false },
5205 		{  1,	true },	/* monaural */
5206 		{  2,	true },	/* stereo */
5207 	};
5208 
5209 	TEST("AUDIO_SETINFO_channels");
5210 	if (netbsd < 8) {
5211 		/*
5212 		 * On NetBSD7, the result depends the hardware and there is
5213 		 * no way to know it.
5214 		 */
5215 		XP_SKIP("The test doesn't make sense on NetBSD7");
5216 		return;
5217 	}
5218 
5219 	mode = openable_mode();
5220 	fd = OPEN(devaudio, mode);
5221 	REQUIRED_SYS_OK(fd);
5222 
5223 	/*
5224 	 * The audio layer always supports monaural and stereo regardless of
5225 	 * the hardware capability.
5226 	 */
5227 	for (i = 0; i < (int)__arraycount(table); i++) {
5228 		ch = table[i].ch;
5229 		bool expected = table[i].expected;
5230 
5231 		AUDIO_INITINFO(&ai);
5232 		if (mode != O_RDONLY)
5233 			ai.play.channels = ch;
5234 		if (mode != O_WRONLY)
5235 			ai.record.channels = ch;
5236 		r = IOCTL(fd, AUDIO_SETINFO, &ai, "channels=%d", ch);
5237 		if (expected) {
5238 			/* Expects to succeed */
5239 			XP_SYS_EQ(0, r);
5240 
5241 			r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
5242 			XP_SYS_EQ(0, r);
5243 			if (mode != O_RDONLY)
5244 				XP_EQ(ch, ai.play.channels);
5245 			if (mode != O_WRONLY)
5246 				XP_EQ(ch, ai.record.channels);
5247 		} else {
5248 			/* Expects to fail */
5249 			XP_SYS_NG(EINVAL, r);
5250 		}
5251 	}
5252 
5253 	/*
5254 	 * The maximum number of supported channels depends the hardware.
5255 	 */
5256 	/* Get the number of channels that the hardware supports */
5257 	r = IOCTL(fd, AUDIO_GETFORMAT, &hwinfo, "");
5258 	REQUIRED_SYS_EQ(0, r);
5259 
5260 	if ((hwinfo.mode & AUMODE_PLAY)) {
5261 		DPRINTF("  > hwinfo.play.channels = %d\n",
5262 		    hwinfo.play.channels);
5263 		for (ch = 3; ch <= hwinfo.play.channels; ch++) {
5264 			AUDIO_INITINFO(&ai);
5265 			ai.play.channels = ch;
5266 			r = IOCTL(fd, AUDIO_SETINFO, &ai, "channels=%d", ch);
5267 			XP_SYS_EQ(0, r);
5268 
5269 			r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
5270 			XP_SYS_EQ(0, r);
5271 			XP_EQ(ch, ai.play.channels);
5272 		}
5273 
5274 		AUDIO_INITINFO(&ai);
5275 		ai.play.channels = ch;
5276 		r = IOCTL(fd, AUDIO_SETINFO, &ai, "channels=%d", ch);
5277 		XP_SYS_NG(EINVAL, r);
5278 	}
5279 	if ((hwinfo.mode & AUMODE_RECORD)) {
5280 		DPRINTF("  > hwinfo.record.channels = %d\n",
5281 		    hwinfo.record.channels);
5282 		for (ch = 3; ch <= hwinfo.record.channels; ch++) {
5283 			AUDIO_INITINFO(&ai);
5284 			ai.record.channels = ch;
5285 			r = IOCTL(fd, AUDIO_SETINFO, &ai, "channels=%d", ch);
5286 			XP_SYS_EQ(0, r);
5287 
5288 			r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
5289 			XP_SYS_EQ(0, r);
5290 			XP_EQ(ch, ai.record.channels);
5291 		}
5292 
5293 		AUDIO_INITINFO(&ai);
5294 		ai.record.channels = ch;
5295 		r = IOCTL(fd, AUDIO_SETINFO, &ai, "channels=%d", ch);
5296 		XP_SYS_NG(EINVAL, r);
5297 	}
5298 
5299 	r = CLOSE(fd);
5300 	XP_SYS_EQ(0, r);
5301 }
5302 
5303 /*
5304  * Check whether the sample rate can be set.
5305  */
DEF(AUDIO_SETINFO_sample_rate)5306 DEF(AUDIO_SETINFO_sample_rate)
5307 {
5308 	struct audio_info ai;
5309 	int mode;
5310 	int r;
5311 	int fd;
5312 	int i;
5313 	struct {
5314 		int freq;
5315 		bool expected;
5316 	} table[] = {
5317 		{    999,	false },
5318 		{   1000,	true },	/* lower limit */
5319 		{  48000,	true },
5320 		{ 192000,	true },	/* upper limit */
5321 		{ 192001,	false },
5322 	};
5323 
5324 	TEST("AUDIO_SETINFO_sample_rate");
5325 	if (netbsd < 8) {
5326 		/*
5327 		 * On NetBSD7, the result depends the hardware and there is
5328 		 * no way to know it.
5329 		 */
5330 		XP_SKIP("The test doesn't make sense on NetBSD7");
5331 		return;
5332 	}
5333 
5334 	mode = openable_mode();
5335 	fd = OPEN(devaudio, mode);
5336 	REQUIRED_SYS_OK(fd);
5337 
5338 	for (i = 0; i < (int)__arraycount(table); i++) {
5339 		int freq = table[i].freq;
5340 		bool expected = table[i].expected;
5341 
5342 		AUDIO_INITINFO(&ai);
5343 		if (mode != O_RDONLY)
5344 			ai.play.sample_rate = freq;
5345 		if (mode != O_WRONLY)
5346 			ai.record.sample_rate = freq;
5347 		r = IOCTL(fd, AUDIO_SETINFO, &ai, "sample_rate=%d", freq);
5348 		if (expected) {
5349 			/* Expects to succeed */
5350 			XP_SYS_EQ(0, r);
5351 
5352 			r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
5353 			XP_SYS_EQ(0, r);
5354 			if (mode != O_RDONLY)
5355 				XP_EQ(freq, ai.play.sample_rate);
5356 			if (mode != O_WRONLY)
5357 				XP_EQ(freq, ai.record.sample_rate);
5358 		} else {
5359 			/* Expects to fail */
5360 			XP_SYS_NG(EINVAL, r);
5361 		}
5362 	}
5363 
5364 	r = CLOSE(fd);
5365 	XP_SYS_EQ(0, r);
5366 }
5367 
5368 /*
5369  * SETINFO(sample_rate = 0) should fail correctly.
5370  */
DEF(AUDIO_SETINFO_sample_rate_0)5371 DEF(AUDIO_SETINFO_sample_rate_0)
5372 {
5373 	struct audio_info ai;
5374 	int mode;
5375 	int r;
5376 	int fd;
5377 
5378 	TEST("AUDIO_SETINFO_sample_rate_0");
5379 	if (netbsd < 9) {
5380 		/*
5381 		 * On NetBSD7,8 this will block system call and you will not
5382 		 * even be able to shutdown...
5383 		 */
5384 		XP_SKIP("This will cause an infinite loop in the kernel");
5385 		return;
5386 	}
5387 
5388 	mode = openable_mode();
5389 	fd = OPEN(devaudio, mode);
5390 	REQUIRED_SYS_OK(fd);
5391 
5392 	AUDIO_INITINFO(&ai);
5393 	ai.play.sample_rate = 0;
5394 	ai.record.sample_rate = 0;
5395 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "sample_rate=0");
5396 	/* Expects to fail */
5397 	XP_SYS_NG(EINVAL, r);
5398 
5399 	r = CLOSE(fd);
5400 	XP_SYS_EQ(0, r);
5401 }
5402 
5403 /*
5404  * Check whether the pause/unpause works.
5405  */
5406 void
test_AUDIO_SETINFO_pause(int openmode,int aimode,int param)5407 test_AUDIO_SETINFO_pause(int openmode, int aimode, int param)
5408 {
5409 	struct audio_info ai;
5410 	int r;
5411 	int fd;
5412 
5413 	/*
5414 	 * aimode is bool value that indicates whether to change ai.mode.
5415 	 * param is bool value that indicates whether to change encoding
5416 	 * parameters of ai.{play,record}.*.
5417 	 */
5418 
5419 	TEST("AUDIO_SETINFO_pause_%s_%d_%d",
5420 	    openmode_str[openmode] + 2, aimode, param);
5421 	if (mode2aumode(openmode) == 0) {
5422 		XP_SKIP("Operation not allowed on this hardware property");
5423 		return;
5424 	}
5425 
5426 	/* On half-duplex, O_RDWR is the same as O_WRONLY, so skip it */
5427 	if (!hw_fulldup() && openmode == O_RDWR) {
5428 		XP_SKIP("This is the same with O_WRONLY on half-duplex");
5429 		return;
5430 	}
5431 
5432 	fd = OPEN(devaudio, openmode);
5433 	REQUIRED_SYS_OK(fd);
5434 
5435 	/* Set pause */
5436 	AUDIO_INITINFO(&ai);
5437 	ai.play.pause = 1;
5438 	ai.record.pause = 1;
5439 	if (aimode)
5440 		ai.mode = mode2aumode(openmode) & ~AUMODE_PLAY_ALL;
5441 	if (param) {
5442 		ai.play.sample_rate = 11025;
5443 		ai.record.sample_rate = 11025;
5444 	}
5445 
5446 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "");
5447 	XP_SYS_EQ(0, r);
5448 
5449 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
5450 	XP_SYS_EQ(0, r);
5451 	int expmode = (aimode)
5452 	    ? (mode2aumode(openmode) & ~AUMODE_PLAY_ALL)
5453 	    : mode2aumode(openmode);
5454 	XP_EQ(expmode, ai.mode);
5455 	XP_EQ(1, ai.play.pause);
5456 	XP_EQ(param ? 11025 : 8000, ai.play.sample_rate);
5457 	XP_EQ(1, ai.record.pause);
5458 	XP_EQ(param ? 11025 : 8000, ai.record.sample_rate);
5459 
5460 	/* Set unpause (?) */
5461 	AUDIO_INITINFO(&ai);
5462 	ai.play.pause = 0;
5463 	ai.record.pause = 0;
5464 	if (aimode)
5465 		ai.mode = mode2aumode(openmode);
5466 	if (param) {
5467 		ai.play.sample_rate = 16000;
5468 		ai.record.sample_rate = 16000;
5469 	}
5470 
5471 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "");
5472 	XP_SYS_EQ(0, r);
5473 
5474 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
5475 	XP_SYS_EQ(0, r);
5476 	XP_EQ(mode2aumode(openmode), ai.mode);
5477 	XP_EQ(0, ai.play.pause);
5478 	XP_EQ(0, ai.record.pause);
5479 	if (openmode != O_RDONLY)
5480 		XP_EQ(param ? 16000 : 8000, ai.play.sample_rate);
5481 	if (openmode != O_WRONLY)
5482 		XP_EQ(param ? 16000 : 8000, ai.record.sample_rate);
5483 
5484 	r = CLOSE(fd);
5485 	XP_SYS_EQ(0, r);
5486 }
DEF(AUDIO_SETINFO_pause_RDONLY_0)5487 DEF(AUDIO_SETINFO_pause_RDONLY_0) { test_AUDIO_SETINFO_pause(O_RDONLY, 0, 0); }
DEF(AUDIO_SETINFO_pause_RDONLY_1)5488 DEF(AUDIO_SETINFO_pause_RDONLY_1) { test_AUDIO_SETINFO_pause(O_RDONLY, 0, 1); }
5489 /* On RDONLY, ai.mode is not changeable
5490  *  AUDIO_SETINFO_pause_RDONLY_2) { test_AUDIO_SETINFO_pause(O_RDONLY, 1, 0); }
5491  *  AUDIO_SETINFO_pause_RDONLY_3) { test_AUDIO_SETINFO_pause(O_RDONLY, 1, 1); }
5492  */
DEF(AUDIO_SETINFO_pause_WRONLY_0)5493 DEF(AUDIO_SETINFO_pause_WRONLY_0) { test_AUDIO_SETINFO_pause(O_WRONLY, 0, 0); }
DEF(AUDIO_SETINFO_pause_WRONLY_1)5494 DEF(AUDIO_SETINFO_pause_WRONLY_1) { test_AUDIO_SETINFO_pause(O_WRONLY, 0, 1); }
DEF(AUDIO_SETINFO_pause_WRONLY_2)5495 DEF(AUDIO_SETINFO_pause_WRONLY_2) { test_AUDIO_SETINFO_pause(O_WRONLY, 1, 0); }
DEF(AUDIO_SETINFO_pause_WRONLY_3)5496 DEF(AUDIO_SETINFO_pause_WRONLY_3) { test_AUDIO_SETINFO_pause(O_WRONLY, 1, 1); }
DEF(AUDIO_SETINFO_pause_RDWR_0)5497 DEF(AUDIO_SETINFO_pause_RDWR_0)   { test_AUDIO_SETINFO_pause(O_RDWR, 0, 0); }
DEF(AUDIO_SETINFO_pause_RDWR_1)5498 DEF(AUDIO_SETINFO_pause_RDWR_1)   { test_AUDIO_SETINFO_pause(O_RDWR, 0, 1); }
DEF(AUDIO_SETINFO_pause_RDWR_2)5499 DEF(AUDIO_SETINFO_pause_RDWR_2)   { test_AUDIO_SETINFO_pause(O_RDWR, 1, 0); }
DEF(AUDIO_SETINFO_pause_RDWR_3)5500 DEF(AUDIO_SETINFO_pause_RDWR_3)   { test_AUDIO_SETINFO_pause(O_RDWR, 1, 1); }
5501 
5502 /*
5503  * Check whether gain can be obtained/set.
5504  * And the gain should work with rich mixer.
5505  * PR kern/52781
5506  */
DEF(AUDIO_SETINFO_gain)5507 DEF(AUDIO_SETINFO_gain)
5508 {
5509 	struct audio_info ai;
5510 	mixer_ctrl_t m;
5511 	int index;
5512 	int master;
5513 	int master_backup;
5514 	int gain;
5515 	int fd;
5516 	int mixerfd;
5517 	int r;
5518 
5519 	TEST("AUDIO_SETINFO_gain");
5520 
5521 	/* Open /dev/mixer */
5522 	mixerfd = OPEN(devmixer, O_RDWR);
5523 	REQUIRED_SYS_OK(mixerfd);
5524 	index = mixer_get_outputs_master(mixerfd);
5525 	if (index == -1) {
5526 		XP_SKIP("Hardware has no outputs.master");
5527 		CLOSE(mixerfd);
5528 		return;
5529 	}
5530 
5531 	/*
5532 	 * Get current outputs.master.
5533 	 * auich(4) requires class type (m.type) and number of channels
5534 	 * (un.value.num_channels) in addition to the index (m.dev)...
5535 	 * What is the index...?
5536 	 */
5537 	memset(&m, 0, sizeof(m));
5538 	m.dev = index;
5539 	m.type = AUDIO_MIXER_VALUE;
5540 	m.un.value.num_channels = 1; /* dummy */
5541 	r = IOCTL(mixerfd, AUDIO_MIXER_READ, &m, "m.dev=%d", m.dev);
5542 	REQUIRED_SYS_EQ(0, r);
5543 	master = m.un.value.level[0];
5544 	DPRINTF("  > outputs.master = %d\n", master);
5545 	master_backup = master;
5546 
5547 	/* Open /dev/audio */
5548 	fd = OPEN(devaudio, O_WRONLY);
5549 	REQUIRED_SYS_OK(fd);
5550 
5551 	/* Check ai.play.gain */
5552 	r = IOCTL(fd, AUDIO_GETINFO, &ai, "");
5553 	XP_SYS_EQ(0, r);
5554 	XP_EQ(master, ai.play.gain);
5555 
5556 	/* Change it some different value */
5557 	AUDIO_INITINFO(&ai);
5558 	if (master == 0)
5559 		gain = 255;
5560 	else
5561 		gain = 0;
5562 	ai.play.gain = gain;
5563 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "play.gain=%d", ai.play.gain);
5564 	XP_SYS_EQ(0, r);
5565 
5566 	/* Check gain has changed */
5567 	r = IOCTL(fd, AUDIO_GETINFO, &ai, "play.gain");
5568 	XP_SYS_EQ(0, r);
5569 	XP_NE(master, ai.play.gain);
5570 
5571 	/* Check whether outputs.master work with gain */
5572 	r = IOCTL(mixerfd, AUDIO_MIXER_READ, &m, "");
5573 	XP_SYS_EQ(0, r);
5574 	XP_EQ(ai.play.gain, m.un.value.level[0]);
5575 
5576 	/* Restore outputs.master */
5577 	AUDIO_INITINFO(&ai);
5578 	ai.play.gain = master_backup;
5579 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "play.gain=%d", ai.play.gain);
5580 	XP_SYS_EQ(0, r);
5581 
5582 	r = CLOSE(fd);
5583 	XP_SYS_EQ(0, r);
5584 	r = CLOSE(mixerfd);
5585 	XP_SYS_EQ(0, r);
5586 }
5587 
5588 /*
5589  * Look if there are any (non-zero) gain values that can be changed.
5590  * If any gain can be set, it is set to gain[0].
5591  * If another gain can be set, it is set to gain[1], otherwise gain[1] = -1.
5592  * This is for AUDIO_SETINFO_gain_balance.
5593  */
5594 static void
get_changeable_gain(int fd,int * gain,const char * dir,int offset)5595 get_changeable_gain(int fd, int *gain, const char *dir, int offset)
5596 {
5597 	struct audio_info ai;
5598 	int *ai_gain;
5599 	int hi;
5600 	int lo;
5601 	int r;
5602 
5603 	/* A hack to handle ai.{play,record}.gain in the same code.. */
5604 	ai_gain = (int *)(((char *)&ai) + offset);
5605 
5606 	/* Try to set the maximum gain */
5607 	AUDIO_INITINFO(&ai);
5608 	*ai_gain = AUDIO_MAX_GAIN;
5609 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "%s.gain=%d", dir, *ai_gain);
5610 	XP_SYS_EQ(0, r);
5611 	/* Get again.  The value you set is not always used as is. */
5612 	AUDIO_INITINFO(&ai);
5613 	r = IOCTL(fd, AUDIO_GETINFO, &ai, "&ai");
5614 	XP_SYS_EQ(0, r);
5615 	hi = *ai_gain;
5616 
5617 	/* Look for next configurable value. */
5618 	for (lo = hi - 1; lo >= 0; lo--) {
5619 		AUDIO_INITINFO(&ai);
5620 		*ai_gain = lo;
5621 		r = IOCTL(fd, AUDIO_SETINFO, &ai, "%s.gain=%d", dir, *ai_gain);
5622 		XP_SYS_EQ(0, r);
5623 		/* Get again */
5624 		r = IOCTL(fd, AUDIO_GETINFO, &ai, "&ai");
5625 		XP_SYS_EQ(0, r);
5626 		if (*ai_gain != hi) {
5627 			lo = *ai_gain;
5628 			break;
5629 		}
5630 	}
5631 
5632 	/* Now gain is lo(=gain[0]). */
5633 
5634 	/*
5635 	 * hi  lo
5636 	 * --- ---
5637 	 *  <0  <0          : not available.
5638 	 * >=0  <0          : available but not changeable.
5639 	 * >=0 >=0 (hi!=lo) : available and changeable.
5640 	 */
5641 	if (hi < 0) {
5642 		gain[0] = -1;
5643 		gain[1] = -1;
5644 		DPRINTF("  > %s.gain cannot be set\n", dir);
5645 	} else if (lo < 0) {
5646 		gain[0] = hi;
5647 		gain[1] = -1;
5648 		DPRINTF("  > %s.gain can only be set %d\n", dir, gain[0]);
5649 	} else {
5650 		gain[0] = lo;
5651 		gain[1] = hi;
5652 		DPRINTF("  > %s.gain can be set %d, %d\n",
5653 		    dir, gain[0], gain[1]);
5654 	}
5655 }
5656 
5657 /*
5658  * Look if there are any balance values that can be changed.
5659  * If any balance value can be set, it is set to balance[0].
5660  * If another balance value can be set, it is set to balance[1],
5661  * otherwise balance[1] = -1.
5662  * This is for AUDIO_SETINFO_gain_balance.
5663  */
5664 static void
get_changeable_balance(int fd,int * balance,const char * dir,int offset)5665 get_changeable_balance(int fd, int *balance, const char *dir, int offset)
5666 {
5667 	struct audio_info ai;
5668 	u_char *ai_balance;
5669 	u_char left;
5670 	u_char right;
5671 	int r;
5672 
5673 	/* A hack to handle ai.{play,record}.balance in the same code.. */
5674 	ai_balance = ((u_char *)&ai) + offset;
5675 
5676 	/* Look for the right side configurable value. */
5677 	AUDIO_INITINFO(&ai);
5678 	*ai_balance = AUDIO_RIGHT_BALANCE;
5679 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "%s.balance=%d", dir, *ai_balance);
5680 	XP_SYS_EQ(0, r);
5681 	/* Get again.  The value you set is not always used as is. */
5682 	r = IOCTL(fd, AUDIO_GETINFO, &ai, "&ai");
5683 	XP_SYS_EQ(0, r);
5684 	right = *ai_balance;
5685 
5686 	/* Look for the left side configurable value. */
5687 	AUDIO_INITINFO(&ai);
5688 	*ai_balance = AUDIO_LEFT_BALANCE;
5689 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "%s.balance=%d", dir, *ai_balance);
5690 	XP_SYS_EQ(0, r);
5691 	/* Get again */
5692 	r = IOCTL(fd, AUDIO_GETINFO, &ai, "&ai");
5693 	XP_SYS_EQ(0, r);
5694 	left = *ai_balance;
5695 
5696 	/* Now balance is the left(=balance[0]). */
5697 
5698 	if (left == right) {
5699 		/* The driver has no balance feature. */
5700 		balance[0] = left;
5701 		balance[1] = -1;
5702 		DPRINTF("  > %s.balance can only be set %d\n",
5703 		    dir, balance[0]);
5704 	} else {
5705 		balance[0] = left;
5706 		balance[1] = right;
5707 		DPRINTF("  > %s.balance can be set %d, %d\n",
5708 		    dir, balance[0], balance[1]);
5709 	}
5710 }
5711 
5712 /*
5713  * Check whether gain and balance can be set at the same time.
5714  * PR kern/56308
5715  */
DEF(AUDIO_SETINFO_gain_balance)5716 DEF(AUDIO_SETINFO_gain_balance)
5717 {
5718 	struct audio_info oai;
5719 	struct audio_info ai;
5720 	int i;
5721 	int mode;
5722 	int fd;
5723 	int r;
5724 	int pgain[2];
5725 	int pbalance[2];
5726 	int rgain[2];
5727 	int rbalance[2];
5728 	bool ptest;
5729 	bool rtest;
5730 
5731 	TEST("AUDIO_SETINFO_gain_balance");
5732 
5733 	mode = openable_mode();
5734 	fd = OPEN(devaudio, mode);
5735 	REQUIRED_SYS_OK(fd);
5736 
5737 	/* Backup current gain and balance */
5738 	r = IOCTL(fd, AUDIO_GETINFO, &oai, "&oai");
5739 	XP_SYS_EQ(0, r);
5740 
5741 	if (debug) {
5742 		printf("  > old play.gain      = %d\n", oai.play.gain);
5743 		printf("  > old play.balance   = %d\n", oai.play.balance);
5744 		printf("  > old record.gain    = %d\n", oai.record.gain);
5745 		printf("  > old record.balance = %d\n", oai.record.balance);
5746 	}
5747 
5748 	for (i = 0; i < 2; i++) {
5749 		pgain[i]    = -1;
5750 		pbalance[i] = -1;
5751 		rgain[i]    = -1;
5752 		rbalance[i] = -1;
5753 	}
5754 
5755 	/*
5756 	 * First, check each one separately can be changed.
5757 	 *
5758 	 * The simplest two different gain values are zero and non-zero.
5759 	 * But some device drivers seem to process balance differently
5760 	 * when the gain is high enough and when the gain is zero or near.
5761 	 * So I needed to select two different "non-zero (and high if
5762 	 * possible)" gains.
5763 	 */
5764 	if (hw_canplay()) {
5765 		get_changeable_gain(fd, pgain, "play",
5766 		    offsetof(struct audio_info, play.gain));
5767 		get_changeable_balance(fd, pbalance, "play",
5768 		    offsetof(struct audio_info, play.balance));
5769 	}
5770 	if (hw_canrec()) {
5771 		get_changeable_gain(fd, rgain, "record",
5772 		    offsetof(struct audio_info, record.gain));
5773 		get_changeable_balance(fd, rbalance, "record",
5774 		    offsetof(struct audio_info, record.balance));
5775 	}
5776 
5777 	/*
5778 	 * [0] [1]
5779 	 * --- ---
5780 	 *  -1  *  : not available.
5781 	 * >=0  -1 : available but not changeable.
5782 	 * >=0 >=0 : available and changeable.  It can be tested.
5783 	 */
5784 	ptest = (pgain[0]    >= 0 && pgain[1]    >= 0 &&
5785 	         pbalance[0] >= 0 && pbalance[1] >= 0);
5786 	rtest = (rgain[0]    >= 0 && rgain[1]    >= 0 &&
5787 	         rbalance[0] >= 0 && rbalance[1] >= 0);
5788 
5789 	if (ptest == false && rtest == false) {
5790 		XP_SKIP(
5791 		    "The test requires changeable gain and changeable balance");
5792 
5793 		/* Restore as possible */
5794 		AUDIO_INITINFO(&ai);
5795 		ai.play.gain      = oai.play.gain;
5796 		ai.play.balance   = oai.play.balance;
5797 		ai.record.gain    = oai.record.gain;
5798 		ai.record.balance = oai.record.balance;
5799 		r = IOCTL(fd, AUDIO_SETINFO, &ai, "restore all");
5800 		XP_SYS_EQ(0, r);
5801 
5802 		r = CLOSE(fd);
5803 		XP_SYS_EQ(0, r);
5804 		return;
5805 	}
5806 
5807 	/*
5808 	 * If both play.gain and play.balance are changeable,
5809 	 * it should be able to set both at the same time.
5810 	 */
5811 	if (ptest) {
5812 		AUDIO_INITINFO(&ai);
5813 		ai.play.gain    = pgain[1];
5814 		ai.play.balance = pbalance[1];
5815 		r = IOCTL(fd, AUDIO_SETINFO, &ai, "play.gain=%d/balance=%d",
5816 		    ai.play.gain, ai.play.balance);
5817 		XP_SYS_EQ(0, r);
5818 
5819 		AUDIO_INITINFO(&ai);
5820 		r = IOCTL(fd, AUDIO_GETINFO, &ai, "&ai");
5821 		XP_SYS_EQ(0, r);
5822 
5823 		DPRINTF("  > setting play.gain=%d/balance=%d: "
5824 		    "result gain=%d/balance=%d\n",
5825 		    pgain[1], pbalance[1], ai.play.gain, ai.play.balance);
5826 		XP_EQ(ai.play.gain,    pgain[1]);
5827 		XP_EQ(ai.play.balance, pbalance[1]);
5828 	}
5829 	/*
5830 	 * If both record.gain and record.balance are changeable,
5831 	 * it should be able to set both at the same time.
5832 	 */
5833 	if (rtest) {
5834 		AUDIO_INITINFO(&ai);
5835 		ai.record.gain    = rgain[1];
5836 		ai.record.balance = rbalance[1];
5837 		r = IOCTL(fd, AUDIO_SETINFO, &ai, "record.gain=%d/balance=%d",
5838 		    ai.record.gain, ai.record.balance);
5839 		XP_SYS_EQ(0, r);
5840 
5841 		AUDIO_INITINFO(&ai);
5842 		r = IOCTL(fd, AUDIO_GETINFO, &ai, "&ai");
5843 		XP_SYS_EQ(0, r);
5844 
5845 		DPRINTF("  > setting record.gain=%d/balance=%d: "
5846 		    "result gain=%d/balance=%d\n",
5847 		    rgain[1], rbalance[1], ai.record.gain, ai.record.balance);
5848 		XP_EQ(ai.record.gain,    rgain[1]);
5849 		XP_EQ(ai.record.balance, rbalance[1]);
5850 	}
5851 
5852 	/*
5853 	 * Restore all values as possible at the same time.
5854 	 * This restore is also a test.
5855 	 */
5856 	AUDIO_INITINFO(&ai);
5857 	ai.play.gain      = oai.play.gain;
5858 	ai.play.balance   = oai.play.balance;
5859 	ai.record.gain    = oai.record.gain;
5860 	ai.record.balance = oai.record.balance;
5861 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "restore all");
5862 	XP_SYS_EQ(0, r);
5863 
5864 	AUDIO_INITINFO(&ai);
5865 	r = IOCTL(fd, AUDIO_GETINFO, &ai, "&ai");
5866 	XP_SYS_EQ(0, r);
5867 	XP_EQ(oai.play.gain,      ai.play.gain);
5868 	XP_EQ(oai.play.balance,   ai.play.balance);
5869 	XP_EQ(oai.record.gain,    ai.record.gain);
5870 	XP_EQ(oai.record.balance, ai.record.balance);
5871 
5872 	r = CLOSE(fd);
5873 	XP_SYS_EQ(0, r);
5874 }
5875 
5876 /*
5877  * Changing track formats after mmap should fail.
5878  */
DEF(AUDIO_SETINFO_mmap_enc)5879 DEF(AUDIO_SETINFO_mmap_enc)
5880 {
5881 	struct audio_info ai;
5882 	void *ptr;
5883 	int fd;
5884 	int r;
5885 
5886 	TEST("AUDIO_SETINFO_mmap");
5887 
5888 #if !defined(NO_RUMP)
5889 	if (use_rump) {
5890 		XP_SKIP("rump doesn't support mmap");
5891 		return;
5892 	}
5893 #endif
5894 
5895 	fd = OPEN(devaudio, O_WRONLY);
5896 	REQUIRED_SYS_OK(fd);
5897 
5898 	ptr = MMAP(NULL, 1, PROT_WRITE, MAP_FILE, fd, 0);
5899 	XP_SYS_PTR(0, ptr);
5900 
5901 	/*
5902 	 * SETINFO after mmap should fail.
5903 	 * NetBSD9 changes errno.
5904 	 */
5905 	AUDIO_INITINFO(&ai);
5906 	ai.play.channels = 2;
5907 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "channels=2");
5908 	if (netbsd < 9) {
5909 		XP_SYS_NG(EINVAL, r);
5910 	} else {
5911 		XP_SYS_NG(EIO, r);
5912 	}
5913 
5914 	r = CLOSE(fd);
5915 	XP_SYS_EQ(0, r);
5916 
5917 	reset_after_mmap();
5918 }
5919 
5920 /*
5921  * Even after mmap, changing pause should succeed.
5922  */
DEF(AUDIO_SETINFO_mmap_pause)5923 DEF(AUDIO_SETINFO_mmap_pause)
5924 {
5925 	struct audio_info ai;
5926 	void *ptr;
5927 	int fd;
5928 	int r;
5929 
5930 	TEST("AUDIO_SETINFO_mmap");
5931 
5932 #if !defined(NO_RUMP)
5933 	if (use_rump) {
5934 		XP_SKIP("rump doesn't support mmap");
5935 		return;
5936 	}
5937 #endif
5938 
5939 	fd = OPEN(devaudio, O_WRONLY);
5940 	REQUIRED_SYS_OK(fd);
5941 
5942 	ptr = MMAP(NULL, 1, PROT_WRITE, MAP_FILE, fd, 0);
5943 	XP_SYS_PTR(0, ptr);
5944 
5945 	/* SETINFO after mmap should fail */
5946 	AUDIO_INITINFO(&ai);
5947 	ai.play.pause = 1;
5948 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "set pause");
5949 	XP_SYS_EQ(0, r);
5950 
5951 	AUDIO_INITINFO(&ai);
5952 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "get pause");
5953 	XP_SYS_EQ(0, r);
5954 
5955 	XP_EQ(1, ai.play.pause);
5956 
5957 	/*
5958 	 * Unpause before close.  Unless, subsequent audioplay(1) which use
5959 	 * /dev/sound by default will pause...
5960 	 */
5961 	AUDIO_INITINFO(&ai);
5962 	ai.play.pause = 0;
5963 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "reset pause");
5964 	XP_SYS_EQ(0, r);
5965 
5966 	r = CLOSE(fd);
5967 	XP_SYS_EQ(0, r);
5968 
5969 	reset_after_mmap();
5970 }
5971 
5972 #define NENC	(AUDIO_ENCODING_AC3 + 1)
5973 #define NPREC	(5)
5974 /*
5975  * Make table of encoding+precision supported by this device.
5976  * Return last used index .
5977  * This function is called from test_AUDIO_GETENC_*()
5978  */
5979 int
getenc_make_table(int fd,int expected[][5])5980 getenc_make_table(int fd, int expected[][5])
5981 {
5982 	audio_encoding_t ae;
5983 	int idx;
5984 	int p;
5985 	int r;
5986 
5987 	/*
5988 	 * expected[][] is two dimensional table.
5989 	 * encoding \ precision| 4  8  16  24  32
5990 	 * --------------------+-----------------
5991 	 * AUDIO_ENCODING_NONE |
5992 	 * AUDIO_ENCODING_ULAW |
5993 	 *  :
5994 	 *
5995 	 * Each cell has expected behavior.
5996 	 *  0: the hardware doesn't support this encoding/precision.
5997 	 *  1: the hardware supports this encoding/precision.
5998 	 *  2: the hardware doesn't support this encoding/precision but
5999 	 *     audio layer will respond as supported for compatibility.
6000 	 */
6001 	for (idx = 0; ; idx++) {
6002 		memset(&ae, 0, sizeof(ae));
6003 		ae.index = idx;
6004 		r = IOCTL(fd, AUDIO_GETENC, &ae, "index=%d", idx);
6005 		if (r != 0) {
6006 			XP_SYS_NG(EINVAL, r);
6007 			break;
6008 		}
6009 
6010 		XP_EQ(idx, ae.index);
6011 		if (0 <= ae.encoding && ae.encoding <= AUDIO_ENCODING_AC3) {
6012 			XP_EQ_STR(encoding_names[ae.encoding], ae.name);
6013 		} else {
6014 			XP_FAIL("ae.encoding %d", ae.encoding);
6015 		}
6016 
6017 		if (ae.precision != 4 &&
6018 		    ae.precision != 8 &&
6019 		    ae.precision != 16 &&
6020 		    ae.precision != 24 &&
6021 		    ae.precision != 32)
6022 		{
6023 			XP_FAIL("ae.precision %d", ae.precision);
6024 		}
6025 		/* Other bits should not be set */
6026 		XP_EQ(0, (ae.flags & ~AUDIO_ENCODINGFLAG_EMULATED));
6027 
6028 		expected[ae.encoding][ae.precision / 8] = 1;
6029 		DPRINTF("  > encoding=%s precision=%d\n",
6030 		    encoding_names[ae.encoding], ae.precision);
6031 	}
6032 
6033 	/*
6034 	 * Backward compatibility bandaid.
6035 	 *
6036 	 * - Some encoding/precision pairs are obviously inconsistent
6037 	 *   (e.g., encoding=AUDIO_ENCODING_PCM8, precision=16) but
6038 	 *   it's due to historical reasons.
6039 	 * - It's incomplete for NetBSD7 and NetBSD8.  I don't really
6040 	 *   understand their rule...  This is just memo, not specification.
6041 	 */
6042 #define SET(x) do {	\
6043 	if ((x) == 0)	\
6044 		x = 2;	\
6045  } while (0)
6046 #define p4 (0)
6047 #define p8 (1)
6048 #define p16 (2)
6049 #define p24 (3)
6050 #define p32 (4)
6051 
6052 	if (expected[AUDIO_ENCODING_SLINEAR][p8]) {
6053 		SET(expected[AUDIO_ENCODING_SLINEAR_LE][p8]);
6054 		SET(expected[AUDIO_ENCODING_SLINEAR_BE][p8]);
6055 	}
6056 	if (expected[AUDIO_ENCODING_ULINEAR][p8]) {
6057 		SET(expected[AUDIO_ENCODING_ULINEAR_LE][p8]);
6058 		SET(expected[AUDIO_ENCODING_ULINEAR_BE][p8]);
6059 		SET(expected[AUDIO_ENCODING_PCM8][p8]);
6060 		SET(expected[AUDIO_ENCODING_PCM16][p8]);
6061 	}
6062 	for (p = p16; p <= p32; p++) {
6063 #if !defined(AUDIO_SUPPORT_LINEAR24)
6064 		if (p == p24)
6065 			continue;
6066 #endif
6067 		if (expected[AUDIO_ENCODING_SLINEAR_NE][p]) {
6068 			SET(expected[AUDIO_ENCODING_SLINEAR][p]);
6069 			SET(expected[AUDIO_ENCODING_PCM16][p]);
6070 		}
6071 		if (expected[AUDIO_ENCODING_ULINEAR_NE][p]) {
6072 			SET(expected[AUDIO_ENCODING_ULINEAR][p]);
6073 		}
6074 	}
6075 
6076 	if (netbsd < 9) {
6077 		if (expected[AUDIO_ENCODING_SLINEAR_LE][p16] ||
6078 		    expected[AUDIO_ENCODING_SLINEAR_BE][p16] ||
6079 		    expected[AUDIO_ENCODING_ULINEAR_LE][p16] ||
6080 		    expected[AUDIO_ENCODING_ULINEAR_BE][p16])
6081 		{
6082 			SET(expected[AUDIO_ENCODING_PCM8][p8]);
6083 			SET(expected[AUDIO_ENCODING_PCM16][p8]);
6084 			SET(expected[AUDIO_ENCODING_SLINEAR_LE][p8]);
6085 			SET(expected[AUDIO_ENCODING_SLINEAR_BE][p8]);
6086 			SET(expected[AUDIO_ENCODING_ULINEAR_LE][p8]);
6087 			SET(expected[AUDIO_ENCODING_ULINEAR_BE][p8]);
6088 			SET(expected[AUDIO_ENCODING_SLINEAR][p8]);
6089 			SET(expected[AUDIO_ENCODING_ULINEAR][p8]);
6090 		}
6091 	}
6092 
6093 	/* Return last used index */
6094 	return idx;
6095 #undef SET
6096 #undef p4
6097 #undef p8
6098 #undef p16
6099 #undef p24
6100 #undef p32
6101 }
6102 
6103 /*
6104  * This function is called from test_AUDIO_GETENC below.
6105  */
6106 void
xp_getenc(int expected[][5],int enc,int j,int r,struct audio_prinfo * pr)6107 xp_getenc(int expected[][5], int enc, int j, int r, struct audio_prinfo *pr)
6108 {
6109 	int prec = (j == 0) ? 4 : j * 8;
6110 
6111 	if (expected[enc][j]) {
6112 		/* expect to succeed */
6113 		XP_SYS_EQ(0, r);
6114 
6115 		XP_EQ(enc, pr->encoding);
6116 		XP_EQ(prec, pr->precision);
6117 	} else {
6118 		/* expect to fail */
6119 		XP_SYS_NG(EINVAL, r);
6120 	}
6121 }
6122 
6123 /*
6124  * This function is called from test_AUDIO_GETENC below.
6125  */
6126 void
getenc_check_encodings(int openmode,int expected[][5])6127 getenc_check_encodings(int openmode, int expected[][5])
6128 {
6129 	struct audio_info ai;
6130 	int fd;
6131 	int i, j;
6132 	int r;
6133 
6134 	fd = OPEN(devaudio, openmode);
6135 	REQUIRED_SYS_OK(fd);
6136 
6137 	for (i = 0; i < NENC; i++) {
6138 		for (j = 0; j < NPREC; j++) {
6139 			/* precisions are 4 and 8, 16, 24, 32 */
6140 			int prec = (j == 0) ? 4 : j * 8;
6141 
6142 			/*
6143 			 * AUDIO_GETENC has no way to know range of
6144 			 * supported channels and sample_rate.
6145 			 */
6146 			AUDIO_INITINFO(&ai);
6147 			ai.play.encoding = i;
6148 			ai.play.precision = prec;
6149 			ai.record.encoding = i;
6150 			ai.record.precision = prec;
6151 
6152 			r = IOCTL(fd, AUDIO_SETINFO, &ai, "%s:%d",
6153 			    encoding_names[i], prec);
6154 			if (mode2play(openmode))
6155 				xp_getenc(expected, i, j, r, &ai.play);
6156 			if (mode2rec(openmode))
6157 				xp_getenc(expected, i, j, r, &ai.record);
6158 		}
6159 	}
6160 	r = CLOSE(fd);
6161 	XP_SYS_EQ(0, r);
6162 }
6163 
6164 /*
6165  * Check whether encoding+precision obtained by AUDIO_GETENC can be set.
6166  */
DEF(AUDIO_GETENC_range)6167 DEF(AUDIO_GETENC_range)
6168 {
6169 	audio_encoding_t ae;
6170 	int fd;
6171 	int r;
6172 	int expected[NENC][NPREC];
6173 	int i, j;
6174 
6175 	TEST("AUDIO_GETENC_range");
6176 
6177 	fd = OPEN(devaudio, openable_mode());
6178 	REQUIRED_SYS_OK(fd);
6179 
6180 	memset(&expected, 0, sizeof(expected));
6181 	i = getenc_make_table(fd, expected);
6182 
6183 	/* When error has occurred, the next index should also occur error */
6184 	ae.index = i + 1;
6185 	r = IOCTL(fd, AUDIO_GETENC, &ae, "index=%d", ae.index);
6186 	XP_SYS_NG(EINVAL, r);
6187 
6188 	r = CLOSE(fd);
6189 	XP_SYS_EQ(0, r);
6190 
6191 	/* For debug */
6192 	if (debug) {
6193 		for (i = 0; i < NENC; i++) {
6194 			printf("expected[%2d] %15s", i, encoding_names[i]);
6195 			for (j = 0; j < NPREC; j++) {
6196 				printf(" %d", expected[i][j]);
6197 			}
6198 			printf("\n");
6199 		}
6200 	}
6201 
6202 	/* Whether obtained encodings can be actually set */
6203 	if (hw_fulldup()) {
6204 		/* Test both R/W at once using single descriptor */
6205 		getenc_check_encodings(O_RDWR, expected);
6206 	} else {
6207 		/* Test playback and recording if available */
6208 		if (hw_canplay()) {
6209 			getenc_check_encodings(O_WRONLY, expected);
6210 		}
6211 		if (hw_canplay() && hw_canrec()) {
6212 			xxx_close_wait();
6213 		}
6214 		if (hw_canrec()) {
6215 			getenc_check_encodings(O_RDONLY, expected);
6216 		}
6217 	}
6218 }
6219 #undef NENC
6220 #undef NPREC
6221 
6222 /*
6223  * Check AUDIO_GETENC out of range.
6224  */
DEF(AUDIO_GETENC_error)6225 DEF(AUDIO_GETENC_error)
6226 {
6227 	audio_encoding_t e;
6228 	int fd;
6229 	int r;
6230 
6231 	TEST("AUDIO_GETENC_error");
6232 
6233 	fd = OPEN(devaudio, openable_mode());
6234 	REQUIRED_SYS_OK(fd);
6235 
6236 	memset(&e, 0, sizeof(e));
6237 	e.index = -1;
6238 	r = IOCTL(fd, AUDIO_GETENC, &e, "index=-1");
6239 	/* NetBSD7 may not fail depending on hardware driver */
6240 	XP_SYS_NG(EINVAL, r);
6241 
6242 	r = CLOSE(fd);
6243 	XP_SYS_EQ(0, r);
6244 }
6245 
6246 /*
6247  * AUDIO_[PR]ERROR should be zero on the initial state even on non-existent
6248  * track.
6249  */
6250 void
test_AUDIO_ERROR(int openmode)6251 test_AUDIO_ERROR(int openmode)
6252 {
6253 	int fd;
6254 	int r;
6255 	int errors;
6256 
6257 	TEST("AUDIO_ERROR_%s", openmode_str[openmode] + 2);
6258 	if (mode2aumode(openmode) == 0) {
6259 		XP_SKIP("Operation not allowed on this hardware property");
6260 		return;
6261 	}
6262 
6263 	fd = OPEN(devaudio, openmode);
6264 	REQUIRED_SYS_OK(fd);
6265 
6266 	/* Check PERROR */
6267 	errors = 0xdeadbeef;
6268 	r = IOCTL(fd, AUDIO_PERROR, &errors, "");
6269 	XP_SYS_EQ(0, r);
6270 	XP_EQ(0, errors);
6271 
6272 	/* Check RERROR */
6273 	errors = 0xdeadbeef;
6274 	r = IOCTL(fd, AUDIO_RERROR, &errors, "");
6275 	XP_SYS_EQ(0, r);
6276 	XP_EQ(0, errors);
6277 
6278 	r = CLOSE(fd);
6279 	XP_SYS_EQ(0, r);
6280 }
DEF(AUDIO_ERROR_RDONLY)6281 DEF(AUDIO_ERROR_RDONLY)	{ test_AUDIO_ERROR(O_RDONLY); }
DEF(AUDIO_ERROR_WRONLY)6282 DEF(AUDIO_ERROR_WRONLY)	{ test_AUDIO_ERROR(O_WRONLY); }
DEF(AUDIO_ERROR_RDWR)6283 DEF(AUDIO_ERROR_RDWR)	{ test_AUDIO_ERROR(O_RDWR); }
6284 
6285 /*
6286  * AUDIO_GETIOFFS at least one block.
6287  */
6288 void
test_AUDIO_GETIOFFS_one(int openmode)6289 test_AUDIO_GETIOFFS_one(int openmode)
6290 {
6291 	struct audio_info ai;
6292 	audio_offset_t o;
6293 	int fd;
6294 	int r;
6295 	u_int blocksize;
6296 	u_int blk_ms;
6297 
6298 	TEST("AUDIO_GETIOFFS_one_%s", openmode_str[openmode] + 2);
6299 	if (mode2aumode(openmode) == 0) {
6300 		XP_SKIP("Operation not allowed on this hardware property");
6301 		return;
6302 	}
6303 
6304 	fd = OPEN(devaudio, openmode);
6305 	REQUIRED_SYS_OK(fd);
6306 
6307 #if 0
6308 	/*
6309 	 * On NetBSD7/8, native encodings and emulated encodings behave
6310 	 * differently.  But it's hard to identify which encoding is native.
6311 	 * If you try other encodings, edit these parameters manually.
6312 	 */
6313 	AUDIO_INITINFO(&ai);
6314 	ai.record.encoding = AUDIO_ENCODING_SLINEAR_NE;
6315 	ai.record.precision = 16;
6316 	ai.record.channels = 2;
6317 	ai.record.sample_rate = 48000;
6318 	/* ai.blocksize is shared by play and record, so set both the same. */
6319 	*ai.play = *ai.record;
6320 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "");
6321 	REQUIRED_SYS_EQ(0, r);
6322 #endif
6323 
6324 	/* Get blocksize to calc blk_ms. */
6325 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
6326 	REQUIRED_SYS_EQ(0, r);
6327 	blocksize = ai.blocksize;
6328 	if (netbsd < 9) {
6329 		blk_ms = 0;
6330 	} else {
6331 		/* On NetBSD9, blocktime can always be calculated. */
6332 		blk_ms = blocksize * 1000 /
6333 		    (ai.play.precision / 8 * ai.play.channels *
6334 		     ai.play.sample_rate);
6335 	}
6336 	if (blk_ms == 0)
6337 		blk_ms = 50;
6338 	DPRINTF("  > blocksize=%u, estimated blk_ms=%u\n", blocksize, blk_ms);
6339 
6340 	/*
6341 	 * Even when just opened, recording counters will start.
6342 	 * Wait a moment, about one block time.
6343 	 */
6344 	usleep(blk_ms * 1000);
6345 
6346 	r = IOCTL(fd, AUDIO_GETIOFFS, &o, "");
6347 	XP_SYS_EQ(0, r);
6348 	if (mode2rec(openmode)) {
6349 		/*
6350 		 * It's difficult to know exact values.
6351 		 * But at least these should not be zero.
6352 		 */
6353 		DPRINTF("  > %d: samples=%u deltablks=%u offset=%u\n",
6354 		    __LINE__, o.samples, o.deltablks, o.offset);
6355 		XP_NE(0, o.samples);
6356 		XP_NE(0, o.deltablks);
6357 		XP_NE(0, o.offset);
6358 	} else {
6359 		/* All are zero on playback track. */
6360 		XP_EQ(0, o.samples);
6361 		XP_EQ(0, o.deltablks);
6362 		XP_EQ(0, o.offset);
6363 	}
6364 
6365 	r = CLOSE(fd);
6366 	XP_SYS_EQ(0, r);
6367 }
DEF(AUDIO_GETIOFFS_one_RDONLY)6368 DEF(AUDIO_GETIOFFS_one_RDONLY) { test_AUDIO_GETIOFFS_one(O_RDONLY); }
DEF(AUDIO_GETIOFFS_one_WRONLY)6369 DEF(AUDIO_GETIOFFS_one_WRONLY) { test_AUDIO_GETIOFFS_one(O_WRONLY); }
DEF(AUDIO_GETIOFFS_one_RDWR)6370 DEF(AUDIO_GETIOFFS_one_RDWR)   { test_AUDIO_GETIOFFS_one(O_RDWR); }
6371 
6372 /*
6373  * AUDIO_GETOOFFS for one block.
6374  */
6375 void
test_AUDIO_GETOOFFS_one(int openmode)6376 test_AUDIO_GETOOFFS_one(int openmode)
6377 {
6378 	struct audio_info ai;
6379 	audio_offset_t o;
6380 	char *buf;
6381 	int fd;
6382 	int r;
6383 	u_int blocksize;
6384 	u_int initial_offset;
6385 	u_int blk_ms;
6386 
6387 	TEST("AUDIO_GETOOFFS_one_%s", openmode_str[openmode] + 2);
6388 	if (mode2aumode(openmode) == 0) {
6389 		XP_SKIP("Operation not allowed on this hardware property");
6390 		return;
6391 	}
6392 
6393 	fd = OPEN(devaudio, openmode);
6394 	REQUIRED_SYS_OK(fd);
6395 
6396 #if 0
6397 	/*
6398 	 * On NetBSD7/8, native encodings and emulated encodings behave
6399 	 * differently.  But it's hard to identify which encoding is native.
6400 	 * If you try other encodings, edit these parameters manually.
6401 	 */
6402 	AUDIO_INITINFO(&ai);
6403 	ai.play.encoding = AUDIO_ENCODING_SLINEAR_NE;
6404 	ai.play.precision = 16;
6405 	ai.play.channels = 2;
6406 	ai.play.sample_rate = 48000;
6407 	/* ai.blocksize is shared by play and record, so set both the same. */
6408 	*ai.record = *ai.play;
6409 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "slinear16/2ch/48000");
6410 	REQUIRED_SYS_EQ(0, r);
6411 #endif
6412 
6413 	/* Get blocksize to calc blk_ms. */
6414 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
6415 	REQUIRED_SYS_EQ(0, r);
6416 	blocksize = ai.blocksize;
6417 	if (netbsd < 9) {
6418 		blk_ms = 0;
6419 	} else {
6420 		/* On NetBSD9, blocktime can always be calculated. */
6421 		blk_ms = blocksize * 1000 /
6422 		    (ai.play.precision / 8 * ai.play.channels *
6423 		     ai.play.sample_rate);
6424 	}
6425 	if (blk_ms == 0)
6426 		blk_ms = 50;
6427 	DPRINTF("  > blocksize=%u, estimated blk_ms=%u\n", blocksize, blk_ms);
6428 
6429 	buf = (char *)malloc(blocksize);
6430 	REQUIRED_IF(buf != NULL);
6431 	memset(buf, 0xff, blocksize);
6432 
6433 	/*
6434 	 * On NetBSD7, .offset starts from one block.  What is the block??
6435 	 * On NetBSD9, .offset starts from zero.
6436 	 */
6437 	if (netbsd < 9) {
6438 		initial_offset = blocksize;
6439 	} else {
6440 		initial_offset = 0;
6441 	}
6442 
6443 	/* When just opened, all are zero. */
6444 	r = IOCTL(fd, AUDIO_GETOOFFS, &o, "");
6445 	XP_SYS_EQ(0, r);
6446 	XP_EQ(0, o.samples);
6447 	XP_EQ(0, o.deltablks);
6448 	XP_EQ(initial_offset, o.offset);
6449 
6450 	/* Even if wait (at least) one block, these remain unchanged. */
6451 	usleep(blk_ms * 1000);
6452 	r = IOCTL(fd, AUDIO_GETOOFFS, &o, "");
6453 	XP_SYS_EQ(0, r);
6454 	XP_EQ(0, o.samples);
6455 	XP_EQ(0, o.deltablks);
6456 	XP_EQ(initial_offset, o.offset);
6457 
6458 	/* Write one block. */
6459 	r = WRITE(fd, buf, blocksize);
6460 	if (mode2play(openmode)) {
6461 		XP_SYS_EQ(blocksize, r);
6462 	} else {
6463 		XP_SYS_NG(EBADF, r);
6464 	}
6465 	r = IOCTL(fd, AUDIO_DRAIN, NULL, "");
6466 	REQUIRED_SYS_EQ(0, r);
6467 
6468 	r = IOCTL(fd, AUDIO_GETOOFFS, &o, "");
6469 	XP_SYS_EQ(0, r);
6470 	if (mode2play(openmode)) {
6471 		/* All advance one block. */
6472 		XP_EQ(blocksize, o.samples);
6473 		XP_EQ(1, o.deltablks);
6474 		XP_EQ(initial_offset + blocksize, o.offset);
6475 	} else {
6476 		/*
6477 		 * All are zero on non-play track.
6478 		 * On NetBSD7, the rec track has play buffer, too.
6479 		 */
6480 		XP_EQ(0, o.samples);
6481 		XP_EQ(0, o.deltablks);
6482 		XP_EQ(initial_offset, o.offset);
6483 	}
6484 
6485 	r = CLOSE(fd);
6486 	XP_SYS_EQ(0, r);
6487 
6488 	free(buf);
6489 }
DEF(AUDIO_GETOOFFS_one_RDONLY)6490 DEF(AUDIO_GETOOFFS_one_RDONLY) { test_AUDIO_GETOOFFS_one(O_RDONLY); }
DEF(AUDIO_GETOOFFS_one_WRONLY)6491 DEF(AUDIO_GETOOFFS_one_WRONLY) { test_AUDIO_GETOOFFS_one(O_WRONLY); }
DEF(AUDIO_GETOOFFS_one_RDWR)6492 DEF(AUDIO_GETOOFFS_one_RDWR)   { test_AUDIO_GETOOFFS_one(O_RDWR); }
6493 
6494 /*
6495  * AUDIO_GETOOFFS when wrap around buffer.
6496  */
6497 void
test_AUDIO_GETOOFFS_wrap(int openmode)6498 test_AUDIO_GETOOFFS_wrap(int openmode)
6499 {
6500 	struct audio_info ai;
6501 	audio_offset_t o;
6502 	char *buf;
6503 	int fd;
6504 	int r;
6505 	u_int blocksize;
6506 	u_int buffer_size;
6507 	u_int initial_offset;
6508 	u_int nblks;
6509 
6510 	TEST("AUDIO_GETOOFFS_wrap_%s", openmode_str[openmode] + 2);
6511 	if (mode2aumode(openmode) == 0) {
6512 		XP_SKIP("Operation not allowed on this hardware property");
6513 		return;
6514 	}
6515 
6516 	fd = OPEN(devaudio, openmode);
6517 	REQUIRED_SYS_OK(fd);
6518 
6519 #if 1
6520 	/* To save test time, use larger format if possible. */
6521 	AUDIO_INITINFO(&ai);
6522 	ai.play.encoding = AUDIO_ENCODING_SLINEAR_NE;
6523 	ai.play.precision = 16;
6524 	ai.play.channels = 2;
6525 	ai.play.sample_rate = 48000;
6526 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "slinear16/2/48000");
6527 	if (r != 0)
6528 #endif
6529 	{
6530 		/*
6531 		 * If it cannot be set, use common format instead.
6532 		 * May be happened on NetBSD7/8.
6533 		 */
6534 		AUDIO_INITINFO(&ai);
6535 		ai.play.encoding = AUDIO_ENCODING_ULAW;
6536 		ai.play.precision = 8;
6537 		ai.play.channels = 1;
6538 		ai.play.sample_rate = 8000;
6539 		r = IOCTL(fd, AUDIO_SETINFO, &ai, "ulaw/1/8000");
6540 	}
6541 	REQUIRED_SYS_EQ(0, r);
6542 
6543 	/* Get buffer_size and blocksize. */
6544 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
6545 	REQUIRED_SYS_EQ(0, r);
6546 	buffer_size = ai.play.buffer_size;
6547 	blocksize = ai.blocksize;
6548 	nblks = buffer_size / blocksize;
6549 	DPRINTF("  > buffer_size=%u blocksize=%u nblks=%u\n",
6550 	    buffer_size, blocksize, nblks);
6551 
6552 	buf = (char *)malloc(buffer_size);
6553 	REQUIRED_IF(buf != NULL);
6554 	memset(buf, 0xff, buffer_size);
6555 
6556 	/*
6557 	 * On NetBSD7, .offset starts from one block.  What is the block??
6558 	 * On NetBSD9, .offset starts from zero.
6559 	 */
6560 	if (netbsd < 9) {
6561 		initial_offset = blocksize;
6562 	} else {
6563 		initial_offset = 0;
6564 	}
6565 
6566 	/* Write full buffer. */
6567 	r = WRITE(fd, buf, buffer_size);
6568 	if (mode2play(openmode)) {
6569 		XP_SYS_EQ(buffer_size, r);
6570 
6571 		/* Then, wait. */
6572 		r = IOCTL(fd, AUDIO_DRAIN, NULL, "");
6573 		REQUIRED_SYS_EQ(0, r);
6574 	} else {
6575 		XP_SYS_NG(EBADF, r);
6576 	}
6577 
6578 	/*
6579 	 * .deltablks is number of blocks since last checked.
6580 	 * .offset is wrapped around to zero.
6581 	 */
6582 	r = IOCTL(fd, AUDIO_GETOOFFS, &o, "");
6583 	XP_SYS_EQ(0, r);
6584 	if (mode2play(openmode)) {
6585 		/*
6586 		 * On NetBSD7, samples may be blocksize * nblks or buffer_size
6587 		 * depending on native/emulated encoding.
6588 		 * On NetBSD9, samples is always equal to buffer_size.
6589 		 */
6590 		if (buffer_size != blocksize * nblks &&
6591 		    o.samples == blocksize * nblks) {
6592 			DPRINTF("  > %d: samples(%u) == blocksize * nblks\n",
6593 			    __LINE__, o.samples);
6594 		} else {
6595 			XP_EQ(buffer_size, o.samples);
6596 		}
6597 		XP_EQ(nblks, o.deltablks);
6598 		XP_EQ(initial_offset, o.offset);
6599 	} else {
6600 		/*
6601 		 * On non-play track, it silently succeeds with zero.
6602 		 * But on NetBSD7, RDONLY descriptor also has play buffer.
6603 		 */
6604 		XP_EQ(0, o.samples);
6605 		XP_EQ(0, o.deltablks);
6606 		XP_EQ(initial_offset, o.offset);
6607 	}
6608 
6609 	r = CLOSE(fd);
6610 	XP_SYS_EQ(0, r);
6611 
6612 	free(buf);
6613 }
DEF(AUDIO_GETOOFFS_wrap_RDONLY)6614 DEF(AUDIO_GETOOFFS_wrap_RDONLY) { test_AUDIO_GETOOFFS_wrap(O_RDONLY); }
DEF(AUDIO_GETOOFFS_wrap_WRONLY)6615 DEF(AUDIO_GETOOFFS_wrap_WRONLY) { test_AUDIO_GETOOFFS_wrap(O_WRONLY); }
DEF(AUDIO_GETOOFFS_wrap_RDWR)6616 DEF(AUDIO_GETOOFFS_wrap_RDWR)   { test_AUDIO_GETOOFFS_wrap(O_RDWR); }
6617 
6618 /*
6619  * Check whether AUDIO_FLUSH clears AUDIO_GETOOFFS.
6620  */
6621 void
test_AUDIO_GETOOFFS_flush(int openmode)6622 test_AUDIO_GETOOFFS_flush(int openmode)
6623 {
6624 	struct audio_info ai;
6625 	audio_offset_t o;
6626 	char *buf;
6627 	int fd;
6628 	int r;
6629 	u_int initial_offset;
6630 	u_int last_offset;
6631 
6632 	TEST("AUDIO_GETOOFFS_flush_%s", openmode_str[openmode] + 2);
6633 	if (mode2aumode(openmode) == 0) {
6634 		XP_SKIP("Operation not allowed on this hardware property");
6635 		return;
6636 	}
6637 
6638 	fd = OPEN(devaudio, openmode);
6639 	REQUIRED_SYS_OK(fd);
6640 
6641 #if 0
6642 	/* On NetBSD7/8, native encoding changes buffer behavior. */
6643 	AUDIO_INITINFO(&ai);
6644 	ai.play.encoding = AUDIO_ENCODING_SLINEAR_NE;
6645 	ai.play.precision = 16;
6646 	ai.play.channels = 2;
6647 	ai.play.sample_rate = 48000;
6648 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "");
6649 	REQUIRED_SYS_EQ(0, r);
6650 #endif
6651 
6652 	/* Get blocksize. */
6653 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
6654 	REQUIRED_SYS_EQ(0, r);
6655 
6656 	buf = (char *)malloc(ai.blocksize);
6657 	REQUIRED_IF(buf != NULL);
6658 	memset(buf, 0xff, ai.blocksize);
6659 
6660 	/*
6661 	 * On NetBSD7, .offset starts from one block.  What is the block??
6662 	 * On NetBSD9, .offset starts from zero.
6663 	 */
6664 	if (netbsd < 9) {
6665 		initial_offset = ai.blocksize;
6666 	} else {
6667 		initial_offset = 0;
6668 	}
6669 
6670 	/* Write one block. */
6671 	r = WRITE(fd, buf, ai.blocksize);
6672 	if (mode2play(openmode)) {
6673 		XP_SYS_EQ(ai.blocksize, r);
6674 	} else {
6675 		XP_SYS_NG(EBADF, r);
6676 	}
6677 	r = IOCTL(fd, AUDIO_DRAIN, NULL, "");
6678 	XP_SYS_EQ(0, r);
6679 
6680 	/* Obtain once. */
6681 	r = IOCTL(fd, AUDIO_GETOOFFS, &o, "");
6682 	XP_SYS_EQ(0, r);
6683 	if (mode2play(openmode)) {
6684 		XP_EQ(ai.blocksize, o.samples);
6685 		XP_EQ(1, o.deltablks);
6686 		XP_EQ(initial_offset + ai.blocksize, o.offset);
6687 	} else {
6688 		/*
6689 		 * On non-play track, it silently succeeds with zero.
6690 		 * But on NetBSD7, RDONLY descriptor also has play buffer.
6691 		 */
6692 		XP_EQ(0, o.samples);
6693 		XP_EQ(0, o.deltablks);
6694 		XP_EQ(initial_offset, o.offset);
6695 	}
6696 
6697 	/* Write one more block to advance .offset. */
6698 	r = WRITE(fd, buf, ai.blocksize);
6699 	if (mode2play(openmode)) {
6700 		XP_SYS_EQ(ai.blocksize, r);
6701 	} else {
6702 		XP_SYS_NG(EBADF, r);
6703 	}
6704 	r = IOCTL(fd, AUDIO_DRAIN, NULL, "");
6705 	XP_SYS_EQ(0, r);
6706 
6707 	/* If offset remains unchanged, this is expected offset. */
6708 	last_offset = initial_offset + ai.blocksize * 2;
6709 
6710 	/* Then, flush. */
6711 	r = IOCTL(fd, AUDIO_FLUSH, NULL, "");
6712 	REQUIRED_SYS_EQ(0, r);
6713 
6714 	/* All should be cleared. */
6715 	r = IOCTL(fd, AUDIO_GETOOFFS, &o, "");
6716 	XP_SYS_EQ(0, r);
6717 	XP_EQ(0, o.samples);
6718 	XP_EQ(0, o.deltablks);
6719 	if (mode2play(openmode)) {
6720 		/*
6721 		 * On NetBSD7,
6722 		 * offset is cleared if native encodings(?), but remains
6723 		 * unchanged if emulated encodings(?).  Looks a bug.
6724 		 * On NetBSD9, it should always be cleared.
6725 		 */
6726 		if (netbsd < 9 && o.offset == last_offset) {
6727 			DPRINTF("  > %d: offset(%u) == last_offset\n",
6728 			    __LINE__, o.offset);
6729 		} else {
6730 			XP_EQ(initial_offset, o.offset);
6731 		}
6732 	} else {
6733 		XP_EQ(initial_offset, o.offset);
6734 	}
6735 
6736 	r = CLOSE(fd);
6737 	XP_SYS_EQ(0, r);
6738 
6739 	free(buf);
6740 }
DEF(AUDIO_GETOOFFS_flush_RDONLY)6741 DEF(AUDIO_GETOOFFS_flush_RDONLY) { test_AUDIO_GETOOFFS_flush(O_RDONLY); }
DEF(AUDIO_GETOOFFS_flush_WRONLY)6742 DEF(AUDIO_GETOOFFS_flush_WRONLY) { test_AUDIO_GETOOFFS_flush(O_WRONLY); }
DEF(AUDIO_GETOOFFS_flush_RDWR)6743 DEF(AUDIO_GETOOFFS_flush_RDWR)   { test_AUDIO_GETOOFFS_flush(O_RDWR); }
6744 
6745 /*
6746  * Check whether AUDIO_SETINFO(encoding) clears AUDIO_GETOOFFS.
6747  */
6748 void
test_AUDIO_GETOOFFS_set(int openmode)6749 test_AUDIO_GETOOFFS_set(int openmode)
6750 {
6751 	struct audio_info ai;
6752 	audio_offset_t o;
6753 	char *buf;
6754 	int fd;
6755 	int r;
6756 	u_int initial_offset;
6757 
6758 	TEST("AUDIO_GETOOFFS_set_%s", openmode_str[openmode] + 2);
6759 	if (mode2aumode(openmode) == 0) {
6760 		XP_SKIP("Operation not allowed on this hardware property");
6761 		return;
6762 	}
6763 
6764 	fd = OPEN(devaudio, openmode);
6765 	REQUIRED_SYS_OK(fd);
6766 
6767 	/* Get blocksize. */
6768 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
6769 	XP_SYS_EQ(0, r);
6770 
6771 	buf = (char *)malloc(ai.blocksize);
6772 	REQUIRED_IF(buf != NULL);
6773 	memset(buf, 0xff, ai.blocksize);
6774 
6775 	/*
6776 	 * On NetBSD7, .offset starts from one block.  What is the block??
6777 	 * On NetBSD9, .offset starts from zero.
6778 	 */
6779 	if (netbsd < 9) {
6780 		initial_offset = ai.blocksize;
6781 	} else {
6782 		initial_offset = 0;
6783 	}
6784 
6785 	/* Write one block. */
6786 	r = WRITE(fd, buf, ai.blocksize);
6787 	if (mode2play(openmode)) {
6788 		XP_SYS_EQ(ai.blocksize, r);
6789 	} else {
6790 		XP_SYS_NG(EBADF, r);
6791 	}
6792 	r = IOCTL(fd, AUDIO_DRAIN, NULL, "");
6793 	XP_SYS_EQ(0, r);
6794 
6795 	/*
6796 	 * Then, change encoding.
6797 	 * If we fail to change it, we cannot continue.  This may happen
6798 	 * on NetBSD7/8.
6799 	 */
6800 	AUDIO_INITINFO(&ai);
6801 	ai.play.encoding = AUDIO_ENCODING_SLINEAR_NE;
6802 	ai.play.precision = 16;
6803 	ai.play.channels = 2;
6804 	ai.play.sample_rate = 48000;
6805 	r = IOCTL(fd, AUDIO_SETINFO, &ai, "slinear16/2ch/48000");
6806 	REQUIRED_SYS_EQ(0, r);
6807 
6808 	r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
6809 	REQUIRED_SYS_EQ(0, r);
6810 	if (netbsd < 9) {
6811 		initial_offset = ai.blocksize;
6812 	} else {
6813 		initial_offset = 0;
6814 	}
6815 
6816 	/* Clear counters? */
6817 	r = IOCTL(fd, AUDIO_GETOOFFS, &o, "");
6818 	XP_SYS_EQ(0, r);
6819 	XP_EQ(0, o.samples);
6820 	XP_EQ(0, o.deltablks);
6821 	XP_EQ(initial_offset, o.offset);
6822 
6823 	r = CLOSE(fd);
6824 	XP_SYS_EQ(0, r);
6825 
6826 	free(buf);
6827 }
DEF(AUDIO_GETOOFFS_set_RDONLY)6828 DEF(AUDIO_GETOOFFS_set_RDONLY) { test_AUDIO_GETOOFFS_set(O_RDONLY); }
DEF(AUDIO_GETOOFFS_set_WRONLY)6829 DEF(AUDIO_GETOOFFS_set_WRONLY) { test_AUDIO_GETOOFFS_set(O_WRONLY); }
DEF(AUDIO_GETOOFFS_set_RDWR)6830 DEF(AUDIO_GETOOFFS_set_RDWR)   { test_AUDIO_GETOOFFS_set(O_RDWR); }
6831 
6832 /*
6833  * /dev/audioctl can always be opened while /dev/audio is open.
6834  */
6835 void
test_audioctl_open_1(int fmode,int cmode)6836 test_audioctl_open_1(int fmode, int cmode)
6837 {
6838 	int fd;
6839 	int ctl;
6840 	int r;
6841 
6842 	TEST("audioctl_open_1_%s_%s",
6843 	    openmode_str[fmode] + 2, openmode_str[cmode] + 2);
6844 	if (hw_canplay() == 0 && fmode == O_WRONLY) {
6845 		XP_SKIP("This test is for playable device");
6846 		return;
6847 	}
6848 	if (hw_canrec() == 0 && fmode == O_RDONLY) {
6849 		XP_SKIP("This test is for recordable device");
6850 		return;
6851 	}
6852 
6853 	fd = OPEN(devaudio, fmode);
6854 	REQUIRED_SYS_OK(fd);
6855 
6856 	ctl = OPEN(devaudioctl, cmode);
6857 	XP_SYS_OK(ctl);
6858 
6859 	r = CLOSE(ctl);
6860 	XP_SYS_EQ(0, r);
6861 
6862 	r = CLOSE(fd);
6863 	XP_SYS_EQ(0, r);
6864 }
DEF(audioctl_open_1_RDONLY_RDONLY)6865 DEF(audioctl_open_1_RDONLY_RDONLY) { test_audioctl_open_1(O_RDONLY, O_RDONLY); }
DEF(audioctl_open_1_RDONLY_RWONLY)6866 DEF(audioctl_open_1_RDONLY_RWONLY) { test_audioctl_open_1(O_RDONLY, O_WRONLY); }
DEF(audioctl_open_1_RDONLY_RDWR)6867 DEF(audioctl_open_1_RDONLY_RDWR)   { test_audioctl_open_1(O_RDONLY, O_RDWR); }
DEF(audioctl_open_1_WRONLY_RDONLY)6868 DEF(audioctl_open_1_WRONLY_RDONLY) { test_audioctl_open_1(O_WRONLY, O_RDONLY); }
DEF(audioctl_open_1_WRONLY_RWONLY)6869 DEF(audioctl_open_1_WRONLY_RWONLY) { test_audioctl_open_1(O_WRONLY, O_WRONLY); }
DEF(audioctl_open_1_WRONLY_RDWR)6870 DEF(audioctl_open_1_WRONLY_RDWR)   { test_audioctl_open_1(O_WRONLY, O_RDWR); }
DEF(audioctl_open_1_RDWR_RDONLY)6871 DEF(audioctl_open_1_RDWR_RDONLY)   { test_audioctl_open_1(O_RDWR, O_RDONLY); }
DEF(audioctl_open_1_RDWR_RWONLY)6872 DEF(audioctl_open_1_RDWR_RWONLY)   { test_audioctl_open_1(O_RDWR, O_WRONLY); }
DEF(audioctl_open_1_RDWR_RDWR)6873 DEF(audioctl_open_1_RDWR_RDWR)     { test_audioctl_open_1(O_RDWR, O_RDWR); }
6874 
6875 /*
6876  * /dev/audio can always be opened while /dev/audioctl is open.
6877  */
6878 void
test_audioctl_open_2(int fmode,int cmode)6879 test_audioctl_open_2(int fmode, int cmode)
6880 {
6881 	int fd;
6882 	int ctl;
6883 	int r;
6884 
6885 	TEST("audioctl_open_2_%s_%s",
6886 	    openmode_str[fmode] + 2, openmode_str[cmode] + 2);
6887 	if (hw_canplay() == 0 && fmode == O_WRONLY) {
6888 		XP_SKIP("This test is for playable device");
6889 		return;
6890 	}
6891 	if (hw_canrec() == 0 && fmode == O_RDONLY) {
6892 		XP_SKIP("This test is for recordable device");
6893 		return;
6894 	}
6895 
6896 	ctl = OPEN(devaudioctl, cmode);
6897 	REQUIRED_SYS_OK(ctl);
6898 
6899 	fd = OPEN(devaudio, fmode);
6900 	XP_SYS_OK(fd);
6901 
6902 	r = CLOSE(fd);
6903 	XP_SYS_EQ(0, r);
6904 
6905 	r = CLOSE(ctl);
6906 	XP_SYS_EQ(0, r);
6907 }
DEF(audioctl_open_2_RDONLY_RDONLY)6908 DEF(audioctl_open_2_RDONLY_RDONLY) { test_audioctl_open_2(O_RDONLY, O_RDONLY); }
DEF(audioctl_open_2_RDONLY_RWONLY)6909 DEF(audioctl_open_2_RDONLY_RWONLY) { test_audioctl_open_2(O_RDONLY, O_WRONLY); }
DEF(audioctl_open_2_RDONLY_RDWR)6910 DEF(audioctl_open_2_RDONLY_RDWR)   { test_audioctl_open_2(O_RDONLY, O_RDWR); }
DEF(audioctl_open_2_WRONLY_RDONLY)6911 DEF(audioctl_open_2_WRONLY_RDONLY) { test_audioctl_open_2(O_WRONLY, O_RDONLY); }
DEF(audioctl_open_2_WRONLY_RWONLY)6912 DEF(audioctl_open_2_WRONLY_RWONLY) { test_audioctl_open_2(O_WRONLY, O_WRONLY); }
DEF(audioctl_open_2_WRONLY_RDWR)6913 DEF(audioctl_open_2_WRONLY_RDWR)   { test_audioctl_open_2(O_WRONLY, O_RDWR); }
DEF(audioctl_open_2_RDWR_RDONLY)6914 DEF(audioctl_open_2_RDWR_RDONLY)   { test_audioctl_open_2(O_RDWR, O_RDONLY); }
DEF(audioctl_open_2_RDWR_RWONLY)6915 DEF(audioctl_open_2_RDWR_RWONLY)   { test_audioctl_open_2(O_RDWR, O_WRONLY); }
DEF(audioctl_open_2_RDWR_RDWR)6916 DEF(audioctl_open_2_RDWR_RDWR)     { test_audioctl_open_2(O_RDWR, O_RDWR); }
6917 
6918 /*
6919  * Open multiple /dev/audioctl.
6920  */
DEF(audioctl_open_simul)6921 DEF(audioctl_open_simul)
6922 {
6923 	int ctl0;
6924 	int ctl1;
6925 	int r;
6926 
6927 	TEST("audioctl_open_simul");
6928 
6929 	ctl0 = OPEN(devaudioctl, O_RDWR);
6930 	REQUIRED_SYS_OK(ctl0);
6931 
6932 	ctl1 = OPEN(devaudioctl, O_RDWR);
6933 	XP_SYS_OK(ctl1);
6934 
6935 	r = CLOSE(ctl0);
6936 	XP_SYS_EQ(0, r);
6937 
6938 	r = CLOSE(ctl1);
6939 	XP_SYS_EQ(0, r);
6940 }
6941 
6942 /*
6943  * /dev/audioctl can be opened by other user who opens /dev/audioctl,
6944  * /dev/audioctl can be opened by other user who opens /dev/audio,
6945  * /dev/audio    can be opened by other user who opens /dev/audioctl,
6946  * regardless of multiuser mode.
6947  */
6948 void
try_audioctl_open_multiuser(const char * dev1,const char * dev2)6949 try_audioctl_open_multiuser(const char *dev1, const char *dev2)
6950 {
6951 	int fd1;
6952 	int fd2;
6953 	int r;
6954 	uid_t ouid;
6955 
6956 	/*
6957 	 * At first, open dev1 as root.
6958 	 * And then open dev2 as unprivileged user.
6959 	 */
6960 
6961 	fd1 = OPEN(dev1, O_RDWR);
6962 	REQUIRED_SYS_OK(fd1);
6963 
6964 	ouid = GETUID();
6965 	r = SETEUID(1);
6966 	REQUIRED_SYS_EQ(0, r);
6967 
6968 	fd2 = OPEN(dev2, O_RDWR);
6969 	XP_SYS_OK(fd2);
6970 
6971 	/* Close */
6972 	r = CLOSE(fd2);
6973 	XP_SYS_EQ(0, r);
6974 
6975 	r = SETEUID(ouid);
6976 	REQUIRED_SYS_EQ(0, r);
6977 
6978 	r = CLOSE(fd1);
6979 	XP_SYS_EQ(0, r);
6980 }
6981 /*
6982  * This is a wrapper for audioctl_open_multiuser.
6983  * XXX XP_* macros are not compatible with on-error-goto, we need try-catch...
6984  */
6985 void
test_audioctl_open_multiuser(bool multiuser,const char * dev1,const char * dev2)6986 test_audioctl_open_multiuser(bool multiuser,
6987 	const char *dev1, const char *dev2)
6988 {
6989 	char mibname[32];
6990 	bool oldval;
6991 	size_t oldlen;
6992 	int r;
6993 
6994 	if (netbsd < 8 && multiuser == 1) {
6995 		XP_SKIP("multiuser is not supported");
6996 		return;
6997 	}
6998 	if (netbsd < 9) {
6999 		/* NetBSD8 has no way (difficult) to determine device name */
7000 		XP_SKIP("NetBSD8 cannot determine device name");
7001 		return;
7002 	}
7003 	if (geteuid() != 0) {
7004 		XP_SKIP("This test must be priviledged user");
7005 		return;
7006 	}
7007 
7008 	/* Get current multiuser mode (and save it) */
7009 	snprintf(mibname, sizeof(mibname), "hw.%s.multiuser", devicename);
7010 	oldlen = sizeof(oldval);
7011 	r = SYSCTLBYNAME(mibname, &oldval, &oldlen, NULL, 0);
7012 	REQUIRED_SYS_EQ(0, r);
7013 	DPRINTF("  > multiuser=%d\n", oldval);
7014 
7015 	/* Change if necessary */
7016 	if (oldval != multiuser) {
7017 		r = SYSCTLBYNAME(mibname, NULL, NULL, &multiuser,
7018 		    sizeof(multiuser));
7019 		REQUIRED_SYS_EQ(0, r);
7020 		DPRINTF("  > new multiuser=%d\n", multiuser);
7021 	}
7022 
7023 	/* Do test */
7024 	try_audioctl_open_multiuser(dev1, dev2);
7025 
7026 	/* Restore multiuser mode */
7027 	if (oldval != multiuser) {
7028 		DPRINTF("  > restore multiuser to %d\n", oldval);
7029 		r = SYSCTLBYNAME(mibname, NULL, NULL, &oldval, sizeof(oldval));
7030 		XP_SYS_EQ(0, r);
7031 	}
7032 }
DEF(audioctl_open_multiuser0_audio1)7033 DEF(audioctl_open_multiuser0_audio1) {
7034 	TEST("audioctl_open_multiuser0_audio1");
7035 	test_audioctl_open_multiuser(false, devaudio, devaudioctl);
7036 }
DEF(audioctl_open_multiuser1_audio1)7037 DEF(audioctl_open_multiuser1_audio1) {
7038 	TEST("audioctl_open_multiuser1_audio1");
7039 	test_audioctl_open_multiuser(true, devaudio, devaudioctl);
7040 }
DEF(audioctl_open_multiuser0_audio2)7041 DEF(audioctl_open_multiuser0_audio2) {
7042 	TEST("audioctl_open_multiuser0_audio2");
7043 	test_audioctl_open_multiuser(false, devaudioctl, devaudio);
7044 }
DEF(audioctl_open_multiuser1_audio2)7045 DEF(audioctl_open_multiuser1_audio2) {
7046 	TEST("audioctl_open_multiuser1_audio2");
7047 	test_audioctl_open_multiuser(true, devaudioctl, devaudio);
7048 }
DEF(audioctl_open_multiuser0_audioctl)7049 DEF(audioctl_open_multiuser0_audioctl) {
7050 	TEST("audioctl_open_multiuser0_audioctl");
7051 	test_audioctl_open_multiuser(false, devaudioctl, devaudioctl);
7052 }
DEF(audioctl_open_multiuser1_audioctl)7053 DEF(audioctl_open_multiuser1_audioctl) {
7054 	TEST("audioctl_open_multiuser1_audioctl");
7055 	test_audioctl_open_multiuser(true, devaudioctl, devaudioctl);
7056 }
7057 
7058 /*
7059  * /dev/audioctl cannot be read/written regardless of its open mode.
7060  */
7061 void
test_audioctl_rw(int openmode)7062 test_audioctl_rw(int openmode)
7063 {
7064 	char buf[1];
7065 	int fd;
7066 	int r;
7067 
7068 	TEST("audioctl_rw_%s", openmode_str[openmode] + 2);
7069 
7070 	fd = OPEN(devaudioctl, openmode);
7071 	REQUIRED_SYS_OK(fd);
7072 
7073 	if (mode2play(openmode)) {
7074 		r = WRITE(fd, buf, sizeof(buf));
7075 		XP_SYS_NG(ENODEV, r);
7076 	}
7077 
7078 	if (mode2rec(openmode)) {
7079 		r = READ(fd, buf, sizeof(buf));
7080 		XP_SYS_NG(ENODEV, r);
7081 	}
7082 
7083 	r = CLOSE(fd);
7084 	XP_SYS_EQ(0, r);
7085 }
DEF(audioctl_rw_RDONLY)7086 DEF(audioctl_rw_RDONLY)	{ test_audioctl_rw(O_RDONLY); }
DEF(audioctl_rw_WRONLY)7087 DEF(audioctl_rw_WRONLY)	{ test_audioctl_rw(O_WRONLY); }
DEF(audioctl_rw_RDWR)7088 DEF(audioctl_rw_RDWR)	{ test_audioctl_rw(O_RDWR); }
7089 
7090 /*
7091  * poll(2) for /dev/audioctl should never raise.
7092  * I'm not sure about consistency between poll(2) and kqueue(2) but
7093  * anyway I follow it.
7094  * XXX Omit checking each openmode
7095  */
DEF(audioctl_poll)7096 DEF(audioctl_poll)
7097 {
7098 	struct pollfd pfd;
7099 	int fd;
7100 	int r;
7101 
7102 	TEST("audioctl_poll");
7103 
7104 	fd = OPEN(devaudioctl, O_WRONLY);
7105 	REQUIRED_SYS_OK(fd);
7106 
7107 	pfd.fd = fd;
7108 	pfd.events = POLLOUT;
7109 	r = POLL(&pfd, 1, 100);
7110 	XP_SYS_EQ(0, r);
7111 	XP_EQ(0, pfd.revents);
7112 
7113 	r = CLOSE(fd);
7114 	XP_SYS_EQ(0, r);
7115 }
7116 
7117 /*
7118  * kqueue(2) for /dev/audioctl fails.
7119  * I'm not sure about consistency between poll(2) and kqueue(2) but
7120  * anyway I follow it.
7121  * XXX Omit checking each openmode
7122  */
DEF(audioctl_kqueue)7123 DEF(audioctl_kqueue)
7124 {
7125 	struct kevent kev;
7126 	int fd;
7127 	int kq;
7128 	int r;
7129 
7130 	TEST("audioctl_kqueue");
7131 
7132 	fd = OPEN(devaudioctl, O_WRONLY);
7133 	REQUIRED_SYS_OK(fd);
7134 
7135 	kq = KQUEUE();
7136 	XP_SYS_OK(kq);
7137 
7138 	EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, 0);
7139 	r = KEVENT_SET(kq, &kev, 1);
7140 	/*
7141 	 * NetBSD7 has a bug.  It looks to wanted to treat it as successful
7142 	 * but returned 1(== EPERM).
7143 	 * On NetBSD9, I decided to return ENODEV.
7144 	 */
7145 	if (netbsd < 8) {
7146 		XP_SYS_NG(1/*EPERM*/, r);
7147 	} else {
7148 		XP_SYS_NG(ENODEV, r);
7149 	}
7150 
7151 	r = CLOSE(fd);
7152 	XP_SYS_EQ(0, r);
7153 }
7154 
7155 
7156 /*
7157  * This table is processed by t_audio.awk!
7158  * Keep /^\tENT(testname),/ format in order to add to atf.
7159  */
7160 #define ENT(x) { #x, test__ ## x }
7161 struct testentry testtable[] = {
7162 	ENT(open_mode_RDONLY),
7163 	ENT(open_mode_WRONLY),
7164 	ENT(open_mode_RDWR),
7165 	ENT(open_audio_RDONLY),
7166 	ENT(open_audio_WRONLY),
7167 	ENT(open_audio_RDWR),
7168 	ENT(open_sound_RDONLY),
7169 	ENT(open_sound_WRONLY),
7170 	ENT(open_sound_RDWR),
7171 	ENT(open_audioctl_RDONLY),
7172 	ENT(open_audioctl_WRONLY),
7173 	ENT(open_audioctl_RDWR),
7174 	ENT(open_sound_sticky),
7175 	ENT(open_audioctl_sticky),
7176 	ENT(open_simul_RDONLY_RDONLY),
7177 	ENT(open_simul_RDONLY_WRONLY),
7178 	ENT(open_simul_RDONLY_RDWR),
7179 	ENT(open_simul_WRONLY_RDONLY),
7180 	ENT(open_simul_WRONLY_WRONLY),
7181 	ENT(open_simul_WRONLY_RDWR),
7182 	ENT(open_simul_RDWR_RDONLY),
7183 	ENT(open_simul_RDWR_WRONLY),
7184 	ENT(open_simul_RDWR_RDWR),
7185 /**/	ENT(open_multiuser_0),		// XXX TODO sysctl
7186 /**/	ENT(open_multiuser_1),		// XXX TODO sysctl
7187 	ENT(write_PLAY_ALL),
7188 	ENT(write_PLAY),
7189 	ENT(read),
7190 	ENT(rept_write),
7191 	ENT(rept_read),
7192 	ENT(rdwr_fallback_RDONLY),
7193 	ENT(rdwr_fallback_WRONLY),
7194 	ENT(rdwr_fallback_RDWR),
7195 	ENT(rdwr_two_RDONLY_RDONLY),
7196 	ENT(rdwr_two_RDONLY_WRONLY),
7197 	ENT(rdwr_two_RDONLY_RDWR),
7198 	ENT(rdwr_two_WRONLY_RDONLY),
7199 	ENT(rdwr_two_WRONLY_WRONLY),
7200 	ENT(rdwr_two_WRONLY_RDWR),
7201 	ENT(rdwr_two_RDWR_RDONLY),
7202 	ENT(rdwr_two_RDWR_WRONLY),
7203 	ENT(rdwr_two_RDWR_RDWR),
7204 	ENT(rdwr_simul),
7205 	ENT(drain_incomplete),
7206 	ENT(drain_pause),
7207 	ENT(drain_onrec),
7208 /**/	ENT(mmap_mode_RDONLY_NONE),	// XXX rump doesn't support mmap
7209 /**/	ENT(mmap_mode_RDONLY_READ),	// XXX rump doesn't support mmap
7210 /**/	ENT(mmap_mode_RDONLY_WRITE),	// XXX rump doesn't support mmap
7211 /**/	ENT(mmap_mode_RDONLY_READWRITE),// XXX rump doesn't support mmap
7212 /**/	ENT(mmap_mode_WRONLY_NONE),	// XXX rump doesn't support mmap
7213 /**/	ENT(mmap_mode_WRONLY_READ),	// XXX rump doesn't support mmap
7214 /**/	ENT(mmap_mode_WRONLY_WRITE),	// XXX rump doesn't support mmap
7215 /**/	ENT(mmap_mode_WRONLY_READWRITE),// XXX rump doesn't support mmap
7216 /**/	ENT(mmap_mode_RDWR_NONE),	// XXX rump doesn't support mmap
7217 /**/	ENT(mmap_mode_RDWR_READ),	// XXX rump doesn't support mmap
7218 /**/	ENT(mmap_mode_RDWR_WRITE),	// XXX rump doesn't support mmap
7219 /**/	ENT(mmap_mode_RDWR_READWRITE),	// XXX rump doesn't support mmap
7220 /**/	ENT(mmap_len_0),		// XXX rump doesn't support mmap
7221 /**/	ENT(mmap_len_1),		// XXX rump doesn't support mmap
7222 /**/	ENT(mmap_len_2),		// XXX rump doesn't support mmap
7223 /**/	ENT(mmap_len_3),		// XXX rump doesn't support mmap
7224 /**/	ENT(mmap_len_4),		// XXX rump doesn't support mmap
7225 /**/	ENT(mmap_len_5),		// XXX rump doesn't support mmap
7226 /**/	ENT(mmap_len_6),		// XXX rump doesn't support mmap
7227 /**/	ENT(mmap_len_7),		// XXX rump doesn't support mmap
7228 /**/	ENT(mmap_len_8),		// XXX rump doesn't support mmap
7229 /**/	ENT(mmap_twice),		// XXX rump doesn't support mmap
7230 /**/	ENT(mmap_multi),		// XXX rump doesn't support mmap
7231 	ENT(poll_mode_RDONLY_IN),
7232 	ENT(poll_mode_RDONLY_OUT),
7233 	ENT(poll_mode_RDONLY_INOUT),
7234 	ENT(poll_mode_WRONLY_IN),
7235 	ENT(poll_mode_WRONLY_OUT),
7236 	ENT(poll_mode_WRONLY_INOUT),
7237 	ENT(poll_mode_RDWR_IN),
7238 	ENT(poll_mode_RDWR_OUT),
7239 	ENT(poll_mode_RDWR_INOUT),
7240 	ENT(poll_out_empty),
7241 	ENT(poll_out_full),
7242 	ENT(poll_out_hiwat),
7243 /**/	ENT(poll_out_unpause),		// XXX does not seem to work on rump
7244 /**/	ENT(poll_out_simul),		// XXX does not seem to work on rump
7245 	ENT(poll_in_open_audio),
7246 	ENT(poll_in_open_sound),
7247 	ENT(poll_in_open_audioctl),
7248 	ENT(poll_in_simul),
7249 	ENT(kqueue_mode_RDONLY_READ),
7250 	ENT(kqueue_mode_RDONLY_WRITE),
7251 	ENT(kqueue_mode_WRONLY_READ),
7252 	ENT(kqueue_mode_WRONLY_WRITE),
7253 	ENT(kqueue_mode_RDWR_READ),
7254 	ENT(kqueue_mode_RDWR_WRITE),
7255 	ENT(kqueue_empty),
7256 	ENT(kqueue_full),
7257 	ENT(kqueue_hiwat),
7258 /**/	ENT(kqueue_unpause),		// XXX does not seem to work on rump
7259 /**/	ENT(kqueue_simul),		// XXX does not seem to work on rump
7260 	ENT(ioctl_while_write),
7261 	ENT(FIOASYNC_reset),
7262 	ENT(FIOASYNC_play_signal),
7263 	ENT(FIOASYNC_rec_signal),
7264 /**/	ENT(FIOASYNC_multi),		// XXX does not seem to work on rump
7265 	ENT(AUDIO_WSEEK),
7266 	ENT(AUDIO_SETFD_RDONLY),
7267 	ENT(AUDIO_SETFD_WRONLY),
7268 	ENT(AUDIO_SETFD_RDWR),
7269 	ENT(AUDIO_GETINFO_eof),
7270 	ENT(AUDIO_SETINFO_mode_RDONLY_0),
7271 	ENT(AUDIO_SETINFO_mode_RDONLY_1),
7272 	ENT(AUDIO_SETINFO_mode_RDONLY_2),
7273 	ENT(AUDIO_SETINFO_mode_RDONLY_3),
7274 	ENT(AUDIO_SETINFO_mode_RDONLY_4),
7275 	ENT(AUDIO_SETINFO_mode_RDONLY_5),
7276 	ENT(AUDIO_SETINFO_mode_RDONLY_6),
7277 	ENT(AUDIO_SETINFO_mode_RDONLY_7),
7278 	ENT(AUDIO_SETINFO_mode_RDONLY_8),
7279 	ENT(AUDIO_SETINFO_mode_WRONLY_0),
7280 	ENT(AUDIO_SETINFO_mode_WRONLY_1),
7281 	ENT(AUDIO_SETINFO_mode_WRONLY_2),
7282 	ENT(AUDIO_SETINFO_mode_WRONLY_3),
7283 	ENT(AUDIO_SETINFO_mode_WRONLY_4),
7284 	ENT(AUDIO_SETINFO_mode_WRONLY_5),
7285 	ENT(AUDIO_SETINFO_mode_WRONLY_6),
7286 	ENT(AUDIO_SETINFO_mode_WRONLY_7),
7287 	ENT(AUDIO_SETINFO_mode_WRONLY_8),
7288 	ENT(AUDIO_SETINFO_mode_RDWR_0),
7289 	ENT(AUDIO_SETINFO_mode_RDWR_1),
7290 	ENT(AUDIO_SETINFO_mode_RDWR_2),
7291 	ENT(AUDIO_SETINFO_mode_RDWR_3),
7292 	ENT(AUDIO_SETINFO_mode_RDWR_4),
7293 	ENT(AUDIO_SETINFO_mode_RDWR_5),
7294 	ENT(AUDIO_SETINFO_mode_RDWR_6),
7295 	ENT(AUDIO_SETINFO_mode_RDWR_7),
7296 	ENT(AUDIO_SETINFO_mode_RDWR_8),
7297 	ENT(AUDIO_SETINFO_params_set_RDONLY_0),
7298 	ENT(AUDIO_SETINFO_params_set_RDONLY_1),
7299 	ENT(AUDIO_SETINFO_params_set_WRONLY_0),
7300 	ENT(AUDIO_SETINFO_params_set_WRONLY_1),
7301 	ENT(AUDIO_SETINFO_params_set_WRONLY_2),
7302 	ENT(AUDIO_SETINFO_params_set_WRONLY_3),
7303 	ENT(AUDIO_SETINFO_params_set_RDWR_0),
7304 	ENT(AUDIO_SETINFO_params_set_RDWR_1),
7305 	ENT(AUDIO_SETINFO_params_set_RDWR_2),
7306 	ENT(AUDIO_SETINFO_params_set_RDWR_3),
7307 	ENT(AUDIO_SETINFO_params_simul),
7308 	ENT(AUDIO_SETINFO_channels),
7309 	ENT(AUDIO_SETINFO_sample_rate),
7310 	ENT(AUDIO_SETINFO_sample_rate_0),
7311 	ENT(AUDIO_SETINFO_pause_RDONLY_0),
7312 	ENT(AUDIO_SETINFO_pause_RDONLY_1),
7313 	ENT(AUDIO_SETINFO_pause_WRONLY_0),
7314 	ENT(AUDIO_SETINFO_pause_WRONLY_1),
7315 	ENT(AUDIO_SETINFO_pause_WRONLY_2),
7316 	ENT(AUDIO_SETINFO_pause_WRONLY_3),
7317 	ENT(AUDIO_SETINFO_pause_RDWR_0),
7318 	ENT(AUDIO_SETINFO_pause_RDWR_1),
7319 	ENT(AUDIO_SETINFO_pause_RDWR_2),
7320 	ENT(AUDIO_SETINFO_pause_RDWR_3),
7321 	ENT(AUDIO_SETINFO_gain),
7322 	ENT(AUDIO_SETINFO_gain_balance),
7323 /**/	ENT(AUDIO_SETINFO_mmap_enc),	// XXX rump doesn't support mmap
7324 /**/	ENT(AUDIO_SETINFO_mmap_pause),	// XXX rump doesn't support mmap
7325 	ENT(AUDIO_GETENC_range),
7326 	ENT(AUDIO_GETENC_error),
7327 	ENT(AUDIO_ERROR_RDONLY),
7328 	ENT(AUDIO_ERROR_WRONLY),
7329 	ENT(AUDIO_ERROR_RDWR),
7330 	ENT(AUDIO_GETIOFFS_one_RDONLY),
7331 	ENT(AUDIO_GETIOFFS_one_WRONLY),
7332 	ENT(AUDIO_GETIOFFS_one_RDWR),
7333 	ENT(AUDIO_GETOOFFS_one_RDONLY),
7334 	ENT(AUDIO_GETOOFFS_one_WRONLY),
7335 	ENT(AUDIO_GETOOFFS_one_RDWR),
7336 	ENT(AUDIO_GETOOFFS_wrap_RDONLY),
7337 	ENT(AUDIO_GETOOFFS_wrap_WRONLY),
7338 	ENT(AUDIO_GETOOFFS_wrap_RDWR),
7339 	ENT(AUDIO_GETOOFFS_flush_RDONLY),
7340 	ENT(AUDIO_GETOOFFS_flush_WRONLY),
7341 	ENT(AUDIO_GETOOFFS_flush_RDWR),
7342 	ENT(AUDIO_GETOOFFS_set_RDONLY),
7343 	ENT(AUDIO_GETOOFFS_set_WRONLY),
7344 	ENT(AUDIO_GETOOFFS_set_RDWR),
7345 	ENT(audioctl_open_1_RDONLY_RDONLY),
7346 	ENT(audioctl_open_1_RDONLY_RWONLY),
7347 	ENT(audioctl_open_1_RDONLY_RDWR),
7348 	ENT(audioctl_open_1_WRONLY_RDONLY),
7349 	ENT(audioctl_open_1_WRONLY_RWONLY),
7350 	ENT(audioctl_open_1_WRONLY_RDWR),
7351 	ENT(audioctl_open_1_RDWR_RDONLY),
7352 	ENT(audioctl_open_1_RDWR_RWONLY),
7353 	ENT(audioctl_open_1_RDWR_RDWR),
7354 	ENT(audioctl_open_2_RDONLY_RDONLY),
7355 	ENT(audioctl_open_2_RDONLY_RWONLY),
7356 	ENT(audioctl_open_2_RDONLY_RDWR),
7357 	ENT(audioctl_open_2_WRONLY_RDONLY),
7358 	ENT(audioctl_open_2_WRONLY_RWONLY),
7359 	ENT(audioctl_open_2_WRONLY_RDWR),
7360 	ENT(audioctl_open_2_RDWR_RDONLY),
7361 	ENT(audioctl_open_2_RDWR_RWONLY),
7362 	ENT(audioctl_open_2_RDWR_RDWR),
7363 	ENT(audioctl_open_simul),
7364 /**/	ENT(audioctl_open_multiuser0_audio1),	// XXX TODO sysctl
7365 /**/	ENT(audioctl_open_multiuser1_audio1),	// XXX TODO sysctl
7366 /**/	ENT(audioctl_open_multiuser0_audio2),	// XXX TODO sysctl
7367 /**/	ENT(audioctl_open_multiuser1_audio2),	// XXX TODO sysctl
7368 /**/	ENT(audioctl_open_multiuser0_audioctl),	// XXX TODO sysctl
7369 /**/	ENT(audioctl_open_multiuser1_audioctl),	// XXX TODO sysctl
7370 	ENT(audioctl_rw_RDONLY),
7371 	ENT(audioctl_rw_WRONLY),
7372 	ENT(audioctl_rw_RDWR),
7373 	ENT(audioctl_poll),
7374 	ENT(audioctl_kqueue),
7375 	{.name = NULL},
7376 };
7377