1 // SPDX-License-Identifier: GPL-2.0
3 // kselftest for the ALSA mixer API
5 // Original author: Mark Brown <broonie@kernel.org>
6 // Copyright (c) 2021-2 Arm Limited
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.
24 #include <alsa/asoundlib.h>
28 #include "../kselftest.h"
29 #include "alsa-local.h"
31 #define TESTS_PER_CONTROL 7
36 snd_ctl_card_info_t
*info
;
37 const char *card_name
;
40 snd_ctl_elem_list_t
*ctls
;
41 struct card_data
*next
;
46 snd_ctl_elem_id_t
*id
;
47 snd_ctl_elem_info_t
*info
;
48 snd_ctl_elem_value_t
*def_val
;
52 struct card_data
*card
;
53 struct ctl_data
*next
;
58 struct card_data
*card_list
= NULL
;
59 struct ctl_data
*ctl_list
= NULL
;
61 static void find_controls(void)
65 struct card_data
*card_data
;
66 struct ctl_data
*ctl_data
;
68 char *card_name
, *card_longname
;
71 if (snd_card_next(&card
) < 0 || card
< 0)
74 config
= get_alsalib_config();
77 sprintf(name
, "hw:%d", card
);
79 card_data
= malloc(sizeof(*card_data
));
81 ksft_exit_fail_msg("Out of memory\n");
83 err
= snd_ctl_open_lconf(&card_data
->handle
, name
, 0, config
);
85 ksft_print_msg("Failed to get hctl for card %d: %s\n",
86 card
, snd_strerror(err
));
90 err
= snd_card_get_name(card
, &card_name
);
92 card_name
= "Unknown";
93 err
= snd_card_get_longname(card
, &card_longname
);
95 card_longname
= "Unknown";
97 err
= snd_ctl_card_info_malloc(&card_data
->info
);
99 ksft_exit_fail_msg("Failed to allocate card info: %d\n",
102 err
= snd_ctl_card_info(card_data
->handle
, card_data
->info
);
104 card_data
->card_name
= snd_ctl_card_info_get_id(card_data
->info
);
105 if (!card_data
->card_name
)
106 ksft_print_msg("Failed to get card ID\n");
108 ksft_print_msg("Failed to get card info: %d\n", err
);
111 if (!card_data
->card_name
)
112 card_data
->card_name
= "Unknown";
114 ksft_print_msg("Card %d/%s - %s (%s)\n", card
,
115 card_data
->card_name
, card_name
, card_longname
);
118 snd_ctl_elem_list_malloc(&card_data
->ctls
);
119 snd_ctl_elem_list(card_data
->handle
, card_data
->ctls
);
120 card_data
->num_ctls
= snd_ctl_elem_list_get_count(card_data
->ctls
);
122 /* Enumerate control information */
123 snd_ctl_elem_list_alloc_space(card_data
->ctls
, card_data
->num_ctls
);
124 snd_ctl_elem_list(card_data
->handle
, card_data
->ctls
);
126 card_data
->card
= num_cards
++;
127 card_data
->next
= card_list
;
128 card_list
= card_data
;
130 num_controls
+= card_data
->num_ctls
;
132 for (ctl
= 0; ctl
< card_data
->num_ctls
; ctl
++) {
133 ctl_data
= malloc(sizeof(*ctl_data
));
135 ksft_exit_fail_msg("Out of memory\n");
137 memset(ctl_data
, 0, sizeof(*ctl_data
));
138 ctl_data
->card
= card_data
;
139 ctl_data
->elem
= ctl
;
140 ctl_data
->name
= snd_ctl_elem_list_get_name(card_data
->ctls
,
143 err
= snd_ctl_elem_id_malloc(&ctl_data
->id
);
145 ksft_exit_fail_msg("Out of memory\n");
147 err
= snd_ctl_elem_info_malloc(&ctl_data
->info
);
149 ksft_exit_fail_msg("Out of memory\n");
151 err
= snd_ctl_elem_value_malloc(&ctl_data
->def_val
);
153 ksft_exit_fail_msg("Out of memory\n");
155 snd_ctl_elem_list_get_id(card_data
->ctls
, ctl
,
157 snd_ctl_elem_info_set_id(ctl_data
->info
, ctl_data
->id
);
158 err
= snd_ctl_elem_info(card_data
->handle
,
161 ksft_print_msg("%s getting info for %s\n",
166 snd_ctl_elem_value_set_id(ctl_data
->def_val
,
169 ctl_data
->next
= ctl_list
;
173 /* Set up for events */
174 err
= snd_ctl_subscribe_events(card_data
->handle
, true);
176 ksft_exit_fail_msg("snd_ctl_subscribe_events() failed for card %d: %d\n",
180 err
= snd_ctl_poll_descriptors_count(card_data
->handle
);
182 ksft_exit_fail_msg("Unexpected descriptor count %d for card %d\n",
186 err
= snd_ctl_poll_descriptors(card_data
->handle
,
187 &card_data
->pollfd
, 1);
189 ksft_exit_fail_msg("snd_ctl_poll_descriptors() failed for card %d: %d\n",
194 if (snd_card_next(&card
) < 0) {
195 ksft_print_msg("snd_card_next");
200 snd_config_delete(config
);
204 * Block for up to timeout ms for an event, returns a negative value
205 * on error, 0 for no event and 1 for an event.
207 static int wait_for_event(struct ctl_data
*ctl
, int timeout
)
209 unsigned short revents
;
210 snd_ctl_event_t
*event
;
212 unsigned int mask
= 0;
215 snd_ctl_event_alloca(&event
);
218 err
= poll(&(ctl
->card
->pollfd
), 1, timeout
);
220 ksft_print_msg("poll() failed for %s: %s (%d)\n",
221 ctl
->name
, strerror(errno
), errno
);
228 err
= snd_ctl_poll_descriptors_revents(ctl
->card
->handle
,
229 &(ctl
->card
->pollfd
),
232 ksft_print_msg("snd_ctl_poll_descriptors_revents() failed for %s: %d\n",
236 if (revents
& POLLERR
) {
237 ksft_print_msg("snd_ctl_poll_descriptors_revents() reported POLLERR for %s\n",
242 if (!(revents
& POLLIN
)) {
243 ksft_print_msg("No POLLIN\n");
247 err
= snd_ctl_read(ctl
->card
->handle
, event
);
249 ksft_print_msg("snd_ctl_read() failed for %s: %d\n",
254 if (snd_ctl_event_get_type(event
) != SND_CTL_EVENT_ELEM
)
257 /* The ID returned from the event is 1 less than numid */
258 mask
= snd_ctl_event_elem_get_mask(event
);
259 ev_id
= snd_ctl_event_elem_get_numid(event
);
260 if (ev_id
!= snd_ctl_elem_info_get_numid(ctl
->info
)) {
261 ksft_print_msg("Event for unexpected ctl %s\n",
262 snd_ctl_event_elem_get_name(event
));
266 if ((mask
& SND_CTL_EVENT_MASK_REMOVE
) == SND_CTL_EVENT_MASK_REMOVE
) {
267 ksft_print_msg("Removal event for %s\n",
271 } while ((mask
& SND_CTL_EVENT_MASK_VALUE
) != SND_CTL_EVENT_MASK_VALUE
);
276 static bool ctl_value_index_valid(struct ctl_data
*ctl
,
277 snd_ctl_elem_value_t
*val
,
283 switch (snd_ctl_elem_info_get_type(ctl
->info
)) {
284 case SND_CTL_ELEM_TYPE_NONE
:
285 ksft_print_msg("%s.%d Invalid control type NONE\n",
289 case SND_CTL_ELEM_TYPE_BOOLEAN
:
290 int_val
= snd_ctl_elem_value_get_boolean(val
, index
);
296 ksft_print_msg("%s.%d Invalid boolean value %ld\n",
297 ctl
->name
, index
, int_val
);
302 case SND_CTL_ELEM_TYPE_INTEGER
:
303 int_val
= snd_ctl_elem_value_get_integer(val
, index
);
305 if (int_val
< snd_ctl_elem_info_get_min(ctl
->info
)) {
306 ksft_print_msg("%s.%d value %ld less than minimum %ld\n",
307 ctl
->name
, index
, int_val
,
308 snd_ctl_elem_info_get_min(ctl
->info
));
312 if (int_val
> snd_ctl_elem_info_get_max(ctl
->info
)) {
313 ksft_print_msg("%s.%d value %ld more than maximum %ld\n",
314 ctl
->name
, index
, int_val
,
315 snd_ctl_elem_info_get_max(ctl
->info
));
319 /* Only check step size if there is one and we're in bounds */
320 if (snd_ctl_elem_info_get_step(ctl
->info
) &&
321 (int_val
- snd_ctl_elem_info_get_min(ctl
->info
) %
322 snd_ctl_elem_info_get_step(ctl
->info
))) {
323 ksft_print_msg("%s.%d value %ld invalid for step %ld minimum %ld\n",
324 ctl
->name
, index
, int_val
,
325 snd_ctl_elem_info_get_step(ctl
->info
),
326 snd_ctl_elem_info_get_min(ctl
->info
));
331 case SND_CTL_ELEM_TYPE_INTEGER64
:
332 int64_val
= snd_ctl_elem_value_get_integer64(val
, index
);
334 if (int64_val
< snd_ctl_elem_info_get_min64(ctl
->info
)) {
335 ksft_print_msg("%s.%d value %lld less than minimum %lld\n",
336 ctl
->name
, index
, int64_val
,
337 snd_ctl_elem_info_get_min64(ctl
->info
));
341 if (int64_val
> snd_ctl_elem_info_get_max64(ctl
->info
)) {
342 ksft_print_msg("%s.%d value %lld more than maximum %ld\n",
343 ctl
->name
, index
, int64_val
,
344 snd_ctl_elem_info_get_max(ctl
->info
));
348 /* Only check step size if there is one and we're in bounds */
349 if (snd_ctl_elem_info_get_step64(ctl
->info
) &&
350 (int64_val
- snd_ctl_elem_info_get_min64(ctl
->info
)) %
351 snd_ctl_elem_info_get_step64(ctl
->info
)) {
352 ksft_print_msg("%s.%d value %lld invalid for step %lld minimum %lld\n",
353 ctl
->name
, index
, int64_val
,
354 snd_ctl_elem_info_get_step64(ctl
->info
),
355 snd_ctl_elem_info_get_min64(ctl
->info
));
360 case SND_CTL_ELEM_TYPE_ENUMERATED
:
361 int_val
= snd_ctl_elem_value_get_enumerated(val
, index
);
364 ksft_print_msg("%s.%d negative value %ld for enumeration\n",
365 ctl
->name
, index
, int_val
);
369 if (int_val
>= snd_ctl_elem_info_get_items(ctl
->info
)) {
370 ksft_print_msg("%s.%d value %ld more than item count %u\n",
371 ctl
->name
, index
, int_val
,
372 snd_ctl_elem_info_get_items(ctl
->info
));
378 /* No tests for other types */
386 * Check that the provided value meets the constraints for the
389 static bool ctl_value_valid(struct ctl_data
*ctl
, snd_ctl_elem_value_t
*val
)
394 for (i
= 0; i
< snd_ctl_elem_info_get_count(ctl
->info
); i
++)
395 if (!ctl_value_index_valid(ctl
, val
, i
))
402 * Check that we can read the default value and it is valid. Write
403 * tests use the read value to restore the default.
405 static void test_ctl_get_value(struct ctl_data
*ctl
)
409 /* If the control is turned off let's be polite */
410 if (snd_ctl_elem_info_is_inactive(ctl
->info
)) {
411 ksft_print_msg("%s is inactive\n", ctl
->name
);
412 ksft_test_result_skip("get_value.%s.%d\n",
413 ctl
->card
->card_name
, ctl
->elem
);
417 /* Can't test reading on an unreadable control */
418 if (!snd_ctl_elem_info_is_readable(ctl
->info
)) {
419 ksft_print_msg("%s is not readable\n", ctl
->name
);
420 ksft_test_result_skip("get_value.%s.%d\n",
421 ctl
->card
->card_name
, ctl
->elem
);
425 err
= snd_ctl_elem_read(ctl
->card
->handle
, ctl
->def_val
);
427 ksft_print_msg("snd_ctl_elem_read() failed: %s\n",
432 if (!ctl_value_valid(ctl
, ctl
->def_val
))
436 ksft_test_result(err
>= 0, "get_value.%s.%d\n",
437 ctl
->card
->card_name
, ctl
->elem
);
440 static bool strend(const char *haystack
, const char *needle
)
442 size_t haystack_len
= strlen(haystack
);
443 size_t needle_len
= strlen(needle
);
445 if (needle_len
> haystack_len
)
447 return strcmp(haystack
+ haystack_len
- needle_len
, needle
) == 0;
450 static void test_ctl_name(struct ctl_data
*ctl
)
454 ksft_print_msg("%s.%d %s\n", ctl
->card
->card_name
, ctl
->elem
,
457 /* Only boolean controls should end in Switch */
458 if (strend(ctl
->name
, " Switch")) {
459 if (snd_ctl_elem_info_get_type(ctl
->info
) != SND_CTL_ELEM_TYPE_BOOLEAN
) {
460 ksft_print_msg("%d.%d %s ends in Switch but is not boolean\n",
461 ctl
->card
->card
, ctl
->elem
, ctl
->name
);
466 /* Writeable boolean controls should end in Switch */
467 if (snd_ctl_elem_info_get_type(ctl
->info
) == SND_CTL_ELEM_TYPE_BOOLEAN
&&
468 snd_ctl_elem_info_is_writable(ctl
->info
)) {
469 if (!strend(ctl
->name
, " Switch")) {
470 ksft_print_msg("%d.%d %s is a writeable boolean but not a Switch\n",
471 ctl
->card
->card
, ctl
->elem
, ctl
->name
);
476 ksft_test_result(name_ok
, "name.%s.%d\n",
477 ctl
->card
->card_name
, ctl
->elem
);
480 static void show_values(struct ctl_data
*ctl
, snd_ctl_elem_value_t
*orig_val
,
481 snd_ctl_elem_value_t
*read_val
)
483 long long orig_int
, read_int
;
486 for (i
= 0; i
< snd_ctl_elem_info_get_count(ctl
->info
); i
++) {
487 switch (snd_ctl_elem_info_get_type(ctl
->info
)) {
488 case SND_CTL_ELEM_TYPE_BOOLEAN
:
489 orig_int
= snd_ctl_elem_value_get_boolean(orig_val
, i
);
490 read_int
= snd_ctl_elem_value_get_boolean(read_val
, i
);
493 case SND_CTL_ELEM_TYPE_INTEGER
:
494 orig_int
= snd_ctl_elem_value_get_integer(orig_val
, i
);
495 read_int
= snd_ctl_elem_value_get_integer(read_val
, i
);
498 case SND_CTL_ELEM_TYPE_INTEGER64
:
499 orig_int
= snd_ctl_elem_value_get_integer64(orig_val
,
501 read_int
= snd_ctl_elem_value_get_integer64(read_val
,
505 case SND_CTL_ELEM_TYPE_ENUMERATED
:
506 orig_int
= snd_ctl_elem_value_get_enumerated(orig_val
,
508 read_int
= snd_ctl_elem_value_get_enumerated(read_val
,
516 ksft_print_msg("%s.%d orig %lld read %lld, is_volatile %d\n",
517 ctl
->name
, i
, orig_int
, read_int
,
518 snd_ctl_elem_info_is_volatile(ctl
->info
));
522 static bool show_mismatch(struct ctl_data
*ctl
, int index
,
523 snd_ctl_elem_value_t
*read_val
,
524 snd_ctl_elem_value_t
*expected_val
)
526 long long expected_int
, read_int
;
529 * We factor out the code to compare values representable as
530 * integers, ensure that check doesn't log otherwise.
535 switch (snd_ctl_elem_info_get_type(ctl
->info
)) {
536 case SND_CTL_ELEM_TYPE_BOOLEAN
:
537 expected_int
= snd_ctl_elem_value_get_boolean(expected_val
,
539 read_int
= snd_ctl_elem_value_get_boolean(read_val
, index
);
542 case SND_CTL_ELEM_TYPE_INTEGER
:
543 expected_int
= snd_ctl_elem_value_get_integer(expected_val
,
545 read_int
= snd_ctl_elem_value_get_integer(read_val
, index
);
548 case SND_CTL_ELEM_TYPE_INTEGER64
:
549 expected_int
= snd_ctl_elem_value_get_integer64(expected_val
,
551 read_int
= snd_ctl_elem_value_get_integer64(read_val
,
555 case SND_CTL_ELEM_TYPE_ENUMERATED
:
556 expected_int
= snd_ctl_elem_value_get_enumerated(expected_val
,
558 read_int
= snd_ctl_elem_value_get_enumerated(read_val
,
566 if (expected_int
!= read_int
) {
568 * NOTE: The volatile attribute means that the hardware
569 * can voluntarily change the state of control element
570 * independent of any operation by software.
572 bool is_volatile
= snd_ctl_elem_info_is_volatile(ctl
->info
);
573 ksft_print_msg("%s.%d expected %lld but read %lld, is_volatile %d\n",
574 ctl
->name
, index
, expected_int
, read_int
, is_volatile
);
582 * Write a value then if possible verify that we get the expected
583 * result. An optional expected value can be provided if we expect
584 * the write to fail, for verifying that invalid writes don't corrupt
587 static int write_and_verify(struct ctl_data
*ctl
,
588 snd_ctl_elem_value_t
*write_val
,
589 snd_ctl_elem_value_t
*expected_val
)
592 bool error_expected
, mismatch_shown
;
593 snd_ctl_elem_value_t
*initial_val
, *read_val
, *w_val
;
594 snd_ctl_elem_value_alloca(&initial_val
);
595 snd_ctl_elem_value_alloca(&read_val
);
596 snd_ctl_elem_value_alloca(&w_val
);
599 * We need to copy the write value since writing can modify
600 * the value which causes surprises, and allocate an expected
601 * value if we expect to read back what we wrote.
603 snd_ctl_elem_value_copy(w_val
, write_val
);
605 error_expected
= true;
607 error_expected
= false;
608 snd_ctl_elem_value_alloca(&expected_val
);
609 snd_ctl_elem_value_copy(expected_val
, write_val
);
612 /* Store the value before we write */
613 if (snd_ctl_elem_info_is_readable(ctl
->info
)) {
614 snd_ctl_elem_value_set_id(initial_val
, ctl
->id
);
616 err
= snd_ctl_elem_read(ctl
->card
->handle
, initial_val
);
618 ksft_print_msg("snd_ctl_elem_read() failed: %s\n",
625 * Do the write, if we have an expected value ignore the error
626 * and carry on to validate the expected value.
628 err
= snd_ctl_elem_write(ctl
->card
->handle
, w_val
);
629 if (err
< 0 && !error_expected
) {
630 ksft_print_msg("snd_ctl_elem_write() failed: %s\n",
635 /* Can we do the verification part? */
636 if (!snd_ctl_elem_info_is_readable(ctl
->info
))
639 snd_ctl_elem_value_set_id(read_val
, ctl
->id
);
641 err
= snd_ctl_elem_read(ctl
->card
->handle
, read_val
);
643 ksft_print_msg("snd_ctl_elem_read() failed: %s\n",
649 * We can't verify any specific value for volatile controls
650 * but we should still check that whatever we read is a valid
651 * vale for the control.
653 if (snd_ctl_elem_info_is_volatile(ctl
->info
)) {
654 if (!ctl_value_valid(ctl
, read_val
)) {
655 ksft_print_msg("Volatile control %s has invalid value\n",
664 * Check for an event if the value changed, or confirm that
665 * there was none if it didn't. We rely on the kernel
666 * generating the notification before it returns from the
667 * write, this is currently true, should that ever change this
668 * will most likely break and need updating.
670 err
= wait_for_event(ctl
, 0);
671 if (snd_ctl_elem_value_compare(initial_val
, read_val
)) {
673 ksft_print_msg("No event generated for %s\n",
675 show_values(ctl
, initial_val
, read_val
);
676 ctl
->event_missing
++;
680 ksft_print_msg("Spurious event generated for %s\n",
682 show_values(ctl
, initial_val
, read_val
);
683 ctl
->event_spurious
++;
688 * Use the libray to compare values, if there's a mismatch
689 * carry on and try to provide a more useful diagnostic than
692 if (!snd_ctl_elem_value_compare(expected_val
, read_val
))
695 mismatch_shown
= false;
696 for (i
= 0; i
< snd_ctl_elem_info_get_count(ctl
->info
); i
++)
697 if (show_mismatch(ctl
, i
, read_val
, expected_val
))
698 mismatch_shown
= true;
701 ksft_print_msg("%s read and written values differ\n",
708 * Make sure we can write the default value back to the control, this
709 * should validate that at least some write works.
711 static void test_ctl_write_default(struct ctl_data
*ctl
)
715 /* If the control is turned off let's be polite */
716 if (snd_ctl_elem_info_is_inactive(ctl
->info
)) {
717 ksft_print_msg("%s is inactive\n", ctl
->name
);
718 ksft_test_result_skip("write_default.%s.%d\n",
719 ctl
->card
->card_name
, ctl
->elem
);
723 if (!snd_ctl_elem_info_is_writable(ctl
->info
)) {
724 ksft_print_msg("%s is not writeable\n", ctl
->name
);
725 ksft_test_result_skip("write_default.%s.%d\n",
726 ctl
->card
->card_name
, ctl
->elem
);
730 /* No idea what the default was for unreadable controls */
731 if (!snd_ctl_elem_info_is_readable(ctl
->info
)) {
732 ksft_print_msg("%s couldn't read default\n", ctl
->name
);
733 ksft_test_result_skip("write_default.%s.%d\n",
734 ctl
->card
->card_name
, ctl
->elem
);
738 err
= write_and_verify(ctl
, ctl
->def_val
, NULL
);
740 ksft_test_result(err
>= 0, "write_default.%s.%d\n",
741 ctl
->card
->card_name
, ctl
->elem
);
744 static bool test_ctl_write_valid_boolean(struct ctl_data
*ctl
)
748 snd_ctl_elem_value_t
*val
;
749 snd_ctl_elem_value_alloca(&val
);
751 snd_ctl_elem_value_set_id(val
, ctl
->id
);
753 for (i
= 0; i
< snd_ctl_elem_info_get_count(ctl
->info
); i
++) {
754 for (j
= 0; j
< 2; j
++) {
755 snd_ctl_elem_value_set_boolean(val
, i
, j
);
756 err
= write_and_verify(ctl
, val
, NULL
);
765 static bool test_ctl_write_valid_integer(struct ctl_data
*ctl
)
771 snd_ctl_elem_value_t
*val
;
772 snd_ctl_elem_value_alloca(&val
);
774 snd_ctl_elem_value_set_id(val
, ctl
->id
);
776 step
= snd_ctl_elem_info_get_step(ctl
->info
);
780 for (i
= 0; i
< snd_ctl_elem_info_get_count(ctl
->info
); i
++) {
781 for (j
= snd_ctl_elem_info_get_min(ctl
->info
);
782 j
<= snd_ctl_elem_info_get_max(ctl
->info
); j
+= step
) {
784 snd_ctl_elem_value_set_integer(val
, i
, j
);
785 err
= write_and_verify(ctl
, val
, NULL
);
795 static bool test_ctl_write_valid_integer64(struct ctl_data
*ctl
)
800 snd_ctl_elem_value_t
*val
;
801 snd_ctl_elem_value_alloca(&val
);
803 snd_ctl_elem_value_set_id(val
, ctl
->id
);
805 step
= snd_ctl_elem_info_get_step64(ctl
->info
);
809 for (i
= 0; i
< snd_ctl_elem_info_get_count(ctl
->info
); i
++) {
810 for (j
= snd_ctl_elem_info_get_min64(ctl
->info
);
811 j
<= snd_ctl_elem_info_get_max64(ctl
->info
); j
+= step
) {
813 snd_ctl_elem_value_set_integer64(val
, i
, j
);
814 err
= write_and_verify(ctl
, val
, NULL
);
823 static bool test_ctl_write_valid_enumerated(struct ctl_data
*ctl
)
827 snd_ctl_elem_value_t
*val
;
828 snd_ctl_elem_value_alloca(&val
);
830 snd_ctl_elem_value_set_id(val
, ctl
->id
);
832 for (i
= 0; i
< snd_ctl_elem_info_get_count(ctl
->info
); i
++) {
833 for (j
= 0; j
< snd_ctl_elem_info_get_items(ctl
->info
); j
++) {
834 snd_ctl_elem_value_set_enumerated(val
, i
, j
);
835 err
= write_and_verify(ctl
, val
, NULL
);
844 static void test_ctl_write_valid(struct ctl_data
*ctl
)
848 /* If the control is turned off let's be polite */
849 if (snd_ctl_elem_info_is_inactive(ctl
->info
)) {
850 ksft_print_msg("%s is inactive\n", ctl
->name
);
851 ksft_test_result_skip("write_valid.%s.%d\n",
852 ctl
->card
->card_name
, ctl
->elem
);
856 if (!snd_ctl_elem_info_is_writable(ctl
->info
)) {
857 ksft_print_msg("%s is not writeable\n", ctl
->name
);
858 ksft_test_result_skip("write_valid.%s.%d\n",
859 ctl
->card
->card_name
, ctl
->elem
);
863 switch (snd_ctl_elem_info_get_type(ctl
->info
)) {
864 case SND_CTL_ELEM_TYPE_BOOLEAN
:
865 pass
= test_ctl_write_valid_boolean(ctl
);
868 case SND_CTL_ELEM_TYPE_INTEGER
:
869 pass
= test_ctl_write_valid_integer(ctl
);
872 case SND_CTL_ELEM_TYPE_INTEGER64
:
873 pass
= test_ctl_write_valid_integer64(ctl
);
876 case SND_CTL_ELEM_TYPE_ENUMERATED
:
877 pass
= test_ctl_write_valid_enumerated(ctl
);
881 /* No tests for this yet */
882 ksft_test_result_skip("write_valid.%s.%d\n",
883 ctl
->card
->card_name
, ctl
->elem
);
887 /* Restore the default value to minimise disruption */
888 write_and_verify(ctl
, ctl
->def_val
, NULL
);
890 ksft_test_result(pass
, "write_valid.%s.%d\n",
891 ctl
->card
->card_name
, ctl
->elem
);
894 static bool test_ctl_write_invalid_value(struct ctl_data
*ctl
,
895 snd_ctl_elem_value_t
*val
)
899 /* Ideally this will fail... */
900 err
= snd_ctl_elem_write(ctl
->card
->handle
, val
);
904 /* ...but some devices will clamp to an in range value */
905 err
= snd_ctl_elem_read(ctl
->card
->handle
, val
);
907 ksft_print_msg("%s failed to read: %s\n",
908 ctl
->name
, snd_strerror(err
));
912 return !ctl_value_valid(ctl
, val
);
915 static bool test_ctl_write_invalid_boolean(struct ctl_data
*ctl
)
919 snd_ctl_elem_value_t
*val
;
920 snd_ctl_elem_value_alloca(&val
);
922 for (i
= 0; i
< snd_ctl_elem_info_get_count(ctl
->info
); i
++) {
923 snd_ctl_elem_value_copy(val
, ctl
->def_val
);
924 snd_ctl_elem_value_set_boolean(val
, i
, 2);
926 if (test_ctl_write_invalid_value(ctl
, val
))
933 static bool test_ctl_write_invalid_integer(struct ctl_data
*ctl
)
937 snd_ctl_elem_value_t
*val
;
938 snd_ctl_elem_value_alloca(&val
);
940 for (i
= 0; i
< snd_ctl_elem_info_get_count(ctl
->info
); i
++) {
941 if (snd_ctl_elem_info_get_min(ctl
->info
) != LONG_MIN
) {
942 /* Just under range */
943 snd_ctl_elem_value_copy(val
, ctl
->def_val
);
944 snd_ctl_elem_value_set_integer(val
, i
,
945 snd_ctl_elem_info_get_min(ctl
->info
) - 1);
947 if (test_ctl_write_invalid_value(ctl
, val
))
950 /* Minimum representable value */
951 snd_ctl_elem_value_copy(val
, ctl
->def_val
);
952 snd_ctl_elem_value_set_integer(val
, i
, LONG_MIN
);
954 if (test_ctl_write_invalid_value(ctl
, val
))
958 if (snd_ctl_elem_info_get_max(ctl
->info
) != LONG_MAX
) {
959 /* Just over range */
960 snd_ctl_elem_value_copy(val
, ctl
->def_val
);
961 snd_ctl_elem_value_set_integer(val
, i
,
962 snd_ctl_elem_info_get_max(ctl
->info
) + 1);
964 if (test_ctl_write_invalid_value(ctl
, val
))
967 /* Maximum representable value */
968 snd_ctl_elem_value_copy(val
, ctl
->def_val
);
969 snd_ctl_elem_value_set_integer(val
, i
, LONG_MAX
);
971 if (test_ctl_write_invalid_value(ctl
, val
))
979 static bool test_ctl_write_invalid_integer64(struct ctl_data
*ctl
)
983 snd_ctl_elem_value_t
*val
;
984 snd_ctl_elem_value_alloca(&val
);
986 for (i
= 0; i
< snd_ctl_elem_info_get_count(ctl
->info
); i
++) {
987 if (snd_ctl_elem_info_get_min64(ctl
->info
) != LLONG_MIN
) {
988 /* Just under range */
989 snd_ctl_elem_value_copy(val
, ctl
->def_val
);
990 snd_ctl_elem_value_set_integer64(val
, i
,
991 snd_ctl_elem_info_get_min64(ctl
->info
) - 1);
993 if (test_ctl_write_invalid_value(ctl
, val
))
996 /* Minimum representable value */
997 snd_ctl_elem_value_copy(val
, ctl
->def_val
);
998 snd_ctl_elem_value_set_integer64(val
, i
, LLONG_MIN
);
1000 if (test_ctl_write_invalid_value(ctl
, val
))
1004 if (snd_ctl_elem_info_get_max64(ctl
->info
) != LLONG_MAX
) {
1005 /* Just over range */
1006 snd_ctl_elem_value_copy(val
, ctl
->def_val
);
1007 snd_ctl_elem_value_set_integer64(val
, i
,
1008 snd_ctl_elem_info_get_max64(ctl
->info
) + 1);
1010 if (test_ctl_write_invalid_value(ctl
, val
))
1013 /* Maximum representable value */
1014 snd_ctl_elem_value_copy(val
, ctl
->def_val
);
1015 snd_ctl_elem_value_set_integer64(val
, i
, LLONG_MAX
);
1017 if (test_ctl_write_invalid_value(ctl
, val
))
1025 static bool test_ctl_write_invalid_enumerated(struct ctl_data
*ctl
)
1029 snd_ctl_elem_value_t
*val
;
1030 snd_ctl_elem_value_alloca(&val
);
1032 snd_ctl_elem_value_set_id(val
, ctl
->id
);
1034 for (i
= 0; i
< snd_ctl_elem_info_get_count(ctl
->info
); i
++) {
1035 /* One beyond maximum */
1036 snd_ctl_elem_value_copy(val
, ctl
->def_val
);
1037 snd_ctl_elem_value_set_enumerated(val
, i
,
1038 snd_ctl_elem_info_get_items(ctl
->info
));
1040 if (test_ctl_write_invalid_value(ctl
, val
))
1043 /* Maximum representable value */
1044 snd_ctl_elem_value_copy(val
, ctl
->def_val
);
1045 snd_ctl_elem_value_set_enumerated(val
, i
, UINT_MAX
);
1047 if (test_ctl_write_invalid_value(ctl
, val
))
1056 static void test_ctl_write_invalid(struct ctl_data
*ctl
)
1060 /* If the control is turned off let's be polite */
1061 if (snd_ctl_elem_info_is_inactive(ctl
->info
)) {
1062 ksft_print_msg("%s is inactive\n", ctl
->name
);
1063 ksft_test_result_skip("write_invalid.%s.%d\n",
1064 ctl
->card
->card_name
, ctl
->elem
);
1068 if (!snd_ctl_elem_info_is_writable(ctl
->info
)) {
1069 ksft_print_msg("%s is not writeable\n", ctl
->name
);
1070 ksft_test_result_skip("write_invalid.%s.%d\n",
1071 ctl
->card
->card_name
, ctl
->elem
);
1075 switch (snd_ctl_elem_info_get_type(ctl
->info
)) {
1076 case SND_CTL_ELEM_TYPE_BOOLEAN
:
1077 pass
= test_ctl_write_invalid_boolean(ctl
);
1080 case SND_CTL_ELEM_TYPE_INTEGER
:
1081 pass
= test_ctl_write_invalid_integer(ctl
);
1084 case SND_CTL_ELEM_TYPE_INTEGER64
:
1085 pass
= test_ctl_write_invalid_integer64(ctl
);
1088 case SND_CTL_ELEM_TYPE_ENUMERATED
:
1089 pass
= test_ctl_write_invalid_enumerated(ctl
);
1093 /* No tests for this yet */
1094 ksft_test_result_skip("write_invalid.%s.%d\n",
1095 ctl
->card
->card_name
, ctl
->elem
);
1099 /* Restore the default value to minimise disruption */
1100 write_and_verify(ctl
, ctl
->def_val
, NULL
);
1102 ksft_test_result(pass
, "write_invalid.%s.%d\n",
1103 ctl
->card
->card_name
, ctl
->elem
);
1106 static void test_ctl_event_missing(struct ctl_data
*ctl
)
1108 ksft_test_result(!ctl
->event_missing
, "event_missing.%s.%d\n",
1109 ctl
->card
->card_name
, ctl
->elem
);
1112 static void test_ctl_event_spurious(struct ctl_data
*ctl
)
1114 ksft_test_result(!ctl
->event_spurious
, "event_spurious.%s.%d\n",
1115 ctl
->card
->card_name
, ctl
->elem
);
1120 struct ctl_data
*ctl
;
1122 ksft_print_header();
1126 ksft_set_plan(num_controls
* TESTS_PER_CONTROL
);
1128 for (ctl
= ctl_list
; ctl
!= NULL
; ctl
= ctl
->next
) {
1130 * Must test get_value() before we write anything, the
1131 * test stores the default value for later cleanup.
1133 test_ctl_get_value(ctl
);
1135 test_ctl_write_default(ctl
);
1136 test_ctl_write_valid(ctl
);
1137 test_ctl_write_invalid(ctl
);
1138 test_ctl_event_missing(ctl
);
1139 test_ctl_event_spurious(ctl
);