/* 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; }
/* * 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; }