audiotest.c revision 1.1 1 /* $NetBSD: audiotest.c,v 1.1 2020/02/11 07:03:16 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.1 2020/02/11 07:03:16 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(int);
1385 void test_open_multiuser(int);
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(int, const char *, const char *);
1404 void test_audioctl_open_multiuser(int, 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(int 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(int multiuser)
2299 {
2300 char mibname[32];
2301 bool newval;
2302 bool oldval;
2303 size_t oldlen;
2304 int r;
2305
2306 TEST("open_multiuser_%d", multiuser);
2307 if (netbsd < 8) {
2308 XP_SKIP("Multiple open is not supported");
2309 return;
2310 }
2311 if (netbsd < 9) {
2312 /* NetBSD8 has no way (difficult) to determine device name */
2313 XP_SKIP("NetBSD8 cannot determine device name");
2314 return;
2315 }
2316 if (geteuid() != 0) {
2317 XP_SKIP("Must be run as a privileged user");
2318 return;
2319 }
2320
2321 /* Get current multiuser mode (and save it) */
2322 snprintf(mibname, sizeof(mibname), "hw.%s.multiuser", devicename);
2323 oldlen = sizeof(oldval);
2324 r = SYSCTLBYNAME(mibname, &oldval, &oldlen, NULL, 0);
2325 REQUIRED_SYS_EQ(0, r);
2326 DPRINTF(" > multiuser=%d\n", oldval);
2327
2328 /* Change if necessary */
2329 if (oldval != multiuser) {
2330 newval = multiuser;
2331 r = SYSCTLBYNAME(mibname, NULL, NULL, &newval, sizeof(newval));
2332 REQUIRED_SYS_EQ(0, r);
2333 DPRINTF(" > new multiuser=%d\n", multiuser);
2334 }
2335
2336 /* Do test */
2337 try_open_multiuser(multiuser);
2338
2339 /* Restore multiuser mode */
2340 if (oldval != newval) {
2341 DPRINTF(" > restore multiuser to %d\n", oldval);
2342 r = SYSCTLBYNAME(mibname, NULL, NULL, &oldval, sizeof(oldval));
2343 REQUIRED_SYS_EQ(0, r);
2344 }
2345 }
2346 DEF(open_multiuser_0) { test_open_multiuser(0); }
2347 DEF(open_multiuser_1) { test_open_multiuser(1); }
2348
2349 /*
2350 * Normal playback (with PLAY_ALL).
2351 * It does not verify real playback data.
2352 */
2353 DEF(write_PLAY_ALL)
2354 {
2355 char buf[8000];
2356 int fd;
2357 int r;
2358
2359 TEST("write_PLAY_ALL");
2360
2361 fd = OPEN(devaudio, O_WRONLY);
2362 if (hw_canplay()) {
2363 REQUIRED_SYS_OK(fd);
2364 } else {
2365 XP_SYS_NG(ENXIO, fd);
2366 return;
2367 }
2368
2369 /* mulaw 1sec silence */
2370 memset(buf, 0xff, sizeof(buf));
2371 r = WRITE(fd, buf, sizeof(buf));
2372 XP_SYS_EQ(sizeof(buf), r);
2373
2374 r = CLOSE(fd);
2375 XP_SYS_EQ(0, r);
2376 }
2377
2378 /*
2379 * Normal playback (without PLAY_ALL).
2380 * It does not verify real playback data.
2381 */
2382 DEF(write_PLAY)
2383 {
2384 struct audio_info ai;
2385 char *wav;
2386 int wavsize;
2387 int totalsize;
2388 int fd;
2389 int r;
2390
2391 TEST("write_PLAY");
2392
2393 fd = OPEN(devaudio, O_WRONLY);
2394 if (hw_canplay()) {
2395 REQUIRED_SYS_OK(fd);
2396 } else {
2397 XP_SYS_NG(ENXIO, fd);
2398 return;
2399 }
2400
2401 /* Drop PLAY_ALL */
2402 AUDIO_INITINFO(&ai);
2403 ai.mode = AUMODE_PLAY;
2404 r = IOCTL(fd, AUDIO_SETINFO, &ai, "mode");
2405 REQUIRED_SYS_EQ(0, r);
2406
2407 /* Check mode and get blocksize */
2408 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
2409 REQUIRED_SYS_EQ(0, r);
2410 XP_EQ(AUMODE_PLAY, ai.mode);
2411
2412 wavsize = ai.blocksize;
2413 wav = (char *)malloc(wavsize);
2414 REQUIRED_IF(wav != NULL);
2415 memset(wav, 0xff, wavsize);
2416
2417 /* Write blocks until 1sec */
2418 for (totalsize = 0; totalsize < 8000; ) {
2419 r = WRITE(fd, wav, wavsize);
2420 XP_SYS_EQ(wavsize, r);
2421 if (r == -1)
2422 break; /* XXX */
2423 totalsize += r;
2424 }
2425
2426 /* XXX What should I test it? */
2427 /* Check ai.play.error */
2428 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
2429 REQUIRED_SYS_EQ(0, r);
2430 XP_EQ(0, ai.play.error);
2431
2432 /* Playback data is no longer necessary */
2433 r = IOCTL(fd, AUDIO_FLUSH, NULL, "");
2434 REQUIRED_SYS_EQ(0, r);
2435
2436 r = CLOSE(fd);
2437 REQUIRED_SYS_EQ(0, r);
2438
2439 free(wav);
2440 }
2441
2442 /*
2443 * Normal recording.
2444 * It does not verify real recorded data.
2445 */
2446 DEF(read)
2447 {
2448 char buf[8000];
2449 int fd;
2450 int r;
2451
2452 TEST("read");
2453
2454 fd = OPEN(devaudio, O_RDONLY);
2455 if (hw_canrec()) {
2456 REQUIRED_SYS_OK(fd);
2457 } else {
2458 XP_SYS_NG(ENXIO, fd);
2459 return;
2460 }
2461
2462 /* mulaw 1sec */
2463 r = READ(fd, buf, sizeof(buf));
2464 XP_SYS_EQ(sizeof(buf), r);
2465
2466 r = CLOSE(fd);
2467 XP_SYS_EQ(0, r);
2468 }
2469
2470 /*
2471 * Repeat open-write-close cycle.
2472 */
2473 DEF(rept_write)
2474 {
2475 struct timeval start, end, result;
2476 double res;
2477 char buf[8000]; /* 1sec in 8bit-mulaw,1ch,8000Hz */
2478 int fd;
2479 int r;
2480 int n;
2481
2482 TEST("rept_write");
2483
2484 if (hw_canplay() == 0) {
2485 XP_SKIP("This test is only for playable device");
2486 return;
2487 }
2488
2489 /* XXX It may timeout on some hardware driver. */
2490 XP_SKIP("not yet");
2491 return;
2492
2493 memset(buf, 0xff, sizeof(buf));
2494 n = 3;
2495 gettimeofday(&start, NULL);
2496 for (int i = 0; i < n; i++) {
2497 fd = OPEN(devaudio, O_WRONLY);
2498 REQUIRED_SYS_OK(fd);
2499
2500 r = WRITE(fd, buf, sizeof(buf));
2501 XP_SYS_EQ(sizeof(buf), r);
2502
2503 r = CLOSE(fd);
2504 XP_SYS_EQ(0, r);
2505 }
2506 gettimeofday(&end, NULL);
2507 timersub(&end, &start, &result);
2508 res = (double)result.tv_sec + (double)result.tv_usec / 1000000;
2509 /* Make judgement but not too strict */
2510 if (res >= n * 1.5) {
2511 XP_FAIL("expects %d sec but %4.1f sec", n, res);
2512 return;
2513 }
2514 }
2515
2516 /*
2517 * Repeat open-read-close cycle.
2518 */
2519 DEF(rept_read)
2520 {
2521 struct timeval start, end, result;
2522 double res;
2523 char buf[8000]; /* 1sec in 8bit-mulaw,1ch,8000Hz */
2524 int fd;
2525 int r;
2526 int n;
2527
2528 TEST("rept_read");
2529
2530 if (hw_canrec() == 0) {
2531 XP_SKIP("This test is only for recordable device");
2532 return;
2533 }
2534
2535 /* XXX It may timeout on some hardware driver. */
2536 XP_SKIP("not yet");
2537 return;
2538
2539 n = 3;
2540 gettimeofday(&start, NULL);
2541 for (int i = 0; i < n; i++) {
2542 fd = OPEN(devaudio, O_RDONLY);
2543 REQUIRED_SYS_OK(fd);
2544
2545 r = READ(fd, buf, sizeof(buf));
2546 XP_SYS_EQ(sizeof(buf), r);
2547
2548 r = CLOSE(fd);
2549 XP_SYS_EQ(0, r);
2550 }
2551 gettimeofday(&end, NULL);
2552 timersub(&end, &start, &result);
2553 res = (double)result.tv_sec + (double)result.tv_usec / 1000000;
2554 /* Make judgement but not too strict */
2555 if (res >= n * 1.5) {
2556 XP_FAIL("expects %d sec but %4.1f sec", n, res);
2557 return;
2558 }
2559 }
2560
2561 /*
2562 * Opening with O_RDWR on half-duplex hardware falls back to O_WRONLY.
2563 * expwrite: expected to be able to play.
2564 * expread : expected to be able to recored.
2565 */
2566 void
2567 test_rdwr_fallback(int openmode, bool expwrite, bool expread)
2568 {
2569 struct audio_info ai;
2570 char buf[10];
2571 int fd;
2572 int r;
2573
2574 TEST("rdwr_fallback_%s", openmode_str[openmode] + 2);
2575
2576 if (hw_bidir() == 0) {
2577 XP_SKIP("This test is only for bi-directional device");
2578 return;
2579 }
2580
2581 AUDIO_INITINFO(&ai);
2582 ai.play.pause = 1;
2583 ai.record.pause = 1;
2584
2585 fd = OPEN(devaudio, openmode);
2586 REQUIRED_SYS_OK(fd);
2587
2588 /* Set pause not to play noise */
2589 r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause");
2590 REQUIRED_SYS_EQ(0, r);
2591
2592 memset(buf, 0xff, sizeof(buf));
2593 r = WRITE(fd, buf, sizeof(buf));
2594 if (expwrite) {
2595 XP_SYS_EQ(sizeof(buf), r);
2596 } else {
2597 XP_SYS_NG(EBADF, r);
2598 }
2599
2600 r = READ(fd, buf, 0);
2601 if (expread) {
2602 XP_SYS_EQ(0, r);
2603 } else {
2604 XP_SYS_NG(EBADF, r);
2605 }
2606
2607 r = CLOSE(fd);
2608 REQUIRED_SYS_EQ(0, r);
2609 }
2610 DEF(rdwr_fallback_RDONLY) { test_rdwr_fallback(O_RDONLY, false, true); }
2611 DEF(rdwr_fallback_WRONLY) { test_rdwr_fallback(O_WRONLY, true, false); }
2612 DEF(rdwr_fallback_RDWR) {
2613 bool expread;
2614 /*
2615 * On NetBSD7, O_RDWR on half-duplex is accepted. It's possible to
2616 * read and write if they don't occur at the same time.
2617 * On NetBSD9, O_RDWR on half-duplex falls back O_WRONLY.
2618 */
2619 if (netbsd < 8) {
2620 expread = true;
2621 } else {
2622 expread = hw_fulldup() ? true : false;
2623 }
2624 test_rdwr_fallback(O_RDWR, true, expread);
2625 }
2626
2627 /*
2628 * On full-duplex hardware, the second descriptor's readablity/writability
2629 * is not depend on the first descriptor('s open mode).
2630 * On half-duplex hardware, it depends on the first descriptor's open mode.
2631 */
2632 void
2633 test_rdwr_two(int mode0, int mode1)
2634 {
2635 struct audio_info ai;
2636 char wbuf[100]; /* 1/80sec in 8bit-mulaw,1ch,8000Hz */
2637 char rbuf[100]; /* 1/80sec in 8bit-mulaw,1ch,8000Hz */
2638 bool canopen;
2639 bool canwrite;
2640 bool canread;
2641 int fd0;
2642 int fd1;
2643 int r;
2644 struct {
2645 bool canopen;
2646 bool canwrite;
2647 bool canread;
2648 } exptable_full[] = {
2649 /* open write read 1st, 2nd mode */
2650 { 1, 0, 1 }, /* REC, REC */
2651 { 1, 1, 0 }, /* REC, PLAY */
2652 { 1, 1, 1 }, /* REC, BOTH */
2653 { 1, 0, 1 }, /* PLAY, REC */
2654 { 1, 1, 0 }, /* PLAY, PLAY */
2655 { 1, 1, 1 }, /* PLAY, BOTH */
2656 { 1, 0, 1 }, /* BOTH, REC */
2657 { 1, 1, 0 }, /* BOTH, PLAY */
2658 { 1, 1, 1 }, /* BOTH, BOTH */
2659 },
2660 exptable_half[] = {
2661 { 1, 0, 1 }, /* REC, REC */
2662 { 0, 0, 0 }, /* REC, PLAY */
2663 { 0, 0, 0 }, /* REC, BOTH */
2664 { 0, 0, 0 }, /* PLAY, REC */
2665 { 1, 1, 0 }, /* PLAY, PLAY */
2666 { 1, 1, 0 }, /* PLAY, BOTH */
2667 { 0, 0, 0 }, /* BOTH, REC */
2668 { 1, 1, 0 }, /* BOTH, PLAY */
2669 { 0, 0, 0 }, /* BOTH, BOTH */
2670 }, *exptable;
2671
2672 TEST("rdwr_two_%s_%s",
2673 openmode_str[mode0] + 2,
2674 openmode_str[mode1] + 2);
2675
2676 if (netbsd < 8) {
2677 XP_SKIP("Multiple open is not supported");
2678 return;
2679 }
2680 if (hw_bidir() == 0) {
2681 XP_SKIP("This test is only for bi-directional device");
2682 return;
2683 }
2684
2685 exptable = hw_fulldup() ? exptable_full : exptable_half;
2686
2687 canopen = exptable[mode0 * 3 + mode1].canopen;
2688 canwrite = exptable[mode0 * 3 + mode1].canwrite;
2689 canread = exptable[mode0 * 3 + mode1].canread;
2690
2691 if (!canopen) {
2692 XP_SKIP("This combination is not openable on half-duplex");
2693 return;
2694 }
2695
2696 fd0 = OPEN(devaudio, mode0);
2697 REQUIRED_SYS_OK(fd0);
2698
2699 fd1 = OPEN(devaudio, mode1);
2700 REQUIRED_SYS_OK(fd1);
2701
2702 /* Silent data to make no sound */
2703 memset(&wbuf, 0xff, sizeof(wbuf));
2704 /* Pause to make no sound */
2705 AUDIO_INITINFO(&ai);
2706 ai.play.pause = 1;
2707 r = IOCTL(fd0, AUDIO_SETINFO, &ai, "pause");
2708 XP_SYS_EQ(0, r);
2709
2710 /* write(fd1) */
2711 r = WRITE(fd1, wbuf, sizeof(wbuf));
2712 if (canwrite) {
2713 XP_SYS_EQ(100, r);
2714 } else {
2715 XP_SYS_NG(EBADF, r);
2716 }
2717
2718 /* read(fd1) */
2719 r = READ(fd1, rbuf, sizeof(rbuf));
2720 if (canread) {
2721 XP_SYS_EQ(100, r);
2722 } else {
2723 XP_SYS_NG(EBADF, r);
2724 }
2725
2726 r = CLOSE(fd0);
2727 XP_SYS_EQ(0, r);
2728 r = CLOSE(fd1);
2729 XP_SYS_EQ(0, r);
2730 }
2731 DEF(rdwr_two_RDONLY_RDONLY) { test_rdwr_two(O_RDONLY, O_RDONLY); }
2732 DEF(rdwr_two_RDONLY_WRONLY) { test_rdwr_two(O_RDONLY, O_WRONLY); }
2733 DEF(rdwr_two_RDONLY_RDWR) { test_rdwr_two(O_RDONLY, O_RDWR); }
2734 DEF(rdwr_two_WRONLY_RDONLY) { test_rdwr_two(O_WRONLY, O_RDONLY); }
2735 DEF(rdwr_two_WRONLY_WRONLY) { test_rdwr_two(O_WRONLY, O_WRONLY); }
2736 DEF(rdwr_two_WRONLY_RDWR) { test_rdwr_two(O_WRONLY, O_RDWR); }
2737 DEF(rdwr_two_RDWR_RDONLY) { test_rdwr_two(O_RDWR, O_RDONLY); }
2738 DEF(rdwr_two_RDWR_WRONLY) { test_rdwr_two(O_RDWR, O_WRONLY); }
2739 DEF(rdwr_two_RDWR_RDWR) { test_rdwr_two(O_RDWR, O_RDWR); }
2740
2741 /*
2742 * Read and write different descriptors simultaneously.
2743 * Only on full-duplex.
2744 */
2745 DEF(rdwr_simul)
2746 {
2747 char wbuf[1000]; /* 1/8sec in mulaw,1ch,8kHz */
2748 char rbuf[1000];
2749 int fd0;
2750 int fd1;
2751 int r;
2752 int status;
2753 pid_t pid;
2754
2755 TEST("rdwr_simul");
2756 if (netbsd < 8) {
2757 XP_SKIP("Multiple open is not supported");
2758 return;
2759 }
2760 if (!hw_fulldup()) {
2761 XP_SKIP("This test is only for full-duplex device");
2762 return;
2763 }
2764
2765 /* Silence data to make no sound */
2766 memset(wbuf, 0xff, sizeof(wbuf));
2767
2768 fd0 = OPEN(devaudio, O_WRONLY);
2769 REQUIRED_SYS_OK(fd0);
2770 fd1 = OPEN(devaudio, O_RDONLY);
2771 REQUIRED_SYS_OK(fd1);
2772
2773 fflush(stdout);
2774 fflush(stderr);
2775 pid = fork();
2776 if (pid == -1)
2777 xp_err(1, __LINE__, "fork");
2778
2779 if (pid == 0) {
2780 /* child (read) */
2781 for (int i = 0; i < 10; i++) {
2782 r = READ(fd1, rbuf, sizeof(rbuf));
2783 if (r == -1)
2784 xp_err(1, __LINE__, "read(i=%d)", i);
2785 }
2786 exit(0);
2787 } else {
2788 /* parent (write) */
2789 for (int i = 0; i < 10; i++) {
2790 r = WRITE(fd0, wbuf, sizeof(wbuf));
2791 if (r == -1)
2792 xp_err(1, __LINE__, "write(i=%d)", i);
2793 }
2794 waitpid(pid, &status, 0);
2795 }
2796
2797 CLOSE(fd0);
2798 CLOSE(fd1);
2799 /* If you reach here, consider as success */
2800 XP_EQ(0, 0);
2801 }
2802
2803 /*
2804 * DRAIN should work even on incomplete data left.
2805 */
2806 DEF(drain_incomplete)
2807 {
2808 struct audio_info ai;
2809 int r;
2810 int fd;
2811
2812 TEST("drain_incomplete");
2813
2814 if (hw_canplay() == 0) {
2815 XP_SKIP("This test is only for playable device");
2816 return;
2817 }
2818
2819 fd = OPEN(devaudio, O_WRONLY);
2820 REQUIRED_SYS_OK(fd);
2821
2822 AUDIO_INITINFO(&ai);
2823 /* let precision > 8 */
2824 ai.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
2825 ai.play.precision = 16;
2826 ai.mode = AUMODE_PLAY;
2827 r = IOCTL(fd, AUDIO_SETINFO, &ai, "");
2828 REQUIRED_SYS_EQ(0, r);
2829 /* Write one byte and then close */
2830 r = WRITE(fd, &r, 1);
2831 XP_SYS_EQ(1, r);
2832 r = CLOSE(fd);
2833 XP_SYS_EQ(0, r);
2834 }
2835
2836 /*
2837 * DRAIN should work even in pause.
2838 */
2839 DEF(drain_pause)
2840 {
2841 struct audio_info ai;
2842 int r;
2843 int fd;
2844
2845 TEST("drain_pause");
2846
2847 if (hw_canplay() == 0) {
2848 XP_SKIP("This test is only for playable device");
2849 return;
2850 }
2851
2852 fd = OPEN(devaudio, O_WRONLY);
2853 REQUIRED_SYS_OK(fd);
2854
2855 /* Set pause */
2856 AUDIO_INITINFO(&ai);
2857 ai.play.pause = 1;
2858 r = IOCTL(fd, AUDIO_SETINFO, &ai, "");
2859 XP_SYS_EQ(0, r);
2860 /* Write some data and then close */
2861 r = WRITE(fd, &r, 4);
2862 XP_SYS_EQ(4, r);
2863 r = CLOSE(fd);
2864 XP_SYS_EQ(0, r);
2865 }
2866
2867 /*
2868 * DRAIN does not affect for record-only descriptor.
2869 */
2870 DEF(drain_onrec)
2871 {
2872 int fd;
2873 int r;
2874
2875 TEST("drain_onrec");
2876
2877 if (hw_canrec() == 0) {
2878 XP_SKIP("This test is only for recordable device");
2879 return;
2880 }
2881
2882 fd = OPEN(devaudio, O_RDONLY);
2883 REQUIRED_SYS_OK(fd);
2884
2885 r = IOCTL(fd, AUDIO_DRAIN, NULL, "");
2886 XP_SYS_EQ(0, r);
2887
2888 r = CLOSE(fd);
2889 XP_SYS_EQ(0, r);
2890 }
2891
2892 /*
2893 * Whether mmap() succeeds with specified parameter.
2894 */
2895 void
2896 test_mmap_mode(int mode, int prot)
2897 {
2898 char buf[10];
2899 struct audio_info ai;
2900 const char *protstr;
2901 int expected;
2902 int fd;
2903 int r;
2904 int len;
2905 void *ptr;
2906
2907 if (prot == PROT_NONE) {
2908 protstr = "NONE";
2909 } else if (prot == PROT_READ) {
2910 protstr = "READ";
2911 } else if (prot == PROT_WRITE) {
2912 protstr = "WRITE";
2913 } else if (prot == (PROT_READ | PROT_WRITE)) {
2914 protstr = "READWRITE";
2915 } else {
2916 xp_errx(1, __LINE__, "unknown prot %x\n", prot);
2917 }
2918 TEST("mmap_%s_%s", openmode_str[mode] + 2, protstr);
2919 if ((props & AUDIO_PROP_MMAP) == 0) {
2920 XP_SKIP("This test is only for mmap-able device");
2921 return;
2922 }
2923 if (mode2aumode(mode) == 0) {
2924 XP_SKIP("Operation not allowed on this hardware property");
2925 return;
2926 }
2927 #if !defined(NO_RUMP)
2928 if (use_rump) {
2929 XP_SKIP("rump doesn't support mmap");
2930 return;
2931 }
2932 #endif
2933
2934 /*
2935 * On NetBSD7 and 8, mmap() always succeeds regardless of open mode.
2936 * On NetBSD9, mmap() succeeds only for writable descriptor.
2937 */
2938 expected = mode2play(mode);
2939 if (netbsd < 9) {
2940 expected = true;
2941 }
2942
2943 fd = OPEN(devaudio, mode);
2944 REQUIRED_SYS_OK(fd);
2945
2946 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "get");
2947 REQUIRED_SYS_EQ(0, r);
2948
2949 len = ai.play.buffer_size;
2950
2951 /* Make it pause */
2952 AUDIO_INITINFO(&ai);
2953 ai.play.pause = 1;
2954 r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause");
2955 REQUIRED_SYS_EQ(0, r);
2956
2957 ptr = MMAP(NULL, len, prot, MAP_FILE, fd, 0);
2958 XP_SYS_PTR(expected ? 0 : EACCES, ptr);
2959 if (expected) {
2960 /* XXX Doing mmap(2) doesn't inhibit read(2) */
2961 if (mode2rec(mode)) {
2962 r = READ(fd, buf, 0);
2963 XP_SYS_EQ(0, r);
2964 }
2965 /* Doing mmap(2) inhibits write(2) */
2966 if (mode2play(mode)) {
2967 /* NetBSD9 changes errno */
2968 r = WRITE(fd, buf, 0);
2969 if (netbsd < 9) {
2970 XP_SYS_NG(EINVAL, r);
2971 } else {
2972 XP_SYS_NG(EPERM, r);
2973 }
2974 }
2975 }
2976 if (ptr != MAP_FAILED) {
2977 r = MUNMAP(ptr, len);
2978 XP_SYS_EQ(0, r);
2979 }
2980
2981 /* Whether the pause is still valid */
2982 if (mode2play(mode)) {
2983 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
2984 XP_SYS_EQ(0, r);
2985 XP_EQ(1, ai.play.pause);
2986 }
2987
2988 r = CLOSE(fd);
2989 XP_SYS_EQ(0, r);
2990
2991 reset_after_mmap();
2992 }
2993 #define PROT_READWRITE (PROT_READ | PROT_WRITE)
2994 DEF(mmap_mode_RDONLY_NONE) { test_mmap_mode(O_RDONLY, PROT_NONE); }
2995 DEF(mmap_mode_RDONLY_READ) { test_mmap_mode(O_RDONLY, PROT_READ); }
2996 DEF(mmap_mode_RDONLY_WRITE) { test_mmap_mode(O_RDONLY, PROT_WRITE); }
2997 DEF(mmap_mode_RDONLY_READWRITE) { test_mmap_mode(O_RDONLY, PROT_READWRITE); }
2998 DEF(mmap_mode_WRONLY_NONE) { test_mmap_mode(O_WRONLY, PROT_NONE); }
2999 DEF(mmap_mode_WRONLY_READ) { test_mmap_mode(O_WRONLY, PROT_READ); }
3000 DEF(mmap_mode_WRONLY_WRITE) { test_mmap_mode(O_WRONLY, PROT_WRITE); }
3001 DEF(mmap_mode_WRONLY_READWRITE) { test_mmap_mode(O_WRONLY, PROT_READWRITE); }
3002 DEF(mmap_mode_RDWR_NONE) { test_mmap_mode(O_RDWR, PROT_NONE); }
3003 DEF(mmap_mode_RDWR_READ) { test_mmap_mode(O_RDWR, PROT_READ); }
3004 DEF(mmap_mode_RDWR_WRITE) { test_mmap_mode(O_RDWR, PROT_WRITE); }
3005 DEF(mmap_mode_RDWR_READWRITE) { test_mmap_mode(O_RDWR, PROT_READWRITE); }
3006
3007 /*
3008 * Check mmap()'s length and offset.
3009 */
3010 DEF(mmap_len)
3011 {
3012 struct audio_info ai;
3013 int fd;
3014 int r;
3015 size_t len;
3016 off_t offset;
3017 void *ptr;
3018 int bufsize;
3019 int pagesize;
3020 int lsize;
3021
3022 TEST("mmap_len");
3023 if ((props & AUDIO_PROP_MMAP) == 0) {
3024 XP_SKIP("This test is only for mmap-able device");
3025 return;
3026 }
3027 #if !defined(NO_RUMP)
3028 if (use_rump) {
3029 XP_SKIP("rump doesn't support mmap");
3030 return;
3031 }
3032 #endif
3033
3034 len = sizeof(pagesize);
3035 r = SYSCTLBYNAME("hw.pagesize", &pagesize, &len, NULL, 0);
3036 REQUIRED_SYS_EQ(0, r);
3037
3038 fd = OPEN(devaudio, O_WRONLY);
3039 REQUIRED_SYS_OK(r);
3040
3041 /* Get buffer_size */
3042 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3043 REQUIRED_SYS_EQ(0, r);
3044 bufsize = ai.play.buffer_size;
3045
3046 /*
3047 * XXX someone refers bufsize and another one does pagesize.
3048 * I'm not sure.
3049 */
3050 lsize = roundup2(bufsize, pagesize);
3051 struct {
3052 size_t len;
3053 off_t offset;
3054 int exp;
3055 } table[] = {
3056 /* len offset expected */
3057
3058 { 0, 0, 0 }, /* len is 0 */
3059 { 1, 0, 0 }, /* len is smaller than lsize */
3060 { lsize, 0, 0 }, /* len is the same as lsize */
3061 { lsize + 1, 0, EOVERFLOW }, /* len is larger */
3062
3063 { 0, -1, EINVAL }, /* offset is negative */
3064 { 0, lsize, 0 }, /* pointless param but ok */
3065 { 0, lsize + 1, EOVERFLOW }, /* exceed */
3066 { 1, lsize, EOVERFLOW }, /* exceed */
3067
3068 /*
3069 * When you treat offset as 32bit, offset will be 0
3070 * and thus it incorrectly succeeds.
3071 */
3072 { lsize, 1ULL<<32, EOVERFLOW },
3073 };
3074
3075 for (int i = 0; i < (int)__arraycount(table); i++) {
3076 len = table[i].len;
3077 offset = table[i].offset;
3078 int exp = table[i].exp;
3079
3080 ptr = MMAP(NULL, len, PROT_WRITE, MAP_FILE, fd, offset);
3081 if (exp == 0) {
3082 XP_SYS_PTR(0, ptr);
3083 } else {
3084 /* NetBSD8 introduces EOVERFLOW */
3085 if (netbsd < 8 && exp == EOVERFLOW)
3086 exp = EINVAL;
3087 XP_SYS_PTR(exp, ptr);
3088 }
3089
3090 if (ptr != MAP_FAILED) {
3091 r = MUNMAP(ptr, len);
3092 XP_SYS_EQ(0, r);
3093 }
3094 }
3095
3096 r = CLOSE(fd);
3097 XP_SYS_EQ(0, r);
3098
3099 reset_after_mmap();
3100 }
3101
3102 /*
3103 * mmap() the same descriptor twice.
3104 */
3105 DEF(mmap_twice)
3106 {
3107 struct audio_info ai;
3108 int fd;
3109 int r;
3110 int len;
3111 void *ptr1;
3112 void *ptr2;
3113
3114 TEST("mmap_twice");
3115 if ((props & AUDIO_PROP_MMAP) == 0) {
3116 XP_SKIP("This test is only for mmap-able device");
3117 return;
3118 }
3119 #if !defined(NO_RUMP)
3120 if (use_rump) {
3121 XP_SKIP("rump doesn't support mmap");
3122 return;
3123 }
3124 #endif
3125
3126 fd = OPEN(devaudio, O_WRONLY);
3127 REQUIRED_SYS_OK(fd);
3128
3129 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "get");
3130 REQUIRED_SYS_EQ(0, r);
3131 len = ai.play.buffer_size;
3132
3133 ptr1 = MMAP(NULL, len, PROT_WRITE, MAP_FILE, fd, 0);
3134 XP_SYS_PTR(0, ptr1);
3135
3136 /* XXX I'm not sure this sucess is intended. Anyway I follow it */
3137 ptr2 = MMAP(NULL, len, PROT_WRITE, MAP_FILE, fd, 0);
3138 XP_SYS_PTR(0, ptr2);
3139
3140 if (ptr2 != MAP_FAILED) {
3141 r = MUNMAP(ptr2, len);
3142 XP_SYS_EQ(0, r);
3143 }
3144 if (ptr1 != MAP_FAILED) {
3145 r = MUNMAP(ptr1, len);
3146 XP_SYS_EQ(0, r);
3147 }
3148
3149 r = CLOSE(fd);
3150 XP_SYS_EQ(0, r);
3151
3152 reset_after_mmap();
3153 }
3154
3155 /*
3156 * mmap() different descriptors.
3157 */
3158 DEF(mmap_multi)
3159 {
3160 struct audio_info ai;
3161 int fd0;
3162 int fd1;
3163 int r;
3164 int len;
3165 void *ptr0;
3166 void *ptr1;
3167
3168 TEST("mmap_multi");
3169 if (netbsd < 8) {
3170 XP_SKIP("Multiple open is not supported");
3171 return;
3172 }
3173 if ((props & AUDIO_PROP_MMAP) == 0) {
3174 XP_SKIP("This test is only for mmap-able device");
3175 return;
3176 }
3177 #if !defined(NO_RUMP)
3178 if (use_rump) {
3179 XP_SKIP("rump doesn't support mmap");
3180 return;
3181 }
3182 #endif
3183
3184 fd0 = OPEN(devaudio, O_WRONLY);
3185 REQUIRED_SYS_OK(fd0);
3186
3187 r = IOCTL(fd0, AUDIO_GETBUFINFO, &ai, "get");
3188 REQUIRED_SYS_EQ(0, r);
3189 len = ai.play.buffer_size;
3190
3191 fd1 = OPEN(devaudio, O_WRONLY);
3192 REQUIRED_SYS_OK(fd1);
3193
3194 ptr0 = MMAP(NULL, len, PROT_WRITE, MAP_FILE, fd0, 0);
3195 XP_SYS_PTR(0, ptr0);
3196
3197 ptr1 = MMAP(NULL, len, PROT_WRITE, MAP_FILE, fd1, 0);
3198 XP_SYS_PTR(0, ptr1);
3199
3200 if (ptr0 != MAP_FAILED) {
3201 r = MUNMAP(ptr1, len);
3202 XP_SYS_EQ(0, r);
3203 }
3204
3205 r = CLOSE(fd1);
3206 XP_SYS_EQ(0, r);
3207
3208 if (ptr1 != MAP_FAILED) {
3209 r = MUNMAP(ptr0, len);
3210 XP_SYS_EQ(0, r);
3211 }
3212
3213 r = CLOSE(fd0);
3214 XP_SYS_EQ(0, r);
3215
3216 reset_after_mmap();
3217 }
3218
3219 #define IN POLLIN
3220 #define OUT POLLOUT
3221 /*
3222 * Whether poll() succeeds with specified mode.
3223 */
3224 void
3225 test_poll_mode(int mode, int events, int expected_revents)
3226 {
3227 struct pollfd pfd;
3228 const char *events_str;
3229 int fd;
3230 int r;
3231 int expected_r;
3232
3233 if (events == IN) {
3234 events_str = "IN";
3235 } else if (events == OUT) {
3236 events_str = "OUT";
3237 } else if (events == (IN | OUT)) {
3238 events_str = "INOUT";
3239 } else {
3240 events_str = "?";
3241 }
3242 TEST("poll_mode_%s_%s", openmode_str[mode] + 2, events_str);
3243 if (mode2aumode(mode) == 0) {
3244 XP_SKIP("Operation not allowed on this hardware property");
3245 return;
3246 }
3247
3248 expected_r = (expected_revents != 0) ? 1 : 0;
3249
3250 fd = OPEN(devaudio, mode);
3251 REQUIRED_SYS_OK(fd);
3252
3253 memset(&pfd, 0, sizeof(pfd));
3254 pfd.fd = fd;
3255 pfd.events = events;
3256
3257 r = POLL(&pfd, 1, 100);
3258 /* It's a bit complicated.. */
3259 if (r < 0 || r > 1) {
3260 /*
3261 * Check these two cases first:
3262 * - system call fails.
3263 * - poll() with one nfds returns >1. It's strange.
3264 */
3265 XP_SYS_EQ(expected_r, r);
3266 } else {
3267 /*
3268 * Otherwise, poll() returned 0 or 1.
3269 */
3270 DPRINTF(" > pfd.revents=%s\n", event_tostr(pfd.revents));
3271
3272 /* NetBSD7,8 have several strange behavior. It must be bug. */
3273
3274 XP_SYS_EQ(expected_r, r);
3275 XP_EQ(expected_revents, pfd.revents);
3276 }
3277 r = CLOSE(fd);
3278 XP_SYS_EQ(0, r);
3279 }
3280 DEF(poll_mode_RDONLY_IN) { test_poll_mode(O_RDONLY, IN, 0); }
3281 DEF(poll_mode_RDONLY_OUT) { test_poll_mode(O_RDONLY, OUT, 0); }
3282 DEF(poll_mode_RDONLY_INOUT) { test_poll_mode(O_RDONLY, IN|OUT, 0); }
3283 DEF(poll_mode_WRONLY_IN) { test_poll_mode(O_WRONLY, IN, 0); }
3284 DEF(poll_mode_WRONLY_OUT) { test_poll_mode(O_WRONLY, OUT, OUT); }
3285 DEF(poll_mode_WRONLY_INOUT) { test_poll_mode(O_WRONLY, IN|OUT, OUT); }
3286 DEF(poll_mode_RDWR_IN) { test_poll_mode(O_RDWR, IN, 0); }
3287 DEF(poll_mode_RDWR_OUT) { test_poll_mode(O_RDWR, OUT, OUT); }
3288 DEF(poll_mode_RDWR_INOUT) { test_poll_mode(O_RDWR, IN|OUT, OUT); }
3289
3290 /*
3291 * Poll(OUT) when buffer is empty.
3292 */
3293 DEF(poll_out_empty)
3294 {
3295 struct pollfd pfd;
3296 int fd;
3297 int r;
3298
3299 TEST("poll_out_empty");
3300
3301 fd = OPEN(devaudio, O_WRONLY);
3302 REQUIRED_SYS_OK(fd);
3303
3304 memset(&pfd, 0, sizeof(pfd));
3305 pfd.fd = fd;
3306 pfd.events = POLLOUT;
3307
3308 /* Check when empty. It should succeed even if timeout == 0 */
3309 r = POLL(&pfd, 1, 0);
3310 XP_SYS_EQ(1, r);
3311 XP_EQ(POLLOUT, pfd.revents);
3312
3313 r = CLOSE(fd);
3314 XP_SYS_EQ(0, r);
3315 }
3316
3317 /*
3318 * Poll(OUT) when buffer is full.
3319 */
3320 DEF(poll_out_full)
3321 {
3322 struct audio_info ai;
3323 struct pollfd pfd;
3324 int fd;
3325 int r;
3326 char *buf;
3327 int buflen;
3328
3329 TEST("poll_out_full");
3330
3331 fd = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3332 REQUIRED_SYS_OK(fd);
3333
3334 /* Pause */
3335 AUDIO_INITINFO(&ai);
3336 ai.play.pause = 1;
3337 r = IOCTL(fd, AUDIO_SETINFO, &ai, "");
3338 XP_SYS_EQ(0, r);
3339
3340 /* Get buffer size */
3341 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3342 XP_SYS_EQ(0, r);
3343
3344 /* Write until full */
3345 buflen = ai.play.buffer_size;
3346 buf = (char *)malloc(buflen);
3347 REQUIRED_IF(buf != NULL);
3348 memset(buf, 0xff, buflen);
3349 do {
3350 r = WRITE(fd, buf, buflen);
3351 } while (r == buflen);
3352 if (r == -1) {
3353 XP_SYS_NG(EAGAIN, r);
3354 }
3355
3356 /* Do poll */
3357 memset(&pfd, 0, sizeof(pfd));
3358 pfd.fd = fd;
3359 pfd.events = POLLOUT;
3360 r = POLL(&pfd, 1, 0);
3361 XP_SYS_EQ(0, r);
3362 XP_EQ(0, pfd.revents);
3363
3364 r = CLOSE(fd);
3365 XP_SYS_EQ(0, r);
3366 free(buf);
3367 }
3368
3369 /*
3370 * Poll(OUT) when buffer is full but hiwat sets lower than full.
3371 */
3372 DEF(poll_out_hiwat)
3373 {
3374 struct audio_info ai;
3375 struct pollfd pfd;
3376 int fd;
3377 int r;
3378 char *buf;
3379 int buflen;
3380 int newhiwat;
3381
3382 TEST("poll_out_hiwat");
3383
3384 fd = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3385 REQUIRED_SYS_OK(fd);
3386
3387 /* Get buffer size and hiwat */
3388 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3389 XP_SYS_EQ(0, r);
3390 /* Change hiwat some different value */
3391 newhiwat = ai.lowat;
3392
3393 /* Set pause and hiwat */
3394 AUDIO_INITINFO(&ai);
3395 ai.play.pause = 1;
3396 ai.hiwat = newhiwat;
3397 r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause=1;hiwat");
3398 XP_SYS_EQ(0, r);
3399
3400 /* Get the set hiwat again */
3401 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3402 XP_SYS_EQ(0, r);
3403
3404 /* Write until full */
3405 buflen = ai.blocksize * ai.hiwat;
3406 buf = (char *)malloc(buflen);
3407 REQUIRED_IF(buf != NULL);
3408 memset(buf, 0xff, buflen);
3409 do {
3410 r = WRITE(fd, buf, buflen);
3411 } while (r == buflen);
3412 if (r == -1) {
3413 XP_SYS_NG(EAGAIN, r);
3414 }
3415
3416 /* Do poll */
3417 memset(&pfd, 0, sizeof(pfd));
3418 pfd.fd = fd;
3419 pfd.events = POLLOUT;
3420 r = POLL(&pfd, 1, 0);
3421 XP_SYS_EQ(0, r);
3422 XP_EQ(0, pfd.revents);
3423
3424 r = CLOSE(fd);
3425 XP_SYS_EQ(0, r);
3426 free(buf);
3427 }
3428
3429 /*
3430 * Unpause from buffer full, POLLOUT should raise.
3431 * XXX poll(2) on NetBSD7 is really incomplete and wierd. I don't test it.
3432 */
3433 DEF(poll_out_unpause)
3434 {
3435 struct audio_info ai;
3436 struct pollfd pfd;
3437 int fd;
3438 int r;
3439 char *buf;
3440 int buflen;
3441 u_int blocksize;
3442 int hiwat;
3443 int lowat;
3444
3445 TEST("poll_out_unpause");
3446 if (netbsd < 8) {
3447 XP_SKIP("NetBSD7's poll() is too incomplete to test.");
3448 return;
3449 }
3450
3451 /* Non-blocking open */
3452 fd = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3453 REQUIRED_SYS_OK(fd);
3454
3455 /* Adjust block size and hiwat/lowat to make the test time 1sec */
3456 blocksize = 1000; /* 1/8 sec in mulaw,1ch,8000Hz */
3457 hiwat = 12; /* 1.5sec */
3458 lowat = 4; /* 0.5sec */
3459 AUDIO_INITINFO(&ai);
3460 ai.blocksize = blocksize;
3461 ai.hiwat = hiwat;
3462 ai.lowat = lowat;
3463 /* and also set encoding */
3464 /*
3465 * XXX NetBSD7 has different results depending on whether the input
3466 * encoding is emulated (AUDIO_ENCODINGFLAG_EMULATED) or not. It's
3467 * not easy to ensure this situation on all hardware environment.
3468 * On NetBSD9, the result is the same regardless of input encoding.
3469 */
3470 r = IOCTL(fd, AUDIO_SETINFO, &ai, "blocksize=%d", blocksize);
3471 XP_SYS_EQ(0, r);
3472 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3473 if (ai.blocksize != blocksize) {
3474 /*
3475 * NetBSD9 can not change the blocksize. Then,
3476 * adjust using hiwat/lowat.
3477 */
3478 blocksize = ai.blocksize;
3479 hiwat = howmany(8000 * 1.5, blocksize);
3480 lowat = howmany(8000 * 0.5, blocksize);
3481 }
3482 /* Anyway, set the parameters */
3483 AUDIO_INITINFO(&ai);
3484 ai.blocksize = blocksize;
3485 ai.hiwat = hiwat;
3486 ai.lowat = lowat;
3487 ai.play.pause = 1;
3488 r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause=1");
3489 XP_SYS_EQ(0, r);
3490
3491 /* Get the set parameters again */
3492 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3493 XP_SYS_EQ(0, r);
3494
3495 /* Write until full */
3496 buflen = ai.blocksize * ai.hiwat;
3497 buf = (char *)malloc(buflen);
3498 REQUIRED_IF(buf != NULL);
3499 memset(buf, 0xff, buflen);
3500 do {
3501 r = WRITE(fd, buf, buflen);
3502 } while (r == buflen);
3503 if (r == -1) {
3504 XP_SYS_NG(EAGAIN, r);
3505 }
3506
3507 /* At this time, POLLOUT should not be set because buffer is full */
3508 memset(&pfd, 0, sizeof(pfd));
3509 pfd.fd = fd;
3510 pfd.events = POLLOUT;
3511 r = POLL(&pfd, 1, 0);
3512 XP_SYS_EQ(0, r);
3513 XP_EQ(0, pfd.revents);
3514
3515 /* Unpause */
3516 AUDIO_INITINFO(&ai);
3517 ai.play.pause = 0;
3518 r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause=0");
3519 XP_SYS_EQ(0, r);
3520
3521 /*
3522 * When unpause occurs:
3523 * - NetBSD7 (emul=0) -> the buffer remains.
3524 * - NetBSD7 (emul=1) -> the buffer is cleared.
3525 * - NetBSD8 -> the buffer remains.
3526 * - NetBSD9 -> the buffer remains.
3527 */
3528
3529 /* Check poll() up to 2sec */
3530 pfd.revents = 0;
3531 r = POLL(&pfd, 1, 2000);
3532 XP_SYS_EQ(1, r);
3533 XP_EQ(POLLOUT, pfd.revents);
3534
3535 /*
3536 * Since POLLOUT is set, it should be writable.
3537 * But at this time, no all buffer may be writable.
3538 */
3539 r = WRITE(fd, buf, buflen);
3540 XP_SYS_OK(r);
3541
3542 /* Flush it because there is no need to play it */
3543 r = IOCTL(fd, AUDIO_FLUSH, NULL, "");
3544 XP_SYS_EQ(0, r);
3545
3546 r = CLOSE(fd);
3547 XP_SYS_EQ(0, r);
3548 free(buf);
3549 }
3550
3551 /*
3552 * poll(2) must not be affected by playback of other descriptors.
3553 */
3554 DEF(poll_out_simul)
3555 {
3556 struct audio_info ai;
3557 struct pollfd pfd[2];
3558 int fd[2];
3559 int r;
3560 char *buf;
3561 u_int blocksize;
3562 int hiwat;
3563 int lowat;
3564 int buflen;
3565 int time;
3566
3567 TEST("poll_out_simul");
3568 if (netbsd < 8) {
3569 XP_SKIP("Multiple open is not supported");
3570 return;
3571 }
3572
3573 /* Make sure that it's not affected by descriptor order */
3574 for (int i = 0; i < 2; i++) {
3575 int a = i;
3576 int b = 1 - i;
3577
3578 fd[0] = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3579 REQUIRED_SYS_OK(fd[0]);
3580 fd[1] = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3581 REQUIRED_SYS_OK(fd[1]);
3582
3583 /*
3584 * Adjust block size and hiwat/lowat.
3585 * I want to choice suitable blocksize (if possible).
3586 */
3587 blocksize = 1000; /* 1/8 sec in mulaw,1ch,8000Hz */
3588 hiwat = 12; /* 1.5sec */
3589 lowat = 4; /* 0.5sec */
3590 AUDIO_INITINFO(&ai);
3591 ai.blocksize = blocksize;
3592 ai.hiwat = hiwat;
3593 ai.lowat = lowat;
3594 r = IOCTL(fd[0], AUDIO_SETINFO, &ai, "blocksize=1000");
3595 XP_SYS_EQ(0, r);
3596 r = IOCTL(fd[0], AUDIO_GETBUFINFO, &ai, "read back blocksize");
3597 if (ai.blocksize != blocksize) {
3598 /*
3599 * NetBSD9 can not change the blocksize. Then,
3600 * adjust using hiwat/lowat.
3601 */
3602 blocksize = ai.blocksize;
3603 hiwat = howmany(8000 * 1.5, blocksize);
3604 lowat = howmany(8000 * 0.5, blocksize);
3605 }
3606 /* Anyway, set the parameters */
3607 AUDIO_INITINFO(&ai);
3608 ai.blocksize = blocksize;
3609 ai.hiwat = hiwat;
3610 ai.lowat = lowat;
3611 /* Pause fdA */
3612 ai.play.pause = 1;
3613 r = IOCTL(fd[a], AUDIO_SETINFO, &ai, "pause=1");
3614 XP_SYS_EQ(0, r);
3615 /* Unpause fdB */
3616 ai.play.pause = 0;
3617 r = IOCTL(fd[b], AUDIO_SETINFO, &ai, "pause=0");
3618 XP_SYS_EQ(0, r);
3619
3620 /* Get again. XXX two individual ioctls are correct */
3621 r = IOCTL(fd[0], AUDIO_GETBUFINFO, &ai, "");
3622 XP_SYS_EQ(0, r);
3623 DPRINTF(" > blocksize=%d lowat=%d hiwat=%d\n",
3624 ai.blocksize, ai.lowat, ai.hiwat);
3625
3626 /* Enough long time than the playback time */
3627 time = (ai.hiwat - ai.lowat) * blocksize / 8; /*[msec]*/
3628 time *= 2;
3629
3630 /* Write fdA full */
3631 buflen = blocksize * ai.lowat;
3632 buf = (char *)malloc(buflen);
3633 REQUIRED_IF(buf != NULL);
3634 memset(buf, 0xff, buflen);
3635 do {
3636 r = WRITE(fd[a], buf, buflen);
3637 } while (r == buflen);
3638 if (r == -1) {
3639 XP_SYS_NG(EAGAIN, r);
3640 }
3641
3642 /* POLLOUT should not be set, because fdA is buffer full */
3643 memset(pfd, 0, sizeof(pfd));
3644 pfd[0].fd = fd[a];
3645 pfd[0].events = POLLOUT;
3646 r = POLL(pfd, 1, 0);
3647 XP_SYS_EQ(0, r);
3648 XP_EQ(0, pfd[0].revents);
3649
3650 /* Write fdB at least lowat */
3651 r = WRITE(fd[b], buf, buflen);
3652 XP_SYS_EQ(buflen, r);
3653 r = WRITE(fd[b], buf, buflen);
3654 if (r == -1) {
3655 XP_SYS_NG(EAGAIN, r);
3656 }
3657
3658 /* Only fdB should become POLLOUT */
3659 memset(pfd, 0, sizeof(pfd));
3660 pfd[0].fd = fd[0];
3661 pfd[0].events = POLLOUT;
3662 pfd[1].fd = fd[1];
3663 pfd[1].events = POLLOUT;
3664 r = POLL(pfd, 2, time);
3665 XP_SYS_EQ(1, r);
3666 if (r != -1) {
3667 XP_EQ(0, pfd[a].revents);
3668 XP_EQ(POLLOUT, pfd[b].revents);
3669 }
3670
3671 /* Drop the rest */
3672 r = IOCTL(fd[0], AUDIO_FLUSH, NULL, "");
3673 XP_SYS_EQ(0, r);
3674 r = IOCTL(fd[1], AUDIO_FLUSH, NULL, "");
3675 XP_SYS_EQ(0, r);
3676
3677 r = CLOSE(fd[0]);
3678 XP_SYS_EQ(0, r);
3679 r = CLOSE(fd[1]);
3680 XP_SYS_EQ(0, r);
3681 free(buf);
3682
3683 xxx_close_wait();
3684 }
3685 }
3686
3687 /*
3688 * poll(2) must not be affected by other recording descriptors even if
3689 * playback descriptor waits with POLLIN (though it's not normal usage).
3690 * In other words, two POLLIN must not interfere.
3691 */
3692 DEF(poll_in_simul)
3693 {
3694 struct audio_info ai;
3695 struct pollfd pfd;
3696 int fd[2];
3697 int r;
3698 char *buf;
3699 int blocksize;
3700
3701 TEST("poll_in_simul");
3702 if (netbsd < 8) {
3703 XP_SKIP("Multiple open is not supported");
3704 return;
3705 }
3706 if (hw_fulldup() == 0) {
3707 XP_SKIP("This test is only for full-duplex device");
3708 return;
3709 }
3710
3711 int play = 0;
3712 int rec = 1;
3713
3714 fd[play] = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3715 REQUIRED_SYS_OK(fd[play]);
3716 fd[rec] = OPEN(devaudio, O_RDONLY);
3717 REQUIRED_SYS_OK(fd[rec]);
3718
3719 /* Get block size */
3720 r = IOCTL(fd[rec], AUDIO_GETBUFINFO, &ai, "");
3721 XP_SYS_EQ(0, r);
3722 blocksize = ai.blocksize;
3723
3724 buf = (char *)malloc(blocksize);
3725 REQUIRED_IF(buf != NULL);
3726
3727 /*
3728 * At first, make sure the playback one doesn't return POLLIN.
3729 */
3730 memset(&pfd, 0, sizeof(pfd));
3731 pfd.fd = fd[play];
3732 pfd.events = POLLIN;
3733 r = POLL(&pfd, 1, 0);
3734 if (r == 0 && pfd.revents == 0) {
3735 XP_SYS_EQ(0, r);
3736 XP_EQ(0, pfd.revents);
3737 } else {
3738 XP_FAIL("play fd returns POLLIN");
3739 goto abort;
3740 }
3741
3742 /* Start recording */
3743 r = READ(fd[rec], buf, blocksize);
3744 XP_SYS_EQ(blocksize, r);
3745
3746 /* Poll()ing playback descriptor with POLLIN should not raise */
3747 r = POLL(&pfd, 1, 1000);
3748 XP_SYS_EQ(0, r);
3749 XP_EQ(0, pfd.revents);
3750
3751 /* Poll()ing recording descriptor with POLLIN should raise */
3752 pfd.fd = fd[rec];
3753 r = POLL(&pfd, 1, 0);
3754 XP_SYS_EQ(1, r);
3755 XP_EQ(POLLIN, pfd.revents);
3756
3757 abort:
3758 r = CLOSE(fd[play]);
3759 XP_SYS_EQ(0, r);
3760 r = CLOSE(fd[rec]);
3761 XP_SYS_EQ(0, r);
3762 free(buf);
3763 }
3764
3765 /*
3766 * Whether kqueue() succeeds with specified mode.
3767 */
3768 void
3769 test_kqueue_mode(int openmode, int filt, int expected)
3770 {
3771 struct kevent kev;
3772 struct timespec ts;
3773 int fd;
3774 int kq;
3775 int r;
3776
3777 TEST("kqueue_mode_%s_%s",
3778 openmode_str[openmode] + 2,
3779 (filt == EVFILT_READ) ? "READ" : "WRITE");
3780 if (mode2aumode(openmode) == 0) {
3781 XP_SKIP("Operation not allowed on this hardware property");
3782 return;
3783 }
3784
3785 ts.tv_sec = 0;
3786 ts.tv_nsec = 100 * 1000 * 1000; // 100msec
3787
3788 kq = KQUEUE();
3789 XP_SYS_OK(kq);
3790
3791 fd = OPEN(devaudio, openmode);
3792 REQUIRED_SYS_OK(fd);
3793
3794 /*
3795 * Check whether the specified filter can be set.
3796 * Any filters can always be set, even if pointless combination.
3797 * For example, EVFILT_READ can be set on O_WRONLY descriptor
3798 * though it will never raise.
3799 * I will not mention about good or bad of this behavior here.
3800 */
3801 EV_SET(&kev, fd, filt, EV_ADD, 0, 0, 0);
3802 r = KEVENT_SET(kq, &kev, 1);
3803 XP_SYS_EQ(0, r);
3804
3805 if (r == 0) {
3806 /* If the filter can be set, try kevent(poll) */
3807 r = KEVENT_POLL(kq, &kev, 1, &ts);
3808 XP_SYS_EQ(expected, r);
3809
3810 /* Delete it */
3811 EV_SET(&kev, fd, filt, EV_DELETE, 0, 0, 0);
3812 r = KEVENT_SET(kq, &kev, 1);
3813 XP_SYS_EQ(0, r);
3814 }
3815
3816 r = CLOSE(fd);
3817 XP_SYS_EQ(0, r);
3818 r = CLOSE(kq);
3819 XP_SYS_EQ(0, r);
3820 }
3821 DEF(kqueue_mode_RDONLY_READ) {
3822 /* Should not raise yet (NetBSD7 has bugs?) */
3823 int expected = (netbsd < 8) ? 1 : 0;
3824 test_kqueue_mode(O_RDONLY, EVFILT_READ, expected);
3825 }
3826 DEF(kqueue_mode_RDONLY_WRITE) {
3827 /* Should never raise (NetBSD7 has bugs) */
3828 int expected = (netbsd < 8) ? 1 : 0;
3829 test_kqueue_mode(O_RDONLY, EVFILT_WRITE, expected);
3830 }
3831 DEF(kqueue_mode_WRONLY_READ) {
3832 /* Should never raise */
3833 test_kqueue_mode(O_WRONLY, EVFILT_READ, 0);
3834 }
3835 DEF(kqueue_mode_WRONLY_WRITE) {
3836 /* Should raise */
3837 test_kqueue_mode(O_WRONLY, EVFILT_WRITE, 1);
3838 }
3839 DEF(kqueue_mode_RDWR_READ) {
3840 /* Should not raise yet (NetBSD7 is something strange) */
3841 int expected = (netbsd < 8 && hw_fulldup()) ? 1 : 0;
3842 test_kqueue_mode(O_RDWR, EVFILT_READ, expected);
3843 }
3844 DEF(kqueue_mode_RDWR_WRITE) {
3845 /* Should raise */
3846 test_kqueue_mode(O_RDWR, EVFILT_WRITE, 1);
3847 }
3848
3849 /*
3850 * kqueue(2) when buffer is empty.
3851 */
3852 DEF(kqueue_empty)
3853 {
3854 struct audio_info ai;
3855 struct kevent kev;
3856 struct timespec ts;
3857 int kq;
3858 int fd;
3859 int r;
3860
3861 TEST("kqueue_empty");
3862
3863 fd = OPEN(devaudio, O_WRONLY);
3864 REQUIRED_SYS_OK(fd);
3865
3866 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3867 XP_SYS_EQ(0, r);
3868
3869 kq = KQUEUE();
3870 XP_SYS_OK(kq);
3871
3872 EV_SET(&kev, fd, EV_ADD, EVFILT_WRITE, 0, 0, 0);
3873 r = KEVENT_SET(kq, &kev, 1);
3874 XP_SYS_EQ(0, r);
3875
3876 /* When the buffer is empty, it should succeed even if timeout == 0 */
3877 memset(&ts, 0, sizeof(ts));
3878 r = KEVENT_POLL(kq, &kev, 1, &ts);
3879 XP_SYS_EQ(1, r);
3880 XP_EQ(fd, kev.ident);
3881 /*
3882 * XXX According to kqueue(2) manpage, returned kev.data contains
3883 * "the amount of space remaining in the write buffer".
3884 * NetBSD7 returns buffer_size. Shouldn't it be blocksize * hiwat?
3885 */
3886 /* XP_EQ(ai.blocksize * ai.hiwat, kev.data); */
3887 XP_EQ(ai.play.buffer_size, kev.data);
3888
3889 r = CLOSE(fd);
3890 XP_SYS_EQ(0, r);
3891 r = CLOSE(kq);
3892 XP_SYS_EQ(0, r);
3893 }
3894
3895 /*
3896 * kqueue(2) when buffer is full.
3897 */
3898 DEF(kqueue_full)
3899 {
3900 struct audio_info ai;
3901 struct kevent kev;
3902 struct timespec ts;
3903 int kq;
3904 int fd;
3905 int r;
3906 char *buf;
3907 int buflen;
3908
3909 TEST("kqueue_full");
3910
3911 fd = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3912 REQUIRED_SYS_OK(fd);
3913
3914 /* Pause */
3915 AUDIO_INITINFO(&ai);
3916 ai.play.pause = 1;
3917 r = IOCTL(fd, AUDIO_SETINFO, &ai, "");
3918 XP_SYS_EQ(0, r);
3919
3920 /* Get buffer size */
3921 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3922 XP_SYS_EQ(0, r);
3923
3924 /* Write until full */
3925 buflen = ai.play.buffer_size;
3926 buf = (char *)malloc(buflen);
3927 REQUIRED_IF(buf != NULL);
3928 memset(buf, 0xff, buflen);
3929 do {
3930 r = WRITE(fd, buf, buflen);
3931 } while (r == buflen);
3932 if (r == -1) {
3933 XP_SYS_NG(EAGAIN, r);
3934 }
3935
3936 kq = KQUEUE();
3937 XP_SYS_OK(kq);
3938
3939 EV_SET(&kev, fd, EV_ADD, EVFILT_WRITE, 0, 0, 0);
3940 r = KEVENT_SET(kq, &kev, 1);
3941 XP_SYS_EQ(0, r);
3942
3943 /* kevent() should not raise */
3944 ts.tv_sec = 0;
3945 ts.tv_nsec = 100L * 1000 * 1000; /* 100msec */
3946 r = KEVENT_POLL(kq, &kev, 1, &ts);
3947 XP_SYS_EQ(0, r);
3948 if (r > 0) {
3949 XP_EQ(fd, kev.ident);
3950 XP_EQ(0, kev.data);
3951 }
3952
3953 r = CLOSE(fd);
3954 XP_SYS_EQ(0, r);
3955 r = CLOSE(kq);
3956 XP_SYS_EQ(0, r);
3957 free(buf);
3958 }
3959
3960 /*
3961 * kqueue(2) when buffer is full but hiwat sets lower than full.
3962 */
3963 DEF(kqueue_hiwat)
3964 {
3965 struct audio_info ai;
3966 struct kevent kev;
3967 struct timespec ts;
3968 int kq;
3969 int fd;
3970 int r;
3971 char *buf;
3972 int buflen;
3973 int newhiwat;
3974
3975 TEST("kqueue_hiwat");
3976
3977 fd = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
3978 REQUIRED_SYS_OK(fd);
3979
3980 /* Get buffer size and hiwat */
3981 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "hiwat");
3982 XP_SYS_EQ(0, r);
3983 /* Change hiwat some different value */
3984 newhiwat = ai.hiwat - 1;
3985
3986 /* Set pause and hiwat */
3987 AUDIO_INITINFO(&ai);
3988 ai.play.pause = 1;
3989 ai.hiwat = newhiwat;
3990 r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause=1;hiwat");
3991 XP_SYS_EQ(0, r);
3992
3993 /* Get the set parameters again */
3994 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
3995 XP_SYS_EQ(0, r);
3996 XP_EQ(1, ai.play.pause);
3997 XP_EQ(newhiwat, ai.hiwat);
3998
3999 /* Write until full */
4000 buflen = ai.blocksize * ai.hiwat;
4001 buf = (char *)malloc(buflen);
4002 REQUIRED_IF(buf != NULL);
4003 memset(buf, 0xff, buflen);
4004 do {
4005 r = WRITE(fd, buf, buflen);
4006 } while (r == buflen);
4007 if (r == -1) {
4008 XP_SYS_NG(EAGAIN, r);
4009 }
4010
4011 kq = KQUEUE();
4012 XP_SYS_OK(kq);
4013
4014 EV_SET(&kev, fd, EV_ADD, EVFILT_WRITE, 0, 0, 0);
4015 r = KEVENT_SET(kq, &kev, 1);
4016 XP_SYS_EQ(0, r);
4017
4018 /* Should not raise because it's not possible to write */
4019 ts.tv_sec = 0;
4020 ts.tv_nsec = 100L * 1000 * 1000; /* 100msec */
4021 r = KEVENT_POLL(kq, &kev, 1, &ts);
4022 if (r > 0)
4023 DEBUG_KEV("kev", &kev);
4024 XP_SYS_EQ(0, r);
4025
4026 r = CLOSE(fd);
4027 XP_SYS_EQ(0, r);
4028 r = CLOSE(kq);
4029 XP_SYS_EQ(0, r);
4030 free(buf);
4031 }
4032
4033 /*
4034 * Unpause from buffer full, kevent() should raise.
4035 */
4036 DEF(kqueue_unpause)
4037 {
4038 struct audio_info ai;
4039 struct kevent kev;
4040 struct timespec ts;
4041 int fd;
4042 int r;
4043 int kq;
4044 char *buf;
4045 int buflen;
4046 u_int blocksize;
4047 int hiwat;
4048 int lowat;
4049
4050 TEST("kqueue_unpause");
4051
4052 /* Non-blocking open */
4053 fd = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
4054 REQUIRED_SYS_OK(fd);
4055
4056 /* Adjust block size and hiwat/lowat to make the test time 1sec */
4057 blocksize = 1000; /* 1/8 sec in mulaw,1ch,8000Hz */
4058 hiwat = 12; /* 1.5sec */
4059 lowat = 4; /* 0.5sec */
4060 AUDIO_INITINFO(&ai);
4061 ai.blocksize = blocksize;
4062 ai.hiwat = hiwat;
4063 ai.lowat = lowat;
4064 /* and also set encoding */
4065 /*
4066 * XXX NetBSD7 has different results depending on whether the input
4067 * encoding is emulated (AUDIO_ENCODINGFLAG_EMULATED) or not. It's
4068 * not easy to ensure this situation on all hardware environment.
4069 * On NetBSD9, the result is the same regardless of input encoding.
4070 */
4071 r = IOCTL(fd, AUDIO_SETINFO, &ai, "blocksize=%d", blocksize);
4072 XP_SYS_EQ(0, r);
4073 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4074 if (ai.blocksize != blocksize) {
4075 /*
4076 * NetBSD9 can not change the blocksize. Then,
4077 * adjust using hiwat/lowat.
4078 */
4079 blocksize = ai.blocksize;
4080 hiwat = howmany(8000 * 1.5, blocksize);
4081 lowat = howmany(8000 * 0.5, blocksize);
4082 }
4083 /* Anyway, set the parameters */
4084 AUDIO_INITINFO(&ai);
4085 ai.blocksize = blocksize;
4086 ai.hiwat = hiwat;
4087 ai.lowat = lowat;
4088 ai.play.pause = 1;
4089 r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause=1");
4090 XP_SYS_EQ(0, r);
4091
4092 /* Get the set parameters again */
4093 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4094 XP_SYS_EQ(0, r);
4095 DPRINTF(" > blocksize=%d hiwat=%d lowat=%d buffer_size=%d\n",
4096 ai.blocksize, ai.hiwat, ai.lowat, ai.play.buffer_size);
4097
4098 /* Write until full */
4099 buflen = ai.blocksize * ai.hiwat;
4100 buf = (char *)malloc(buflen);
4101 REQUIRED_IF(buf != NULL);
4102 memset(buf, 0xff, buflen);
4103 do {
4104 r = WRITE(fd, buf, buflen);
4105 } while (r == buflen);
4106 if (r == -1) {
4107 XP_SYS_NG(EAGAIN, r);
4108 }
4109
4110 kq = KQUEUE();
4111 XP_SYS_OK(kq);
4112
4113 EV_SET(&kev, fd, EV_ADD, EVFILT_WRITE, 0, 0, 0);
4114 r = KEVENT_SET(kq, &kev, 1);
4115 XP_SYS_EQ(0, r);
4116
4117 /* Unpause */
4118 AUDIO_INITINFO(&ai);
4119 ai.play.pause = 0;
4120 r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause=0");
4121 XP_SYS_EQ(0, r);
4122
4123 /* Check kevent() up to 2sec */
4124 ts.tv_sec = 2;
4125 ts.tv_nsec = 0;
4126 r = KEVENT_POLL(kq, &kev, 1, &ts);
4127 if (r >= 1)
4128 DEBUG_KEV("kev", &kev);
4129 if (netbsd < 8) {
4130 /*
4131 * NetBSD7 with EMULATED_FLAG unset has bugs. Unpausing
4132 * unintentionally clears buffer (and therefore it becomes
4133 * writable) but it doesn't raise EVFILT_WRITE.
4134 */
4135 } else {
4136 XP_SYS_EQ(1, r);
4137 }
4138
4139 /* Flush it because there is no need to play it */
4140 r = IOCTL(fd, AUDIO_FLUSH, NULL, "");
4141 XP_SYS_EQ(0, r);
4142
4143 r = CLOSE(fd);
4144 XP_SYS_EQ(0, r);
4145 r = CLOSE(kq);
4146 XP_SYS_EQ(0, r);
4147 free(buf);
4148 }
4149
4150 /*
4151 * kevent(2) must not be affected by other audio descriptors.
4152 */
4153 DEF(kqueue_simul)
4154 {
4155 struct audio_info ai;
4156 struct audio_info ai2;
4157 struct kevent kev[2];
4158 struct timespec ts;
4159 int fd[2];
4160 int r;
4161 int kq;
4162 u_int blocksize;
4163 int hiwat;
4164 int lowat;
4165 char *buf;
4166 int buflen;
4167
4168 TEST("kqueue_simul");
4169 if (netbsd < 8) {
4170 XP_SKIP("Multiple open is not supported");
4171 return;
4172 }
4173
4174 memset(&ts, 0, sizeof(ts));
4175
4176 /* Make sure that it's not affected by descriptor order */
4177 for (int i = 0; i < 2; i++) {
4178 int a = i;
4179 int b = 1 - i;
4180
4181 fd[0] = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
4182 REQUIRED_SYS_OK(fd[0]);
4183 fd[1] = OPEN(devaudio, O_WRONLY | O_NONBLOCK);
4184 REQUIRED_SYS_OK(fd[1]);
4185
4186 /*
4187 * Adjust block size and hiwat/lowat.
4188 * I want to choice suitable blocksize (if possible).
4189 */
4190 blocksize = 1000; /* 1/8 sec in mulaw,1ch,8000Hz */
4191 hiwat = 12; /* 1.5sec */
4192 lowat = 4; /* 0.5sec */
4193 AUDIO_INITINFO(&ai);
4194 ai.blocksize = blocksize;
4195 ai.hiwat = hiwat;
4196 ai.lowat = lowat;
4197 r = IOCTL(fd[0], AUDIO_SETINFO, &ai, "blocksize=1000");
4198 XP_SYS_EQ(0, r);
4199 r = IOCTL(fd[0], AUDIO_GETBUFINFO, &ai, "read back blocksize");
4200 if (ai.blocksize != blocksize) {
4201 /*
4202 * NetBSD9 can not change the blocksize. Then,
4203 * adjust using hiwat/lowat.
4204 */
4205 blocksize = ai.blocksize;
4206 hiwat = howmany(8000 * 1.5, blocksize);
4207 lowat = howmany(8000 * 0.5, blocksize);
4208 }
4209 /* Anyway, set the parameters to both */
4210 AUDIO_INITINFO(&ai);
4211 ai.blocksize = blocksize;
4212 ai.hiwat = hiwat;
4213 ai.lowat = lowat;
4214 ai.play.pause = 1;
4215 r = IOCTL(fd[a], AUDIO_SETINFO, &ai, "pause=1");
4216 XP_SYS_EQ(0, r);
4217 r = IOCTL(fd[b], AUDIO_SETINFO, &ai, "pause=1");
4218 XP_SYS_EQ(0, r);
4219
4220 /* Write both until full */
4221 buflen = ai.blocksize * ai.hiwat;
4222 buf = (char *)malloc(buflen);
4223 REQUIRED_IF(buf != NULL);
4224 memset(buf, 0xff, buflen);
4225 /* Write fdA */
4226 do {
4227 r = WRITE(fd[a], buf, buflen);
4228 } while (r == buflen);
4229 if (r == -1) {
4230 XP_SYS_NG(EAGAIN, r);
4231 }
4232 /* Write fdB */
4233 do {
4234 r = WRITE(fd[b], buf, buflen);
4235 } while (r == buflen);
4236 if (r == -1) {
4237 XP_SYS_NG(EAGAIN, r);
4238 }
4239
4240 /* Get fdB's initial seek for later */
4241 r = IOCTL(fd[b], AUDIO_GETBUFINFO, &ai2, "");
4242 XP_SYS_EQ(0, r);
4243
4244 kq = KQUEUE();
4245 XP_SYS_OK(kq);
4246
4247 /* Both aren't raised at this point */
4248 EV_SET(&kev[0], fd[a], EV_ADD, EVFILT_WRITE, 0, 0, 0);
4249 EV_SET(&kev[1], fd[b], EV_ADD, EVFILT_WRITE, 0, 0, 0);
4250 r = KEVENT_SET(kq, kev, 2);
4251 XP_SYS_EQ(0, r);
4252
4253 /* Unpause only fdA */
4254 AUDIO_INITINFO(&ai);
4255 ai.play.pause = 0;
4256 r = IOCTL(fd[a], AUDIO_SETINFO, &ai, "pause=0");
4257 XP_SYS_EQ(0, r);
4258
4259 /* kevent() up to 2sec */
4260 ts.tv_sec = 2;
4261 ts.tv_nsec = 0;
4262 r = KEVENT_POLL(kq, &kev[0], 1, &ts);
4263 if (r >= 1)
4264 DEBUG_KEV("kev", &kev[0]);
4265 /* fdA should raise */
4266 XP_SYS_EQ(1, r);
4267 XP_EQ(fd[a], kev[0].ident);
4268
4269 /* Make sure that fdB keeps whole data */
4270 r = IOCTL(fd[b], AUDIO_GETBUFINFO, &ai, "");
4271 XP_EQ(ai2.play.seek, ai.play.seek);
4272
4273 /* Flush it because there is no need to play it */
4274 r = IOCTL(fd[0], AUDIO_FLUSH, NULL, "");
4275 XP_SYS_EQ(0, r);
4276 r = IOCTL(fd[1], AUDIO_FLUSH, NULL, "");
4277 XP_SYS_EQ(0, r);
4278
4279 r = CLOSE(fd[0]);
4280 XP_SYS_EQ(0, r);
4281 r = CLOSE(fd[1]);
4282 XP_SYS_EQ(0, r);
4283 r = CLOSE(kq);
4284 XP_SYS_EQ(0, r);
4285 free(buf);
4286
4287 xxx_close_wait();
4288 }
4289 }
4290
4291 /* Shared data between threads for ioctl_while_write */
4292 struct ioctl_while_write_data {
4293 int fd;
4294 struct timeval start;
4295 int terminated;
4296 };
4297
4298 /* Test thread for ioctl_while_write */
4299 void *thread_ioctl_while_write(void *);
4300 void *
4301 thread_ioctl_while_write(void *arg)
4302 {
4303 struct ioctl_while_write_data *data = arg;
4304 struct timeval now, res;
4305 struct audio_info ai;
4306 int r;
4307
4308 /* If 0.5 seconds have elapsed since writing, assume it's blocked */
4309 do {
4310 usleep(100);
4311 gettimeofday(&now, NULL);
4312 timersub(&now, &data->start, &res);
4313 } while (res.tv_usec < 500000);
4314
4315 /* Then, do ioctl() */
4316 r = IOCTL(data->fd, AUDIO_GETBUFINFO, &ai, "");
4317 XP_SYS_EQ(0, r);
4318
4319 /* Terminate */
4320 data->terminated = 1;
4321
4322 /* Resume write() by unpause */
4323 AUDIO_INITINFO(&ai);
4324 if (netbsd < 8) {
4325 /*
4326 * XXX NetBSD7 has bugs and it cannot be unpaused.
4327 * However, it also has another bug and it clears buffer
4328 * when encoding is changed. I use it. :-P
4329 */
4330 ai.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
4331 }
4332 ai.play.pause = 0;
4333 r = IOCTL(data->fd, AUDIO_SETINFO, &ai, "pause=0");
4334 XP_SYS_EQ(0, r);
4335
4336 return NULL;
4337 }
4338
4339 /*
4340 * ioctl(2) can be issued while write(2)-ing.
4341 */
4342 DEF(ioctl_while_write)
4343 {
4344 struct audio_info ai;
4345 struct ioctl_while_write_data data0, *data;
4346 char buf[8000]; /* 1sec in mulaw,1ch,8000Hz */
4347 pthread_t tid;
4348 int r;
4349
4350 TEST("ioctl_while_write");
4351
4352 data = &data0;
4353 memset(data, 0, sizeof(*data));
4354 memset(buf, 0xff, sizeof(buf));
4355
4356 data->fd = OPEN(devaudio, O_WRONLY);
4357 REQUIRED_SYS_OK(data->fd);
4358
4359 /* Pause to block write(2)ing */
4360 AUDIO_INITINFO(&ai);
4361 ai.play.pause = 1;
4362 r = IOCTL(data->fd, AUDIO_SETINFO, &ai, "pause=1");
4363 XP_SYS_EQ(0, r);
4364
4365 gettimeofday(&data->start, NULL);
4366
4367 pthread_create(&tid, NULL, thread_ioctl_while_write, data);
4368
4369 /* Write until blocking */
4370 for (;;) {
4371 r = WRITE(data->fd, buf, sizeof(buf));
4372 if (data->terminated)
4373 break;
4374 XP_SYS_EQ(sizeof(buf), r);
4375
4376 /* Update written time */
4377 gettimeofday(&data->start, NULL);
4378 }
4379
4380 pthread_join(tid, NULL);
4381
4382 /* Flush */
4383 r = IOCTL(data->fd, AUDIO_FLUSH, NULL, "");
4384 XP_SYS_EQ(0, r);
4385 r = CLOSE(data->fd);
4386 XP_SYS_EQ(0, r);
4387 }
4388
4389 volatile int sigio_caught;
4390 void
4391 signal_FIOASYNC(int signo)
4392 {
4393 if (signo == SIGIO) {
4394 sigio_caught = 1;
4395 DPRINTF(" > %d: pid %d got SIGIO\n", __LINE__, (int)getpid());
4396 }
4397 }
4398
4399 /*
4400 * FIOASYNC between two descriptors should be splitted.
4401 */
4402 DEF(FIOASYNC_reset)
4403 {
4404 int fd0, fd1;
4405 int r;
4406 int val;
4407
4408 TEST("FIOASYNC_reset");
4409 if (netbsd < 8) {
4410 XP_SKIP("Multiple open is not supported");
4411 return;
4412 }
4413
4414 /* The first one opens */
4415 fd0 = OPEN(devaudio, O_WRONLY);
4416 REQUIRED_SYS_OK(fd0);
4417
4418 /* The second one opens, enables ASYNC, and closes */
4419 fd1 = OPEN(devaudio, O_WRONLY);
4420 REQUIRED_SYS_OK(fd1);
4421 val = 1;
4422 r = IOCTL(fd1, FIOASYNC, &val, "on");
4423 XP_SYS_EQ(0, r);
4424 r = CLOSE(fd1);
4425 XP_SYS_EQ(0, r);
4426
4427 /* Again, the second one opens and enables ASYNC */
4428 fd1 = OPEN(devaudio, O_WRONLY);
4429 REQUIRED_SYS_OK(fd1);
4430 val = 1;
4431 r = IOCTL(fd1, FIOASYNC, &val, "on");
4432 XP_SYS_EQ(0, r); /* NetBSD8 fails */
4433 r = CLOSE(fd1);
4434 XP_SYS_EQ(0, r);
4435 r = CLOSE(fd0);
4436 XP_SYS_EQ(0, r);
4437 }
4438
4439 /*
4440 * Whether SIGIO is emitted on plyaback.
4441 * XXX I don't understand conditions that NetBSD7 emits signal.
4442 */
4443 DEF(FIOASYNC_play_signal)
4444 {
4445 struct audio_info ai;
4446 int r;
4447 int fd;
4448 int val;
4449 char *data;
4450 int i;
4451
4452 TEST("FIOASYNC_play_signal");
4453 if (hw_canplay() == 0) {
4454 XP_SKIP("This test is only for playable device");
4455 return;
4456 }
4457
4458 signal(SIGIO, signal_FIOASYNC);
4459 sigio_caught = 0;
4460
4461 fd = OPEN(devaudio, O_WRONLY);
4462 REQUIRED_SYS_OK(fd);
4463
4464 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4465 REQUIRED_SYS_EQ(0, r);
4466 REQUIRED_IF(ai.blocksize != 0);
4467 data = (char *)malloc(ai.blocksize);
4468 REQUIRED_IF(data != NULL);
4469 memset(data, 0xff, ai.blocksize);
4470
4471 val = 1;
4472 r = IOCTL(fd, FIOASYNC, &val, "on");
4473 XP_SYS_EQ(0, r);
4474
4475 r = WRITE(fd, data, ai.blocksize);
4476 XP_SYS_EQ(ai.blocksize, r);
4477
4478 /* Waits signal until 1sec */
4479 for (i = 0; i < 100 && sigio_caught == 0; i++) {
4480 usleep(10000);
4481 }
4482 signal(SIGIO, SIG_IGN);
4483 XP_EQ(1, sigio_caught);
4484
4485 r = CLOSE(fd);
4486 XP_SYS_EQ(0, r);
4487
4488 free(data);
4489 signal(SIGIO, SIG_IGN);
4490 sigio_caught = 0;
4491 }
4492
4493 /*
4494 * Whether SIGIO is emitted on recording.
4495 */
4496 DEF(FIOASYNC_rec_signal)
4497 {
4498 char buf[10];
4499 int r;
4500 int fd;
4501 int val;
4502 int i;
4503
4504 TEST("FIOASYNC_rec_signal");
4505 if (hw_canrec() == 0) {
4506 XP_SKIP("This test is only for recordable device");
4507 return;
4508 }
4509
4510 signal(SIGIO, signal_FIOASYNC);
4511 sigio_caught = 0;
4512
4513 fd = OPEN(devaudio, O_RDONLY);
4514 REQUIRED_SYS_OK(fd);
4515
4516 val = 1;
4517 r = IOCTL(fd, FIOASYNC, &val, "on");
4518 XP_SYS_EQ(0, r);
4519
4520 r = READ(fd, buf, sizeof(buf));
4521 XP_SYS_EQ(sizeof(buf), r);
4522
4523 /* Wait signal until 1sec */
4524 for (i = 0; i < 100 && sigio_caught == 0; i++) {
4525 usleep(10000);
4526 }
4527 signal(SIGIO, SIG_IGN);
4528 XP_EQ(1, sigio_caught);
4529
4530 r = CLOSE(fd);
4531 XP_SYS_EQ(0, r);
4532
4533 signal(SIGIO, SIG_IGN);
4534 sigio_caught = 0;
4535 }
4536
4537 /*
4538 * FIOASYNC doesn't affect other descriptor.
4539 * For simplify, test only for playback...
4540 */
4541 DEF(FIOASYNC_multi)
4542 {
4543 struct audio_info ai;
4544 char *buf;
4545 char pipebuf[1];
4546 int r;
4547 int i;
4548 int fd1;
4549 int fd2;
4550 int pd[2];
4551 int val;
4552 pid_t pid;
4553 int status;
4554
4555 TEST("FIOASYNC_multi");
4556 if (netbsd < 8) {
4557 XP_SKIP("Multiple open is not supported");
4558 return;
4559 }
4560 if (hw_canplay() == 0) {
4561 XP_SKIP("This test is only for playable device");
4562 return;
4563 }
4564
4565 /* Pipe used between parent and child */
4566 r = pipe(pd);
4567 REQUIRED_SYS_EQ(0, r);
4568
4569 fd1 = OPEN(devaudio, O_WRONLY);
4570 REQUIRED_SYS_OK(fd1);
4571 fd2 = OPEN(devaudio, O_WRONLY);
4572 REQUIRED_SYS_OK(fd2);
4573
4574 /* Pause fd2 */
4575 AUDIO_INITINFO(&ai);
4576 ai.play.pause = 1;
4577 r = IOCTL(fd2, AUDIO_SETINFO, &ai, "pause");
4578 REQUIRED_SYS_EQ(0, r);
4579
4580 /* Fill both */
4581 r = IOCTL(fd1, AUDIO_GETBUFINFO, &ai, "");
4582 REQUIRED_SYS_EQ(0, r);
4583 REQUIRED_IF(ai.blocksize != 0);
4584 buf = (char *)malloc(ai.blocksize);
4585 REQUIRED_IF(buf != NULL);
4586 memset(buf, 0xff, ai.blocksize);
4587 r = WRITE(fd1, buf, ai.blocksize);
4588 XP_SYS_EQ(ai.blocksize, r);
4589
4590 sigio_caught = 0;
4591 val = 1;
4592
4593 fflush(stdout);
4594 fflush(stderr);
4595 pid = fork();
4596 if (pid == -1) {
4597 REQUIRED_SYS_OK(pid);
4598 }
4599 if (pid == 0) {
4600 /* Child */
4601 close(fd1);
4602
4603 /* Child enables ASYNC on fd2 */
4604 signal(SIGIO, signal_FIOASYNC);
4605 r = IOCTL(fd2, FIOASYNC, &val, "on");
4606 /* It cannot count errors because here is a child process */
4607 /* XP_SYS_EQ(0, r); */
4608
4609 /*
4610 * Waits signal until 1sec.
4611 * But fd2 is paused so it should never raise.
4612 */
4613 for (i = 0; i < 100 && sigio_caught == 0; i++) {
4614 usleep(10000);
4615 }
4616 signal(SIGIO, SIG_IGN);
4617 pipebuf[0] = sigio_caught;
4618 /* This is not WRITE() macro here */
4619 write(pd[1], pipebuf, sizeof(pipebuf));
4620
4621 /* XXX? */
4622 close(fd2);
4623 sleep(1);
4624 exit(0);
4625 } else {
4626 /* Parent */
4627 DPRINTF(" > fork() = %d\n", (int)pid);
4628
4629 /* Parent enables ASYNC on fd1 */
4630 signal(SIGIO, signal_FIOASYNC);
4631 r = IOCTL(fd1, FIOASYNC, &val, "on");
4632 XP_SYS_EQ(0, r);
4633
4634 /* Waits signal until 1sec */
4635 for (i = 0; i < 100 && sigio_caught == 0; i++) {
4636 usleep(10000);
4637 }
4638 signal(SIGIO, SIG_IGN);
4639 XP_EQ(1, sigio_caught);
4640
4641 /* Then read child's result from pipe */
4642 r = read(pd[0], pipebuf, sizeof(pipebuf));
4643 if (r != 1) {
4644 XP_FAIL("reading from child failed");
4645 }
4646 DPRINTF(" > child's sigio_cauht = %d\n", pipebuf[0]);
4647 XP_EQ(0, pipebuf[0]);
4648
4649 waitpid(pid, &status, 0);
4650 }
4651
4652 r = CLOSE(fd1);
4653 XP_SYS_EQ(0, r);
4654 r = CLOSE(fd2);
4655 XP_SYS_EQ(0, r);
4656
4657 signal(SIGIO, SIG_IGN);
4658 sigio_caught = 0;
4659 free(buf);
4660 }
4661
4662 /*
4663 * Check AUDIO_WSEEK behavior.
4664 */
4665 DEF(AUDIO_WSEEK)
4666 {
4667 char buf[4];
4668 struct audio_info ai;
4669 int r;
4670 int fd;
4671 int n;
4672
4673 TEST("AUDIO_WSEEK");
4674
4675 fd = OPEN(devaudio, O_WRONLY);
4676 REQUIRED_SYS_OK(fd);
4677
4678 /* Pause to count sample data */
4679 AUDIO_INITINFO(&ai);
4680 ai.play.pause = 1;
4681 r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause=1");
4682 REQUIRED_SYS_EQ(0, r);
4683
4684 /* On the initial state, it should be 0 bytes */
4685 n = 0;
4686 r = IOCTL(fd, AUDIO_WSEEK, &n, "");
4687 XP_SYS_EQ(0, r);
4688 XP_EQ(0, n);
4689
4690 /* When writing 4 bytes, it should be 4 bytes */
4691 memset(buf, 0xff, sizeof(buf));
4692 r = WRITE(fd, buf, sizeof(buf));
4693 REQUIRED_EQ(sizeof(buf), r);
4694 r = IOCTL(fd, AUDIO_WSEEK, &n, "");
4695 XP_SYS_EQ(0, r);
4696 if (netbsd < 9) {
4697 /*
4698 * On NetBSD7, it will return 0.
4699 * Perhaps, WSEEK returns the number of pustream bytes but
4700 * data has already advanced...
4701 */
4702 XP_EQ(0, n);
4703 } else {
4704 /* Data less than one block remains here */
4705 XP_EQ(4, n);
4706 }
4707
4708 r = CLOSE(fd);
4709 XP_SYS_EQ(0, r);
4710 }
4711
4712 /*
4713 * Check AUDIO_SETFD behavior for O_*ONLY descriptor.
4714 * On NetBSD7, SETFD modify audio layer's state (and MD driver's state)
4715 * regardless of open mode. GETFD obtains audio layer's duplex.
4716 * On NetBSD9, SETFD is obsoleted. GETFD obtains hardware's duplex.
4717 */
4718 void
4719 test_AUDIO_SETFD_xxONLY(int openmode)
4720 {
4721 struct audio_info ai;
4722 int r;
4723 int fd;
4724 int n;
4725
4726 TEST("AUDIO_SETFD_%s", openmode_str[openmode] + 2);
4727 if (openmode == O_RDONLY && hw_canrec() == 0) {
4728 XP_SKIP("This test is for recordable device");
4729 return;
4730 }
4731 if (openmode == O_WRONLY && hw_canplay() == 0) {
4732 XP_SKIP("This test is for playable device");
4733 return;
4734 }
4735
4736 fd = OPEN(devaudio, openmode);
4737 REQUIRED_SYS_OK(fd);
4738
4739 /*
4740 * Just after open(2),
4741 * - On NetBSD7, it's always half-duplex.
4742 * - On NetBSD9, it's the same as hardware one regardless of openmode.
4743 */
4744 n = 0;
4745 r = IOCTL(fd, AUDIO_GETFD, &n, "");
4746 XP_SYS_EQ(0, r);
4747 if (netbsd < 9) {
4748 XP_EQ(0, n);
4749 } else {
4750 XP_EQ(hw_fulldup(), n);
4751 }
4752
4753 /*
4754 * When trying to set to full-duplex,
4755 * - On NetBSD7, it will succeed if the hardware is full-duplex, or
4756 * will fail if the hardware is half-duplex.
4757 * - On NetBSD9, it will always succeed but will not be modified.
4758 */
4759 n = 1;
4760 r = IOCTL(fd, AUDIO_SETFD, &n, "on");
4761 if (netbsd < 8) {
4762 if (hw_fulldup()) {
4763 XP_SYS_EQ(0, r);
4764 } else {
4765 XP_SYS_NG(ENOTTY, r);
4766 }
4767 } else if (netbsd == 8) {
4768 XP_FAIL("expected result is unknown");
4769 } else {
4770 XP_SYS_EQ(0, r);
4771 }
4772
4773 /*
4774 * When obtain it,
4775 * - On NetBSD7, it will be 1 if the hardware is full-duplex or
4776 * 0 if half-duplex.
4777 * - On NetBSD9, it will never be changed because it's the hardware
4778 * property.
4779 */
4780 n = 0;
4781 r = IOCTL(fd, AUDIO_GETFD, &n, "");
4782 XP_SYS_EQ(0, r);
4783 if (netbsd < 8) {
4784 XP_EQ(hw_fulldup(), n);
4785 } else if (netbsd == 8) {
4786 XP_FAIL("expected result is unknown");
4787 } else {
4788 XP_EQ(hw_fulldup(), n);
4789 }
4790
4791 /* Some track parameters like ai.*.open should not change */
4792 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4793 XP_SYS_EQ(0, r);
4794 XP_EQ(mode2play(openmode), ai.play.open);
4795 XP_EQ(mode2rec(openmode), ai.record.open);
4796
4797 /*
4798 * When trying to set to half-duplex,
4799 * - On NetBSD7, it will succeed if the hardware is full-duplex, or
4800 * it will succeed with nothing happens.
4801 * - On NetBSD9, it will always succeed but nothing happens.
4802 */
4803 n = 0;
4804 r = IOCTL(fd, AUDIO_SETFD, &n, "off");
4805 XP_SYS_EQ(0, r);
4806
4807 /*
4808 * When obtain it again,
4809 * - On NetBSD7, it will be 0 if the hardware is full-duplex, or
4810 * still 0 if half-duplex.
4811 * - On NetBSD9, it should not change.
4812 */
4813 n = 0;
4814 r = IOCTL(fd, AUDIO_GETFD, &n, "");
4815 XP_SYS_EQ(0, r);
4816 if (netbsd < 9) {
4817 XP_EQ(0, n);
4818 } else {
4819 XP_EQ(hw_fulldup(), n);
4820 }
4821
4822 /* Some track parameters like ai.*.open should not change */
4823 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4824 XP_SYS_EQ(0, r);
4825 XP_EQ(mode2play(openmode), ai.play.open);
4826 XP_EQ(mode2rec(openmode), ai.record.open);
4827
4828 r = CLOSE(fd);
4829 XP_SYS_EQ(0, r);
4830 }
4831 DEF(AUDIO_SETFD_RDONLY) { test_AUDIO_SETFD_xxONLY(O_RDONLY); }
4832 DEF(AUDIO_SETFD_WRONLY) { test_AUDIO_SETFD_xxONLY(O_WRONLY); }
4833
4834 /*
4835 * Check AUDIO_SETFD behavior for O_RDWR descriptor.
4836 */
4837 DEF(AUDIO_SETFD_RDWR)
4838 {
4839 struct audio_info ai;
4840 int r;
4841 int fd;
4842 int n;
4843
4844 TEST("AUDIO_SETFD_RDWR");
4845 if (!hw_fulldup()) {
4846 XP_SKIP("This test is only for full-duplex device");
4847 return;
4848 }
4849
4850 fd = OPEN(devaudio, O_RDWR);
4851 REQUIRED_SYS_OK(fd);
4852
4853 /*
4854 * - audio(4) manpage until NetBSD7 said "If a full-duplex capable
4855 * audio device is opened for both reading and writing it will
4856 * start in half-duplex play mode", but implementation doesn't
4857 * seem to follow it. It returns full-duplex.
4858 * - On NetBSD9, it should return full-duplex on full-duplex, or
4859 * half-duplex on half-duplex.
4860 */
4861 n = 0;
4862 r = IOCTL(fd, AUDIO_GETFD, &n, "");
4863 XP_SYS_EQ(0, r);
4864 XP_EQ(hw_fulldup(), n);
4865
4866 /*
4867 * When trying to set to full-duplex,
4868 * - On NetBSD7, it will succeed with nothing happens if full-duplex,
4869 * or will fail if half-duplex.
4870 * - On NetBSD9, it will always succeed with nothing happens.
4871 */
4872 n = 1;
4873 r = IOCTL(fd, AUDIO_SETFD, &n, "on");
4874 if (netbsd < 9) {
4875 if (hw_fulldup()) {
4876 XP_SYS_EQ(0, r);
4877 } else {
4878 XP_SYS_NG(ENOTTY, r);
4879 }
4880 } else {
4881 XP_SYS_EQ(0, r);
4882 }
4883
4884 /* When obtains it, it retuns half/full-duplex as is */
4885 n = 0;
4886 r = IOCTL(fd, AUDIO_GETFD, &n, "");
4887 XP_SYS_EQ(0, r);
4888 XP_EQ(hw_fulldup(), n);
4889
4890 /* Some track parameters like ai.*.open should not change */
4891 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4892 XP_SYS_EQ(0, r);
4893 XP_EQ(1, ai.play.open);
4894 XP_EQ(mode2rec(O_RDWR), ai.record.open);
4895
4896 /*
4897 * When trying to set to half-duplex,
4898 * - On NetBSD7, it will succeed if the hardware is full-duplex, or
4899 * it will succeed with nothing happens.
4900 * - On NetBSD9, it will always succeed but nothing happens.
4901 */
4902 n = 0;
4903 r = IOCTL(fd, AUDIO_SETFD, &n, "off");
4904 if (netbsd < 8) {
4905 XP_SYS_EQ(0, r);
4906 } else if (netbsd == 8) {
4907 XP_FAIL("expected result is unknown");
4908 } else {
4909 XP_SYS_EQ(0, r);
4910 }
4911
4912 /*
4913 * When obtain it again,
4914 * - On NetBSD7, it will be 0 if the hardware is full-duplex, or
4915 * still 0 if half-duplex.
4916 * - On NetBSD9, it should be 1 if the hardware is full-duplex, or
4917 * 0 if half-duplex.
4918 */
4919 n = 0;
4920 r = IOCTL(fd, AUDIO_GETFD, &n, "");
4921 XP_SYS_EQ(0, r);
4922 if (netbsd < 8) {
4923 XP_EQ(0, n);
4924 } else if (netbsd == 8) {
4925 XP_FAIL("expected result is unknown");
4926 } else {
4927 XP_EQ(hw_fulldup(), n);
4928 }
4929
4930 /* Some track parameters like ai.*.open should not change */
4931 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4932 XP_SYS_EQ(0, r);
4933 XP_EQ(1, ai.play.open);
4934 XP_EQ(mode2rec(O_RDWR), ai.record.open);
4935
4936 r = CLOSE(fd);
4937 XP_SYS_EQ(0, r);
4938 }
4939
4940 /*
4941 * Check AUDIO_GETINFO.eof behavior.
4942 */
4943 DEF(AUDIO_GETINFO_eof)
4944 {
4945 struct audio_info ai;
4946 char buf[4];
4947 int r;
4948 int fd, fd1;
4949
4950 TEST("AUDIO_GETINFO_eof");
4951 if (hw_canplay() == 0) {
4952 XP_SKIP("This test is for playable device");
4953 return;
4954 }
4955
4956 fd = OPEN(devaudio, O_RDWR);
4957 REQUIRED_SYS_OK(fd);
4958
4959 /* Pause to make no sound */
4960 AUDIO_INITINFO(&ai);
4961 ai.play.pause = 1;
4962 r = IOCTL(fd, AUDIO_SETINFO, &ai, "pause");
4963 REQUIRED_SYS_EQ(0, r);
4964
4965 /* It should be 0 initially */
4966 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4967 XP_SYS_EQ(0, r);
4968 XP_EQ(0, ai.play.eof);
4969 XP_EQ(0, ai.record.eof);
4970
4971 /* Writing zero bytes should increment it */
4972 r = WRITE(fd, &r, 0);
4973 REQUIRED_SYS_OK(r);
4974 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4975 XP_SYS_EQ(0, r);
4976 XP_EQ(1, ai.play.eof);
4977 XP_EQ(0, ai.record.eof);
4978
4979 /* Writing one ore more bytes should noto increment it */
4980 memset(buf, 0xff, sizeof(buf));
4981 r = WRITE(fd, buf, sizeof(buf));
4982 REQUIRED_SYS_OK(r);
4983 memset(&ai, 0, sizeof(ai));
4984 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4985 XP_SYS_EQ(0, r);
4986 XP_EQ(1, ai.play.eof);
4987 XP_EQ(0, ai.record.eof);
4988
4989 /* Writing zero bytes again should increment it */
4990 r = WRITE(fd, buf, 0);
4991 REQUIRED_SYS_OK(r);
4992 memset(&ai, 0, sizeof(ai));
4993 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
4994 XP_SYS_EQ(0, r);
4995 XP_EQ(2, ai.play.eof);
4996 XP_EQ(0, ai.record.eof);
4997
4998 /* Reading zero bytes should not increment it */
4999 if (hw_fulldup()) {
5000 r = READ(fd, buf, 0);
5001 REQUIRED_SYS_OK(r);
5002 memset(&ai, 0, sizeof(ai));
5003 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
5004 XP_SYS_EQ(0, r);
5005 XP_EQ(2, ai.play.eof);
5006 XP_EQ(0, ai.record.eof);
5007 }
5008
5009 /* should not interfere with other descriptor */
5010 if (netbsd >= 8) {
5011 fd1 = OPEN(devaudio, O_RDWR);
5012 REQUIRED_SYS_OK(fd1);
5013 memset(&ai, 0, sizeof(ai));
5014 r = IOCTL(fd1, AUDIO_GETBUFINFO, &ai, "");
5015 XP_SYS_EQ(0, r);
5016 XP_EQ(0, ai.play.eof);
5017 XP_EQ(0, ai.record.eof);
5018 r = CLOSE(fd1);
5019 XP_SYS_EQ(0, r);
5020 }
5021
5022 r = CLOSE(fd);
5023 XP_SYS_EQ(0, r);
5024
5025 xxx_close_wait();
5026
5027 /* When reopen, it should reset the counter */
5028 fd = OPEN(devaudio, O_RDWR);
5029 REQUIRED_SYS_OK(fd);
5030
5031 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
5032 XP_SYS_EQ(0, r);
5033 XP_EQ(0, ai.play.eof);
5034 XP_EQ(0, ai.record.eof);
5035
5036 r = CLOSE(fd);
5037 XP_SYS_EQ(0, r);
5038 }
5039
5040 /*
5041 * Check relationship between openmode and mode set by AUDIO_SETINFO.
5042 */
5043 void
5044 test_AUDIO_SETINFO_mode(int openmode, int index, int setmode, int expected)
5045 {
5046 struct audio_info ai;
5047 char buf[10];
5048 int inimode;
5049 int r;
5050 int fd;
5051 bool canwrite;
5052 bool canread;
5053
5054 /* index was passed only for displaying here */
5055 TEST("AUDIO_SETINFO_mode_%s_%d", openmode_str[openmode] + 2, index);
5056 if (mode2aumode(openmode) == 0) {
5057 XP_SKIP("Operation not allowed on this hardware property");
5058 return;
5059 }
5060
5061 inimode = mode2aumode(openmode);
5062
5063 fd = OPEN(devaudio, openmode);
5064 REQUIRED_SYS_OK(fd);
5065
5066 /* When just after opening */
5067 memset(&ai, 0, sizeof(ai));
5068 r = IOCTL(fd, AUDIO_GETINFO, &ai, "");
5069 REQUIRED_SYS_EQ(0, r);
5070 XP_EQ(inimode, ai.mode);
5071 XP_EQ(mode2play(openmode), ai.play.open);
5072 XP_EQ(mode2rec(openmode), ai.record.open);
5073
5074 /*
5075 * On NetBSD7 and 8, both playback and recording buffer are always
5076 * allocated. So I won't check it.
5077 * On NetBSD9, buffer should be allocated only if necessary.
5078 */
5079 if (netbsd >= 9) {
5080 XP_BUFFSIZE(mode2play(openmode), ai.play.buffer_size);
5081 XP_BUFFSIZE(mode2rec(openmode), ai.record.buffer_size);
5082 }
5083
5084 /* Change mode (and pause here) */
5085 ai.mode = setmode;
5086 ai.play.pause = 1;
5087 ai.record.pause = 1;
5088 r = IOCTL(fd, AUDIO_SETINFO, &ai, "mode");
5089 XP_SYS_EQ(0, r);
5090 if (r == 0) {
5091 r = IOCTL(fd, AUDIO_GETINFO, &ai, "");
5092 XP_SYS_EQ(0, r);
5093 XP_EQ(expected, ai.mode);
5094
5095 /* It seems to keep the initial openmode regardless of mode */
5096 XP_EQ(mode2play(openmode), ai.play.open);
5097 XP_EQ(mode2rec(openmode), ai.record.open);
5098 /* buffers are always allocated on NetBSD 7 and 8 */
5099 if (netbsd >= 9) {
5100 XP_BUFFSIZE(mode2play(openmode), ai.play.buffer_size);
5101 XP_BUFFSIZE(mode2rec(openmode), ai.record.buffer_size);
5102 }
5103 }
5104
5105 /*
5106 * On NetBSD7, whether writable depends openmode when open.
5107 * On NetBSD9, whether writable should depend inimode when open.
5108 * Modifying after open should not affect this mode.
5109 */
5110 if (netbsd < 9) {
5111 canwrite = (openmode != O_RDONLY);
5112 } else {
5113 canwrite = ((inimode & AUMODE_PLAY) != 0);
5114 }
5115 r = WRITE(fd, buf, 0);
5116 if (canwrite) {
5117 XP_SYS_EQ(0, r);
5118 } else {
5119 XP_SYS_NG(EBADF, r);
5120 }
5121
5122 /*
5123 * On NetBSD7, whether readable depends openmode when open.
5124 * On NetBSD9, whether readable should depend inimode when open.
5125 * Modifying after open should not affect this mode.
5126 */
5127 if (netbsd < 9) {
5128 canread = (openmode != O_WRONLY);
5129 } else {
5130 canread = ((inimode & AUMODE_RECORD) != 0);
5131 }
5132 r = READ(fd, buf, 0);
5133 if (canread) {
5134 XP_SYS_EQ(0, r);
5135 } else {
5136 XP_SYS_NG(EBADF, r);
5137 }
5138
5139 r = CLOSE(fd);
5140 XP_SYS_EQ(0, r);
5141 }
5142 /*
5143 * XXX hmm... it's too complex
5144 */
5145 /* shortcut for table form */
5146 #define P AUMODE_PLAY
5147 #define A AUMODE_PLAY_ALL
5148 #define R AUMODE_RECORD
5149 struct setinfo_mode_t {
5150 int setmode; /* mode used in SETINFO */
5151 int expmode7; /* expected mode on NetBSD7 */
5152 int expmode9; /* expected mode on NetBSD9 */
5153 };
5154 /*
5155 * The following tables show this operation on NetBSD7 is almost 'undefined'.
5156 * In contrast, NetBSD9 never changes mode by AUDIO_SETINFO except
5157 * AUMODE_PLAY_ALL.
5158 *
5159 * setmode == 0 and 8 are out of range and invalid input samples.
5160 * But NetBSD7 seems to accept it as is.
5161 */
5162 struct setinfo_mode_t table_SETINFO_mode_O_RDONLY[] = {
5163 /* setmode expmode7 expmode9 */
5164 { 0, 0, R },
5165 { P, P, R },
5166 { A , A|P, R },
5167 { A|P, A|P, R },
5168 { R , R , R },
5169 { R| P, P, R },
5170 { R|A , A|P, R },
5171 { R|A|P, A|P, R },
5172 { 8, 8, R },
5173 };
5174 struct setinfo_mode_t table_SETINFO_mode_O_WRONLY[] = {
5175 /* setmode expmode7 expmode9 */
5176 { 0, 0, P },
5177 { P, P, P },
5178 { A , A|P, A|P },
5179 { A|P, A|P, A|P },
5180 { R , R , P },
5181 { R| P, P, P },
5182 { R|A , A|P, A|P },
5183 { R|A|P, A|P, A|P },
5184 { 8, 8, P },
5185 };
5186 #define f(openmode, index) do { \
5187 struct setinfo_mode_t *table = table_SETINFO_mode_##openmode; \
5188 int setmode = table[index].setmode; \
5189 int expected = (netbsd < 9) \
5190 ? table[index].expmode7 \
5191 : table[index].expmode9; \
5192 test_AUDIO_SETINFO_mode(openmode, index, setmode, expected); \
5193 } while (0)
5194 DEF(AUDIO_SETINFO_mode_RDONLY_0) { f(O_RDONLY, 0); }
5195 DEF(AUDIO_SETINFO_mode_RDONLY_1) { f(O_RDONLY, 1); }
5196 DEF(AUDIO_SETINFO_mode_RDONLY_2) { f(O_RDONLY, 2); }
5197 DEF(AUDIO_SETINFO_mode_RDONLY_3) { f(O_RDONLY, 3); }
5198 DEF(AUDIO_SETINFO_mode_RDONLY_4) { f(O_RDONLY, 4); }
5199 DEF(AUDIO_SETINFO_mode_RDONLY_5) { f(O_RDONLY, 5); }
5200 DEF(AUDIO_SETINFO_mode_RDONLY_6) { f(O_RDONLY, 6); }
5201 DEF(AUDIO_SETINFO_mode_RDONLY_7) { f(O_RDONLY, 7); }
5202 DEF(AUDIO_SETINFO_mode_RDONLY_8) { f(O_RDONLY, 8); }
5203 DEF(AUDIO_SETINFO_mode_WRONLY_0) { f(O_WRONLY, 0); }
5204 DEF(AUDIO_SETINFO_mode_WRONLY_1) { f(O_WRONLY, 1); }
5205 DEF(AUDIO_SETINFO_mode_WRONLY_2) { f(O_WRONLY, 2); }
5206 DEF(AUDIO_SETINFO_mode_WRONLY_3) { f(O_WRONLY, 3); }
5207 DEF(AUDIO_SETINFO_mode_WRONLY_4) { f(O_WRONLY, 4); }
5208 DEF(AUDIO_SETINFO_mode_WRONLY_5) { f(O_WRONLY, 5); }
5209 DEF(AUDIO_SETINFO_mode_WRONLY_6) { f(O_WRONLY, 6); }
5210 DEF(AUDIO_SETINFO_mode_WRONLY_7) { f(O_WRONLY, 7); }
5211 DEF(AUDIO_SETINFO_mode_WRONLY_8) { f(O_WRONLY, 8); }
5212 #undef f
5213 /*
5214 * The following tables also show that NetBSD7's behavior is almost
5215 * 'undefined'.
5216 */
5217 struct setinfo_mode_t table_SETINFO_mode_O_RDWR_full[] = {
5218 /* setmode expmode7 expmode9 */
5219 { 0, 0, R| P },
5220 { P, P, R| P },
5221 { A , A|P, R|A|P },
5222 { A|P, A|P, R|A|P },
5223 { R , R , R| P },
5224 { R| P, R| P, R| P },
5225 { R|A , R|A|P, R|A|P },
5226 { R|A|P, R|A|P, R|A|P },
5227 { 8, 8, R| P },
5228 };
5229 struct setinfo_mode_t table_SETINFO_mode_O_RDWR_half[] = {
5230 /* setmode expmode7 expmode9 */
5231 { 0, 0, P },
5232 { P, P, P },
5233 { A , A|P, A|P },
5234 { A|P, A|P, A|P },
5235 { R , R , P },
5236 { R| P, P, P },
5237 { R|A , A|P, A|P },
5238 { R|A|P, A|P, A|P },
5239 { 8, 8, P },
5240 };
5241 #define f(index) do { \
5242 struct setinfo_mode_t *table = (hw_fulldup()) \
5243 ? table_SETINFO_mode_O_RDWR_full \
5244 : table_SETINFO_mode_O_RDWR_half; \
5245 int setmode = table[index].setmode; \
5246 int expected = (netbsd < 9) \
5247 ? table[index].expmode7 \
5248 : table[index].expmode9; \
5249 test_AUDIO_SETINFO_mode(O_RDWR, index, setmode, expected); \
5250 } while (0)
5251 DEF(AUDIO_SETINFO_mode_RDWR_0) { f(0); }
5252 DEF(AUDIO_SETINFO_mode_RDWR_1) { f(1); }
5253 DEF(AUDIO_SETINFO_mode_RDWR_2) { f(2); }
5254 DEF(AUDIO_SETINFO_mode_RDWR_3) { f(3); }
5255 DEF(AUDIO_SETINFO_mode_RDWR_4) { f(4); }
5256 DEF(AUDIO_SETINFO_mode_RDWR_5) { f(5); }
5257 DEF(AUDIO_SETINFO_mode_RDWR_6) { f(6); }
5258 DEF(AUDIO_SETINFO_mode_RDWR_7) { f(7); }
5259 DEF(AUDIO_SETINFO_mode_RDWR_8) { f(8); }
5260 #undef f
5261 #undef P
5262 #undef A
5263 #undef R
5264
5265 /*
5266 * Check whether encoding params can be set.
5267 */
5268 void
5269 test_AUDIO_SETINFO_params_set(int openmode, int aimode, int pause)
5270 {
5271 struct audio_info ai;
5272 int r;
5273 int fd;
5274
5275 /*
5276 * aimode is bool value that indicates whether to change ai.mode.
5277 * pause is bool value that indicates whether to change ai.*.pause.
5278 */
5279
5280 TEST("AUDIO_SETINFO_params_%s_%d_%d",
5281 openmode_str[openmode] + 2, aimode, pause);
5282 if (mode2aumode(openmode) == 0) {
5283 XP_SKIP("Operation not allowed on this hardware property");
5284 return;
5285 }
5286
5287 /* On half-duplex, O_RDWR is the same as O_WRONLY, so skip it */
5288 if (!hw_fulldup() && openmode == O_RDWR) {
5289 XP_SKIP("This is the same with O_WRONLY on half-duplex");
5290 return;
5291 }
5292
5293 fd = OPEN(devaudio, openmode);
5294 REQUIRED_SYS_OK(fd);
5295
5296 AUDIO_INITINFO(&ai);
5297 /*
5298 * It takes time and effort to check all parameters independently,
5299 * so that use sample_rate as a representative.
5300 */
5301 ai.play.sample_rate = 11025;
5302 ai.record.sample_rate = 11025;
5303 if (aimode)
5304 ai.mode = mode2aumode(openmode) & ~AUMODE_PLAY_ALL;
5305 if (pause) {
5306 ai.play.pause = 1;
5307 ai.record.pause = 1;
5308 }
5309
5310 r = IOCTL(fd, AUDIO_SETINFO, &ai, "");
5311 XP_SYS_EQ(0, r);
5312
5313 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
5314 XP_SYS_EQ(0, r);
5315 int expmode = (aimode)
5316 ? (mode2aumode(openmode) & ~AUMODE_PLAY_ALL)
5317 : mode2aumode(openmode);
5318 XP_EQ(expmode, ai.mode);
5319
5320 if (openmode == O_RDONLY) {
5321 /* Playback track doesn't exist */
5322 if (netbsd < 9)
5323 XP_EQ(pause, ai.play.pause);
5324 else
5325 XP_EQ(0, ai.play.pause);
5326 } else {
5327 /* Playback track exists */
5328 XP_EQ(11025, ai.play.sample_rate);
5329 XP_EQ(pause, ai.play.pause);
5330 }
5331
5332 if (openmode == O_WRONLY) {
5333 /* Recording track doesn't exist */
5334 if (netbsd < 9)
5335 XP_EQ(pause, ai.record.pause);
5336 else
5337 XP_EQ(0, ai.record.pause);
5338 } else {
5339 /* Recording track exists */
5340 XP_EQ(11025, ai.record.sample_rate);
5341 XP_EQ(pause, ai.record.pause);
5342 }
5343
5344 r = CLOSE(fd);
5345 XP_SYS_EQ(0, r);
5346 }
5347 #define f(a,b,c) test_AUDIO_SETINFO_params_set(a, b, c)
5348 DEF(AUDIO_SETINFO_params_set_RDONLY_0) { f(O_RDONLY, 0, 0); }
5349 DEF(AUDIO_SETINFO_params_set_RDONLY_1) { f(O_RDONLY, 0, 1); }
5350 /* On RDONLY, ai.mode is not changable
5351 * AUDIO_SETINFO_params_set_RDONLY_2) { f(O_RDONLY, 1, 0); }
5352 * AUDIO_SETINFO_params_set_RDONLY_3) { f(O_RDONLY, 1, 1); }
5353 */
5354 DEF(AUDIO_SETINFO_params_set_WRONLY_0) { f(O_WRONLY, 0, 0); }
5355 DEF(AUDIO_SETINFO_params_set_WRONLY_1) { f(O_WRONLY, 0, 1); }
5356 DEF(AUDIO_SETINFO_params_set_WRONLY_2) { f(O_WRONLY, 1, 0); }
5357 DEF(AUDIO_SETINFO_params_set_WRONLY_3) { f(O_WRONLY, 1, 1); }
5358 DEF(AUDIO_SETINFO_params_set_RDWR_0) { f(O_RDWR, 0, 0); }
5359 DEF(AUDIO_SETINFO_params_set_RDWR_1) { f(O_RDWR, 0, 1); }
5360 DEF(AUDIO_SETINFO_params_set_RDWR_2) { f(O_RDWR, 1, 0); }
5361 DEF(AUDIO_SETINFO_params_set_RDWR_3) { f(O_RDWR, 1, 1); }
5362 #undef f
5363
5364 /*
5365 * AUDIO_SETINFO should not be interfere by other descriptor.
5366 */
5367 DEF(AUDIO_SETINFO_params_simul)
5368 {
5369 struct audio_info ai;
5370 int fd0;
5371 int fd1;
5372 int r;
5373
5374 TEST("AUDIO_SETINFO_params_simul");
5375 if (netbsd < 8) {
5376 XP_SKIP("Multiple open is not supported");
5377 return;
5378 }
5379
5380 /* Open the 1st one as playback only */
5381 fd0 = OPEN(devaudio, O_WRONLY);
5382 REQUIRED_SYS_OK(fd0);
5383
5384 /* Open the 2nd one as both of playback and recording */
5385 fd1 = OPEN(devaudio, O_RDWR);
5386 REQUIRED_SYS_OK(fd1);
5387
5388 /* Change some parameters of both track on the 2nd one */
5389 AUDIO_INITINFO(&ai);
5390 ai.play.sample_rate = 11025;
5391 ai.record.sample_rate = 11025;
5392 r = IOCTL(fd1, AUDIO_SETINFO, &ai, "");
5393 XP_SYS_EQ(0, r);
5394
5395 /* Both track of the 1st one should not be affected */
5396 memset(&ai, 0, sizeof(ai));
5397 r = IOCTL(fd0, AUDIO_GETINFO, &ai, "");
5398 XP_SYS_EQ(0, r);
5399 XP_EQ(8000, ai.play.sample_rate);
5400 XP_EQ(8000, ai.record.sample_rate);
5401
5402 r = CLOSE(fd0);
5403 XP_SYS_EQ(0, r);
5404 r = CLOSE(fd1);
5405 XP_SYS_EQ(0, r);
5406 }
5407
5408 /*
5409 * Check whether the pause/unpause works.
5410 */
5411 void
5412 test_AUDIO_SETINFO_pause(int openmode, int aimode, int param)
5413 {
5414 struct audio_info ai;
5415 int r;
5416 int fd;
5417
5418 /*
5419 * aimode is bool value that indicates whether to change ai.mode.
5420 * param is bool value that indicates whether to change encoding
5421 * parameters of ai.{play,record}.*.
5422 */
5423
5424 TEST("AUDIO_SETINFO_pause_%s_%d_%d",
5425 openmode_str[openmode] + 2, aimode, param);
5426 if (mode2aumode(openmode) == 0) {
5427 XP_SKIP("Operation not allowed on this hardware property");
5428 return;
5429 }
5430
5431 /* On half-duplex, O_RDWR is the same as O_WRONLY, so skip it */
5432 if (!hw_fulldup() && openmode == O_RDWR) {
5433 XP_SKIP("This is the same with O_WRONLY on half-duplex");
5434 return;
5435 }
5436
5437 fd = OPEN(devaudio, openmode);
5438 REQUIRED_SYS_OK(fd);
5439
5440 /* Set pause */
5441 AUDIO_INITINFO(&ai);
5442 ai.play.pause = 1;
5443 ai.record.pause = 1;
5444 if (aimode)
5445 ai.mode = mode2aumode(openmode) & ~AUMODE_PLAY_ALL;
5446 if (param) {
5447 ai.play.sample_rate = 11025;
5448 ai.record.sample_rate = 11025;
5449 }
5450
5451 r = IOCTL(fd, AUDIO_SETINFO, &ai, "");
5452 XP_SYS_EQ(0, r);
5453
5454 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
5455 XP_SYS_EQ(0, r);
5456 int expmode = (aimode)
5457 ? (mode2aumode(openmode) & ~AUMODE_PLAY_ALL)
5458 : mode2aumode(openmode);
5459 XP_EQ(expmode, ai.mode);
5460 if (openmode == O_RDONLY) {
5461 /* Playback track doesn't exists */
5462 if (netbsd < 9)
5463 XP_EQ(1, ai.play.pause);
5464 else
5465 XP_EQ(0, ai.play.pause);
5466 } else {
5467 /* Playback track exists */
5468 XP_EQ(1, ai.play.pause);
5469 XP_EQ(param ? 11025 : 8000, ai.play.sample_rate);
5470 }
5471 if (openmode == O_WRONLY) {
5472 /* Recording track doesn't exist */
5473 if (netbsd < 9)
5474 XP_EQ(1, ai.record.pause);
5475 else
5476 XP_EQ(0, ai.record.pause);
5477 } else {
5478 /* Recording track exists */
5479 XP_EQ(1, ai.record.pause);
5480 XP_EQ(param ? 11025 : 8000, ai.record.sample_rate);
5481 }
5482
5483 /* Set unpause (?) */
5484 AUDIO_INITINFO(&ai);
5485 ai.play.pause = 0;
5486 ai.record.pause = 0;
5487 if (aimode)
5488 ai.mode = mode2aumode(openmode);
5489 if (param) {
5490 ai.play.sample_rate = 16000;
5491 ai.record.sample_rate = 16000;
5492 }
5493
5494 r = IOCTL(fd, AUDIO_SETINFO, &ai, "");
5495 XP_SYS_EQ(0, r);
5496
5497 r = IOCTL(fd, AUDIO_GETBUFINFO, &ai, "");
5498 XP_SYS_EQ(0, r);
5499 XP_EQ(mode2aumode(openmode), ai.mode);
5500 XP_EQ(0, ai.play.pause);
5501 XP_EQ(0, ai.record.pause);
5502 if (openmode != O_RDONLY)
5503 XP_EQ(param ? 16000 : 8000, ai.play.sample_rate);
5504 if (openmode != O_WRONLY)
5505 XP_EQ(param ? 16000 : 8000, ai.record.sample_rate);
5506
5507 r = CLOSE(fd);
5508 XP_SYS_EQ(0, r);
5509 }
5510 DEF(AUDIO_SETINFO_pause_RDONLY_0) { test_AUDIO_SETINFO_pause(O_RDONLY, 0, 0); }
5511 DEF(AUDIO_SETINFO_pause_RDONLY_1) { test_AUDIO_SETINFO_pause(O_RDONLY, 0, 1); }
5512 /* On RDONLY, ai.mode is not changable
5513 * AUDIO_SETINFO_pause_RDONLY_2) { test_AUDIO_SETINFO_pause(O_RDONLY, 1, 0); }
5514 * AUDIO_SETINFO_pause_RDONLY_3) { test_AUDIO_SETINFO_pause(O_RDONLY, 1, 1); }
5515 */
5516 DEF(AUDIO_SETINFO_pause_WRONLY_0) { test_AUDIO_SETINFO_pause(O_WRONLY, 0, 0); }
5517 DEF(AUDIO_SETINFO_pause_WRONLY_1) { test_AUDIO_SETINFO_pause(O_WRONLY, 0, 1); }
5518 DEF(AUDIO_SETINFO_pause_WRONLY_2) { test_AUDIO_SETINFO_pause(O_WRONLY, 1, 0); }
5519 DEF(AUDIO_SETINFO_pause_WRONLY_3) { test_AUDIO_SETINFO_pause(O_WRONLY, 1, 1); }
5520 DEF(AUDIO_SETINFO_pause_RDWR_0) { test_AUDIO_SETINFO_pause(O_RDWR, 0, 0); }
5521 DEF(AUDIO_SETINFO_pause_RDWR_1) { test_AUDIO_SETINFO_pause(O_RDWR, 0, 1); }
5522 DEF(AUDIO_SETINFO_pause_RDWR_2) { test_AUDIO_SETINFO_pause(O_RDWR, 1, 0); }
5523 DEF(AUDIO_SETINFO_pause_RDWR_3) { test_AUDIO_SETINFO_pause(O_RDWR, 1, 1); }
5524
5525 /*
5526 * Check whether gain can be obtained/set.
5527 * And the gain should work with rich mixer.
5528 * PR kern/52781
5529 */
5530 DEF(AUDIO_SETINFO_gain)
5531 {
5532 struct audio_info ai;
5533 mixer_ctrl_t m;
5534 int index;
5535 int master;
5536 int master_backup;
5537 int gain;
5538 int fd;
5539 int mixerfd;
5540 int r;
5541
5542 TEST("AUDIO_SETINFO_gain");
5543
5544 /* Open /dev/mixer */
5545 mixerfd = OPEN(devmixer, O_RDWR);
5546 REQUIRED_SYS_OK(mixerfd);
5547 index = mixer_get_outputs_master(mixerfd);
5548 if (index == -1) {
5549 XP_SKIP("Hardware has no outputs.master");
5550 CLOSE(mixerfd);
5551 return;
5552 }
5553
5554 /*
5555 * Get current outputs.master.
5556 * auich(4) requires class type (m.type) and number of channels
5557 * (un.value.num_channels) in addition to the index (m.dev)...
5558 * What is the index...?
5559 */
5560 memset(&m, 0, sizeof(m));
5561 m.dev = index;
5562 m.type = AUDIO_MIXER_VALUE;
5563 m.un.value.num_channels = 1; /* dummy */
5564 r = IOCTL(mixerfd, AUDIO_MIXER_READ, &m, "m.dev=%d", m.dev);
5565 REQUIRED_SYS_EQ(0, r);
5566 master = m.un.value.level[0];
5567 DPRINTF(" > outputs.master = %d\n", master);
5568 master_backup = master;
5569
5570 /* Open /dev/audio */
5571 fd = OPEN(devaudio, O_WRONLY);
5572 REQUIRED_SYS_OK(fd);
5573
5574 /* Check ai.play.gain */
5575 r = IOCTL(fd, AUDIO_GETINFO, &ai, "");
5576 XP_SYS_EQ(0, r);
5577 XP_EQ(master, ai.play.gain);
5578
5579 /* Change it some different value */
5580 AUDIO_INITINFO(&ai);
5581 if (master == 0)
5582 gain = 255;
5583 else
5584 gain = 0;
5585 ai.play.gain = gain;
5586 r = IOCTL(fd, AUDIO_SETINFO, &ai, "play.gain=%d", ai.play.gain);
5587 XP_SYS_EQ(0, r);
5588
5589 /* Check gain has changed */
5590 r = IOCTL(fd, AUDIO_GETINFO, &ai, "play.gain");
5591 XP_SYS_EQ(0, r);
5592 XP_NE(master, ai.play.gain);
5593
5594 /* Check whether outputs.master work with gain */
5595 r = IOCTL(mixerfd, AUDIO_MIXER_READ, &m, "");
5596 XP_SYS_EQ(0, r);
5597 XP_EQ(ai.play.gain, m.un.value.level[0]);
5598
5599 /* Restore outputs.master */
5600 AUDIO_INITINFO(&ai);
5601 ai.play.gain = master_backup;
5602 r = IOCTL(fd, AUDIO_SETINFO, &ai, "play.gain=%d", ai.play.gain);
5603 XP_SYS_EQ(0, r);
5604
5605 r = CLOSE(fd);
5606 XP_SYS_EQ(0, r);
5607 r = CLOSE(mixerfd);
5608 XP_SYS_EQ(0, r);
5609 }
5610
5611 #define NENC (AUDIO_ENCODING_AC3 + 1)
5612 #define NPREC (5)
5613 /*
5614 * Make table of encoding+precision supported by this device.
5615 * Return last used index .
5616 * This function is called from test_AUDIO_GETENC_*()
5617 */
5618 int
5619 getenc_make_table(int fd, int expected[][5])
5620 {
5621 audio_encoding_t ae;
5622 int idx;
5623 int p;
5624 int r;
5625
5626 /*
5627 * expected[][] is two dimensional table.
5628 * encoding \ precision| 4 8 16 24 32
5629 * --------------------+-----------------
5630 * AUDIO_ENCODING_NONE |
5631 * AUDIO_ENCODING_ULAW |
5632 * :
5633 *
5634 * Each cell has expected behavior.
5635 * 0: the hardware doesn't support this encoding/precision.
5636 * 1: the hardware supports this encoding/precision.
5637 * 2: the hardware doesn't support this encoding/precision but
5638 * audio layer will respond as supported for compatibility.
5639 */
5640 for (idx = 0; ; idx++) {
5641 memset(&ae, 0, sizeof(ae));
5642 ae.index = idx;
5643 r = IOCTL(fd, AUDIO_GETENC, &ae, "index=%d", idx);
5644 if (r != 0) {
5645 XP_SYS_NG(EINVAL, r);
5646 break;
5647 }
5648
5649 XP_EQ(idx, ae.index);
5650 if (0 <= ae.encoding && ae.encoding <= AUDIO_ENCODING_AC3) {
5651 XP_EQ_STR(encoding_names[ae.encoding], ae.name);
5652 } else {
5653 XP_FAIL("ae.encoding %d", ae.encoding);
5654 }
5655
5656 if (ae.precision != 4 &&
5657 ae.precision != 8 &&
5658 ae.precision != 16 &&
5659 ae.precision != 24 &&
5660 ae.precision != 32)
5661 {
5662 XP_FAIL("ae.precision %d", ae.precision);
5663 }
5664 /* Other bits should not be set */
5665 XP_EQ(0, (ae.flags & ~AUDIO_ENCODINGFLAG_EMULATED));
5666
5667 expected[ae.encoding][ae.precision / 8] = 1;
5668 DPRINTF(" > encoding=%s precision=%d\n",
5669 encoding_names[ae.encoding], ae.precision);
5670 }
5671
5672 /*
5673 * Backward compatibility bandaid.
5674 *
5675 * - Some encoding/precision pairs are obviously inconsistent
5676 * (e.g., encoding=AUDIO_ENCODING_PCM8, precision=16) but
5677 * it's due to historical reasons.
5678 * - It's incomplete for NetBSD7 and NetBSD8. I don't really
5679 * understand thier rule... This is just memo, not specification.
5680 */
5681 #define SET(x) do { \
5682 if ((x) == 0) \
5683 x = 2; \
5684 } while (0)
5685 #define p4 (0)
5686 #define p8 (1)
5687 #define p16 (2)
5688 #define p24 (3)
5689 #define p32 (4)
5690
5691 if (expected[AUDIO_ENCODING_SLINEAR][p8]) {
5692 SET(expected[AUDIO_ENCODING_SLINEAR_LE][p8]);
5693 SET(expected[AUDIO_ENCODING_SLINEAR_BE][p8]);
5694 }
5695 if (expected[AUDIO_ENCODING_ULINEAR][p8]) {
5696 SET(expected[AUDIO_ENCODING_ULINEAR_LE][p8]);
5697 SET(expected[AUDIO_ENCODING_ULINEAR_BE][p8]);
5698 SET(expected[AUDIO_ENCODING_PCM8][p8]);
5699 SET(expected[AUDIO_ENCODING_PCM16][p8]);
5700 }
5701 for (p = p16; p <= p32; p++) {
5702 #if !defined(AUDIO_SUPPORT_LINEAR24)
5703 if (p == p24)
5704 continue;
5705 #endif
5706 if (expected[AUDIO_ENCODING_SLINEAR_NE][p]) {
5707 SET(expected[AUDIO_ENCODING_SLINEAR][p]);
5708 SET(expected[AUDIO_ENCODING_PCM16][p]);
5709 }
5710 if (expected[AUDIO_ENCODING_ULINEAR_NE][p]) {
5711 SET(expected[AUDIO_ENCODING_ULINEAR][p]);
5712 }
5713 }
5714
5715 if (netbsd < 9) {
5716 if (expected[AUDIO_ENCODING_SLINEAR_LE][p16] ||
5717 expected[AUDIO_ENCODING_SLINEAR_BE][p16] ||
5718 expected[AUDIO_ENCODING_ULINEAR_LE][p16] ||
5719 expected[AUDIO_ENCODING_ULINEAR_BE][p16])
5720 {
5721 SET(expected[AUDIO_ENCODING_PCM8][p8]);
5722 SET(expected[AUDIO_ENCODING_PCM16][p8]);
5723 SET(expected[AUDIO_ENCODING_SLINEAR_LE][p8]);
5724 SET(expected[AUDIO_ENCODING_SLINEAR_BE][p8]);
5725 SET(expected[AUDIO_ENCODING_ULINEAR_LE][p8]);
5726 SET(expected[AUDIO_ENCODING_ULINEAR_BE][p8]);
5727 SET(expected[AUDIO_ENCODING_SLINEAR][p8]);
5728 SET(expected[AUDIO_ENCODING_ULINEAR][p8]);
5729 }
5730 }
5731
5732 /* Return last used index */
5733 return idx;
5734 #undef SET
5735 #undef p4
5736 #undef p8
5737 #undef p16
5738 #undef p24
5739 #undef p32
5740 }
5741
5742 /*
5743 * This function is called from test_AUDIO_GETENC below.
5744 */
5745 void
5746 xp_getenc(int expected[][5], int enc, int j, int r, struct audio_prinfo *pr)
5747 {
5748 int prec = (j == 0) ? 4 : j * 8;
5749
5750 if (expected[enc][j]) {
5751 /* expect to succeed */
5752 XP_SYS_EQ(0, r);
5753
5754 XP_EQ(enc, pr->encoding);
5755 XP_EQ(prec, pr->precision);
5756 } else {
5757 /* expect to fail */
5758 XP_SYS_NG(EINVAL, r);
5759 }
5760 }
5761
5762 /*
5763 * This function is called from test_AUDIO_GETENC below.
5764 */
5765 void
5766 getenc_check_encodings(int openmode, int expected[][5])
5767 {
5768 struct audio_info ai;
5769 int fd;
5770 int i, j;
5771 int r;
5772
5773 fd = OPEN(devaudio, openmode);
5774 REQUIRED_SYS_OK(fd);
5775
5776 for (i = 0; i < NENC; i++) {
5777 for (j = 0; j < NPREC; j++) {
5778 /* precisions are 4 and 8, 16, 24, 32 */
5779 int prec = (j == 0) ? 4 : j * 8;
5780
5781 /*
5782 * AUDIO_GETENC has no way to know range of
5783 * supported channels and sample_rate.
5784 */
5785 AUDIO_INITINFO(&ai);
5786 ai.play.encoding = i;
5787 ai.play.precision = prec;
5788 ai.record.encoding = i;
5789 ai.record.precision = prec;
5790
5791 r = IOCTL(fd, AUDIO_SETINFO, &ai, "%s:%d",
5792 encoding_names[i], prec);
5793 if (mode2play(openmode))
5794 xp_getenc(expected, i, j, r, &ai.play);
5795 if (mode2rec(openmode))
5796 xp_getenc(expected, i, j, r, &ai.record);
5797 }
5798 }
5799 r = CLOSE(fd);
5800 XP_SYS_EQ(0, r);
5801 }
5802
5803 /*
5804 * Check whether encoding+precision obtained by AUDIO_GETENC can be set.
5805 */
5806 DEF(AUDIO_GETENC_range)
5807 {
5808 audio_encoding_t ae;
5809 int fd;
5810 int r;
5811 int expected[NENC][NPREC];
5812 int i, j;
5813
5814 TEST("AUDIO_GETENC_range");
5815
5816 fd = OPEN(devaudio, openable_mode());
5817 REQUIRED_SYS_OK(fd);
5818
5819 memset(&expected, 0, sizeof(expected));
5820 i = getenc_make_table(fd, expected);
5821
5822 /* When error has occured, the next index should also occur error */
5823 ae.index = i + 1;
5824 r = IOCTL(fd, AUDIO_GETENC, &ae, "index=%d", ae.index);
5825 XP_SYS_NG(EINVAL, r);
5826
5827 r = CLOSE(fd);
5828 XP_SYS_EQ(0, r);
5829
5830 /* For debug */
5831 if (debug) {
5832 for (i = 0; i < NENC; i++) {
5833 printf("expected[%2d] %15s", i, encoding_names[i]);
5834 for (j = 0; j < NPREC; j++) {
5835 printf(" %d", expected[i][j]);
5836 }
5837 printf("\n");
5838 }
5839 }
5840
5841 /* Whether obtained encodings can be actually set */
5842 if (hw_fulldup()) {
5843 /* Test both R/W at once using single descriptor */
5844 getenc_check_encodings(O_RDWR, expected);
5845 } else {
5846 /* Test playback and recording if available */
5847 if (hw_canplay()) {
5848 getenc_check_encodings(O_WRONLY, expected);
5849 }
5850 if (hw_canplay() && hw_canrec()) {
5851 xxx_close_wait();
5852 }
5853 if (hw_canrec()) {
5854 getenc_check_encodings(O_RDONLY, expected);
5855 }
5856 }
5857 }
5858 #undef NENC
5859 #undef NPREC
5860
5861 /*
5862 * Check AUDIO_GETENC out of range.
5863 */
5864 DEF(AUDIO_GETENC_error)
5865 {
5866 audio_encoding_t e;
5867 int fd;
5868 int r;
5869
5870 TEST("AUDIO_GETENC_error");
5871
5872 fd = OPEN(devaudio, openable_mode());
5873 REQUIRED_SYS_OK(fd);
5874
5875 memset(&e, 0, sizeof(e));
5876 e.index = -1;
5877 r = IOCTL(fd, AUDIO_GETENC, &e, "index=-1");
5878 /* NetBSD7 may not fail depending on hardware driver */
5879 XP_SYS_NG(EINVAL, r);
5880
5881 r = CLOSE(fd);
5882 XP_SYS_EQ(0, r);
5883 }
5884
5885 /*
5886 * AUDIO_[PR]ERROR should be zero on the initial state even on non-existent
5887 * track.
5888 */
5889 void
5890 test_AUDIO_ERROR(int openmode)
5891 {
5892 int fd;
5893 int r;
5894 int errors;
5895
5896 TEST("AUDIO_ERROR_%s", openmode_str[openmode] + 2);
5897 if (mode2aumode(openmode) == 0) {
5898 XP_SKIP("Operation not allowed on this hardware property");
5899 return;
5900 }
5901
5902 fd = OPEN(devaudio, openmode);
5903 REQUIRED_SYS_OK(fd);
5904
5905 /* Check PERROR */
5906 errors = 0xdeadbeef;
5907 r = IOCTL(fd, AUDIO_PERROR, &errors, "");
5908 XP_SYS_EQ(0, r);
5909 XP_EQ(0, errors);
5910
5911 /* Check RERROR */
5912 errors = 0xdeadbeef;
5913 r = IOCTL(fd, AUDIO_RERROR, &errors, "");
5914 XP_SYS_EQ(0, r);
5915 XP_EQ(0, errors);
5916
5917 r = CLOSE(fd);
5918 XP_SYS_EQ(0, r);
5919 }
5920 DEF(AUDIO_ERROR_RDONLY) { test_AUDIO_ERROR(O_RDONLY); }
5921 DEF(AUDIO_ERROR_WRONLY) { test_AUDIO_ERROR(O_WRONLY); }
5922 DEF(AUDIO_ERROR_RDWR) { test_AUDIO_ERROR(O_RDWR); }
5923
5924 /*
5925 * /dev/audioctl can always be opened while /dev/audio is open.
5926 */
5927 void
5928 test_audioctl_open_1(int fmode, int cmode)
5929 {
5930 int fd;
5931 int ctl;
5932 int r;
5933
5934 TEST("audioctl_open_1_%s_%s",
5935 openmode_str[fmode] + 2, openmode_str[cmode] + 2);
5936 if (hw_canplay() == 0 && fmode == O_WRONLY) {
5937 XP_SKIP("This test is for playable device");
5938 return;
5939 }
5940 if (hw_canrec() == 0 && fmode == O_RDONLY) {
5941 XP_SKIP("This test is for recordable device");
5942 return;
5943 }
5944
5945 fd = OPEN(devaudio, fmode);
5946 REQUIRED_SYS_OK(fd);
5947
5948 ctl = OPEN(devaudioctl, cmode);
5949 XP_SYS_OK(ctl);
5950
5951 r = CLOSE(ctl);
5952 XP_SYS_EQ(0, r);
5953
5954 r = CLOSE(fd);
5955 XP_SYS_EQ(0, r);
5956 }
5957 DEF(audioctl_open_1_RDONLY_RDONLY) { test_audioctl_open_1(O_RDONLY, O_RDONLY); }
5958 DEF(audioctl_open_1_RDONLY_RWONLY) { test_audioctl_open_1(O_RDONLY, O_WRONLY); }
5959 DEF(audioctl_open_1_RDONLY_RDWR) { test_audioctl_open_1(O_RDONLY, O_RDWR); }
5960 DEF(audioctl_open_1_WRONLY_RDONLY) { test_audioctl_open_1(O_WRONLY, O_RDONLY); }
5961 DEF(audioctl_open_1_WRONLY_RWONLY) { test_audioctl_open_1(O_WRONLY, O_WRONLY); }
5962 DEF(audioctl_open_1_WRONLY_RDWR) { test_audioctl_open_1(O_WRONLY, O_RDWR); }
5963 DEF(audioctl_open_1_RDWR_RDONLY) { test_audioctl_open_1(O_RDWR, O_RDONLY); }
5964 DEF(audioctl_open_1_RDWR_RWONLY) { test_audioctl_open_1(O_RDWR, O_WRONLY); }
5965 DEF(audioctl_open_1_RDWR_RDWR) { test_audioctl_open_1(O_RDWR, O_RDWR); }
5966
5967 /*
5968 * /dev/audio can always be opened while /dev/audioctl is open.
5969 */
5970 void
5971 test_audioctl_open_2(int fmode, int cmode)
5972 {
5973 int fd;
5974 int ctl;
5975 int r;
5976
5977 TEST("audioctl_open_2_%s_%s",
5978 openmode_str[fmode] + 2, openmode_str[cmode] + 2);
5979 if (hw_canplay() == 0 && fmode == O_WRONLY) {
5980 XP_SKIP("This test is for playable device");
5981 return;
5982 }
5983 if (hw_canrec() == 0 && fmode == O_RDONLY) {
5984 XP_SKIP("This test is for recordable device");
5985 return;
5986 }
5987
5988 ctl = OPEN(devaudioctl, cmode);
5989 REQUIRED_SYS_OK(ctl);
5990
5991 fd = OPEN(devaudio, fmode);
5992 XP_SYS_OK(fd);
5993
5994 r = CLOSE(fd);
5995 XP_SYS_EQ(0, r);
5996
5997 r = CLOSE(ctl);
5998 XP_SYS_EQ(0, r);
5999 }
6000 DEF(audioctl_open_2_RDONLY_RDONLY) { test_audioctl_open_2(O_RDONLY, O_RDONLY); }
6001 DEF(audioctl_open_2_RDONLY_RWONLY) { test_audioctl_open_2(O_RDONLY, O_WRONLY); }
6002 DEF(audioctl_open_2_RDONLY_RDWR) { test_audioctl_open_2(O_RDONLY, O_RDWR); }
6003 DEF(audioctl_open_2_WRONLY_RDONLY) { test_audioctl_open_2(O_WRONLY, O_RDONLY); }
6004 DEF(audioctl_open_2_WRONLY_RWONLY) { test_audioctl_open_2(O_WRONLY, O_WRONLY); }
6005 DEF(audioctl_open_2_WRONLY_RDWR) { test_audioctl_open_2(O_WRONLY, O_RDWR); }
6006 DEF(audioctl_open_2_RDWR_RDONLY) { test_audioctl_open_2(O_RDWR, O_RDONLY); }
6007 DEF(audioctl_open_2_RDWR_RWONLY) { test_audioctl_open_2(O_RDWR, O_WRONLY); }
6008 DEF(audioctl_open_2_RDWR_RDWR) { test_audioctl_open_2(O_RDWR, O_RDWR); }
6009
6010 /*
6011 * Open multiple /dev/audioctl.
6012 */
6013 DEF(audioctl_open_simul)
6014 {
6015 int ctl0;
6016 int ctl1;
6017 int r;
6018
6019 TEST("audioctl_open_simul");
6020
6021 ctl0 = OPEN(devaudioctl, O_RDWR);
6022 REQUIRED_SYS_OK(ctl0);
6023
6024 ctl1 = OPEN(devaudioctl, O_RDWR);
6025 XP_SYS_OK(ctl1);
6026
6027 r = CLOSE(ctl0);
6028 XP_SYS_EQ(0, r);
6029
6030 r = CLOSE(ctl1);
6031 XP_SYS_EQ(0, r);
6032 }
6033
6034 /*
6035 * /dev/audioctl can be opened by other user who opens /dev/audioctl.
6036 * /dev/audioctl can be opened by other user who opens /dev/audio.
6037 * /dev/audio can be opened by other user who opens /dev/audioct.
6038 */
6039 void
6040 try_audioctl_open_multiuser(int 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(int multiuser, const char *dev1, const char *dev2)
6078 {
6079 char mibname[32];
6080 bool newval;
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 newval = multiuser;
6109 r = SYSCTLBYNAME(mibname, NULL, NULL, &newval, sizeof(newval));
6110 REQUIRED_SYS_EQ(0, r);
6111 DPRINTF(" > new multiuser=%d\n", multiuser);
6112 }
6113
6114 /* Do test */
6115 try_audioctl_open_multiuser(multiuser, dev1, dev2);
6116
6117 /* Restore multiuser mode */
6118 if (oldval != newval) {
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(0, devaudio, devaudioctl);
6127 }
6128 DEF(audioctl_open_multiuser1_audio1) {
6129 TEST("audioctl_open_multiuser1_audio1");
6130 test_audioctl_open_multiuser(1, devaudio, devaudioctl);
6131 }
6132 DEF(audioctl_open_multiuser0_audio2) {
6133 TEST("audioctl_open_multiuser0_audio2");
6134 test_audioctl_open_multiuser(0, devaudioctl, devaudio);
6135 }
6136 DEF(audioctl_open_multiuser1_audio2) {
6137 TEST("audioctl_open_multiuser1_audio2");
6138 test_audioctl_open_multiuser(1, devaudioctl, devaudio);
6139 }
6140 DEF(audioctl_open_multiuser0_audioctl) {
6141 TEST("audioctl_open_multiuser0_audioctl");
6142 test_audioctl_open_multiuser(0, devaudioctl, devaudioctl);
6143 }
6144 DEF(audioctl_open_multiuser1_audioctl) {
6145 TEST("audioctl_open_multiuser1_audioctl");
6146 test_audioctl_open_multiuser(1, 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 };
6435