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