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