1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // kselftest for the ALSA mixer API 4 // 5 // Original author: Mark Brown <broonie@kernel.org> 6 // Copyright (c) 2021-2 Arm Limited 7 8 // This test will iterate over all cards detected in the system, exercising 9 // every mixer control it can find. This may conflict with other system 10 // software if there is audio activity so is best run on a system with a 11 // minimal active userspace. 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <stdbool.h> 16 #include <limits.h> 17 #include <string.h> 18 #include <getopt.h> 19 #include <stdarg.h> 20 #include <ctype.h> 21 #include <math.h> 22 #include <errno.h> 23 #include <assert.h> 24 #include <alsa/asoundlib.h> 25 #include <poll.h> 26 #include <stdint.h> 27 28 #include "../kselftest.h" 29 30 #define TESTS_PER_CONTROL 6 31 32 struct card_data { 33 snd_ctl_t *handle; 34 int card; 35 struct pollfd pollfd; 36 int num_ctls; 37 snd_ctl_elem_list_t *ctls; 38 struct card_data *next; 39 }; 40 41 struct ctl_data { 42 const char *name; 43 snd_ctl_elem_id_t *id; 44 snd_ctl_elem_info_t *info; 45 snd_ctl_elem_value_t *def_val; 46 int elem; 47 int event_missing; 48 int event_spurious; 49 struct card_data *card; 50 struct ctl_data *next; 51 }; 52 53 static const char *alsa_config = 54 "ctl.hw {\n" 55 " @args [ CARD ]\n" 56 " @args.CARD.type string\n" 57 " type hw\n" 58 " card $CARD\n" 59 "}\n" 60 ; 61 62 int num_cards = 0; 63 int num_controls = 0; 64 struct card_data *card_list = NULL; 65 struct ctl_data *ctl_list = NULL; 66 67 #ifdef SND_LIB_VER 68 #if SND_LIB_VERSION >= SND_LIB_VER(1, 2, 6) 69 #define LIB_HAS_LOAD_STRING 70 #endif 71 #endif 72 73 #ifndef LIB_HAS_LOAD_STRING 74 static int snd_config_load_string(snd_config_t **config, const char *s, 75 size_t size) 76 { 77 snd_input_t *input; 78 snd_config_t *dst; 79 int err; 80 81 assert(config && s); 82 if (size == 0) 83 size = strlen(s); 84 err = snd_input_buffer_open(&input, s, size); 85 if (err < 0) 86 return err; 87 err = snd_config_top(&dst); 88 if (err < 0) { 89 snd_input_close(input); 90 return err; 91 } 92 err = snd_config_load(dst, input); 93 snd_input_close(input); 94 if (err < 0) { 95 snd_config_delete(dst); 96 return err; 97 } 98 *config = dst; 99 return 0; 100 } 101 #endif 102 103 static void find_controls(void) 104 { 105 char name[32]; 106 int card, ctl, err; 107 struct card_data *card_data; 108 struct ctl_data *ctl_data; 109 snd_config_t *config; 110 111 card = -1; 112 if (snd_card_next(&card) < 0 || card < 0) 113 return; 114 115 err = snd_config_load_string(&config, alsa_config, strlen(alsa_config)); 116 if (err < 0) { 117 ksft_print_msg("Unable to parse custom alsa-lib configuration: %s\n", 118 snd_strerror(err)); 119 ksft_exit_fail(); 120 } 121 122 while (card >= 0) { 123 sprintf(name, "hw:%d", card); 124 125 card_data = malloc(sizeof(*card_data)); 126 if (!card_data) 127 ksft_exit_fail_msg("Out of memory\n"); 128 129 err = snd_ctl_open_lconf(&card_data->handle, name, 0, config); 130 if (err < 0) { 131 ksft_print_msg("Failed to get hctl for card %d: %s\n", 132 card, snd_strerror(err)); 133 goto next_card; 134 } 135 136 /* Count controls */ 137 snd_ctl_elem_list_malloc(&card_data->ctls); 138 snd_ctl_elem_list(card_data->handle, card_data->ctls); 139 card_data->num_ctls = snd_ctl_elem_list_get_count(card_data->ctls); 140 141 /* Enumerate control information */ 142 snd_ctl_elem_list_alloc_space(card_data->ctls, card_data->num_ctls); 143 snd_ctl_elem_list(card_data->handle, card_data->ctls); 144 145 card_data->card = num_cards++; 146 card_data->next = card_list; 147 card_list = card_data; 148 149 num_controls += card_data->num_ctls; 150 151 for (ctl = 0; ctl < card_data->num_ctls; ctl++) { 152 ctl_data = malloc(sizeof(*ctl_data)); 153 if (!ctl_data) 154 ksft_exit_fail_msg("Out of memory\n"); 155 156 memset(ctl_data, 0, sizeof(*ctl_data)); 157 ctl_data->card = card_data; 158 ctl_data->elem = ctl; 159 ctl_data->name = snd_ctl_elem_list_get_name(card_data->ctls, 160 ctl); 161 162 err = snd_ctl_elem_id_malloc(&ctl_data->id); 163 if (err < 0) 164 ksft_exit_fail_msg("Out of memory\n"); 165 166 err = snd_ctl_elem_info_malloc(&ctl_data->info); 167 if (err < 0) 168 ksft_exit_fail_msg("Out of memory\n"); 169 170 err = snd_ctl_elem_value_malloc(&ctl_data->def_val); 171 if (err < 0) 172 ksft_exit_fail_msg("Out of memory\n"); 173 174 snd_ctl_elem_list_get_id(card_data->ctls, ctl, 175 ctl_data->id); 176 snd_ctl_elem_info_set_id(ctl_data->info, ctl_data->id); 177 err = snd_ctl_elem_info(card_data->handle, 178 ctl_data->info); 179 if (err < 0) { 180 ksft_print_msg("%s getting info for %d\n", 181 snd_strerror(err), 182 ctl_data->name); 183 } 184 185 snd_ctl_elem_value_set_id(ctl_data->def_val, 186 ctl_data->id); 187 188 ctl_data->next = ctl_list; 189 ctl_list = ctl_data; 190 } 191 192 /* Set up for events */ 193 err = snd_ctl_subscribe_events(card_data->handle, true); 194 if (err < 0) { 195 ksft_exit_fail_msg("snd_ctl_subscribe_events() failed for card %d: %d\n", 196 card, err); 197 } 198 199 err = snd_ctl_poll_descriptors_count(card_data->handle); 200 if (err != 1) { 201 ksft_exit_fail_msg("Unexpected descriptor count %d for card %d\n", 202 err, card); 203 } 204 205 err = snd_ctl_poll_descriptors(card_data->handle, 206 &card_data->pollfd, 1); 207 if (err != 1) { 208 ksft_exit_fail_msg("snd_ctl_poll_descriptors() failed for %d\n", 209 card, err); 210 } 211 212 next_card: 213 if (snd_card_next(&card) < 0) { 214 ksft_print_msg("snd_card_next"); 215 break; 216 } 217 } 218 219 snd_config_delete(config); 220 } 221 222 /* 223 * Block for up to timeout ms for an event, returns a negative value 224 * on error, 0 for no event and 1 for an event. 225 */ 226 static int wait_for_event(struct ctl_data *ctl, int timeout) 227 { 228 unsigned short revents; 229 snd_ctl_event_t *event; 230 int count, err; 231 unsigned int mask = 0; 232 unsigned int ev_id; 233 234 snd_ctl_event_alloca(&event); 235 236 do { 237 err = poll(&(ctl->card->pollfd), 1, timeout); 238 if (err < 0) { 239 ksft_print_msg("poll() failed for %s: %s (%d)\n", 240 ctl->name, strerror(errno), errno); 241 return -1; 242 } 243 /* Timeout */ 244 if (err == 0) 245 return 0; 246 247 err = snd_ctl_poll_descriptors_revents(ctl->card->handle, 248 &(ctl->card->pollfd), 249 1, &revents); 250 if (err < 0) { 251 ksft_print_msg("snd_ctl_poll_descriptors_revents() failed for %s: %d\n", 252 ctl->name, err); 253 return err; 254 } 255 if (revents & POLLERR) { 256 ksft_print_msg("snd_ctl_poll_descriptors_revents() reported POLLERR for %s\n", 257 ctl->name); 258 return -1; 259 } 260 /* No read events */ 261 if (!(revents & POLLIN)) { 262 ksft_print_msg("No POLLIN\n"); 263 continue; 264 } 265 266 err = snd_ctl_read(ctl->card->handle, event); 267 if (err < 0) { 268 ksft_print_msg("snd_ctl_read() failed for %s: %d\n", 269 ctl->name, err); 270 return err; 271 } 272 273 if (snd_ctl_event_get_type(event) != SND_CTL_EVENT_ELEM) 274 continue; 275 276 /* The ID returned from the event is 1 less than numid */ 277 mask = snd_ctl_event_elem_get_mask(event); 278 ev_id = snd_ctl_event_elem_get_numid(event); 279 if (ev_id != snd_ctl_elem_info_get_numid(ctl->info)) { 280 ksft_print_msg("Event for unexpected ctl %s\n", 281 snd_ctl_event_elem_get_name(event)); 282 continue; 283 } 284 285 if ((mask & SND_CTL_EVENT_MASK_REMOVE) == SND_CTL_EVENT_MASK_REMOVE) { 286 ksft_print_msg("Removal event for %s\n", 287 ctl->name); 288 return -1; 289 } 290 } while ((mask & SND_CTL_EVENT_MASK_VALUE) != SND_CTL_EVENT_MASK_VALUE); 291 292 return 1; 293 } 294 295 static bool ctl_value_index_valid(struct ctl_data *ctl, 296 snd_ctl_elem_value_t *val, 297 int index) 298 { 299 long int_val; 300 long long int64_val; 301 302 switch (snd_ctl_elem_info_get_type(ctl->info)) { 303 case SND_CTL_ELEM_TYPE_NONE: 304 ksft_print_msg("%s.%d Invalid control type NONE\n", 305 ctl->name, index); 306 return false; 307 308 case SND_CTL_ELEM_TYPE_BOOLEAN: 309 int_val = snd_ctl_elem_value_get_boolean(val, index); 310 switch (int_val) { 311 case 0: 312 case 1: 313 break; 314 default: 315 ksft_print_msg("%s.%d Invalid boolean value %ld\n", 316 ctl->name, index, int_val); 317 return false; 318 } 319 break; 320 321 case SND_CTL_ELEM_TYPE_INTEGER: 322 int_val = snd_ctl_elem_value_get_integer(val, index); 323 324 if (int_val < snd_ctl_elem_info_get_min(ctl->info)) { 325 ksft_print_msg("%s.%d value %ld less than minimum %ld\n", 326 ctl->name, index, int_val, 327 snd_ctl_elem_info_get_min(ctl->info)); 328 return false; 329 } 330 331 if (int_val > snd_ctl_elem_info_get_max(ctl->info)) { 332 ksft_print_msg("%s.%d value %ld more than maximum %ld\n", 333 ctl->name, index, int_val, 334 snd_ctl_elem_info_get_max(ctl->info)); 335 return false; 336 } 337 338 /* Only check step size if there is one and we're in bounds */ 339 if (snd_ctl_elem_info_get_step(ctl->info) && 340 (int_val - snd_ctl_elem_info_get_min(ctl->info) % 341 snd_ctl_elem_info_get_step(ctl->info))) { 342 ksft_print_msg("%s.%d value %ld invalid for step %ld minimum %ld\n", 343 ctl->name, index, int_val, 344 snd_ctl_elem_info_get_step(ctl->info), 345 snd_ctl_elem_info_get_min(ctl->info)); 346 return false; 347 } 348 break; 349 350 case SND_CTL_ELEM_TYPE_INTEGER64: 351 int64_val = snd_ctl_elem_value_get_integer64(val, index); 352 353 if (int64_val < snd_ctl_elem_info_get_min64(ctl->info)) { 354 ksft_print_msg("%s.%d value %lld less than minimum %lld\n", 355 ctl->name, index, int64_val, 356 snd_ctl_elem_info_get_min64(ctl->info)); 357 return false; 358 } 359 360 if (int64_val > snd_ctl_elem_info_get_max64(ctl->info)) { 361 ksft_print_msg("%s.%d value %lld more than maximum %lld\n", 362 ctl->name, index, int64_val, 363 snd_ctl_elem_info_get_max(ctl->info)); 364 return false; 365 } 366 367 /* Only check step size if there is one and we're in bounds */ 368 if (snd_ctl_elem_info_get_step64(ctl->info) && 369 (int64_val - snd_ctl_elem_info_get_min64(ctl->info)) % 370 snd_ctl_elem_info_get_step64(ctl->info)) { 371 ksft_print_msg("%s.%d value %lld invalid for step %lld minimum %lld\n", 372 ctl->name, index, int64_val, 373 snd_ctl_elem_info_get_step64(ctl->info), 374 snd_ctl_elem_info_get_min64(ctl->info)); 375 return false; 376 } 377 break; 378 379 case SND_CTL_ELEM_TYPE_ENUMERATED: 380 int_val = snd_ctl_elem_value_get_enumerated(val, index); 381 382 if (int_val < 0) { 383 ksft_print_msg("%s.%d negative value %ld for enumeration\n", 384 ctl->name, index, int_val); 385 return false; 386 } 387 388 if (int_val >= snd_ctl_elem_info_get_items(ctl->info)) { 389 ksft_print_msg("%s.%d value %ld more than item count %ld\n", 390 ctl->name, index, int_val, 391 snd_ctl_elem_info_get_items(ctl->info)); 392 return false; 393 } 394 break; 395 396 default: 397 /* No tests for other types */ 398 break; 399 } 400 401 return true; 402 } 403 404 /* 405 * Check that the provided value meets the constraints for the 406 * provided control. 407 */ 408 static bool ctl_value_valid(struct ctl_data *ctl, snd_ctl_elem_value_t *val) 409 { 410 int i; 411 bool valid = true; 412 413 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) 414 if (!ctl_value_index_valid(ctl, val, i)) 415 valid = false; 416 417 return valid; 418 } 419 420 /* 421 * Check that we can read the default value and it is valid. Write 422 * tests use the read value to restore the default. 423 */ 424 static void test_ctl_get_value(struct ctl_data *ctl) 425 { 426 int err; 427 428 /* If the control is turned off let's be polite */ 429 if (snd_ctl_elem_info_is_inactive(ctl->info)) { 430 ksft_print_msg("%s is inactive\n", ctl->name); 431 ksft_test_result_skip("get_value.%d.%d\n", 432 ctl->card->card, ctl->elem); 433 return; 434 } 435 436 /* Can't test reading on an unreadable control */ 437 if (!snd_ctl_elem_info_is_readable(ctl->info)) { 438 ksft_print_msg("%s is not readable\n", ctl->name); 439 ksft_test_result_skip("get_value.%d.%d\n", 440 ctl->card->card, ctl->elem); 441 return; 442 } 443 444 err = snd_ctl_elem_read(ctl->card->handle, ctl->def_val); 445 if (err < 0) { 446 ksft_print_msg("snd_ctl_elem_read() failed: %s\n", 447 snd_strerror(err)); 448 goto out; 449 } 450 451 if (!ctl_value_valid(ctl, ctl->def_val)) 452 err = -EINVAL; 453 454 out: 455 ksft_test_result(err >= 0, "get_value.%d.%d\n", 456 ctl->card->card, ctl->elem); 457 } 458 459 static bool show_mismatch(struct ctl_data *ctl, int index, 460 snd_ctl_elem_value_t *read_val, 461 snd_ctl_elem_value_t *expected_val) 462 { 463 long long expected_int, read_int; 464 465 /* 466 * We factor out the code to compare values representable as 467 * integers, ensure that check doesn't log otherwise. 468 */ 469 expected_int = 0; 470 read_int = 0; 471 472 switch (snd_ctl_elem_info_get_type(ctl->info)) { 473 case SND_CTL_ELEM_TYPE_BOOLEAN: 474 expected_int = snd_ctl_elem_value_get_boolean(expected_val, 475 index); 476 read_int = snd_ctl_elem_value_get_boolean(read_val, index); 477 break; 478 479 case SND_CTL_ELEM_TYPE_INTEGER: 480 expected_int = snd_ctl_elem_value_get_integer(expected_val, 481 index); 482 read_int = snd_ctl_elem_value_get_integer(read_val, index); 483 break; 484 485 case SND_CTL_ELEM_TYPE_INTEGER64: 486 expected_int = snd_ctl_elem_value_get_integer64(expected_val, 487 index); 488 read_int = snd_ctl_elem_value_get_integer64(read_val, 489 index); 490 break; 491 492 case SND_CTL_ELEM_TYPE_ENUMERATED: 493 expected_int = snd_ctl_elem_value_get_enumerated(expected_val, 494 index); 495 read_int = snd_ctl_elem_value_get_enumerated(read_val, 496 index); 497 break; 498 499 default: 500 break; 501 } 502 503 if (expected_int != read_int) { 504 /* 505 * NOTE: The volatile attribute means that the hardware 506 * can voluntarily change the state of control element 507 * independent of any operation by software. 508 */ 509 bool is_volatile = snd_ctl_elem_info_is_volatile(ctl->info); 510 ksft_print_msg("%s.%d expected %lld but read %lld, is_volatile %d\n", 511 ctl->name, index, expected_int, read_int, is_volatile); 512 return !is_volatile; 513 } else { 514 return false; 515 } 516 } 517 518 /* 519 * Write a value then if possible verify that we get the expected 520 * result. An optional expected value can be provided if we expect 521 * the write to fail, for verifying that invalid writes don't corrupt 522 * anything. 523 */ 524 static int write_and_verify(struct ctl_data *ctl, 525 snd_ctl_elem_value_t *write_val, 526 snd_ctl_elem_value_t *expected_val) 527 { 528 int err, i; 529 bool error_expected, mismatch_shown; 530 snd_ctl_elem_value_t *initial_val, *read_val, *w_val; 531 snd_ctl_elem_value_alloca(&initial_val); 532 snd_ctl_elem_value_alloca(&read_val); 533 snd_ctl_elem_value_alloca(&w_val); 534 535 /* 536 * We need to copy the write value since writing can modify 537 * the value which causes surprises, and allocate an expected 538 * value if we expect to read back what we wrote. 539 */ 540 snd_ctl_elem_value_copy(w_val, write_val); 541 if (expected_val) { 542 error_expected = true; 543 } else { 544 error_expected = false; 545 snd_ctl_elem_value_alloca(&expected_val); 546 snd_ctl_elem_value_copy(expected_val, write_val); 547 } 548 549 /* Store the value before we write */ 550 if (snd_ctl_elem_info_is_readable(ctl->info)) { 551 snd_ctl_elem_value_set_id(initial_val, ctl->id); 552 553 err = snd_ctl_elem_read(ctl->card->handle, initial_val); 554 if (err < 0) { 555 ksft_print_msg("snd_ctl_elem_read() failed: %s\n", 556 snd_strerror(err)); 557 return err; 558 } 559 } 560 561 /* 562 * Do the write, if we have an expected value ignore the error 563 * and carry on to validate the expected value. 564 */ 565 err = snd_ctl_elem_write(ctl->card->handle, w_val); 566 if (err < 0 && !error_expected) { 567 ksft_print_msg("snd_ctl_elem_write() failed: %s\n", 568 snd_strerror(err)); 569 return err; 570 } 571 572 /* Can we do the verification part? */ 573 if (!snd_ctl_elem_info_is_readable(ctl->info)) 574 return err; 575 576 snd_ctl_elem_value_set_id(read_val, ctl->id); 577 578 err = snd_ctl_elem_read(ctl->card->handle, read_val); 579 if (err < 0) { 580 ksft_print_msg("snd_ctl_elem_read() failed: %s\n", 581 snd_strerror(err)); 582 return err; 583 } 584 585 /* 586 * Check for an event if the value changed, or confirm that 587 * there was none if it didn't. We rely on the kernel 588 * generating the notification before it returns from the 589 * write, this is currently true, should that ever change this 590 * will most likely break and need updating. 591 */ 592 if (!snd_ctl_elem_info_is_volatile(ctl->info)) { 593 err = wait_for_event(ctl, 0); 594 if (snd_ctl_elem_value_compare(initial_val, read_val)) { 595 if (err < 1) { 596 ksft_print_msg("No event generated for %s\n", 597 ctl->name); 598 ctl->event_missing++; 599 } 600 } else { 601 if (err != 0) { 602 ksft_print_msg("Spurious event generated for %s\n", 603 ctl->name); 604 ctl->event_spurious++; 605 } 606 } 607 } 608 609 /* 610 * Use the libray to compare values, if there's a mismatch 611 * carry on and try to provide a more useful diagnostic than 612 * just "mismatch". 613 */ 614 if (!snd_ctl_elem_value_compare(expected_val, read_val)) 615 return 0; 616 617 mismatch_shown = false; 618 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) 619 if (show_mismatch(ctl, i, read_val, expected_val)) 620 mismatch_shown = true; 621 622 if (!mismatch_shown) 623 ksft_print_msg("%s read and written values differ\n", 624 ctl->name); 625 626 return -1; 627 } 628 629 /* 630 * Make sure we can write the default value back to the control, this 631 * should validate that at least some write works. 632 */ 633 static void test_ctl_write_default(struct ctl_data *ctl) 634 { 635 int err; 636 637 /* If the control is turned off let's be polite */ 638 if (snd_ctl_elem_info_is_inactive(ctl->info)) { 639 ksft_print_msg("%s is inactive\n", ctl->name); 640 ksft_test_result_skip("write_default.%d.%d\n", 641 ctl->card->card, ctl->elem); 642 return; 643 } 644 645 if (!snd_ctl_elem_info_is_writable(ctl->info)) { 646 ksft_print_msg("%s is not writeable\n", ctl->name); 647 ksft_test_result_skip("write_default.%d.%d\n", 648 ctl->card->card, ctl->elem); 649 return; 650 } 651 652 /* No idea what the default was for unreadable controls */ 653 if (!snd_ctl_elem_info_is_readable(ctl->info)) { 654 ksft_print_msg("%s couldn't read default\n", ctl->name); 655 ksft_test_result_skip("write_default.%d.%d\n", 656 ctl->card->card, ctl->elem); 657 return; 658 } 659 660 err = write_and_verify(ctl, ctl->def_val, NULL); 661 662 ksft_test_result(err >= 0, "write_default.%d.%d\n", 663 ctl->card->card, ctl->elem); 664 } 665 666 static bool test_ctl_write_valid_boolean(struct ctl_data *ctl) 667 { 668 int err, i, j; 669 bool fail = false; 670 snd_ctl_elem_value_t *val; 671 snd_ctl_elem_value_alloca(&val); 672 673 snd_ctl_elem_value_set_id(val, ctl->id); 674 675 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) { 676 for (j = 0; j < 2; j++) { 677 snd_ctl_elem_value_set_boolean(val, i, j); 678 err = write_and_verify(ctl, val, NULL); 679 if (err != 0) 680 fail = true; 681 } 682 } 683 684 return !fail; 685 } 686 687 static bool test_ctl_write_valid_integer(struct ctl_data *ctl) 688 { 689 int err; 690 int i; 691 long j, step; 692 bool fail = false; 693 snd_ctl_elem_value_t *val; 694 snd_ctl_elem_value_alloca(&val); 695 696 snd_ctl_elem_value_set_id(val, ctl->id); 697 698 step = snd_ctl_elem_info_get_step(ctl->info); 699 if (!step) 700 step = 1; 701 702 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) { 703 for (j = snd_ctl_elem_info_get_min(ctl->info); 704 j <= snd_ctl_elem_info_get_max(ctl->info); j += step) { 705 706 snd_ctl_elem_value_set_integer(val, i, j); 707 err = write_and_verify(ctl, val, NULL); 708 if (err != 0) 709 fail = true; 710 } 711 } 712 713 714 return !fail; 715 } 716 717 static bool test_ctl_write_valid_integer64(struct ctl_data *ctl) 718 { 719 int err, i; 720 long long j, step; 721 bool fail = false; 722 snd_ctl_elem_value_t *val; 723 snd_ctl_elem_value_alloca(&val); 724 725 snd_ctl_elem_value_set_id(val, ctl->id); 726 727 step = snd_ctl_elem_info_get_step64(ctl->info); 728 if (!step) 729 step = 1; 730 731 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) { 732 for (j = snd_ctl_elem_info_get_min64(ctl->info); 733 j <= snd_ctl_elem_info_get_max64(ctl->info); j += step) { 734 735 snd_ctl_elem_value_set_integer64(val, i, j); 736 err = write_and_verify(ctl, val, NULL); 737 if (err != 0) 738 fail = true; 739 } 740 } 741 742 return !fail; 743 } 744 745 static bool test_ctl_write_valid_enumerated(struct ctl_data *ctl) 746 { 747 int err, i, j; 748 bool fail = false; 749 snd_ctl_elem_value_t *val; 750 snd_ctl_elem_value_alloca(&val); 751 752 snd_ctl_elem_value_set_id(val, ctl->id); 753 754 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) { 755 for (j = 0; j < snd_ctl_elem_info_get_items(ctl->info); j++) { 756 snd_ctl_elem_value_set_enumerated(val, i, j); 757 err = write_and_verify(ctl, val, NULL); 758 if (err != 0) 759 fail = true; 760 } 761 } 762 763 return !fail; 764 } 765 766 static void test_ctl_write_valid(struct ctl_data *ctl) 767 { 768 bool pass; 769 int err; 770 771 /* If the control is turned off let's be polite */ 772 if (snd_ctl_elem_info_is_inactive(ctl->info)) { 773 ksft_print_msg("%s is inactive\n", ctl->name); 774 ksft_test_result_skip("write_valid.%d.%d\n", 775 ctl->card->card, ctl->elem); 776 return; 777 } 778 779 if (!snd_ctl_elem_info_is_writable(ctl->info)) { 780 ksft_print_msg("%s is not writeable\n", ctl->name); 781 ksft_test_result_skip("write_valid.%d.%d\n", 782 ctl->card->card, ctl->elem); 783 return; 784 } 785 786 switch (snd_ctl_elem_info_get_type(ctl->info)) { 787 case SND_CTL_ELEM_TYPE_BOOLEAN: 788 pass = test_ctl_write_valid_boolean(ctl); 789 break; 790 791 case SND_CTL_ELEM_TYPE_INTEGER: 792 pass = test_ctl_write_valid_integer(ctl); 793 break; 794 795 case SND_CTL_ELEM_TYPE_INTEGER64: 796 pass = test_ctl_write_valid_integer64(ctl); 797 break; 798 799 case SND_CTL_ELEM_TYPE_ENUMERATED: 800 pass = test_ctl_write_valid_enumerated(ctl); 801 break; 802 803 default: 804 /* No tests for this yet */ 805 ksft_test_result_skip("write_valid.%d.%d\n", 806 ctl->card->card, ctl->elem); 807 return; 808 } 809 810 /* Restore the default value to minimise disruption */ 811 err = write_and_verify(ctl, ctl->def_val, NULL); 812 if (err < 0) 813 pass = false; 814 815 ksft_test_result(pass, "write_valid.%d.%d\n", 816 ctl->card->card, ctl->elem); 817 } 818 819 static bool test_ctl_write_invalid_value(struct ctl_data *ctl, 820 snd_ctl_elem_value_t *val) 821 { 822 int err; 823 long val_read; 824 825 /* Ideally this will fail... */ 826 err = snd_ctl_elem_write(ctl->card->handle, val); 827 if (err < 0) 828 return false; 829 830 /* ...but some devices will clamp to an in range value */ 831 err = snd_ctl_elem_read(ctl->card->handle, val); 832 if (err < 0) { 833 ksft_print_msg("%s failed to read: %s\n", 834 ctl->name, snd_strerror(err)); 835 return true; 836 } 837 838 return !ctl_value_valid(ctl, val); 839 } 840 841 static bool test_ctl_write_invalid_boolean(struct ctl_data *ctl) 842 { 843 int err, i; 844 long val_read; 845 bool fail = false; 846 snd_ctl_elem_value_t *val; 847 snd_ctl_elem_value_alloca(&val); 848 849 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) { 850 snd_ctl_elem_value_copy(val, ctl->def_val); 851 snd_ctl_elem_value_set_boolean(val, i, 2); 852 853 if (test_ctl_write_invalid_value(ctl, val)) 854 fail = true; 855 } 856 857 return !fail; 858 } 859 860 static bool test_ctl_write_invalid_integer(struct ctl_data *ctl) 861 { 862 int i; 863 bool fail = false; 864 snd_ctl_elem_value_t *val; 865 snd_ctl_elem_value_alloca(&val); 866 867 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) { 868 if (snd_ctl_elem_info_get_min(ctl->info) != LONG_MIN) { 869 /* Just under range */ 870 snd_ctl_elem_value_copy(val, ctl->def_val); 871 snd_ctl_elem_value_set_integer(val, i, 872 snd_ctl_elem_info_get_min(ctl->info) - 1); 873 874 if (test_ctl_write_invalid_value(ctl, val)) 875 fail = true; 876 877 /* Minimum representable value */ 878 snd_ctl_elem_value_copy(val, ctl->def_val); 879 snd_ctl_elem_value_set_integer(val, i, LONG_MIN); 880 881 if (test_ctl_write_invalid_value(ctl, val)) 882 fail = true; 883 } 884 885 if (snd_ctl_elem_info_get_max(ctl->info) != LONG_MAX) { 886 /* Just over range */ 887 snd_ctl_elem_value_copy(val, ctl->def_val); 888 snd_ctl_elem_value_set_integer(val, i, 889 snd_ctl_elem_info_get_max(ctl->info) + 1); 890 891 if (test_ctl_write_invalid_value(ctl, val)) 892 fail = true; 893 894 /* Maximum representable value */ 895 snd_ctl_elem_value_copy(val, ctl->def_val); 896 snd_ctl_elem_value_set_integer(val, i, LONG_MAX); 897 898 if (test_ctl_write_invalid_value(ctl, val)) 899 fail = true; 900 } 901 } 902 903 return !fail; 904 } 905 906 static bool test_ctl_write_invalid_integer64(struct ctl_data *ctl) 907 { 908 int i; 909 bool fail = false; 910 snd_ctl_elem_value_t *val; 911 snd_ctl_elem_value_alloca(&val); 912 913 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) { 914 if (snd_ctl_elem_info_get_min64(ctl->info) != LLONG_MIN) { 915 /* Just under range */ 916 snd_ctl_elem_value_copy(val, ctl->def_val); 917 snd_ctl_elem_value_set_integer64(val, i, 918 snd_ctl_elem_info_get_min64(ctl->info) - 1); 919 920 if (test_ctl_write_invalid_value(ctl, val)) 921 fail = true; 922 923 /* Minimum representable value */ 924 snd_ctl_elem_value_copy(val, ctl->def_val); 925 snd_ctl_elem_value_set_integer64(val, i, LLONG_MIN); 926 927 if (test_ctl_write_invalid_value(ctl, val)) 928 fail = true; 929 } 930 931 if (snd_ctl_elem_info_get_max64(ctl->info) != LLONG_MAX) { 932 /* Just over range */ 933 snd_ctl_elem_value_copy(val, ctl->def_val); 934 snd_ctl_elem_value_set_integer64(val, i, 935 snd_ctl_elem_info_get_max64(ctl->info) + 1); 936 937 if (test_ctl_write_invalid_value(ctl, val)) 938 fail = true; 939 940 /* Maximum representable value */ 941 snd_ctl_elem_value_copy(val, ctl->def_val); 942 snd_ctl_elem_value_set_integer64(val, i, LLONG_MAX); 943 944 if (test_ctl_write_invalid_value(ctl, val)) 945 fail = true; 946 } 947 } 948 949 return !fail; 950 } 951 952 static bool test_ctl_write_invalid_enumerated(struct ctl_data *ctl) 953 { 954 int err, i; 955 unsigned int val_read; 956 bool fail = false; 957 snd_ctl_elem_value_t *val; 958 snd_ctl_elem_value_alloca(&val); 959 960 snd_ctl_elem_value_set_id(val, ctl->id); 961 962 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) { 963 /* One beyond maximum */ 964 snd_ctl_elem_value_copy(val, ctl->def_val); 965 snd_ctl_elem_value_set_enumerated(val, i, 966 snd_ctl_elem_info_get_items(ctl->info)); 967 968 if (test_ctl_write_invalid_value(ctl, val)) 969 fail = true; 970 971 /* Maximum representable value */ 972 snd_ctl_elem_value_copy(val, ctl->def_val); 973 snd_ctl_elem_value_set_enumerated(val, i, UINT_MAX); 974 975 if (test_ctl_write_invalid_value(ctl, val)) 976 fail = true; 977 978 } 979 980 return !fail; 981 } 982 983 984 static void test_ctl_write_invalid(struct ctl_data *ctl) 985 { 986 bool pass; 987 int err; 988 989 /* If the control is turned off let's be polite */ 990 if (snd_ctl_elem_info_is_inactive(ctl->info)) { 991 ksft_print_msg("%s is inactive\n", ctl->name); 992 ksft_test_result_skip("write_invalid.%d.%d\n", 993 ctl->card->card, ctl->elem); 994 return; 995 } 996 997 if (!snd_ctl_elem_info_is_writable(ctl->info)) { 998 ksft_print_msg("%s is not writeable\n", ctl->name); 999 ksft_test_result_skip("write_invalid.%d.%d\n", 1000 ctl->card->card, ctl->elem); 1001 return; 1002 } 1003 1004 switch (snd_ctl_elem_info_get_type(ctl->info)) { 1005 case SND_CTL_ELEM_TYPE_BOOLEAN: 1006 pass = test_ctl_write_invalid_boolean(ctl); 1007 break; 1008 1009 case SND_CTL_ELEM_TYPE_INTEGER: 1010 pass = test_ctl_write_invalid_integer(ctl); 1011 break; 1012 1013 case SND_CTL_ELEM_TYPE_INTEGER64: 1014 pass = test_ctl_write_invalid_integer64(ctl); 1015 break; 1016 1017 case SND_CTL_ELEM_TYPE_ENUMERATED: 1018 pass = test_ctl_write_invalid_enumerated(ctl); 1019 break; 1020 1021 default: 1022 /* No tests for this yet */ 1023 ksft_test_result_skip("write_invalid.%d.%d\n", 1024 ctl->card->card, ctl->elem); 1025 return; 1026 } 1027 1028 /* Restore the default value to minimise disruption */ 1029 err = write_and_verify(ctl, ctl->def_val, NULL); 1030 if (err < 0) 1031 pass = false; 1032 1033 ksft_test_result(pass, "write_invalid.%d.%d\n", 1034 ctl->card->card, ctl->elem); 1035 } 1036 1037 static void test_ctl_event_missing(struct ctl_data *ctl) 1038 { 1039 ksft_test_result(!ctl->event_missing, "event_missing.%d.%d\n", 1040 ctl->card->card, ctl->elem); 1041 } 1042 1043 static void test_ctl_event_spurious(struct ctl_data *ctl) 1044 { 1045 ksft_test_result(!ctl->event_spurious, "event_spurious.%d.%d\n", 1046 ctl->card->card, ctl->elem); 1047 } 1048 1049 int main(void) 1050 { 1051 struct ctl_data *ctl; 1052 1053 ksft_print_header(); 1054 1055 find_controls(); 1056 1057 ksft_set_plan(num_controls * TESTS_PER_CONTROL); 1058 1059 for (ctl = ctl_list; ctl != NULL; ctl = ctl->next) { 1060 /* 1061 * Must test get_value() before we write anything, the 1062 * test stores the default value for later cleanup. 1063 */ 1064 test_ctl_get_value(ctl); 1065 test_ctl_write_default(ctl); 1066 test_ctl_write_valid(ctl); 1067 test_ctl_write_invalid(ctl); 1068 test_ctl_event_missing(ctl); 1069 test_ctl_event_spurious(ctl); 1070 } 1071 1072 ksft_exit_pass(); 1073 1074 return 0; 1075 } 1076