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