1 /*        $NetBSD: audiotest.c,v 1.32 2023/12/11 09:26:08 mlelstv 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.32 2023/12/11 09:26:08 mlelstv 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,   EINVAL); }      /* 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,  EINVAL); }      /* len is 0 */
DEF(mmap_len_6)2782 DEF(mmap_len_6)     { f(0,   LS1, EINVAL); }      /* len is 0 */
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