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