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