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
find_controls(void)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 */
wait_for_event(struct ctl_data * ctl,int timeout)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
ctl_value_index_valid(struct ctl_data * ctl,snd_ctl_elem_value_t * val,int index)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 */
ctl_value_valid(struct ctl_data * ctl,snd_ctl_elem_value_t * val)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 */
test_ctl_get_value(struct ctl_data * ctl)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
strend(const char * haystack,const char * needle)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
test_ctl_name(struct ctl_data * ctl)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
show_values(struct ctl_data * ctl,snd_ctl_elem_value_t * orig_val,snd_ctl_elem_value_t * read_val)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
show_mismatch(struct ctl_data * ctl,int index,snd_ctl_elem_value_t * read_val,snd_ctl_elem_value_t * expected_val)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 */
write_and_verify(struct ctl_data * ctl,snd_ctl_elem_value_t * write_val,snd_ctl_elem_value_t * expected_val)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 */
test_ctl_write_default(struct ctl_data * ctl)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
test_ctl_write_valid_boolean(struct ctl_data * ctl)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
test_ctl_write_valid_integer(struct ctl_data * ctl)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
test_ctl_write_valid_integer64(struct ctl_data * ctl)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
test_ctl_write_valid_enumerated(struct ctl_data * ctl)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
test_ctl_write_valid(struct ctl_data * ctl)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
test_ctl_write_invalid_value(struct ctl_data * ctl,snd_ctl_elem_value_t * val)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
test_ctl_write_invalid_boolean(struct ctl_data * ctl)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
test_ctl_write_invalid_integer(struct ctl_data * ctl)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
test_ctl_write_invalid_integer64(struct ctl_data * ctl)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
test_ctl_write_invalid_enumerated(struct ctl_data * ctl)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
test_ctl_write_invalid(struct ctl_data * ctl)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
test_ctl_event_missing(struct ctl_data * ctl)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
test_ctl_event_spurious(struct ctl_data * ctl)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
main(void)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