Lines Matching +full:system +full:- +full:ctl
1 // SPDX-License-Identifier: GPL-2.0
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
29 #include "alsa-local.h"
64 int card, ctl, err; in find_controls() local
70 card = -1; in find_controls()
83 err = snd_ctl_open_lconf(&card_data->handle, name, 0, config); in find_controls()
97 err = snd_ctl_card_info_malloc(&card_data->info); in find_controls()
102 err = snd_ctl_card_info(card_data->handle, card_data->info); in find_controls()
104 card_data->card_name = snd_ctl_card_info_get_id(card_data->info); in find_controls()
105 if (!card_data->card_name) in find_controls()
111 if (!card_data->card_name) in find_controls()
112 card_data->card_name = "Unknown"; in find_controls()
114 ksft_print_msg("Card %d/%s - %s (%s)\n", card, in find_controls()
115 card_data->card_name, card_name, card_longname); in find_controls()
118 snd_ctl_elem_list_malloc(&card_data->ctls); in find_controls()
119 snd_ctl_elem_list(card_data->handle, card_data->ctls); in find_controls()
120 card_data->num_ctls = snd_ctl_elem_list_get_count(card_data->ctls); in find_controls()
123 snd_ctl_elem_list_alloc_space(card_data->ctls, card_data->num_ctls); in find_controls()
124 snd_ctl_elem_list(card_data->handle, card_data->ctls); in find_controls()
126 card_data->card = num_cards++; in find_controls()
127 card_data->next = card_list; in find_controls()
130 num_controls += card_data->num_ctls; in find_controls()
132 for (ctl = 0; ctl < card_data->num_ctls; ctl++) { in find_controls()
138 ctl_data->card = card_data; in find_controls()
139 ctl_data->elem = ctl; in find_controls()
140 ctl_data->name = snd_ctl_elem_list_get_name(card_data->ctls, in find_controls()
141 ctl); in find_controls()
143 err = snd_ctl_elem_id_malloc(&ctl_data->id); in find_controls()
147 err = snd_ctl_elem_info_malloc(&ctl_data->info); in find_controls()
151 err = snd_ctl_elem_value_malloc(&ctl_data->def_val); in find_controls()
155 snd_ctl_elem_list_get_id(card_data->ctls, ctl, in find_controls()
156 ctl_data->id); in find_controls()
157 snd_ctl_elem_info_set_id(ctl_data->info, ctl_data->id); in find_controls()
158 err = snd_ctl_elem_info(card_data->handle, in find_controls()
159 ctl_data->info); in find_controls()
163 ctl_data->name); in find_controls()
166 snd_ctl_elem_value_set_id(ctl_data->def_val, in find_controls()
167 ctl_data->id); in find_controls()
169 ctl_data->next = ctl_list; in find_controls()
174 err = snd_ctl_subscribe_events(card_data->handle, true); in find_controls()
180 err = snd_ctl_poll_descriptors_count(card_data->handle); in find_controls()
186 err = snd_ctl_poll_descriptors(card_data->handle, in find_controls()
187 &card_data->pollfd, 1); in find_controls()
207 static int wait_for_event(struct ctl_data *ctl, int timeout) in wait_for_event() argument
218 err = poll(&(ctl->card->pollfd), 1, timeout); in wait_for_event()
221 ctl->name, strerror(errno), errno); in wait_for_event()
222 return -1; in wait_for_event()
228 err = snd_ctl_poll_descriptors_revents(ctl->card->handle, in wait_for_event()
229 &(ctl->card->pollfd), in wait_for_event()
233 ctl->name, err); in wait_for_event()
238 ctl->name); in wait_for_event()
239 return -1; in wait_for_event()
247 err = snd_ctl_read(ctl->card->handle, event); in wait_for_event()
250 ctl->name, err); in wait_for_event()
260 if (ev_id != snd_ctl_elem_info_get_numid(ctl->info)) { in wait_for_event()
261 ksft_print_msg("Event for unexpected ctl %s\n", in wait_for_event()
268 ctl->name); in wait_for_event()
269 return -1; in wait_for_event()
276 static bool ctl_value_index_valid(struct ctl_data *ctl, in ctl_value_index_valid() argument
283 switch (snd_ctl_elem_info_get_type(ctl->info)) { in ctl_value_index_valid()
286 ctl->name, index); in ctl_value_index_valid()
297 ctl->name, index, int_val); in ctl_value_index_valid()
305 if (int_val < snd_ctl_elem_info_get_min(ctl->info)) { in ctl_value_index_valid()
307 ctl->name, index, int_val, in ctl_value_index_valid()
308 snd_ctl_elem_info_get_min(ctl->info)); in ctl_value_index_valid()
312 if (int_val > snd_ctl_elem_info_get_max(ctl->info)) { in ctl_value_index_valid()
314 ctl->name, index, int_val, in ctl_value_index_valid()
315 snd_ctl_elem_info_get_max(ctl->info)); in ctl_value_index_valid()
320 if (snd_ctl_elem_info_get_step(ctl->info) && in ctl_value_index_valid()
321 (int_val - snd_ctl_elem_info_get_min(ctl->info) % in ctl_value_index_valid()
322 snd_ctl_elem_info_get_step(ctl->info))) { in ctl_value_index_valid()
324 ctl->name, index, int_val, in ctl_value_index_valid()
325 snd_ctl_elem_info_get_step(ctl->info), in ctl_value_index_valid()
326 snd_ctl_elem_info_get_min(ctl->info)); in ctl_value_index_valid()
334 if (int64_val < snd_ctl_elem_info_get_min64(ctl->info)) { in ctl_value_index_valid()
336 ctl->name, index, int64_val, in ctl_value_index_valid()
337 snd_ctl_elem_info_get_min64(ctl->info)); in ctl_value_index_valid()
341 if (int64_val > snd_ctl_elem_info_get_max64(ctl->info)) { in ctl_value_index_valid()
343 ctl->name, index, int64_val, in ctl_value_index_valid()
344 snd_ctl_elem_info_get_max(ctl->info)); in ctl_value_index_valid()
349 if (snd_ctl_elem_info_get_step64(ctl->info) && in ctl_value_index_valid()
350 (int64_val - snd_ctl_elem_info_get_min64(ctl->info)) % in ctl_value_index_valid()
351 snd_ctl_elem_info_get_step64(ctl->info)) { in ctl_value_index_valid()
353 ctl->name, index, int64_val, in ctl_value_index_valid()
354 snd_ctl_elem_info_get_step64(ctl->info), in ctl_value_index_valid()
355 snd_ctl_elem_info_get_min64(ctl->info)); in ctl_value_index_valid()
365 ctl->name, index, int_val); in ctl_value_index_valid()
369 if (int_val >= snd_ctl_elem_info_get_items(ctl->info)) { in ctl_value_index_valid()
371 ctl->name, index, int_val, in ctl_value_index_valid()
372 snd_ctl_elem_info_get_items(ctl->info)); in ctl_value_index_valid()
389 static bool ctl_value_valid(struct ctl_data *ctl, snd_ctl_elem_value_t *val) in ctl_value_valid() argument
394 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) in ctl_value_valid()
395 if (!ctl_value_index_valid(ctl, val, i)) in ctl_value_valid()
405 static void test_ctl_get_value(struct ctl_data *ctl) in test_ctl_get_value() argument
410 if (snd_ctl_elem_info_is_inactive(ctl->info)) { in test_ctl_get_value()
411 ksft_print_msg("%s is inactive\n", ctl->name); in test_ctl_get_value()
413 ctl->card->card_name, ctl->elem); in test_ctl_get_value()
418 if (!snd_ctl_elem_info_is_readable(ctl->info)) { in test_ctl_get_value()
419 ksft_print_msg("%s is not readable\n", ctl->name); in test_ctl_get_value()
421 ctl->card->card_name, ctl->elem); in test_ctl_get_value()
425 err = snd_ctl_elem_read(ctl->card->handle, ctl->def_val); in test_ctl_get_value()
432 if (!ctl_value_valid(ctl, ctl->def_val)) in test_ctl_get_value()
433 err = -EINVAL; in test_ctl_get_value()
437 ctl->card->card_name, ctl->elem); in test_ctl_get_value()
447 return strcmp(haystack + haystack_len - needle_len, needle) == 0; in strend()
450 static void test_ctl_name(struct ctl_data *ctl) in test_ctl_name() argument
454 ksft_print_msg("%s.%d %s\n", ctl->card->card_name, ctl->elem, in test_ctl_name()
455 ctl->name); in test_ctl_name()
458 if (strend(ctl->name, " Switch")) { in test_ctl_name()
459 if (snd_ctl_elem_info_get_type(ctl->info) != SND_CTL_ELEM_TYPE_BOOLEAN) { in test_ctl_name()
461 ctl->card->card, ctl->elem, ctl->name); in test_ctl_name()
467 if (snd_ctl_elem_info_get_type(ctl->info) == SND_CTL_ELEM_TYPE_BOOLEAN && in test_ctl_name()
468 snd_ctl_elem_info_is_writable(ctl->info)) { in test_ctl_name()
469 if (!strend(ctl->name, " Switch")) { in test_ctl_name()
471 ctl->card->card, ctl->elem, ctl->name); in test_ctl_name()
477 ctl->card->card_name, ctl->elem); in test_ctl_name()
480 static void show_values(struct ctl_data *ctl, snd_ctl_elem_value_t *orig_val, in show_values() argument
486 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) { in show_values()
487 switch (snd_ctl_elem_info_get_type(ctl->info)) { in show_values()
517 ctl->name, i, orig_int, read_int, in show_values()
518 snd_ctl_elem_info_is_volatile(ctl->info)); in show_values()
522 static bool show_mismatch(struct ctl_data *ctl, int index, in show_mismatch() argument
535 switch (snd_ctl_elem_info_get_type(ctl->info)) { in show_mismatch()
572 bool is_volatile = snd_ctl_elem_info_is_volatile(ctl->info); in show_mismatch()
574 ctl->name, index, expected_int, read_int, is_volatile); in show_mismatch()
587 static int write_and_verify(struct ctl_data *ctl, in write_and_verify() argument
613 if (snd_ctl_elem_info_is_readable(ctl->info)) { in write_and_verify()
614 snd_ctl_elem_value_set_id(initial_val, ctl->id); in write_and_verify()
616 err = snd_ctl_elem_read(ctl->card->handle, initial_val); in write_and_verify()
628 err = snd_ctl_elem_write(ctl->card->handle, w_val); in write_and_verify()
636 if (!snd_ctl_elem_info_is_readable(ctl->info)) in write_and_verify()
639 snd_ctl_elem_value_set_id(read_val, ctl->id); in write_and_verify()
641 err = snd_ctl_elem_read(ctl->card->handle, read_val); in write_and_verify()
653 if (snd_ctl_elem_info_is_volatile(ctl->info)) { in write_and_verify()
654 if (!ctl_value_valid(ctl, read_val)) { in write_and_verify()
656 ctl->name); in write_and_verify()
657 return -EINVAL; in write_and_verify()
670 err = wait_for_event(ctl, 0); in write_and_verify()
674 ctl->name); in write_and_verify()
675 show_values(ctl, initial_val, read_val); in write_and_verify()
676 ctl->event_missing++; in write_and_verify()
681 ctl->name); in write_and_verify()
682 show_values(ctl, initial_val, read_val); in write_and_verify()
683 ctl->event_spurious++; in write_and_verify()
696 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) in write_and_verify()
697 if (show_mismatch(ctl, i, read_val, expected_val)) in write_and_verify()
702 ctl->name); in write_and_verify()
704 return -1; in write_and_verify()
711 static void test_ctl_write_default(struct ctl_data *ctl) in test_ctl_write_default() argument
716 if (snd_ctl_elem_info_is_inactive(ctl->info)) { in test_ctl_write_default()
717 ksft_print_msg("%s is inactive\n", ctl->name); in test_ctl_write_default()
719 ctl->card->card_name, ctl->elem); in test_ctl_write_default()
723 if (!snd_ctl_elem_info_is_writable(ctl->info)) { in test_ctl_write_default()
724 ksft_print_msg("%s is not writeable\n", ctl->name); in test_ctl_write_default()
726 ctl->card->card_name, ctl->elem); in test_ctl_write_default()
731 if (!snd_ctl_elem_info_is_readable(ctl->info)) { in test_ctl_write_default()
732 ksft_print_msg("%s couldn't read default\n", ctl->name); in test_ctl_write_default()
734 ctl->card->card_name, ctl->elem); in test_ctl_write_default()
738 err = write_and_verify(ctl, ctl->def_val, NULL); in test_ctl_write_default()
741 ctl->card->card_name, ctl->elem); in test_ctl_write_default()
744 static bool test_ctl_write_valid_boolean(struct ctl_data *ctl) in test_ctl_write_valid_boolean() argument
751 snd_ctl_elem_value_set_id(val, ctl->id); in test_ctl_write_valid_boolean()
753 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) { in test_ctl_write_valid_boolean()
756 err = write_and_verify(ctl, val, NULL); in test_ctl_write_valid_boolean()
765 static bool test_ctl_write_valid_integer(struct ctl_data *ctl) in test_ctl_write_valid_integer() argument
774 snd_ctl_elem_value_set_id(val, ctl->id); in test_ctl_write_valid_integer()
776 step = snd_ctl_elem_info_get_step(ctl->info); in test_ctl_write_valid_integer()
780 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) { in test_ctl_write_valid_integer()
781 for (j = snd_ctl_elem_info_get_min(ctl->info); in test_ctl_write_valid_integer()
782 j <= snd_ctl_elem_info_get_max(ctl->info); j += step) { in test_ctl_write_valid_integer()
785 err = write_and_verify(ctl, val, NULL); in test_ctl_write_valid_integer()
795 static bool test_ctl_write_valid_integer64(struct ctl_data *ctl) in test_ctl_write_valid_integer64() argument
803 snd_ctl_elem_value_set_id(val, ctl->id); in test_ctl_write_valid_integer64()
805 step = snd_ctl_elem_info_get_step64(ctl->info); in test_ctl_write_valid_integer64()
809 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) { in test_ctl_write_valid_integer64()
810 for (j = snd_ctl_elem_info_get_min64(ctl->info); in test_ctl_write_valid_integer64()
811 j <= snd_ctl_elem_info_get_max64(ctl->info); j += step) { in test_ctl_write_valid_integer64()
814 err = write_and_verify(ctl, val, NULL); in test_ctl_write_valid_integer64()
823 static bool test_ctl_write_valid_enumerated(struct ctl_data *ctl) in test_ctl_write_valid_enumerated() argument
830 snd_ctl_elem_value_set_id(val, ctl->id); in test_ctl_write_valid_enumerated()
832 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) { in test_ctl_write_valid_enumerated()
833 for (j = 0; j < snd_ctl_elem_info_get_items(ctl->info); j++) { in test_ctl_write_valid_enumerated()
835 err = write_and_verify(ctl, val, NULL); in test_ctl_write_valid_enumerated()
844 static void test_ctl_write_valid(struct ctl_data *ctl) in test_ctl_write_valid() argument
849 if (snd_ctl_elem_info_is_inactive(ctl->info)) { in test_ctl_write_valid()
850 ksft_print_msg("%s is inactive\n", ctl->name); in test_ctl_write_valid()
852 ctl->card->card_name, ctl->elem); in test_ctl_write_valid()
856 if (!snd_ctl_elem_info_is_writable(ctl->info)) { in test_ctl_write_valid()
857 ksft_print_msg("%s is not writeable\n", ctl->name); in test_ctl_write_valid()
859 ctl->card->card_name, ctl->elem); in test_ctl_write_valid()
863 switch (snd_ctl_elem_info_get_type(ctl->info)) { in test_ctl_write_valid()
865 pass = test_ctl_write_valid_boolean(ctl); in test_ctl_write_valid()
869 pass = test_ctl_write_valid_integer(ctl); in test_ctl_write_valid()
873 pass = test_ctl_write_valid_integer64(ctl); in test_ctl_write_valid()
877 pass = test_ctl_write_valid_enumerated(ctl); in test_ctl_write_valid()
883 ctl->card->card_name, ctl->elem); in test_ctl_write_valid()
888 write_and_verify(ctl, ctl->def_val, NULL); in test_ctl_write_valid()
891 ctl->card->card_name, ctl->elem); in test_ctl_write_valid()
894 static bool test_ctl_write_invalid_value(struct ctl_data *ctl, in test_ctl_write_invalid_value() argument
900 err = snd_ctl_elem_write(ctl->card->handle, val); in test_ctl_write_invalid_value()
905 err = snd_ctl_elem_read(ctl->card->handle, val); in test_ctl_write_invalid_value()
908 ctl->name, snd_strerror(err)); in test_ctl_write_invalid_value()
912 return !ctl_value_valid(ctl, val); in test_ctl_write_invalid_value()
915 static bool test_ctl_write_invalid_boolean(struct ctl_data *ctl) in test_ctl_write_invalid_boolean() argument
922 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) { in test_ctl_write_invalid_boolean()
923 snd_ctl_elem_value_copy(val, ctl->def_val); in test_ctl_write_invalid_boolean()
926 if (test_ctl_write_invalid_value(ctl, val)) in test_ctl_write_invalid_boolean()
933 static bool test_ctl_write_invalid_integer(struct ctl_data *ctl) in test_ctl_write_invalid_integer() argument
940 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) { in test_ctl_write_invalid_integer()
941 if (snd_ctl_elem_info_get_min(ctl->info) != LONG_MIN) { in test_ctl_write_invalid_integer()
943 snd_ctl_elem_value_copy(val, ctl->def_val); in test_ctl_write_invalid_integer()
945 snd_ctl_elem_info_get_min(ctl->info) - 1); in test_ctl_write_invalid_integer()
947 if (test_ctl_write_invalid_value(ctl, val)) in test_ctl_write_invalid_integer()
951 snd_ctl_elem_value_copy(val, ctl->def_val); in test_ctl_write_invalid_integer()
954 if (test_ctl_write_invalid_value(ctl, val)) in test_ctl_write_invalid_integer()
958 if (snd_ctl_elem_info_get_max(ctl->info) != LONG_MAX) { in test_ctl_write_invalid_integer()
960 snd_ctl_elem_value_copy(val, ctl->def_val); in test_ctl_write_invalid_integer()
962 snd_ctl_elem_info_get_max(ctl->info) + 1); in test_ctl_write_invalid_integer()
964 if (test_ctl_write_invalid_value(ctl, val)) in test_ctl_write_invalid_integer()
968 snd_ctl_elem_value_copy(val, ctl->def_val); in test_ctl_write_invalid_integer()
971 if (test_ctl_write_invalid_value(ctl, val)) in test_ctl_write_invalid_integer()
979 static bool test_ctl_write_invalid_integer64(struct ctl_data *ctl) in test_ctl_write_invalid_integer64() argument
986 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) { in test_ctl_write_invalid_integer64()
987 if (snd_ctl_elem_info_get_min64(ctl->info) != LLONG_MIN) { in test_ctl_write_invalid_integer64()
989 snd_ctl_elem_value_copy(val, ctl->def_val); in test_ctl_write_invalid_integer64()
991 snd_ctl_elem_info_get_min64(ctl->info) - 1); in test_ctl_write_invalid_integer64()
993 if (test_ctl_write_invalid_value(ctl, val)) in test_ctl_write_invalid_integer64()
997 snd_ctl_elem_value_copy(val, ctl->def_val); in test_ctl_write_invalid_integer64()
1000 if (test_ctl_write_invalid_value(ctl, val)) in test_ctl_write_invalid_integer64()
1004 if (snd_ctl_elem_info_get_max64(ctl->info) != LLONG_MAX) { in test_ctl_write_invalid_integer64()
1006 snd_ctl_elem_value_copy(val, ctl->def_val); in test_ctl_write_invalid_integer64()
1008 snd_ctl_elem_info_get_max64(ctl->info) + 1); in test_ctl_write_invalid_integer64()
1010 if (test_ctl_write_invalid_value(ctl, val)) in test_ctl_write_invalid_integer64()
1014 snd_ctl_elem_value_copy(val, ctl->def_val); in test_ctl_write_invalid_integer64()
1017 if (test_ctl_write_invalid_value(ctl, val)) in test_ctl_write_invalid_integer64()
1025 static bool test_ctl_write_invalid_enumerated(struct ctl_data *ctl) in test_ctl_write_invalid_enumerated() argument
1032 snd_ctl_elem_value_set_id(val, ctl->id); in test_ctl_write_invalid_enumerated()
1034 for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) { in test_ctl_write_invalid_enumerated()
1036 snd_ctl_elem_value_copy(val, ctl->def_val); in test_ctl_write_invalid_enumerated()
1038 snd_ctl_elem_info_get_items(ctl->info)); in test_ctl_write_invalid_enumerated()
1040 if (test_ctl_write_invalid_value(ctl, val)) in test_ctl_write_invalid_enumerated()
1044 snd_ctl_elem_value_copy(val, ctl->def_val); in test_ctl_write_invalid_enumerated()
1047 if (test_ctl_write_invalid_value(ctl, val)) in test_ctl_write_invalid_enumerated()
1056 static void test_ctl_write_invalid(struct ctl_data *ctl) in test_ctl_write_invalid() argument
1061 if (snd_ctl_elem_info_is_inactive(ctl->info)) { in test_ctl_write_invalid()
1062 ksft_print_msg("%s is inactive\n", ctl->name); in test_ctl_write_invalid()
1064 ctl->card->card_name, ctl->elem); in test_ctl_write_invalid()
1068 if (!snd_ctl_elem_info_is_writable(ctl->info)) { in test_ctl_write_invalid()
1069 ksft_print_msg("%s is not writeable\n", ctl->name); in test_ctl_write_invalid()
1071 ctl->card->card_name, ctl->elem); in test_ctl_write_invalid()
1075 switch (snd_ctl_elem_info_get_type(ctl->info)) { in test_ctl_write_invalid()
1077 pass = test_ctl_write_invalid_boolean(ctl); in test_ctl_write_invalid()
1081 pass = test_ctl_write_invalid_integer(ctl); in test_ctl_write_invalid()
1085 pass = test_ctl_write_invalid_integer64(ctl); in test_ctl_write_invalid()
1089 pass = test_ctl_write_invalid_enumerated(ctl); in test_ctl_write_invalid()
1095 ctl->card->card_name, ctl->elem); in test_ctl_write_invalid()
1100 write_and_verify(ctl, ctl->def_val, NULL); in test_ctl_write_invalid()
1103 ctl->card->card_name, ctl->elem); in test_ctl_write_invalid()
1106 static void test_ctl_event_missing(struct ctl_data *ctl) in test_ctl_event_missing() argument
1108 ksft_test_result(!ctl->event_missing, "event_missing.%s.%d\n", in test_ctl_event_missing()
1109 ctl->card->card_name, ctl->elem); in test_ctl_event_missing()
1112 static void test_ctl_event_spurious(struct ctl_data *ctl) in test_ctl_event_spurious() argument
1114 ksft_test_result(!ctl->event_spurious, "event_spurious.%s.%d\n", in test_ctl_event_spurious()
1115 ctl->card->card_name, ctl->elem); in test_ctl_event_spurious()
1120 struct ctl_data *ctl; in main() local
1128 for (ctl = ctl_list; ctl != NULL; ctl = ctl->next) { in main()
1133 test_ctl_get_value(ctl); in main()
1134 test_ctl_name(ctl); in main()
1135 test_ctl_write_default(ctl); in main()
1136 test_ctl_write_valid(ctl); in main()
1137 test_ctl_write_invalid(ctl); in main()
1138 test_ctl_event_missing(ctl); in main()
1139 test_ctl_event_spurious(ctl); in main()