/** * \brief Set TLV value for an HCTL element * \param elem HCTL element * \param tlv TLV array for value * \retval 0 on success * \retval >1 on success when value was changed * \retval <0 a negative error code on failure */ int snd_hctl_elem_tlv_write(snd_hctl_elem_t *elem, const unsigned int *tlv) { assert(elem); assert(tlv); assert(tlv[1] >= 4); return snd_ctl_elem_tlv_write(elem->hctl->ctl, &elem->id, tlv); }
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; }
static int execute_cset(snd_ctl_t *ctl, const char *cset, unsigned int type) { const char *pos; int err; snd_ctl_elem_id_t *id; snd_ctl_elem_value_t *value; snd_ctl_elem_info_t *info; unsigned int *res = NULL; snd_ctl_elem_id_malloc(&id); snd_ctl_elem_value_malloc(&value); snd_ctl_elem_info_malloc(&info); err = __snd_ctl_ascii_elem_id_parse(id, cset, &pos); if (err < 0) goto __fail; while (*pos && isspace(*pos)) pos++; if (!*pos) { uc_error("undefined value for cset >%s<", cset); err = -EINVAL; goto __fail; } snd_ctl_elem_info_set_id(info, id); err = snd_ctl_elem_info(ctl, info); if (err < 0) goto __fail; if (type == SEQUENCE_ELEMENT_TYPE_CSET_TLV) { if (!snd_ctl_elem_info_is_tlv_writable(info)) { err = -EINVAL; goto __fail; } err = read_tlv_file(&res, pos); if (err < 0) goto __fail; err = snd_ctl_elem_tlv_write(ctl, id, res); if (err < 0) goto __fail; } else { snd_ctl_elem_value_set_id(value, id); err = snd_ctl_elem_read(ctl, value); if (err < 0) goto __fail; if (type == SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE) err = binary_file_parse(value, info, pos); else err = snd_ctl_ascii_value_parse(ctl, value, info, pos); if (err < 0) goto __fail; err = snd_ctl_elem_write(ctl, value); if (err < 0) goto __fail; } err = 0; __fail: if (id != NULL) free(id); if (value != NULL) free(value); if (info != NULL) free(info); if (res != NULL) free(res); return err; }