File Index
Files and directories
Sign in
FILE

mixer-test.c

File preview with syntax highlighting.

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