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