cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mixer-test.c (28463B)


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