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