/* initialize dB range information, reading TLV via hcontrol
 */
static int init_db_range(snd_hctl_elem_t *ctl, struct selem_str *rec)
{
	snd_ctl_elem_info_t *info;
	unsigned int *tlv = NULL;
	const unsigned int tlv_size = 4096;
	unsigned int *dbrec;
	int db_size;

	if (rec->db_init_error)
		return -EINVAL;
	if (rec->db_initialized)
		return 0;

	snd_ctl_elem_info_alloca(&info);
	if (snd_hctl_elem_info(ctl, info) < 0)
		goto error;
	if (! snd_ctl_elem_info_is_tlv_readable(info))
		goto error;
	tlv = malloc(tlv_size);
	if (! tlv)
		return -ENOMEM;
	if (snd_hctl_elem_tlv_read(ctl, tlv, tlv_size) < 0)
		goto error;
	db_size = snd_tlv_parse_dB_info(tlv, tlv_size, &dbrec);
	if (db_size < 0)
		goto error;
	rec->db_info = malloc(db_size);
	if (!rec->db_info)
		goto error;
	memcpy(rec->db_info, dbrec, db_size);
	free(tlv);
	rec->db_initialized = 1;
	return 0;

 error:
	free(tlv);
	rec->db_init_error = 1;
	return -EINVAL;
}
예제 #2
0
/*
 * add the TLV string and dB ranges to comment fields
 */
static int add_tlv_comments(snd_ctl_t *handle, snd_ctl_elem_id_t *id,
			    snd_ctl_elem_info_t *info, snd_config_t *comment)
{
	unsigned int tlv[MAX_USER_TLV_SIZE];
	unsigned int *db;
	long dbmin, dbmax;
	int err;

	if (snd_ctl_elem_tlv_read(handle, id, tlv, sizeof(tlv)) < 0)
		return 0; /* ignore error */

	if (snd_ctl_elem_info_is_tlv_writable(info)) {
		char *s = tlv_to_str(tlv);
		if (s) {
			err = snd_config_string_add(comment, "tlv", s);
			if (err < 0) {
				error("snd_config_string_add: %s", snd_strerror(err));
				return err;
			}
			free(s);
		}
	}

	err = snd_tlv_parse_dB_info(tlv, sizeof(tlv), &db);
	if (err <= 0)
		return 0;

	snd_tlv_get_dB_range(db, snd_ctl_elem_info_get_min(info),
			     snd_ctl_elem_info_get_max(info),
			     &dbmin, &dbmax);
	if (err < 0)
		return err;
	snd_config_integer_add(comment, "dbmin", dbmin);
	snd_config_integer_add(comment, "dbmax", dbmax);
	return 0;
}