mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-10-29 05:40:25 -04:00 
			
		
		
		
	 d61d71a9bb
			
		
	
	
		d61d71a9bb
		
	
	
	
	
		
			
			Currently, this test program has a bug related to dimension information. When testing an element set with byte type, the program adds 512 members to an element. This is a maximum number permitted for this type. On the other hand, dimension information of the elements consists of [8, 4, 8, 4]. Calculated members in the multi-dimensional matrix is 1024. This should be less than 512. This commit fixes the bug. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
		
			
				
	
	
		
			639 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			639 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * user-control-element-set.c - a program to test in-kernel implementation of
 | |
|  *				user-defined control element set.
 | |
|  *
 | |
|  * Copyright (c) 2015-2016 Takashi Sakamoto
 | |
|  *
 | |
|  * Licensed under the terms of the GNU General Public License, version 2.
 | |
|  */
 | |
| 
 | |
| #include "../include/asoundlib.h"
 | |
| 
 | |
| struct elem_set_trial {
 | |
| 	snd_ctl_t *handle;
 | |
| 
 | |
| 	snd_ctl_elem_type_t type;
 | |
| 	unsigned int member_count;
 | |
| 	unsigned int element_count;
 | |
| 
 | |
| 	snd_ctl_elem_id_t *id;
 | |
| 	int dimension[4];
 | |
| 
 | |
| 	int (*add_elem_set)(struct elem_set_trial *trial,
 | |
| 			    snd_ctl_elem_info_t *info);
 | |
| 	int (*check_elem_props)(struct elem_set_trial *trial,
 | |
| 				snd_ctl_elem_info_t *info);
 | |
| 	void (*change_elem_members)(struct elem_set_trial *trial,
 | |
| 				    snd_ctl_elem_value_t *elem_data);
 | |
| };
 | |
| 
 | |
| /* Operations for elements in an element set with boolean type. */
 | |
| static int add_bool_elem_set(struct elem_set_trial *trial,
 | |
| 			     snd_ctl_elem_info_t *info)
 | |
| {
 | |
| 	return snd_ctl_elem_add_boolean_set(trial->handle, info,
 | |
| 				trial->element_count, trial->member_count);
 | |
| }
 | |
| 
 | |
| static void change_bool_elem_members(struct elem_set_trial *trial,
 | |
| 				     snd_ctl_elem_value_t *elem_data)
 | |
