Blame test/user-ctl-element-set.c

Packit Service db8eaa
/*
Packit Service db8eaa
 * user-control-element-set.c - a program to test in-kernel implementation of
Packit Service db8eaa
 *				user-defined control element set.
Packit Service db8eaa
 *
Packit Service db8eaa
 * Copyright (c) 2015-2016 Takashi Sakamoto
Packit Service db8eaa
 *
Packit Service db8eaa
 * Licensed under the terms of the GNU General Public License, version 2.
Packit Service db8eaa
 */
Packit Service db8eaa
Packit Service db8eaa
#include "../include/asoundlib.h"
Packit Service db8eaa
#include <sound/tlv.h>
Packit Service db8eaa
#include <stdbool.h>
Packit Service db8eaa
Packit Service db8eaa
struct elem_set_trial {
Packit Service db8eaa
	snd_ctl_t *handle;
Packit Service db8eaa
Packit Service db8eaa
	snd_ctl_elem_type_t type;
Packit Service db8eaa
	unsigned int member_count;
Packit Service db8eaa
	unsigned int element_count;
Packit Service db8eaa
Packit Service db8eaa
	snd_ctl_elem_id_t *id;
Packit Service db8eaa
Packit Service db8eaa
	int (*add_elem_set)(struct elem_set_trial *trial,
Packit Service db8eaa
			    snd_ctl_elem_info_t *info);
Packit Service db8eaa
	int (*check_elem_props)(struct elem_set_trial *trial,
Packit Service db8eaa
				snd_ctl_elem_info_t *info);
Packit Service db8eaa
	void (*change_elem_members)(struct elem_set_trial *trial,
Packit Service db8eaa
				    snd_ctl_elem_value_t *elem_data);
Packit Service db8eaa
	int (*allocate_elem_set_tlv)(struct elem_set_trial *trial,
Packit Service db8eaa
				     unsigned int **tlv);
Packit Service db8eaa
Packit Service db8eaa
	bool tlv_readable;
Packit Service db8eaa
};
Packit Service db8eaa
Packit Service db8eaa
struct chmap_entry {
Packit Service db8eaa
	unsigned int type;
Packit Service db8eaa
	unsigned int length;
Packit Service db8eaa
	unsigned int maps[0];
Packit Service db8eaa
};
Packit Service db8eaa
Packit Service db8eaa
/*
Packit Service db8eaa
 * History of TLV feature:
Packit Service db8eaa
 *
Packit Service db8eaa
 * 2016/09/15: 398fa4db6c69 ("ALSA: control: move layout of TLV payload to UAPI
Packit Service db8eaa
 *			      header")
Packit Service db8eaa
 * 2012/07/21: 2d3391ec0ecc ("ALSA: PCM: channel mapping API implementation")
Packit Service db8eaa
 * 2011/11/20: bf1d1c9b6179 ("ALSA: tlv: add DECLARE_TLV_DB_RANGE()")
Packit Service db8eaa
 * 2009/07/16: 085f30654175 ("ALSA: Add new TLV types for dBwith min/max")
Packit Service db8eaa
 * 2006/09/06: 55a29af5ed5d ("[ALSA] Add definition of TLV dB range compound")
Packit Service db8eaa
 * 2006/08/28: 063a40d9111c ("Add the definition of linear volume TLV")
Packit Service db8eaa
 * 2006/08/28: 42750b04c5ba ("[ALSA] Control API - TLV implementation for
Packit Service db8eaa
 *			      additional information like dB scale")
Packit Service db8eaa
 */
Packit Service db8eaa
Packit Service db8eaa
/* Operations for elements in an element set with boolean type. */
Packit Service db8eaa
static int add_bool_elem_set(struct elem_set_trial *trial,
Packit Service db8eaa
			     snd_ctl_elem_info_t *info)
