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