| {
 | |
| 	int val;
 | |
| 	unsigned int i;
 | |
| 
 | |
| 	for (i = 0; i < trial->member_count; ++i) {
 | |
| 		val = snd_ctl_elem_value_get_boolean(elem_data, i);
 | |
| 		snd_ctl_elem_value_set_boolean(elem_data, i, !val);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* Operations for elements in an element set with integer type. */
 | |
| static int add_int_elem_set(struct elem_set_trial *trial,
 | |
| 			    snd_ctl_elem_info_t *info)
 | |
| {
 | |
| 	return snd_ctl_elem_add_integer_set(trial->handle, info,
 | |
| 				trial->element_count, trial->member_count,
 | |
| 				0, 99, 1);
 | |
| }
 | |
| 
 | |
| static int check_int_elem_props(struct elem_set_trial *trial,
 | |
| 				snd_ctl_elem_info_t *info)
 | |
| {
 | |
| 	if (snd_ctl_elem_info_get_min(info) != 0)
 | |
| 		return -EIO;
 | |
| 	if (snd_ctl_elem_info_get_max(info) != 99)
 | |
| 		return -EIO;
 | |
| 	if (snd_ctl_elem_info_get_step(info) != 1)
 | |
| 		return -EIO;
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static void change_int_elem_members(struct elem_set_trial *trial,
 | |
| 				    snd_ctl_elem_value_t *elem_data)
 | |
| {
 | |
| 	long val;
 | |
| 	unsigned int i;
 | |
| 
 | |
| 	for (i = 0; i < trial->member_count; ++i) {
 | |
| 		val = snd_ctl_elem_value_get_integer(elem_data, i);
 | |
| 		snd_ctl_elem_value_set_integer(elem_data, i, ++val);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* Operations for elements in an element set with enumerated type. */
 | |
| static const char *const labels[] = {
 | |
| 	"trusty",
 | |
| 	"utopic",
 | |
| 	"vivid",
 | |
| 	"willy",
 | |
| 	"xenial",
 | |
| };
 | |
| 
 | |
| static int add_enum_elem_set(struct elem_set_trial *trial,
 | |
| 			     snd_ctl_elem_info_t *info)
 | |
| {
 | |
| 	return snd_ctl_elem_add_enumerated_set(trial->handle, info,
 | |
| 				trial->element_count, trial->member_count,
 | |
| 				sizeof(labels) / sizeof(labels[0]),
 | |
| 				labels);
 | |
| }
 | |
| 
 | |
| static int check_enum_elem_props(struct elem_set_trial *trial,
 | |
| 				 snd_ctl_elem_info_t *info)
 | |
| {
 | |
| 	unsigned int items;
 | |
| 	unsigned int i;
 | |
| 	const char *label;
 | |
| 	int err;
 | |
| 
 | |
| 	items = snd_ctl_elem_info_get_items(info);
 | |
| 	if (items != sizeof(labels) / sizeof(labels[0]))
 | |
| 		return -EIO;
 | |
| 
 | |
| 	/* Enumerate and validate all of labels registered to this element. */
 | |
| 	for (i = 0; i < items; ++i) {
 | |
| 		snd_ctl_elem_info_set_item(info, i);
 | |
| 		err = snd_ctl_elem_info(trial->handle, info);
 | |
| 		if (err < 0)
 | |
| 			return err;
 | |
| 
 | |
| 		label = snd_ctl_elem_info_get_item_name(info);
 | |
| 		if (strncmp(label, labels[i], strlen(labels[i])) != 0)
 | |
| 			return -EIO;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static void change_enum_elem_members(struct elem_set_trial *trial,
 | |
| 				     snd_ctl_elem_value_t *elem_data)
 | |
| {
 | |
| 	unsigned int val;
 | |
| 	unsigned int i;
 | |
| 
 | |
| 	for (i = 0; i < trial->member_count; ++i) {
 | |
| 		val = snd_ctl_elem_value_get_enumerated(elem_data, i);
 | |
| 		snd_ctl_elem_value_set_enumerated(elem_data, i, ++val);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* Operations for elements in an element set with bytes type. */
 | |
| static int add_bytes_elem_set(struct elem_set_trial *trial,
 | |
| 			      snd_ctl_elem_info_t *info)
 | |
| {
 | |
| 	return snd_ctl_elem_add_bytes_set(trial->handle, info,
 | |
| 				trial->element_count, trial->member_count);
 | |
| }
 | |
| 
 | |
| static void change_bytes_elem_members(struct elem_set_trial *trial,
 | |
| 				      snd_ctl_elem_value_t *elem_data)
 | |
| {
 | |
| 	unsigned char val;
 | |
| 	unsigned int i;
 | |
| 
 | |
| 	for (i = 0; i < trial->member_count; ++i) {
 | |
| 		val = snd_ctl_elem_value_get_byte(elem_data, i);
 | |
| 		snd_ctl_elem_value_set_byte(elem_data, i, ++val);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* Operations for elements in an element set with iec958 type. */
 | |
| static int add_iec958_elem_set(struct elem_set_trial *trial,
 | |
| 			       snd_ctl_elem_info_t *info)
 | |
| {
 | |
| 	int err;
 | |
| 
 | |
| 	snd_ctl_elem_info_get_id(info, trial->id);
 | |
| 
 | |
| 	err = snd_ctl_elem_add_iec958(trial->handle, trial->id);
 | |
| 	if (err < 0)
 | |
| 	        return err;
 | |
| 
 | |
| 	/*
 | |
| 	 * In historical reason, the above API is not allowed to fill all of
 | |
| 	 * fields in identification data.
 | |
| 	 */
 | |
| 	return snd_ctl_elem_info(trial->handle, info);
 | |
| }
 | |
| 
 | |
| static void change_iec958_elem_members(struct elem_set_trial *trial,
 | |
| 				       snd_ctl_elem_value_t *elem_data)
 | |
| {
 | |
| 	snd_aes_iec958_t data;
 | |
| 
 | |
| 	/* To suppress GCC warnings. */
 | |
| 	trial->element_count = 1;
 | |
| 
 | |
| 	snd_ctl_elem_value_get_iec958(elem_data, &data);
 | |
| 	/* This is an arbitrary number. */
 | |
| 	data.pad = 10;
 | |
| 	snd_ctl_elem_value_set_iec958(elem_data, &data);
 | |
| }
 | |
| 
 | |
| /* Operations for elements in an element set with integer64 type. */
 | |
| static int add_int64_elem_set(struct elem_set_trial *trial,
 | |
| 			      snd_ctl_elem_info_t *info)
 | |
| {
 | |
| 	return snd_ctl_elem_add_integer64_set(trial->handle, info,
 | |
| 				trial->element_count, trial->member_count,
 | |
| 				100, 10000, 30);
 | |
| }
 | |
| 
 | |
| static int check_int64_elem_props(struct elem_set_trial *trial,
 | |
| 				  snd_ctl_elem_info_t *info)
 | |
| {
 | |
| 	if (snd_ctl_elem_info_get_min64(info) != 100)
 | |
| 		return -EIO;
 | |
| 	if (snd_ctl_elem_info_get_max64(info) != 10000)
 | |
| 		return -EIO;
 | |
| 	if (snd_ctl_elem_info_get_step64(info) != 30)
 | |
| 		return -EIO;
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static void change_int64_elem_members(struct elem_set_trial *trial,
 | |
| 				      snd_ctl_elem_value_t *elem_data)
 | |
| {
 | |
| 	long long val;
 | |
| 	unsigned int i;
 | |
| 
 | |
| 	for (i = 0; i < trial->member_count; ++i) {
 | |
| 		val = snd_ctl_elem_value_get_integer64(elem_data, i);
 | |
| 		snd_ctl_elem_value_set_integer64(elem_data, i, ++val);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* Common operations. */
 | |
| static int add_elem_set(struct elem_set_trial *trial)
 | |
| {
 | |
| 	snd_ctl_elem_info_t *info;
 | |
| 	char name[64] = {0};
 | |
| 	int err;
 | |
| 
 | |
| 	snprintf(name, 64, "userspace-control-element-%s",
 | |
| 		 snd_ctl_elem_type_name(trial->type));
 | |
| 
 | |
| 	snd_ctl_elem_info_alloca(&info);
 | |
| 	snd_ctl_elem_info_set_interface(info, SND_CTL_ELEM_IFACE_MIXER);
 | |
| 	snd_ctl_elem_info_set_name(info, name);
 | |
| 	snd_ctl_elem_info_set_dimension(info, trial->dimension);
 | |
| 
 | |
| 	err = trial->add_elem_set(trial, info);
 | |
| 	if (err >= 0)
 | |
| 		snd_ctl_elem_info_get_id(info, trial->id);
 | |
| 
 | |
| 	return err;
 | |
| }
 | |
| 
 | |
| static int check_event(struct elem_set_trial *trial, unsigned int mask,
 | |
| 		       unsigned int expected_count)
 | |
| {
 | |
| 	struct pollfd pfds;
 | |
| 	int count;
 | |
| 	unsigned short revents;
 | |
| 	snd_ctl_event_t *event;
 | |
| 	int err;
 | |
| 
 | |
| 	snd_ctl_event_alloca(&event);
 | |
| 
 | |
| 	if (snd_ctl_poll_descriptors_count(trial->handle) != 1)
 | |
| 		return -ENXIO;
 | |
| 
 | |
| 	if (snd_ctl_poll_descriptors(trial->handle, &pfds, 1) != 1)
 | |
| 		return -ENXIO;
 | |
| 
 | |
| 	while (expected_count > 0) {
 | |
| 		count = poll(&pfds, 1, 1000);
 | |
| 		if (count < 0)
 | |
| 			return errno;
 | |
| 		/* Some events are already supplied. */
 | |
| 		if (count == 0)
 | |
| 			return -ETIMEDOUT;
 | |
| 
 | |
| 		err = snd_ctl_poll_descriptors_revents(trial->handle, &pfds,
 | |
| 						       count, &revents);
 | |
| 		if (err < 0)
 | |
| 			return err;
 | |
| 		if (revents & POLLERR)
 | |
| 			return -EIO;
 | |
| 		if (!(revents & POLLIN))
 | |
| 			continue;
 | |
| 
 | |
| 		err = snd_ctl_read(trial->handle, event);
 | |
| 		if (err < 0)
 | |
| 			return err;
 | |
| 		if (snd_ctl_event_get_type(event) != SND_CTL_EVENT_ELEM)
 | |
| 			continue;
 | |
| 		/*
 | |
| 		 * I expect each event is generated separately to the same
 | |
| 		 * element.
 | |
| 		 */
 | |
| 		if (!(snd_ctl_event_elem_get_mask(event) & mask))
 | |
| 			continue;
 | |
| 		--expected_count;
 | |
| 	}
 | |
| 
 | |
| 	if (expected_count != 0)
 | |
| 		return -EIO;
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int check_elem_set_props(struct elem_set_trial *trial)
 | |
| {
 | |
| 	snd_ctl_elem_id_t *id;
 | |
| 	snd_ctl_elem_info_t *info;
 | |
| 	unsigned int numid;
 | |
| 	unsigned int index;
 | |
| 	unsigned int i;
 | |
| 	unsigned int j;
 | |
| 	int err;
 | |
| 
 | |
| 	snd_ctl_elem_id_alloca(&id);
 | |
| 	snd_ctl_elem_info_alloca(&info);
 | |
| 
 | |
| 	snd_ctl_elem_info_set_id(info, trial->id);
 | |
| 	numid = snd_ctl_elem_id_get_numid(trial->id);
 | |
| 	index = snd_ctl_elem_id_get_index(trial->id);
 | |
| 
 | |
| 	for (i = 0; i < trial->element_count; ++i) {
 | |
| 		snd_ctl_elem_info_set_index(info, index + i);
 | |
| 
 | |
| 		/*
 | |
| 		 * In Linux 4.0 or former, ioctl(SNDRV_CTL_IOCTL_ELEM_ADD)
 | |
| 		 * doesn't fill all of fields for identification.
 | |
| 		 */
 | |
| 		if (numid > 0)
 | |
| 			snd_ctl_elem_info_set_numid(info, numid + i);
 | |
| 
 | |
| 		err = snd_ctl_elem_info(trial->handle, info);
 | |
| 		if (err < 0)
 | |
| 			return err;
 | |
| 
 | |
| 		/* Check some common properties. */
 | |
| 		if (snd_ctl_elem_info_get_type(info) != trial->type)
 | |
| 			return -EIO;
 | |
| 		if (snd_ctl_elem_info_get_count(info) != trial->member_count)
 | |
| 			return -EIO;
 | |
| 		for (j = 0; j < 4; ++j) {
 | |
| 			if (snd_ctl_elem_info_get_dimension(info, j) !=
 | |
| 							trial->dimension[j])
 | |
| 				return -EIO;
 | |
| 		}
 | |
| 
 | |
| 		/*
 | |
| 		 * In a case of IPC, this is the others. But in this case,
 | |
| 		 * it's myself.
 | |
| 		 */
 | |
| 		if (snd_ctl_elem_info_get_owner(info) != getpid())
 | |
| 			return -EIO;
 | |
| 
 | |
| 		/*
 | |
| 		 * Just adding an element set by userspace applications,
 | |
| 		 * included elements are initially locked.
 | |
| 		 */
 | |
| 		if (!snd_ctl_elem_info_is_locked(info))
 | |
| 			return -EIO;
 | |
| 
 | |
| 		/* Check type-specific properties. */
 | |
| 		if (trial->check_elem_props != NULL) {
 | |
| 			err = trial->check_elem_props(trial, info);
 | |
| 			if (err < 0)
 | |
| 				return err;
 | |
| 		}
 | |
| 
 | |
| 		snd_ctl_elem_info_get_id(info, id);
 | |
| 		err = snd_ctl_elem_unlock(trial->handle, id);
 | |
| 		if (err < 0)
 | |
| 			return err;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int check_elems(struct elem_set_trial *trial)
 | |
| {
 | |
| 	snd_ctl_elem_value_t *data;
 | |
| 	unsigned int numid;
 | |
| 	unsigned int index;
 | |
| 	unsigned int i;
 | |
| 	int err;
 | |
| 
 | |
| 	snd_ctl_elem_value_alloca(&data);
 | |
| 
 | |
| 	snd_ctl_elem_value_set_id(data, trial->id);
 | |
| 	numid = snd_ctl_elem_id_get_numid(trial->id);
 | |
| 	index = snd_ctl_elem_id_get_index(trial->id);
 | |
| 
 | |
| 	for (i = 0; i < trial->element_count; ++i) {
 | |
| 		snd_ctl_elem_value_set_index(data, index + i);
 | |
| 
 | |
| 		/*
 | |
| 		 * In Linux 4.0 or former, ioctl(SNDRV_CTL_IOCTL_ELEM_ADD)
 | |
| 		 * doesn't fill all of fields for identification.
 | |
| 		 */
 | |
| 		if (numid > 0)
 | |
| 			snd_ctl_elem_value_set_numid(data, numid + i);
 | |
| 
 | |
| 		err = snd_ctl_elem_read(trial->handle, data);
 | |
| 		if (err < 0)
 | |
| 			return err;
 | |
| 
 | |
| 		/* Change members of an element in this element set. */
 | |
| 		trial->change_elem_members(trial, data);
 | |
| 
 | |
| 		err = snd_ctl_elem_write(trial->handle, data);
 | |
| 		if (err < 0)
 | |
| 			return err;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int check_tlv(struct elem_set_trial *trial)
 | |
| {
 | |
| 	unsigned int orig[8], curr[8];
 | |
| 	int err;
 | |
| 
 | |
| 	/*
 | |
| 	 * See a layout of 'struct snd_ctl_tlv'. I don't know the reason to
 | |
| 	 * construct this buffer with the same layout. It should be abstracted
 | |
| 	 * inner userspace library...
 | |
| 	 */
 | |
| 	orig[0] = snd_ctl_elem_id_get_numid(trial->id);
 | |
| 	orig[1] = 6 * sizeof(orig[0]);
 | |
| 	orig[2] = 'a';
 | |
| 	orig[3] = 'b';
 | |
| 	orig[4] = 'c';
 | |
| 	orig[5] = 'd';
 | |
| 	orig[6] = 'e';
 | |
| 	orig[7] = 'f';
 | |
| 
 | |
| 	/*
 | |
| 	 * In in-kernel implementation, write and command operations are the
 | |
| 	 * same  for an element set added by userspace applications. Here, I
 | |
| 	 * use write.
 | |
| 	 */
 | |
| 	err = snd_ctl_elem_tlv_write(trial->handle, trial->id,
 | |
| 				     (const unsigned int *)orig);
 | |
| 	if (err < 0)
 | |
| 		return err;
 | |
| 
 | |
| 	err = snd_ctl_elem_tlv_read(trial->handle, trial->id, curr,
 | |
| 				    sizeof(curr));
 | |
| 	if (err < 0)
 | |
| 		return err;
 | |
| 
 | |
| 	if (memcmp(curr, orig, sizeof(orig)) != 0)
 | |
| 		return -EIO;
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int main(void)
 | |
| {
 | |
| 	struct elem_set_trial trial = {0};
 | |
| 	unsigned int i;
 | |
| 	int err;
 | |
| 
 | |
| 	snd_ctl_elem_id_alloca(&trial.id);
 | |
| 
 | |
| 	err = snd_ctl_open(&trial.handle, "hw:0", 0);
 | |
| 	if (err < 0)
 | |
| 		return EXIT_FAILURE;
 | |
| 
 | |
| 	err = snd_ctl_subscribe_events(trial.handle, 1);
 | |
| 	if (err < 0)
 | |
| 		return EXIT_FAILURE;
 | |
| 
 | |
| 	/* Test all of types. */
 | |
| 	for (i = 0; i < SND_CTL_ELEM_TYPE_LAST; ++i) {
 | |
| 		trial.type = i + 1;
 | |
| 
 | |
| 		/* Assign type-dependent operations. */
 | |
| 		switch (trial.type) {
 | |
| 		case SND_CTL_ELEM_TYPE_BOOLEAN:
 | |
| 			trial.element_count = 900;
 | |
| 			trial.member_count = 128;
 | |
| 			trial.dimension[0] = 4;
 | |
| 			trial.dimension[1] = 4;
 | |
| 			trial.dimension[2] = 8;
 | |
| 			trial.dimension[3] = 0;
 | |
| 			trial.add_elem_set = add_bool_elem_set;
 | |
| 			trial.check_elem_props = NULL;
 | |
| 			trial.change_elem_members = change_bool_elem_members;
 | |
| 			break;
 | |
| 		case SND_CTL_ELEM_TYPE_INTEGER:
 | |
| 			trial.element_count = 900;
 | |
| 			trial.member_count = 128;
 | |
| 			trial.dimension[0] = 128;
 | |
| 			trial.dimension[1] = 0;
 | |
| 			trial.dimension[2] = 0;
 | |
| 			trial.dimension[3] = 0;
 | |
| 			trial.add_elem_set = add_int_elem_set;
 | |
| 			trial.check_elem_props = check_int_elem_props;
 | |
| 			trial.change_elem_members = change_int_elem_members;
 | |
| 			break;
 | |
| 		case SND_CTL_ELEM_TYPE_ENUMERATED:
 | |
| 			trial.element_count = 900;
 | |
| 			trial.member_count = 128;
 | |
| 			trial.dimension[0] = 16;
 | |
| 			trial.dimension[1] = 8;
 | |
| 			trial.dimension[2] = 0;
 | |
| 			trial.dimension[3] = 0;
 | |
| 			trial.add_elem_set = add_enum_elem_set;
 | |
| 			trial.check_elem_props = check_enum_elem_props;
 | |
| 			trial.change_elem_members = change_enum_elem_members;
 | |
| 			break;
 | |
| 		case SND_CTL_ELEM_TYPE_BYTES:
 | |
| 			trial.element_count = 900;
 | |
| 			trial.member_count = 512;
 | |
| 			trial.dimension[0] = 8;
 | |
| 			trial.dimension[1] = 4;
 | |
| 			trial.dimension[2] = 8;
 | |
| 			trial.dimension[3] = 2;
 | |
| 			trial.add_elem_set = add_bytes_elem_set;
 | |
| 			trial.check_elem_props = NULL;
 | |
| 			trial.change_elem_members = change_bytes_elem_members;
 | |
| 			break;
 | |
| 		case SND_CTL_ELEM_TYPE_IEC958:
 | |
| 			trial.element_count = 1;
 | |
| 			trial.member_count = 1;
 | |
| 			trial.dimension[0] = 0;
 | |
| 			trial.dimension[1] = 0;
 | |
| 			trial.dimension[2] = 0;
 | |
| 			trial.dimension[3] = 0;
 | |
| 			trial.add_elem_set = add_iec958_elem_set;
 | |
| 			trial.check_elem_props = NULL;
 | |
| 			trial.change_elem_members = change_iec958_elem_members;
 | |
| 			break;
 | |
| 		case SND_CTL_ELEM_TYPE_INTEGER64:
 | |
| 		default:
 | |
| 			trial.element_count = 900;
 | |
| 			trial.member_count = 64;
 | |
| 			trial.dimension[0] = 0;
 | |
| 			trial.dimension[1] = 0;
 | |
| 			trial.dimension[2] = 0;
 | |
| 			trial.dimension[3] = 0;
 | |
| 			trial.add_elem_set = add_int64_elem_set;
 | |
| 			trial.check_elem_props = check_int64_elem_props;
 | |
| 			trial.change_elem_members = change_int64_elem_members;
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 		/* Test an operation to add an element set. */
 | |
| 		err = add_elem_set(&trial);
 | |
| 		if (err < 0) {
 | |
| 			printf("Fail to add an element set with %s type.\n",
 | |
| 			       snd_ctl_elem_type_name(trial.type));
 | |
| 			break;
 | |
| 		}
 | |
| 		err = check_event(&trial, SND_CTL_EVENT_MASK_ADD,
 | |
| 				  trial.element_count);
 | |
| 		if (err < 0) {
 | |
| 			printf("Fail to check some events to add elements with "
 | |
| 			       "%s type.\n",
 | |
| 			       snd_ctl_elem_type_name(trial.type));
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 		/* Check properties of each element in this element set. */
 | |
| 		err = check_elem_set_props(&trial);
 | |
| 		if (err < 0) {
 | |
| 			printf("Fail to check propetries of each element with "
 | |
| 			       "%s type.\n",
 | |
| 			       snd_ctl_elem_type_name(trial.type));
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 		/*
 | |
| 		 * Test operations to change the state of members in each
 | |
| 		 * element in the element set.
 | |
| 		 */
 | |
| 		err = check_elems(&trial);
 | |
| 		if (err < 0) {
 | |
| 			printf("Fail to change status of each element with %s "
 | |
| 			       "type.\n",
 | |
| 			       snd_ctl_elem_type_name(trial.type));
 | |
| 			break;
 | |
| 		}
 | |
| 		err = check_event(&trial, SND_CTL_EVENT_MASK_VALUE,
 | |
| 				  trial.element_count);
 | |
| 		if (err < 0) {
 | |
| 			printf("Fail to check some events to change status of "
 | |
| 			       "each elements with %s type.\n",
 | |
| 			       snd_ctl_elem_type_name(trial.type));
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 		/*
 | |
| 		 * Test an operation to change threshold data of this element set,
 | |
| 		 * except for IEC958 type.
 | |
| 		 */
 | |
| 		if (trial.type != SND_CTL_ELEM_TYPE_IEC958) {
 | |
| 			err = check_tlv(&trial);
 | |
| 			if (err < 0) {
 | |
| 				printf("Fail to change threshold level of an "
 | |
| 				       "element set with %s type.\n",
 | |
| 				       snd_ctl_elem_type_name(trial.type));
 | |
| 				break;
 | |
| 			}
 | |
| 			err = check_event(&trial, SND_CTL_EVENT_MASK_TLV, 1);
 | |
| 			if (err < 0) {
 | |
| 				printf("Fail to check an event to change "
 | |
| 				       "threshold level of an an element set "
 | |
| 				       "with %s type.\n",
 | |
| 				       snd_ctl_elem_type_name(trial.type));
 | |
| 				break;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		/* Test an operation to remove elements in this element set. */
 | |
| 		err = snd_ctl_elem_remove(trial.handle, trial.id);
 | |
| 		if (err < 0) {
 | |
| 			printf("Fail to remove elements with %s type.\n",
 | |
| 			       snd_ctl_elem_type_name(trial.type));
 | |
| 			break;
 | |
| 		}
 | |
| 		err = check_event(&trial, SND_CTL_EVENT_MASK_REMOVE,
 | |
| 						  trial.element_count);
 | |
| 		if (err < 0) {
 | |
| 			printf("Fail to check some events to remove each "
 | |
| 			       "element with %s type.\n",
 | |
| 			       snd_ctl_elem_type_name(trial.type));
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (err < 0) {
 | |
| 		printf("%s\n", snd_strerror(err));
 | |
| 
 | |
| 		/* To ensure. */
 | |
| 		snd_ctl_elem_remove(trial.handle, trial.id);
 | |
| 		return EXIT_FAILURE;
 | |
| 	}
 | |
| 
 | |
| 	return EXIT_SUCCESS;
 | |
| }
 |