kselftest: alsa: Add test case for writing invalid values
[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 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
30 #define TESTS_PER_CONTROL 4
31
32 struct card_data {
33         snd_ctl_t *handle;
34         int card;
35         int num_ctls;
36         snd_ctl_elem_list_t *ctls;
37         struct card_data *next;
38 };
39
40 struct ctl_data {
41         const char *name;
42         snd_ctl_elem_id_t *id;
43         snd_ctl_elem_info_t *info;
44         snd_ctl_elem_value_t *def_val;
45         int elem;
46         struct card_data *card;
47         struct ctl_data *next;
48 };
49
50 static const char *alsa_config =
51 "ctl.hw {\n"
52 "       @args [ CARD ]\n"
53 "       @args.CARD.type string\n"
54 "       type hw\n"
55 "       card $CARD\n"
56 "}\n"
57 ;
58
59 int num_cards = 0;
60 int num_controls = 0;
61 struct card_data *card_list = NULL;
62 struct ctl_data *ctl_list = NULL;
63
64 #ifdef SND_LIB_VER
65 #if SND_LIB_VERSION >= SND_LIB_VER(1, 2, 6)
66 #define LIB_HAS_LOAD_STRING
67 #endif
68 #endif
69
70 #ifndef LIB_HAS_LOAD_STRING
71 int snd_config_load_string(snd_config_t **config, const char *s, size_t size)
72 {
73         snd_input_t *input;
74         snd_config_t *dst;
75         int err;
76
77         assert(config && s);
78         if (size == 0)
79                 size = strlen(s);
80         err = snd_input_buffer_open(&input, s, size);
81         if (err < 0)
82                 return err;
83         err = snd_config_top(&dst);
84         if (err < 0) {
85                 snd_input_close(input);
86                 return err;
87         }
88         err = snd_config_load(dst, input);
89         snd_input_close(input);
90         if (err < 0) {
91                 snd_config_delete(dst);
92                 return err;
93         }
94         *config = dst;
95         return 0;
96 }
97 #endif
98
99 void find_controls(void)
100 {
101         char name[32];
102         int card, ctl, err;
103         struct card_data *card_data;
104         struct ctl_data *ctl_data;
105         snd_config_t *config;
106
107         card = -1;
108         if (snd_card_next(&card) < 0 || card < 0)
109                 return;
110
111         err = snd_config_load_string(&config, alsa_config, strlen(alsa_config));
112         if (err < 0) {
113                 ksft_print_msg("Unable to parse custom alsa-lib configuration: %s\n",
114                                snd_strerror(err));
115                 ksft_exit_fail();
116         }
117
118         while (card >= 0) {
119                 sprintf(name, "hw:%d", card);
120
121                 card_data = malloc(sizeof(*card_data));
122                 if (!card_data)
123                         ksft_exit_fail_msg("Out of memory\n");
124
125                 err = snd_ctl_open_lconf(&card_data->handle, name, 0, config);
126                 if (err < 0) {
127                         ksft_print_msg("Failed to get hctl for card %d: %s\n",
128                                        card, snd_strerror(err));
129                         goto next_card;
130                 }
131
132                 /* Count controls */
133                 snd_ctl_elem_list_malloc(&card_data->ctls);
134                 snd_ctl_elem_list(card_data->handle, card_data->ctls);
135                 card_data->num_ctls = snd_ctl_elem_list_get_count(card_data->ctls);
136
137                 /* Enumerate control information */
138                 snd_ctl_elem_list_alloc_space(card_data->ctls, card_data->num_ctls);
139                 snd_ctl_elem_list(card_data->handle, card_data->ctls);
140
141                 card_data->card = num_cards++;
142                 card_data->next = card_list;
143                 card_list = card_data;
144
145                 num_controls += card_data->num_ctls;
146
147                 for (ctl = 0; ctl < card_data->num_ctls; ctl++) {
148                         ctl_data = malloc(sizeof(*ctl_data));
149                         if (!ctl_data)
150                                 ksft_exit_fail_msg("Out of memory\n");
151
152                         ctl_data->card = card_data;
153                         ctl_data->elem = ctl;
154                         ctl_data->name = snd_ctl_elem_list_get_name(card_data->ctls,
155                                                                     ctl);
156
157                         err = snd_ctl_elem_id_malloc(&ctl_data->id);
158                         if (err < 0)
159                                 ksft_exit_fail_msg("Out of memory\n");
160
161                         err = snd_ctl_elem_info_malloc(&ctl_data->info);
162                         if (err < 0)
163                                 ksft_exit_fail_msg("Out of memory\n");
164
165                         err = snd_ctl_elem_value_malloc(&ctl_data->def_val);
166                         if (err < 0)
167                                 ksft_exit_fail_msg("Out of memory\n");
168
169                         snd_ctl_elem_list_get_id(card_data->ctls, ctl,
170                                                  ctl_data->id);
171                         snd_ctl_elem_info_set_id(ctl_data->info, ctl_data->id);
172                         err = snd_ctl_elem_info(card_data->handle,
173                                                 ctl_data->info);
174                         if (err < 0) {
175                                 ksft_print_msg("%s getting info for %d\n",
176                                                snd_strerror(err),
177                                                ctl_data->name);
178                         }
179
180                         snd_ctl_elem_value_set_id(ctl_data->def_val,
181                                                   ctl_data->id);
182
183                         ctl_data->next = ctl_list;
184                         ctl_list = ctl_data;
185                 }
186
187         next_card:
188                 if (snd_card_next(&card) < 0) {
189                         ksft_print_msg("snd_card_next");
190                         break;
191                 }
192         }
193
194         snd_config_delete(config);
195 }
196
197 bool ctl_value_index_valid(struct ctl_data *ctl, snd_ctl_elem_value_t *val,
198                            int index)
199 {
200         long int_val;
201         long long int64_val;
202
203         switch (snd_ctl_elem_info_get_type(ctl->info)) {
204         case SND_CTL_ELEM_TYPE_NONE:
205                 ksft_print_msg("%s.%d Invalid control type NONE\n",
206                                ctl->name, index);
207                 return false;
208
209         case SND_CTL_ELEM_TYPE_BOOLEAN:
210                 int_val = snd_ctl_elem_value_get_boolean(val, index);
211                 switch (int_val) {
212                 case 0:
213                 case 1:
214                         break;
215                 default:
216                         ksft_print_msg("%s.%d Invalid boolean value %ld\n",
217                                        ctl->name, index, int_val);
218                         return false;
219                 }
220                 break;
221
222         case SND_CTL_ELEM_TYPE_INTEGER:
223                 int_val = snd_ctl_elem_value_get_integer(val, index);
224
225                 if (int_val < snd_ctl_elem_info_get_min(ctl->info)) {
226                         ksft_print_msg("%s.%d value %ld less than minimum %ld\n",
227                                        ctl->name, index, int_val,
228                                        snd_ctl_elem_info_get_min(ctl->info));
229                         return false;
230                 }
231
232                 if (int_val > snd_ctl_elem_info_get_max(ctl->info)) {
233                         ksft_print_msg("%s.%d value %ld more than maximum %ld\n",
234                                        ctl->name, index, int_val,
235                                        snd_ctl_elem_info_get_max(ctl->info));
236                         return false;
237                 }
238
239                 /* Only check step size if there is one and we're in bounds */
240                 if (snd_ctl_elem_info_get_step(ctl->info) &&
241                     (int_val - snd_ctl_elem_info_get_min(ctl->info) %
242                      snd_ctl_elem_info_get_step(ctl->info))) {
243                         ksft_print_msg("%s.%d value %ld invalid for step %ld minimum %ld\n",
244                                        ctl->name, index, int_val,
245                                        snd_ctl_elem_info_get_step(ctl->info),
246                                        snd_ctl_elem_info_get_min(ctl->info));
247                         return false;
248                 }
249                 break;
250
251         case SND_CTL_ELEM_TYPE_INTEGER64:
252                 int64_val = snd_ctl_elem_value_get_integer64(val, index);
253
254                 if (int64_val < snd_ctl_elem_info_get_min64(ctl->info)) {
255                         ksft_print_msg("%s.%d value %lld less than minimum %lld\n",
256                                        ctl->name, index, int64_val,
257                                        snd_ctl_elem_info_get_min64(ctl->info));
258                         return false;
259                 }
260
261                 if (int64_val > snd_ctl_elem_info_get_max64(ctl->info)) {
262                         ksft_print_msg("%s.%d value %lld more than maximum %lld\n",
263                                        ctl->name, index, int64_val,
264                                        snd_ctl_elem_info_get_max(ctl->info));
265                         return false;
266                 }
267
268                 /* Only check step size if there is one and we're in bounds */
269                 if (snd_ctl_elem_info_get_step64(ctl->info) &&
270                     (int64_val - snd_ctl_elem_info_get_min64(ctl->info)) %
271                     snd_ctl_elem_info_get_step64(ctl->info)) {
272                         ksft_print_msg("%s.%d value %lld invalid for step %lld minimum %lld\n",
273                                        ctl->name, index, int64_val,
274                                        snd_ctl_elem_info_get_step64(ctl->info),
275                                        snd_ctl_elem_info_get_min64(ctl->info));
276                         return false;
277                 }
278                 break;
279
280         case SND_CTL_ELEM_TYPE_ENUMERATED:
281                 int_val = snd_ctl_elem_value_get_enumerated(val, index);
282
283                 if (int_val < 0) {
284                         ksft_print_msg("%s.%d negative value %ld for enumeration\n",
285                                        ctl->name, index, int_val);
286                         return false;
287                 }
288
289                 if (int_val >= snd_ctl_elem_info_get_items(ctl->info)) {
290                         ksft_print_msg("%s.%d value %ld more than item count %ld\n",
291                                        ctl->name, index, int_val,
292                                        snd_ctl_elem_info_get_items(ctl->info));
293                         return false;
294                 }
295                 break;
296
297         default:
298                 /* No tests for other types */
299                 break;
300         }
301
302         return true;
303 }
304
305 /*
306  * Check that the provided value meets the constraints for the
307  * provided control.
308  */
309 bool ctl_value_valid(struct ctl_data *ctl, snd_ctl_elem_value_t *val)
310 {
311         int i;
312         bool valid = true;
313
314         for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++)
315                 if (!ctl_value_index_valid(ctl, val, i))
316                         valid = false;
317
318         return valid;
319 }
320
321 /*
322  * Check that we can read the default value and it is valid. Write
323  * tests use the read value to restore the default.
324  */
325 void test_ctl_get_value(struct ctl_data *ctl)
326 {
327         int err;
328
329         /* If the control is turned off let's be polite */
330         if (snd_ctl_elem_info_is_inactive(ctl->info)) {
331                 ksft_print_msg("%s is inactive\n", ctl->name);
332                 ksft_test_result_skip("get_value.%d.%d\n",
333                                       ctl->card->card, ctl->elem);
334                 return;
335         }
336
337         /* Can't test reading on an unreadable control */
338         if (!snd_ctl_elem_info_is_readable(ctl->info)) {
339                 ksft_print_msg("%s is not readable\n", ctl->name);
340                 ksft_test_result_skip("get_value.%d.%d\n",
341                                       ctl->card->card, ctl->elem);
342                 return;
343         }
344
345         err = snd_ctl_elem_read(ctl->card->handle, ctl->def_val);
346         if (err < 0) {
347                 ksft_print_msg("snd_ctl_elem_read() failed: %s\n",
348                                snd_strerror(err));
349                 goto out;
350         }
351
352         if (!ctl_value_valid(ctl, ctl->def_val))
353                 err = -EINVAL;
354
355 out:
356         ksft_test_result(err >= 0, "get_value.%d.%d\n",
357                          ctl->card->card, ctl->elem);
358 }
359
360 bool show_mismatch(struct ctl_data *ctl, int index,
361                    snd_ctl_elem_value_t *read_val,
362                    snd_ctl_elem_value_t *expected_val)
363 {
364         long long expected_int, read_int;
365
366         /*
367          * We factor out the code to compare values representable as
368          * integers, ensure that check doesn't log otherwise.
369          */
370         expected_int = 0;
371         read_int = 0;
372
373         switch (snd_ctl_elem_info_get_type(ctl->info)) {
374         case SND_CTL_ELEM_TYPE_BOOLEAN:
375                 expected_int = snd_ctl_elem_value_get_boolean(expected_val,
376                                                               index);
377                 read_int = snd_ctl_elem_value_get_boolean(read_val, index);
378                 break;
379
380         case SND_CTL_ELEM_TYPE_INTEGER:
381                 expected_int = snd_ctl_elem_value_get_integer(expected_val,
382                                                               index);
383                 read_int = snd_ctl_elem_value_get_integer(read_val, index);
384                 break;
385
386         case SND_CTL_ELEM_TYPE_INTEGER64:
387                 expected_int = snd_ctl_elem_value_get_integer64(expected_val,
388                                                                 index);
389                 read_int = snd_ctl_elem_value_get_integer64(read_val,
390                                                             index);
391                 break;
392
393         case SND_CTL_ELEM_TYPE_ENUMERATED:
394                 expected_int = snd_ctl_elem_value_get_enumerated(expected_val,
395                                                                  index);
396                 read_int = snd_ctl_elem_value_get_enumerated(read_val,
397                                                              index);
398                 break;
399
400         default:
401                 break;
402         }
403
404         if (expected_int != read_int) {
405                 /*
406                  * NOTE: The volatile attribute means that the hardware
407                  * can voluntarily change the state of control element
408                  * independent of any operation by software.  
409                  */
410                 bool is_volatile = snd_ctl_elem_info_is_volatile(ctl->info);
411                 ksft_print_msg("%s.%d expected %lld but read %lld, is_volatile %d\n",
412                                ctl->name, index, expected_int, read_int, is_volatile);
413                 return !is_volatile;
414         } else {
415                 return false;
416         }
417 }
418
419 /*
420  * Write a value then if possible verify that we get the expected
421  * result.  An optional expected value can be provided if we expect
422  * the write to fail, for verifying that invalid writes don't corrupt
423  * anything.
424  */
425 int write_and_verify(struct ctl_data *ctl,
426                      snd_ctl_elem_value_t *write_val,
427                      snd_ctl_elem_value_t *expected_val)
428 {
429         int err, i;
430         bool error_expected, mismatch_shown;
431         snd_ctl_elem_value_t *read_val, *w_val;
432         snd_ctl_elem_value_alloca(&read_val);
433         snd_ctl_elem_value_alloca(&w_val);
434
435         /*
436          * We need to copy the write value since writing can modify
437          * the value which causes surprises, and allocate an expected
438          * value if we expect to read back what we wrote.
439          */
440         snd_ctl_elem_value_copy(w_val, write_val);
441         if (expected_val) {
442                 error_expected = true;
443         } else {
444                 error_expected = false;
445                 snd_ctl_elem_value_alloca(&expected_val);
446                 snd_ctl_elem_value_copy(expected_val, write_val);
447         }
448
449         /*
450          * Do the write, if we have an expected value ignore the error
451          * and carry on to validate the expected value.
452          */
453         err = snd_ctl_elem_write(ctl->card->handle, w_val);
454         if (err < 0 && !error_expected) {
455                 ksft_print_msg("snd_ctl_elem_write() failed: %s\n",
456                                snd_strerror(err));
457                 return err;
458         }
459
460         /* Can we do the verification part? */
461         if (!snd_ctl_elem_info_is_readable(ctl->info))
462                 return err;
463
464         snd_ctl_elem_value_set_id(read_val, ctl->id);
465
466         err = snd_ctl_elem_read(ctl->card->handle, read_val);
467         if (err < 0) {
468                 ksft_print_msg("snd_ctl_elem_read() failed: %s\n",
469                                snd_strerror(err));
470                 return err;
471         }
472
473         /*
474          * Use the libray to compare values, if there's a mismatch
475          * carry on and try to provide a more useful diagnostic than
476          * just "mismatch".
477          */
478         if (!snd_ctl_elem_value_compare(expected_val, read_val))
479                 return 0;
480
481         mismatch_shown = false;
482         for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++)
483                 if (show_mismatch(ctl, i, read_val, expected_val))
484                         mismatch_shown = true;
485
486         if (!mismatch_shown)
487                 ksft_print_msg("%s read and written values differ\n",
488                                ctl->name);
489
490         return -1;
491 }
492
493 /*
494  * Make sure we can write the default value back to the control, this
495  * should validate that at least some write works.
496  */
497 void test_ctl_write_default(struct ctl_data *ctl)
498 {
499         int err;
500
501         /* If the control is turned off let's be polite */
502         if (snd_ctl_elem_info_is_inactive(ctl->info)) {
503                 ksft_print_msg("%s is inactive\n", ctl->name);
504                 ksft_test_result_skip("write_default.%d.%d\n",
505                                       ctl->card->card, ctl->elem);
506                 return;
507         }
508
509         if (!snd_ctl_elem_info_is_writable(ctl->info)) {
510                 ksft_print_msg("%s is not writeable\n", ctl->name);
511                 ksft_test_result_skip("write_default.%d.%d\n",
512                                       ctl->card->card, ctl->elem);
513                 return;
514         }
515
516         /* No idea what the default was for unreadable controls */
517         if (!snd_ctl_elem_info_is_readable(ctl->info)) {
518                 ksft_print_msg("%s couldn't read default\n", ctl->name);
519                 ksft_test_result_skip("write_default.%d.%d\n",
520                                       ctl->card->card, ctl->elem);
521                 return;
522         }
523
524         err = write_and_verify(ctl, ctl->def_val, NULL);
525
526         ksft_test_result(err >= 0, "write_default.%d.%d\n",
527                          ctl->card->card, ctl->elem);
528 }
529
530 bool test_ctl_write_valid_boolean(struct ctl_data *ctl)
531 {
532         int err, i, j;
533         bool fail = false;
534         snd_ctl_elem_value_t *val;
535         snd_ctl_elem_value_alloca(&val);
536
537         snd_ctl_elem_value_set_id(val, ctl->id);
538
539         for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) {
540                 for (j = 0; j < 2; j++) {
541                         snd_ctl_elem_value_set_boolean(val, i, j);
542                         err = write_and_verify(ctl, val, NULL);
543                         if (err != 0)
544                                 fail = true;
545                 }
546         }
547
548         return !fail;
549 }
550
551 bool test_ctl_write_valid_integer(struct ctl_data *ctl)
552 {
553         int err;
554         int i;
555         long j, step;
556         bool fail = false;
557         snd_ctl_elem_value_t *val;
558         snd_ctl_elem_value_alloca(&val);
559
560         snd_ctl_elem_value_set_id(val, ctl->id);
561
562         step = snd_ctl_elem_info_get_step(ctl->info);
563         if (!step)
564                 step = 1;
565
566         for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) {
567                 for (j = snd_ctl_elem_info_get_min(ctl->info);
568                      j <= snd_ctl_elem_info_get_max(ctl->info); j += step) {
569
570                         snd_ctl_elem_value_set_integer(val, i, j);
571                         err = write_and_verify(ctl, val, NULL);
572                         if (err != 0)
573                                 fail = true;
574                 }
575         }
576
577
578         return !fail;
579 }
580
581 bool test_ctl_write_valid_integer64(struct ctl_data *ctl)
582 {
583         int err, i;
584         long long j, step;
585         bool fail = false;
586         snd_ctl_elem_value_t *val;
587         snd_ctl_elem_value_alloca(&val);
588
589         snd_ctl_elem_value_set_id(val, ctl->id);
590
591         step = snd_ctl_elem_info_get_step64(ctl->info);
592         if (!step)
593                 step = 1;
594
595         for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) {
596                 for (j = snd_ctl_elem_info_get_min64(ctl->info);
597                      j <= snd_ctl_elem_info_get_max64(ctl->info); j += step) {
598
599                         snd_ctl_elem_value_set_integer64(val, i, j);
600                         err = write_and_verify(ctl, val, NULL);
601                         if (err != 0)
602                                 fail = true;
603                 }
604         }
605
606         return !fail;
607 }
608
609 bool test_ctl_write_valid_enumerated(struct ctl_data *ctl)
610 {
611         int err, i, j;
612         bool fail = false;
613         snd_ctl_elem_value_t *val;
614         snd_ctl_elem_value_alloca(&val);
615
616         snd_ctl_elem_value_set_id(val, ctl->id);
617
618         for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) {
619                 for (j = 0; j < snd_ctl_elem_info_get_items(ctl->info); j++) {
620                         snd_ctl_elem_value_set_enumerated(val, i, j);
621                         err = write_and_verify(ctl, val, NULL);
622                         if (err != 0)
623                                 fail = true;
624                 }
625         }
626
627         return !fail;
628 }
629
630 void test_ctl_write_valid(struct ctl_data *ctl)
631 {
632         bool pass;
633         int err;
634
635         /* If the control is turned off let's be polite */
636         if (snd_ctl_elem_info_is_inactive(ctl->info)) {
637                 ksft_print_msg("%s is inactive\n", ctl->name);
638                 ksft_test_result_skip("write_valid.%d.%d\n",
639                                       ctl->card->card, ctl->elem);
640                 return;
641         }
642
643         if (!snd_ctl_elem_info_is_writable(ctl->info)) {
644                 ksft_print_msg("%s is not writeable\n", ctl->name);
645                 ksft_test_result_skip("write_valid.%d.%d\n",
646                                       ctl->card->card, ctl->elem);
647                 return;
648         }
649
650         switch (snd_ctl_elem_info_get_type(ctl->info)) {
651         case SND_CTL_ELEM_TYPE_BOOLEAN:
652                 pass = test_ctl_write_valid_boolean(ctl);
653                 break;
654
655         case SND_CTL_ELEM_TYPE_INTEGER:
656                 pass = test_ctl_write_valid_integer(ctl);
657                 break;
658
659         case SND_CTL_ELEM_TYPE_INTEGER64:
660                 pass = test_ctl_write_valid_integer64(ctl);
661                 break;
662
663         case SND_CTL_ELEM_TYPE_ENUMERATED:
664                 pass = test_ctl_write_valid_enumerated(ctl);
665                 break;
666
667         default:
668                 /* No tests for this yet */
669                 ksft_test_result_skip("write_valid.%d.%d\n",
670                                       ctl->card->card, ctl->elem);
671                 return;
672         }
673
674         /* Restore the default value to minimise disruption */
675         err = write_and_verify(ctl, ctl->def_val, NULL);
676         if (err < 0)
677                 pass = false;
678
679         ksft_test_result(pass, "write_valid.%d.%d\n",
680                          ctl->card->card, ctl->elem);
681 }
682
683 bool test_ctl_write_invalid_value(struct ctl_data *ctl,
684                                   snd_ctl_elem_value_t *val)
685 {
686         int err;
687         long val_read;
688
689         /* Ideally this will fail... */
690         err = snd_ctl_elem_write(ctl->card->handle, val);
691         if (err < 0)
692                 return false;
693
694         /* ...but some devices will clamp to an in range value */
695         err = snd_ctl_elem_read(ctl->card->handle, val);
696         if (err < 0) {
697                 ksft_print_msg("%s failed to read: %s\n",
698                                ctl->name, snd_strerror(err));
699                 return true;
700         }
701
702         return !ctl_value_valid(ctl, val);
703 }
704
705 bool test_ctl_write_invalid_boolean(struct ctl_data *ctl)
706 {
707         int err, i;
708         long val_read;
709         bool fail = false;
710         snd_ctl_elem_value_t *val;
711         snd_ctl_elem_value_alloca(&val);
712
713         for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) {
714                 snd_ctl_elem_value_copy(val, ctl->def_val);
715                 snd_ctl_elem_value_set_boolean(val, i, 2);
716
717                 if (test_ctl_write_invalid_value(ctl, val))
718                         fail = true;
719         }
720
721         return !fail;
722 }
723
724 bool test_ctl_write_invalid_integer(struct ctl_data *ctl)
725 {
726         int i;
727         bool fail = false;
728         snd_ctl_elem_value_t *val;
729         snd_ctl_elem_value_alloca(&val);
730
731         for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) {
732                 if (snd_ctl_elem_info_get_min(ctl->info) != LONG_MIN) {
733                         /* Just under range */
734                         snd_ctl_elem_value_copy(val, ctl->def_val);
735                         snd_ctl_elem_value_set_integer(val, i,
736                                snd_ctl_elem_info_get_min(ctl->info) - 1);
737
738                         if (test_ctl_write_invalid_value(ctl, val))
739                                 fail = true;
740
741                         /* Minimum representable value */
742                         snd_ctl_elem_value_copy(val, ctl->def_val);
743                         snd_ctl_elem_value_set_integer(val, i, LONG_MIN);
744
745                         if (test_ctl_write_invalid_value(ctl, val))
746                                 fail = true;
747                 }
748
749                 if (snd_ctl_elem_info_get_max(ctl->info) != LONG_MAX) {
750                         /* Just over range */
751                         snd_ctl_elem_value_copy(val, ctl->def_val);
752                         snd_ctl_elem_value_set_integer(val, i,
753                                snd_ctl_elem_info_get_max(ctl->info) + 1);
754
755                         if (test_ctl_write_invalid_value(ctl, val))
756                                 fail = true;
757
758                         /* Maximum representable value */
759                         snd_ctl_elem_value_copy(val, ctl->def_val);
760                         snd_ctl_elem_value_set_integer(val, i, LONG_MAX);
761
762                         if (test_ctl_write_invalid_value(ctl, val))
763                                 fail = true;
764                 }
765         }
766
767         return !fail;
768 }
769
770 bool test_ctl_write_invalid_integer64(struct ctl_data *ctl)
771 {
772         int i;
773         bool fail = false;
774         snd_ctl_elem_value_t *val;
775         snd_ctl_elem_value_alloca(&val);
776
777         for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) {
778                 if (snd_ctl_elem_info_get_min64(ctl->info) != LLONG_MIN) {
779                         /* Just under range */
780                         snd_ctl_elem_value_copy(val, ctl->def_val);
781                         snd_ctl_elem_value_set_integer64(val, i,
782                                 snd_ctl_elem_info_get_min64(ctl->info) - 1);
783
784                         if (test_ctl_write_invalid_value(ctl, val))
785                                 fail = true;
786
787                         /* Minimum representable value */
788                         snd_ctl_elem_value_copy(val, ctl->def_val);
789                         snd_ctl_elem_value_set_integer64(val, i, LLONG_MIN);
790
791                         if (test_ctl_write_invalid_value(ctl, val))
792                                 fail = true;
793                 }
794
795                 if (snd_ctl_elem_info_get_max64(ctl->info) != LLONG_MAX) {
796                         /* Just over range */
797                         snd_ctl_elem_value_copy(val, ctl->def_val);
798                         snd_ctl_elem_value_set_integer64(val, i,
799                                 snd_ctl_elem_info_get_max64(ctl->info) + 1);
800
801                         if (test_ctl_write_invalid_value(ctl, val))
802                                 fail = true;
803
804                         /* Maximum representable value */
805                         snd_ctl_elem_value_copy(val, ctl->def_val);
806                         snd_ctl_elem_value_set_integer64(val, i, LLONG_MAX);
807
808                         if (test_ctl_write_invalid_value(ctl, val))
809                                 fail = true;
810                 }
811         }
812
813         return !fail;
814 }
815
816 bool test_ctl_write_invalid_enumerated(struct ctl_data *ctl)
817 {
818         int err, i;
819         unsigned int val_read;
820         bool fail = false;
821         snd_ctl_elem_value_t *val;
822         snd_ctl_elem_value_alloca(&val);
823
824         snd_ctl_elem_value_set_id(val, ctl->id);
825
826         for (i = 0; i < snd_ctl_elem_info_get_count(ctl->info); i++) {
827                 /* One beyond maximum */
828                 snd_ctl_elem_value_copy(val, ctl->def_val);
829                 snd_ctl_elem_value_set_enumerated(val, i,
830                                   snd_ctl_elem_info_get_items(ctl->info));
831
832                 if (test_ctl_write_invalid_value(ctl, val))
833                         fail = true;
834
835                 /* Maximum representable value */
836                 snd_ctl_elem_value_copy(val, ctl->def_val);
837                 snd_ctl_elem_value_set_enumerated(val, i, UINT_MAX);
838
839                 if (test_ctl_write_invalid_value(ctl, val))
840                         fail = true;
841
842         }
843
844         return !fail;
845 }
846
847
848 void test_ctl_write_invalid(struct ctl_data *ctl)
849 {
850         bool pass;
851         int err;
852
853         /* If the control is turned off let's be polite */
854         if (snd_ctl_elem_info_is_inactive(ctl->info)) {
855                 ksft_print_msg("%s is inactive\n", ctl->name);
856                 ksft_test_result_skip("write_invalid.%d.%d\n",
857                                       ctl->card->card, ctl->elem);
858                 return;
859         }
860
861         if (!snd_ctl_elem_info_is_writable(ctl->info)) {
862                 ksft_print_msg("%s is not writeable\n", ctl->name);
863                 ksft_test_result_skip("write_invalid.%d.%d\n",
864                                       ctl->card->card, ctl->elem);
865                 return;
866         }
867
868         switch (snd_ctl_elem_info_get_type(ctl->info)) {
869         case SND_CTL_ELEM_TYPE_BOOLEAN:
870                 pass = test_ctl_write_invalid_boolean(ctl);
871                 break;
872
873         case SND_CTL_ELEM_TYPE_INTEGER:
874                 pass = test_ctl_write_invalid_integer(ctl);
875                 break;
876
877         case SND_CTL_ELEM_TYPE_INTEGER64:
878                 pass = test_ctl_write_invalid_integer64(ctl);
879                 break;
880
881         case SND_CTL_ELEM_TYPE_ENUMERATED:
882                 pass = test_ctl_write_invalid_enumerated(ctl);
883                 break;
884
885         default:
886                 /* No tests for this yet */
887                 ksft_test_result_skip("write_invalid.%d.%d\n",
888                                       ctl->card->card, ctl->elem);
889                 return;
890         }
891
892         /* Restore the default value to minimise disruption */
893         err = write_and_verify(ctl, ctl->def_val, NULL);
894         if (err < 0)
895                 pass = false;
896
897         ksft_test_result(pass, "write_invalid.%d.%d\n",
898                          ctl->card->card, ctl->elem);
899 }
900
901 int main(void)
902 {
903         struct ctl_data *ctl;
904
905         ksft_print_header();
906
907         find_controls();
908
909         ksft_set_plan(num_controls * TESTS_PER_CONTROL);
910
911         for (ctl = ctl_list; ctl != NULL; ctl = ctl->next) {
912                 /*
913                  * Must test get_value() before we write anything, the
914                  * test stores the default value for later cleanup.
915                  */
916                 test_ctl_get_value(ctl);
917                 test_ctl_write_default(ctl);
918                 test_ctl_write_valid(ctl);
919                 test_ctl_write_invalid(ctl);
920         }
921
922         ksft_exit_pass();
923
924         return 0;
925 }