/** * \brief Get TLV value for an HCTL element * \param elem HCTL element * \param tlv TLV array for value * \param tlv_size size of TLV array in bytes * \return 0 otherwise a negative error code on failure */ int snd_hctl_elem_tlv_read(snd_hctl_elem_t *elem, unsigned int *tlv, unsigned int tlv_size) { assert(elem); assert(tlv); assert(tlv_size >= 12); return snd_ctl_elem_tlv_read(elem->hctl->ctl, &elem->id, tlv, tlv_size); }
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; }
/* * 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; }