Packit Service db8eaa
{
Packit Service db8eaa
	return snd_ctl_add_boolean_elem_set(trial->handle, info,
Packit Service db8eaa
				trial->element_count, trial->member_count);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static void change_bool_elem_members(struct elem_set_trial *trial,
Packit Service db8eaa
				     snd_ctl_elem_value_t *elem_data)
Packit Service db8eaa
{
Packit Service db8eaa
	int val;
Packit Service db8eaa
	unsigned int i;
Packit Service db8eaa
Packit Service db8eaa
	for (i = 0; i < trial->member_count; ++i) {
Packit Service db8eaa
		val = snd_ctl_elem_value_get_boolean(elem_data, i);
Packit Service db8eaa
		snd_ctl_elem_value_set_boolean(elem_data, i, !val);
Packit Service db8eaa
	}
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int allocate_bool_elem_set_tlv(struct elem_set_trial *trial,
Packit Service db8eaa
				      unsigned int **tlv)
Packit Service db8eaa
{
Packit Service db8eaa
	/*
Packit Service db8eaa
	 * Performs like a toggle switch for attenuation, because they're bool
Packit Service db8eaa
	 * elements.
Packit Service db8eaa
	 */
Packit Service db8eaa
	static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(range, -10000, 0);
Packit Service db8eaa
Packit Service db8eaa
	*tlv = malloc(sizeof(range));
Packit Service db8eaa
	if (*tlv == NULL)
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
	memcpy(*tlv, range, sizeof(range));
Packit Service db8eaa
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/* Operations for elements in an element set with integer type. */
Packit Service db8eaa
static int add_int_elem_set(struct elem_set_trial *trial,
Packit Service db8eaa
			    snd_ctl_elem_info_t *info)
Packit Service db8eaa
{
Packit Service db8eaa
	return snd_ctl_add_integer_elem_set(trial->handle, info,
Packit Service db8eaa
				trial->element_count, trial->member_count,
Packit Service db8eaa
				0, 25, 1);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int check_int_elem_props(struct elem_set_trial *trial,
Packit Service db8eaa
				snd_ctl_elem_info_t *info)
Packit Service db8eaa
{
Packit Service db8eaa
	if (snd_ctl_elem_info_get_min(info) != 0)
Packit Service db8eaa
		return -EIO;
Packit Service db8eaa
	if (snd_ctl_elem_info_get_max(info) != 25)
Packit Service db8eaa
		return -EIO;
Packit Service db8eaa
	if (snd_ctl_elem_info_get_step(info) != 1)
Packit Service db8eaa
		return -EIO;
Packit Service db8eaa
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static void change_int_elem_members(struct elem_set_trial *trial,
Packit Service db8eaa
				    snd_ctl_elem_value_t *elem_data)
Packit Service db8eaa
{
Packit Service db8eaa
	long val;
Packit Service db8eaa
	unsigned int i;
Packit Service db8eaa
Packit Service db8eaa
	for (i = 0; i < trial->member_count; ++i) {
Packit Service db8eaa
		val = snd_ctl_elem_value_get_integer(elem_data, i);
Packit Service db8eaa
		snd_ctl_elem_value_set_integer(elem_data, i, ++val);
Packit Service db8eaa
	}
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int allocate_int_elem_set_tlv(struct elem_set_trial *trial,
Packit Service db8eaa
				     unsigned int **tlv)
Packit Service db8eaa
{
Packit Service db8eaa
	unsigned int count, pos;
Packit Service db8eaa
	unsigned int i, j;
Packit Service db8eaa
	struct chmap_entry *entry;
Packit Service db8eaa
Packit Service db8eaa
	/* Calculate size of TLV packet for channel-mapping information. */
Packit Service db8eaa
	count = 0;
Packit Service db8eaa
	for (i = 1; i <= 25; ++i) {
Packit Service db8eaa
		count += 2; /* sizeof(struct chmap_entry). */
Packit Service db8eaa
		count += i; /* struct chmap_entry.maps. */
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	*tlv = malloc((2 + count) * sizeof(unsigned int));
Packit Service db8eaa
	if (!*tlv)
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
Packit Service db8eaa
	/*
Packit Service db8eaa
	 * Emulate channel-mapping information in in-kernel implementation.
Packit Service db8eaa
	 * Here, 25 entries are for each different channel.
Packit Service db8eaa
	 */
Packit Service db8eaa
	(*tlv)[0] = SNDRV_CTL_TLVT_CONTAINER;
Packit Service db8eaa
	(*tlv)[1] = count * sizeof(unsigned int);
Packit Service db8eaa
	pos = 2;
Packit Service db8eaa
Packit Service db8eaa
	for (i = 1; i <= 25 && pos < count; ++i) {
Packit Service db8eaa
		entry = (struct chmap_entry *)&(*tlv)[pos];
Packit Service db8eaa
Packit Service db8eaa
		entry->type = SNDRV_CTL_TLVT_CHMAP_FIXED;
Packit Service db8eaa
		entry->length = i * sizeof(unsigned int);
Packit Service db8eaa
		pos += 2;
Packit Service db8eaa
Packit Service db8eaa
		for (j = 0; j < i; ++j)
Packit Service db8eaa
			entry->maps[j] = SND_CHMAP_MONO + j;
Packit Service db8eaa
		pos += i;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/* Operations for elements in an element set with enumerated type. */
Packit Service db8eaa
static const char *const labels[] = {
Packit Service db8eaa
	"trusty",
Packit Service db8eaa
	"utopic",
Packit Service db8eaa
	"vivid",
Packit Service db8eaa
	"willy",
Packit Service db8eaa
	"xenial",
Packit Service db8eaa
};
Packit Service db8eaa
Packit Service db8eaa
static int add_enum_elem_set(struct elem_set_trial *trial,
Packit Service db8eaa
			     snd_ctl_elem_info_t *info)
Packit Service db8eaa
{
Packit Service db8eaa
	return snd_ctl_add_enumerated_elem_set(trial->handle, info,
Packit Service db8eaa
				trial->element_count, trial->member_count,
Packit Service db8eaa
				sizeof(labels) / sizeof(labels[0]),
Packit Service db8eaa
				labels);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int check_enum_elem_props(struct elem_set_trial *trial,
Packit Service db8eaa
				 snd_ctl_elem_info_t *info)
Packit Service db8eaa
{
Packit Service db8eaa
	unsigned int items;
Packit Service db8eaa
	unsigned int i;
Packit Service db8eaa
	const char *label;
Packit Service db8eaa
	int err;
Packit Service db8eaa
Packit Service db8eaa
	items = snd_ctl_elem_info_get_items(info);
Packit Service db8eaa
	if (items != sizeof(labels) / sizeof(labels[0]))
Packit Service db8eaa
		return -EIO;
Packit Service db8eaa
Packit Service db8eaa
	/* Enumerate and validate all of labels registered to this element. */
Packit Service db8eaa
	for (i = 0; i < items; ++i) {
Packit Service db8eaa
		snd_ctl_elem_info_set_item(info, i);
Packit Service db8eaa
		err = snd_ctl_elem_info(trial->handle, info);
Packit Service db8eaa
		if (err < 0)
Packit Service db8eaa
			return err;
Packit Service db8eaa
Packit Service db8eaa
		label = snd_ctl_elem_info_get_item_name(info);
Packit Service db8eaa
		if (strncmp(label, labels[i], strlen(labels[i])) != 0)
Packit Service db8eaa
			return -EIO;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static void change_enum_elem_members(struct elem_set_trial *trial,
Packit Service db8eaa
				     snd_ctl_elem_value_t *elem_data)
Packit Service db8eaa
{
Packit Service db8eaa
	unsigned int val;
Packit Service db8eaa
	unsigned int i;
Packit Service db8eaa
Packit Service db8eaa
	for (i = 0; i < trial->member_count; ++i) {
Packit Service db8eaa
		val = snd_ctl_elem_value_get_enumerated(elem_data, i);
Packit Service db8eaa
		snd_ctl_elem_value_set_enumerated(elem_data, i, ++val);
Packit Service db8eaa
	}
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/* Operations for elements in an element set with bytes type. */
Packit Service db8eaa
static int add_bytes_elem_set(struct elem_set_trial *trial,
Packit Service db8eaa
			      snd_ctl_elem_info_t *info)
Packit Service db8eaa
{
Packit Service db8eaa
	return snd_ctl_add_bytes_elem_set(trial->handle, info,
Packit Service db8eaa
				trial->element_count, trial->member_count);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static void change_bytes_elem_members(struct elem_set_trial *trial,
Packit Service db8eaa
				      snd_ctl_elem_value_t *elem_data)
Packit Service db8eaa
{
Packit Service db8eaa
	unsigned char val;
Packit Service db8eaa
	unsigned int i;
Packit Service db8eaa
Packit Service db8eaa
	for (i = 0; i < trial->member_count; ++i) {
Packit Service db8eaa
		val = snd_ctl_elem_value_get_byte(elem_data, i);
Packit Service db8eaa
		snd_ctl_elem_value_set_byte(elem_data, i, ++val);
Packit Service db8eaa
	}
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int allocate_bytes_elem_set_tlv(struct elem_set_trial *trial,
Packit Service db8eaa
				       unsigned int **tlv)
Packit Service db8eaa
{
Packit Service db8eaa
	/*
Packit Service db8eaa
	 * Emulate AK4396.
Packit Service db8eaa
	 * 20 * log10(x/255) (dB)
Packit Service db8eaa
	 * Here, x is written value.
Packit Service db8eaa
	 */
Packit Service db8eaa
	static const SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(range, -4813, 0);
Packit Service db8eaa
Packit Service db8eaa
	*tlv = malloc(sizeof(range));
Packit Service db8eaa
	if (*tlv == NULL)
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
	memcpy(*tlv, range, sizeof(range));
Packit Service db8eaa
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/* Operations for elements in an element set with iec958 type. */
Packit Service db8eaa
static int add_iec958_elem_set(struct elem_set_trial *trial,
Packit Service db8eaa
			       snd_ctl_elem_info_t *info)
Packit Service db8eaa
{
Packit Service db8eaa
	int err;
Packit Service db8eaa
Packit Service db8eaa
	snd_ctl_elem_info_get_id(info, trial->id);
Packit Service db8eaa
Packit Service db8eaa
	err = snd_ctl_elem_add_iec958(trial->handle, trial->id);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
	        return err;
Packit Service db8eaa
Packit Service db8eaa
	/*
Packit Service db8eaa
	 * In historical reason, the above API is not allowed to fill all of
Packit Service db8eaa
	 * fields in identification data.
Packit Service db8eaa
	 */
Packit Service db8eaa
	return snd_ctl_elem_info(trial->handle, info);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static void change_iec958_elem_members(struct elem_set_trial *trial,
Packit Service db8eaa
				       snd_ctl_elem_value_t *elem_data)
Packit Service db8eaa
{
Packit Service db8eaa
	snd_aes_iec958_t data;
Packit Service db8eaa
Packit Service db8eaa
	/* To suppress GCC warnings. */
Packit Service db8eaa
	trial->element_count = 1;
Packit Service db8eaa
Packit Service db8eaa
	snd_ctl_elem_value_get_iec958(elem_data, &data);
Packit Service db8eaa
	/* This is an arbitrary number. */
Packit Service db8eaa
	data.pad = 10;
Packit Service db8eaa
	snd_ctl_elem_value_set_iec958(elem_data, &data);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/* Operations for elements in an element set with integer64 type. */
Packit Service db8eaa
static int add_int64_elem_set(struct elem_set_trial *trial,
Packit Service db8eaa
			      snd_ctl_elem_info_t *info)
Packit Service db8eaa
{
Packit Service db8eaa
	return snd_ctl_add_integer64_elem_set(trial->handle, info,
Packit Service db8eaa
				trial->element_count, trial->member_count,
Packit Service db8eaa
				0, 10000, 1);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int check_int64_elem_props(struct elem_set_trial *trial,
Packit Service db8eaa
				  snd_ctl_elem_info_t *info)
Packit Service db8eaa
{
Packit Service db8eaa
	if (snd_ctl_elem_info_get_min64(info) != 0)
Packit Service db8eaa
		return -EIO;
Packit Service db8eaa
	if (snd_ctl_elem_info_get_max64(info) != 10000)
Packit Service db8eaa
		return -EIO;
Packit Service db8eaa
	if (snd_ctl_elem_info_get_step64(info) != 1)
Packit Service db8eaa
		return -EIO;
Packit Service db8eaa
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static void change_int64_elem_members(struct elem_set_trial *trial,
Packit Service db8eaa
				      snd_ctl_elem_value_t *elem_data)
Packit Service db8eaa
{
Packit Service db8eaa
	long long val;
Packit Service db8eaa
	unsigned int i;
Packit Service db8eaa
Packit Service db8eaa
	for (i = 0; i < trial->member_count; ++i) {
Packit Service db8eaa
		val = snd_ctl_elem_value_get_integer64(elem_data, i);
Packit Service db8eaa
		snd_ctl_elem_value_set_integer64(elem_data, i, ++val);
Packit Service db8eaa
	}
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int allocate_int64_elem_set_tlv(struct elem_set_trial *trial,
Packit Service db8eaa
				       unsigned int **tlv)
Packit Service db8eaa
{
Packit Service db8eaa
	/*
Packit Service db8eaa
	 * Use this fomula between linear/dB value:
Packit Service db8eaa
	 *
Packit Service db8eaa
	 *  Linear: dB range (coeff)
Packit Service db8eaa
	 *   0<-> 4: -59.40<->-56.36 (44)
Packit Service db8eaa
	 *   4<->22: -56.36<->-45.56 (60)
Packit Service db8eaa
	 *  22<->33: -45.56<->-40.72 (76)
Packit Service db8eaa
	 *  33<->37: -40.72<->-38.32 (44)
Packit Service db8eaa
	 *  37<->48: -38.32<->-29.96 (76)
Packit Service db8eaa
	 *  48<->66: -29.96<->-22.04 (60)
Packit Service db8eaa
	 *  66<->84: -22.04<-> -8.36 (44)
Packit Service db8eaa
	 *  84<->95:  -8.36<-> -1.76 (60)
Packit Service db8eaa
	 *  95<->99:  -1.76<->  0.00 (76)
Packit Service db8eaa
	 * 100<->..:   0.0
Packit Service db8eaa
	 */
Packit Service db8eaa
	static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(range,
Packit Service db8eaa
		 0,   4, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-5940, 44, 1),
Packit Service db8eaa
		 4,  22, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-5636, 60, 0),
Packit Service db8eaa
		22,  33, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-4556, 76, 0),
Packit Service db8eaa
		33,  37, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-4072, 44, 0),
Packit Service db8eaa
		37,  48, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-3832, 76, 0),
Packit Service db8eaa
		48,  66, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-2996, 60, 0),
Packit Service db8eaa
		66,  84, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-2204, 44, 0),
Packit Service db8eaa
		84,  95, SNDRV_CTL_TLVD_DB_SCALE_ITEM( -836, 60, 0),
Packit Service db8eaa
		95,  99, SNDRV_CTL_TLVD_DB_SCALE_ITEM( -176, 76, 0),
Packit Service db8eaa
		100, 10000, SNDRV_CTL_TLVD_DB_SCALE_ITEM(0, 0, 0),
Packit Service db8eaa
	);
Packit Service db8eaa
Packit Service db8eaa
	*tlv = malloc(sizeof(range));
Packit Service db8eaa
	if (*tlv == NULL)
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
	memcpy(*tlv, range, sizeof(range));
Packit Service db8eaa
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/* Common operations. */
Packit Service db8eaa
static int add_elem_set(struct elem_set_trial *trial)
Packit Service db8eaa
{
Packit Service db8eaa
	snd_ctl_elem_info_t *info;
Packit Service db8eaa
	char name[64] = {0};
Packit Service db8eaa
	int err;
Packit Service db8eaa
Packit Service db8eaa
	snprintf(name, 64, "userspace-control-element-%s",
Packit Service db8eaa
		 snd_ctl_elem_type_name(trial->type));
Packit Service db8eaa
Packit Service db8eaa
	snd_ctl_elem_info_alloca(&info;;
Packit Service db8eaa
	snd_ctl_elem_info_set_interface(info, SND_CTL_ELEM_IFACE_MIXER);
Packit Service db8eaa
	snd_ctl_elem_info_set_name(info, name);
Packit Service db8eaa
Packit Service db8eaa
	err = trial->add_elem_set(trial, info);
Packit Service db8eaa
	if (err >= 0)
Packit Service db8eaa
		snd_ctl_elem_info_get_id(info, trial->id);
Packit Service db8eaa
Packit Service db8eaa
	return err;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int check_event(struct elem_set_trial *trial, unsigned int mask,
Packit Service db8eaa
		       unsigned int expected_count)
Packit Service db8eaa
{
Packit Service db8eaa
	struct pollfd pfds;
Packit Service db8eaa
	int count;
Packit Service db8eaa
	unsigned short revents;
Packit Service db8eaa
	snd_ctl_event_t *event;
Packit Service db8eaa
	int err;
Packit Service db8eaa
Packit Service db8eaa
	snd_ctl_event_alloca(&event);
Packit Service db8eaa
Packit Service db8eaa
	if (snd_ctl_poll_descriptors_count(trial->handle) != 1)
Packit Service db8eaa
		return -ENXIO;
Packit Service db8eaa
Packit Service db8eaa
	if (snd_ctl_poll_descriptors(trial->handle, &pfds, 1) != 1)
Packit Service db8eaa
		return -ENXIO;
Packit Service db8eaa
Packit Service db8eaa
	while (expected_count > 0) {
Packit Service db8eaa
		count = poll(&pfds, 1, 1000);
Packit Service db8eaa
		if (count < 0)
Packit Service db8eaa
			return errno;
Packit Service db8eaa
		/* Some events are already supplied. */
Packit Service db8eaa
		if (count == 0)
Packit Service db8eaa
			return -ETIMEDOUT;
Packit Service db8eaa
Packit Service db8eaa
		err = snd_ctl_poll_descriptors_revents(trial->handle, &pfds,
Packit Service db8eaa
						       count, &revents);
Packit Service db8eaa
		if (err < 0)
Packit Service db8eaa
			return err;
Packit Service db8eaa
		if (revents & POLLERR)
Packit Service db8eaa
			return -EIO;
Packit Service db8eaa
		if (!(revents & POLLIN))
Packit Service db8eaa
			continue;
Packit Service db8eaa
Packit Service db8eaa
		err = snd_ctl_read(trial->handle, event);
Packit Service db8eaa
		if (err < 0)
Packit Service db8eaa
			return err;
Packit Service db8eaa
		if (snd_ctl_event_get_type(event) != SND_CTL_EVENT_ELEM)
Packit Service db8eaa
			continue;
Packit Service db8eaa
		/*
Packit Service db8eaa
		 * I expect each event is generated separately to the same
Packit Service db8eaa
		 * element or several events are generated at once.
Packit Service db8eaa
		 */
Packit Service db8eaa
		if ((snd_ctl_event_elem_get_mask(event) & mask) != mask)
Packit Service db8eaa
			continue;
Packit Service db8eaa
		--expected_count;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	if (expected_count != 0)
Packit Service db8eaa
		return -EIO;
Packit Service db8eaa
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int check_elem_list(struct elem_set_trial *trial)
Packit Service db8eaa
{
Packit Service db8eaa
	snd_ctl_elem_list_t *list;
Packit Service db8eaa
	snd_ctl_elem_id_t *id;
Packit Service db8eaa
	int e;
Packit Service db8eaa
	unsigned int i;
Packit Service db8eaa
	int err;
Packit Service db8eaa
Packit Service db8eaa
	snd_ctl_elem_list_alloca(&list);
Packit Service db8eaa
	snd_ctl_elem_id_alloca(&id;;
Packit Service db8eaa
Packit Service db8eaa
	err = snd_ctl_elem_list(trial->handle, list);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		return err;
Packit Service db8eaa
Packit Service db8eaa
	/* Certainly some elements are already added. */
Packit Service db8eaa
	if (snd_ctl_elem_list_get_count(list) == 0)
Packit Service db8eaa
		return -EIO;
Packit Service db8eaa
Packit Service db8eaa
	err = snd_ctl_elem_list_alloc_space(list,
Packit Service db8eaa
					    snd_ctl_elem_list_get_count(list));
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		return err;
Packit Service db8eaa
Packit Service db8eaa
	err = snd_ctl_elem_list(trial->handle, list);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		goto end;
Packit Service db8eaa
Packit Service db8eaa
	if (trial->element_count > snd_ctl_elem_list_get_count(list)) {
Packit Service db8eaa
		err = -EIO;
Packit Service db8eaa
		goto end;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	i = 0;
Packit Service db8eaa
	for (e = 0; e < snd_ctl_elem_list_get_count(list); ++e) {
Packit Service db8eaa
		snd_ctl_elem_list_get_id(list, e, id);
Packit Service db8eaa
Packit Service db8eaa
		if (strcmp(snd_ctl_elem_id_get_name(id),
Packit Service db8eaa
			   snd_ctl_elem_id_get_name(trial->id)) != 0)
Packit Service db8eaa
			continue;
Packit Service db8eaa
		if (snd_ctl_elem_id_get_interface(id) !=
Packit Service db8eaa
		    snd_ctl_elem_id_get_interface(trial->id))
Packit Service db8eaa
			continue;
Packit Service db8eaa
		if (snd_ctl_elem_id_get_device(id) !=
Packit Service db8eaa
		    snd_ctl_elem_id_get_device(trial->id))
Packit Service db8eaa
			continue;
Packit Service db8eaa
		if (snd_ctl_elem_id_get_subdevice(id) !=
Packit Service db8eaa
		    snd_ctl_elem_id_get_subdevice(trial->id))
Packit Service db8eaa
			continue;
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 * Here, I expect the list includes element ID data in numerical
Packit Service db8eaa
		 * order. Actually, it does.
Packit Service db8eaa
		 */
Packit Service db8eaa
		if (snd_ctl_elem_id_get_numid(id) !=
Packit Service db8eaa
		    snd_ctl_elem_id_get_numid(trial->id) + i)
Packit Service db8eaa
			continue;
Packit Service db8eaa
		if (snd_ctl_elem_id_get_index(id) !=
Packit Service db8eaa
		    snd_ctl_elem_id_get_index(trial->id) + i)
Packit Service db8eaa
			continue;
Packit Service db8eaa
Packit Service db8eaa
		++i;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	if (i != trial->element_count)
Packit Service db8eaa
		err = -EIO;
Packit Service db8eaa
end:
Packit Service db8eaa
	snd_ctl_elem_list_free_space(list);
Packit Service db8eaa
Packit Service db8eaa
	return err;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int check_elem_set_props(struct elem_set_trial *trial)
Packit Service db8eaa
{
Packit Service db8eaa
	snd_ctl_elem_id_t *id;
Packit Service db8eaa
	snd_ctl_elem_info_t *info;
Packit Service db8eaa
	unsigned int numid;
Packit Service db8eaa
	unsigned int index;
Packit Service db8eaa
	unsigned int i;
Packit Service db8eaa
	unsigned int j;
Packit Service db8eaa
	int err;
Packit Service db8eaa
Packit Service db8eaa
	snd_ctl_elem_id_alloca(&id;;
Packit Service db8eaa
	snd_ctl_elem_info_alloca(&info;;
Packit Service db8eaa
Packit Service db8eaa
	snd_ctl_elem_info_set_id(info, trial->id);
Packit Service db8eaa
	numid = snd_ctl_elem_id_get_numid(trial->id);
Packit Service db8eaa
	index = snd_ctl_elem_id_get_index(trial->id);
Packit Service db8eaa
Packit Service db8eaa
	for (i = 0; i < trial->element_count; ++i) {
Packit Service db8eaa
		snd_ctl_elem_info_set_index(info, index + i);
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 * In Linux 4.0 or former, ioctl(SNDRV_CTL_IOCTL_ELEM_ADD)
Packit Service db8eaa
		 * doesn't fill all of fields for identification.
Packit Service db8eaa
		 */
Packit Service db8eaa
		if (numid > 0)
Packit Service db8eaa
			snd_ctl_elem_info_set_numid(info, numid + i);
Packit Service db8eaa
Packit Service db8eaa
		err = snd_ctl_elem_info(trial->handle, info);
Packit Service db8eaa
		if (err < 0)
Packit Service db8eaa
			return err;
Packit Service db8eaa
Packit Service db8eaa
		/* Check some common properties. */
Packit Service db8eaa
		if (snd_ctl_elem_info_get_type(info) != trial->type)
Packit Service db8eaa
			return -EIO;
Packit Service db8eaa
		if (snd_ctl_elem_info_get_count(info) != trial->member_count)
Packit Service db8eaa
			return -EIO;
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 * In a case of IPC, this is the others. But in this case,
Packit Service db8eaa
		 * it's myself.
Packit Service db8eaa
		 */
Packit Service db8eaa
		if (snd_ctl_elem_info_get_owner(info) != getpid())
Packit Service db8eaa
			return -EIO;
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 * Just adding an element set by userspace applications,
Packit Service db8eaa
		 * included elements are initially locked.
Packit Service db8eaa
		 */
Packit Service db8eaa
		if (!snd_ctl_elem_info_is_locked(info))
Packit Service db8eaa
			return -EIO;
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 * In initial state, any application can register TLV data for
Packit Service db8eaa
		 * user-defined element set except for IEC 958 type, thus
Packit Service db8eaa
		 * elements in any user-defined set should allow any write
Packit Service db8eaa
		 * operation.
Packit Service db8eaa
		 */
Packit Service db8eaa
		if (trial->type != SND_CTL_ELEM_TYPE_IEC958 &&
Packit Service db8eaa
		    !snd_ctl_elem_info_is_tlv_writable(info))
Packit Service db8eaa
			return -EIO;
Packit Service db8eaa
Packit Service db8eaa
		/* Check type-specific properties. */
Packit Service db8eaa
		if (trial->check_elem_props != NULL) {
Packit Service db8eaa
			err = trial->check_elem_props(trial, info);
Packit Service db8eaa
			if (err < 0)
Packit Service db8eaa
				return err;
Packit Service db8eaa
		}
Packit Service db8eaa
Packit Service db8eaa
		snd_ctl_elem_info_get_id(info, id);
Packit Service db8eaa
		err = snd_ctl_elem_unlock(trial->handle, id);
Packit Service db8eaa
		if (err < 0)
Packit Service db8eaa
			return err;
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 * Till kernel v4.14, ALSA control core allows elements in any
Packit Service db8eaa
		 * user-defined set to have TLV_READ flag even if they have no
Packit Service db8eaa
		 * TLV data in their initial state. In this case, any read
Packit Service db8eaa
		 * operation for TLV data should return -ENXIO.
Packit Service db8eaa
		 */
Packit Service db8eaa
		if (snd_ctl_elem_info_is_tlv_readable(info)) {
Packit Service db8eaa
			unsigned int data[32];
Packit Service db8eaa
			err = snd_ctl_elem_tlv_read(trial->handle, trial->id,
Packit Service db8eaa
						    data, sizeof(data));
Packit Service db8eaa
			if (err >= 0)
Packit Service db8eaa
				return -EIO;
Packit Service db8eaa
			if (err != -ENXIO)
Packit Service db8eaa
				return err;
Packit Service db8eaa
Packit Service db8eaa
			trial->tlv_readable = true;
Packit Service db8eaa
		}
Packit Service db8eaa
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int check_elems(struct elem_set_trial *trial)
Packit Service db8eaa
{
Packit Service db8eaa
	snd_ctl_elem_value_t *data;
Packit Service db8eaa
	unsigned int numid;
Packit Service db8eaa
	unsigned int index;
Packit Service db8eaa
	unsigned int i;
Packit Service db8eaa
	int err;
Packit Service db8eaa
Packit Service db8eaa
	snd_ctl_elem_value_alloca(&data);
Packit Service db8eaa
Packit Service db8eaa
	snd_ctl_elem_value_set_id(data, trial->id);
Packit Service db8eaa
	numid = snd_ctl_elem_id_get_numid(trial->id);
Packit Service db8eaa
	index = snd_ctl_elem_id_get_index(trial->id);
Packit Service db8eaa
Packit Service db8eaa
	for (i = 0; i < trial->element_count; ++i) {
Packit Service db8eaa
		snd_ctl_elem_value_set_index(data, index + i);
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 * In Linux 4.0 or former, ioctl(SNDRV_CTL_IOCTL_ELEM_ADD)
Packit Service db8eaa
		 * doesn't fill all of fields for identification.
Packit Service db8eaa
		 */
Packit Service db8eaa
		if (numid > 0)
Packit Service db8eaa
			snd_ctl_elem_value_set_numid(data, numid + i);
Packit Service db8eaa
Packit Service db8eaa
		err = snd_ctl_elem_read(trial->handle, data);
Packit Service db8eaa
		if (err < 0)
Packit Service db8eaa
			return err;
Packit Service db8eaa
Packit Service db8eaa
		/* Change members of an element in this element set. */
Packit Service db8eaa
		trial->change_elem_members(trial, data);
Packit Service db8eaa
Packit Service db8eaa
		err = snd_ctl_elem_write(trial->handle, data);
Packit Service db8eaa
		if (err < 0)
Packit Service db8eaa
			return err;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int check_tlv(struct elem_set_trial *trial)
Packit Service db8eaa
{
Packit Service db8eaa
	unsigned int *tlv;
Packit Service db8eaa
	int mask;
Packit Service db8eaa
	unsigned int count;
Packit Service db8eaa
	unsigned int len;
Packit Service db8eaa
	unsigned int *curr;
Packit Service db8eaa
	int err;
Packit Service db8eaa
Packit Service db8eaa
	err = trial->allocate_elem_set_tlv(trial, &tlv);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		return err;
Packit Service db8eaa
Packit Service db8eaa
	len = tlv[SNDRV_CTL_TLVO_LEN] + sizeof(unsigned int) * 2;
Packit Service db8eaa
	curr = malloc(len);
Packit Service db8eaa
	if (curr == NULL) {
Packit Service db8eaa
		free(tlv);
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	/*
Packit Service db8eaa
	 * In in-kernel implementation, write and command operations are the
Packit Service db8eaa
	 * same for an element set added by userspace applications. Here, I
Packit Service db8eaa
	 * use write.
Packit Service db8eaa
	 */
Packit Service db8eaa
	err = snd_ctl_elem_tlv_write(trial->handle, trial->id,
Packit Service db8eaa
				     (const unsigned int *)tlv);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		goto end;
Packit Service db8eaa
Packit Service db8eaa
	/*
Packit Service db8eaa
	 * Since kernel v4.14, any write operation to an element in user-defined
Packit Service db8eaa
	 * set can change state of the other elements in the same set. In this
Packit Service db8eaa
	 * case, any TLV data is firstly available after the operation.
Packit Service db8eaa
	 */
Packit Service db8eaa
	if (!trial->tlv_readable) {
Packit Service db8eaa
		mask = SND_CTL_EVENT_MASK_INFO | SND_CTL_EVENT_MASK_TLV;
Packit Service db8eaa
		count = trial->element_count;
Packit Service db8eaa
	} else {
Packit Service db8eaa
		mask = SND_CTL_EVENT_MASK_TLV;
Packit Service db8eaa
		count = 1;
Packit Service db8eaa
	}
Packit Service db8eaa
	err = check_event(trial, mask, count);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		goto end;
Packit Service db8eaa
	if (!trial->tlv_readable) {
Packit Service db8eaa
		snd_ctl_elem_info_t *info;
Packit Service db8eaa
		snd_ctl_elem_info_alloca(&info;;
Packit Service db8eaa
Packit Service db8eaa
		snd_ctl_elem_info_set_id(info, trial->id);
Packit Service db8eaa
		err = snd_ctl_elem_info(trial->handle, info);
Packit Service db8eaa
		if (err < 0)
Packit Service db8eaa
			return err;
Packit Service db8eaa
		if (!snd_ctl_elem_info_is_tlv_readable(info))
Packit Service db8eaa
			return -EIO;
Packit Service db8eaa
Packit Service db8eaa
		/* Now TLV data is available for this element set. */
Packit Service db8eaa
		trial->tlv_readable = true;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	err = snd_ctl_elem_tlv_read(trial->handle, trial->id, curr, len);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		goto end;
Packit Service db8eaa
Packit Service db8eaa
	if (memcmp(curr, tlv, len) != 0)
Packit Service db8eaa
		err = -EIO;
Packit Service db8eaa
end:
Packit Service db8eaa
	free(tlv);
Packit Service db8eaa
	free(curr);
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
int main(void)
Packit Service db8eaa
{
Packit Service db8eaa
	struct elem_set_trial trial = {0};
Packit Service db8eaa
	unsigned int i;
Packit Service db8eaa
	int err;
Packit Service db8eaa
Packit Service db8eaa
	snd_ctl_elem_id_alloca(&trial.id);
Packit Service db8eaa
Packit Service db8eaa
	err = snd_ctl_open(&trial.handle, "hw:0", 0);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		return EXIT_FAILURE;
Packit Service db8eaa
Packit Service db8eaa
	err = snd_ctl_subscribe_events(trial.handle, 1);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		return EXIT_FAILURE;
Packit Service db8eaa
Packit Service db8eaa
	/* Test all of types. */
Packit Service db8eaa
	for (i = 0; i < SND_CTL_ELEM_TYPE_LAST; ++i) {
Packit Service db8eaa
		trial.type = i + 1;
Packit Service db8eaa
Packit Service db8eaa
		/* Assign type-dependent operations. */
Packit Service db8eaa
		switch (trial.type) {
Packit Service db8eaa
		case SND_CTL_ELEM_TYPE_BOOLEAN:
Packit Service db8eaa
			trial.element_count = 900;
Packit Service db8eaa
			trial.member_count = 128;
Packit Service db8eaa
			trial.add_elem_set = add_bool_elem_set;
Packit Service db8eaa
			trial.check_elem_props = NULL;
Packit Service db8eaa
			trial.change_elem_members = change_bool_elem_members;
Packit Service db8eaa
			trial.allocate_elem_set_tlv =
Packit Service db8eaa
						allocate_bool_elem_set_tlv;
Packit Service db8eaa
			trial.tlv_readable = false;
Packit Service db8eaa
			break;
Packit Service db8eaa
		case SND_CTL_ELEM_TYPE_INTEGER:
Packit Service db8eaa
			trial.element_count = 900;
Packit Service db8eaa
			trial.member_count = 128;
Packit Service db8eaa
			trial.add_elem_set = add_int_elem_set;
Packit Service db8eaa
			trial.check_elem_props = check_int_elem_props;
Packit Service db8eaa
			trial.change_elem_members = change_int_elem_members;
Packit Service db8eaa
			trial.allocate_elem_set_tlv =
Packit Service db8eaa
						allocate_int_elem_set_tlv;
Packit Service db8eaa
			trial.tlv_readable = false;
Packit Service db8eaa
			break;
Packit Service db8eaa
		case SND_CTL_ELEM_TYPE_ENUMERATED:
Packit Service db8eaa
			trial.element_count = 900;
Packit Service db8eaa
			trial.member_count = 128;
Packit Service db8eaa
			trial.add_elem_set = add_enum_elem_set;
Packit Service db8eaa
			trial.check_elem_props = check_enum_elem_props;
Packit Service db8eaa
			trial.change_elem_members = change_enum_elem_members;
Packit Service db8eaa
			trial.allocate_elem_set_tlv = NULL;
Packit Service db8eaa
			trial.tlv_readable = false;
Packit Service db8eaa
			break;
Packit Service db8eaa
		case SND_CTL_ELEM_TYPE_BYTES:
Packit Service db8eaa
			trial.element_count = 900;
Packit Service db8eaa
			trial.member_count = 512;
Packit Service db8eaa
			trial.add_elem_set = add_bytes_elem_set;
Packit Service db8eaa
			trial.check_elem_props = NULL;
Packit Service db8eaa
			trial.change_elem_members = change_bytes_elem_members;
Packit Service db8eaa
			trial.allocate_elem_set_tlv =
Packit Service db8eaa
						allocate_bytes_elem_set_tlv;
Packit Service db8eaa
			trial.tlv_readable = false;
Packit Service db8eaa
			break;
Packit Service db8eaa
		case SND_CTL_ELEM_TYPE_IEC958:
Packit Service db8eaa
			trial.element_count = 1;
Packit Service db8eaa
			trial.member_count = 1;
Packit Service db8eaa
			trial.add_elem_set = add_iec958_elem_set;
Packit Service db8eaa
			trial.check_elem_props = NULL;
Packit Service db8eaa
			trial.change_elem_members = change_iec958_elem_members;
Packit Service db8eaa
			trial.allocate_elem_set_tlv = NULL;
Packit Service db8eaa
			trial.tlv_readable = false;
Packit Service db8eaa
			break;
Packit Service db8eaa
		case SND_CTL_ELEM_TYPE_INTEGER64:
Packit Service db8eaa
		default:
Packit Service db8eaa
			trial.element_count = 900;
Packit Service db8eaa
			trial.member_count = 64;
Packit Service db8eaa
			trial.add_elem_set = add_int64_elem_set;
Packit Service db8eaa
			trial.check_elem_props = check_int64_elem_props;
Packit Service db8eaa
			trial.change_elem_members = change_int64_elem_members;
Packit Service db8eaa
			trial.allocate_elem_set_tlv =
Packit Service db8eaa
						allocate_int64_elem_set_tlv;
Packit Service db8eaa
			trial.tlv_readable = false;
Packit Service db8eaa
			break;
Packit Service db8eaa
		}
Packit Service db8eaa
Packit Service db8eaa
		/* Test an operation to add an element set. */
Packit Service db8eaa
		err = add_elem_set(&trial;;
Packit Service db8eaa
		if (err < 0) {
Packit Service db8eaa
			printf("Fail to add an element set with %s type.\n",
Packit Service db8eaa
			       snd_ctl_elem_type_name(trial.type));
Packit Service db8eaa
			break;
Packit Service db8eaa
		}
Packit Service db8eaa
		err = check_event(&trial, SND_CTL_EVENT_MASK_ADD,
Packit Service db8eaa
				  trial.element_count);
Packit Service db8eaa
		if (err < 0) {
Packit Service db8eaa
			printf("Fail to check some events to add elements with "
Packit Service db8eaa
			       "%s type.\n",
Packit Service db8eaa
			       snd_ctl_elem_type_name(trial.type));
Packit Service db8eaa
			break;
Packit Service db8eaa
		}
Packit Service db8eaa
Packit Service db8eaa
		/* Check added elements are retrieved in a list. */
Packit Service db8eaa
		err = check_elem_list(&trial;;
Packit Service db8eaa
		if (err < 0) {
Packit Service db8eaa
			printf("Fail to list each element with %s type.\n",
Packit Service db8eaa
			       snd_ctl_elem_type_name(trial.type));
Packit Service db8eaa
			break;
Packit Service db8eaa
		}
Packit Service db8eaa
Packit Service db8eaa
		/* Check properties of each element in this element set. */
Packit Service db8eaa
		err = check_elem_set_props(&trial;;
Packit Service db8eaa
		if (err < 0) {
Packit Service db8eaa
			printf("Fail to check properties of each element with "
Packit Service db8eaa
			       "%s type.\n",
Packit Service db8eaa
			       snd_ctl_elem_type_name(trial.type));
Packit Service db8eaa
			break;
Packit Service db8eaa
		}
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 * Test operations to change the state of members in each
Packit Service db8eaa
		 * element in the element set.
Packit Service db8eaa
		 */
Packit Service db8eaa
		err = check_elems(&trial;;
Packit Service db8eaa
		if (err < 0) {
Packit Service db8eaa
			printf("Fail to change status of each element with %s "
Packit Service db8eaa
			       "type.\n",
Packit Service db8eaa
			       snd_ctl_elem_type_name(trial.type));
Packit Service db8eaa
			break;
Packit Service db8eaa
		}
Packit Service db8eaa
		err = check_event(&trial, SND_CTL_EVENT_MASK_VALUE,
Packit Service db8eaa
				  trial.element_count);
Packit Service db8eaa
		if (err < 0) {
Packit Service db8eaa
			printf("Fail to check some events to change status of "
Packit Service db8eaa
			       "each elements with %s type.\n",
Packit Service db8eaa
			       snd_ctl_elem_type_name(trial.type));
Packit Service db8eaa
			break;
Packit Service db8eaa
		}
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 * Test an operation to change TLV data of this element set,
Packit Service db8eaa
		 * except for enumerated and IEC958 type.
Packit Service db8eaa
		 */
Packit Service db8eaa
		if (trial.allocate_elem_set_tlv != NULL) {
Packit Service db8eaa
			err = check_tlv(&trial;;
Packit Service db8eaa
			if (err < 0) {
Packit Service db8eaa
				printf("Fail to change TLV data of an element "
Packit Service db8eaa
				       "set with %s type.\n",
Packit Service db8eaa
				       snd_ctl_elem_type_name(trial.type));
Packit Service db8eaa
				break;
Packit Service db8eaa
			}
Packit Service db8eaa
		}
Packit Service db8eaa
Packit Service db8eaa
		/* Test an operation to remove elements in this element set. */
Packit Service db8eaa
		err = snd_ctl_elem_remove(trial.handle, trial.id);
Packit Service db8eaa
		if (err < 0) {
Packit Service db8eaa
			printf("Fail to remove elements with %s type.\n",
Packit Service db8eaa
			       snd_ctl_elem_type_name(trial.type));
Packit Service db8eaa
			break;
Packit Service db8eaa
		}
Packit Service db8eaa
		err = check_event(&trial, SND_CTL_EVENT_MASK_REMOVE,
Packit Service db8eaa
						  trial.element_count);
Packit Service db8eaa
		if (err < 0) {
Packit Service db8eaa
			printf("Fail to check some events to remove each "
Packit Service db8eaa
			       "element with %s type.\n",
Packit Service db8eaa
			       snd_ctl_elem_type_name(trial.type));
Packit Service db8eaa
			break;
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	if (err < 0) {
Packit Service db8eaa
		printf("%s\n", snd_strerror(err));
Packit Service db8eaa
Packit Service db8eaa
		/* To ensure. */
Packit Service db8eaa
		snd_ctl_elem_remove(trial.handle, trial.id);
Packit Service db8eaa
		return EXIT_FAILURE;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	return EXIT_SUCCESS;
Packit Service db8eaa
}