Control API - add TLV support

snd_ctl_elem_tlv_read
snd_ctl_elem_tlv_write
snd_ctl_elem_tlv_command
snd_ctl_elem_info_is_tlv_readable
snd_ctl_elem_info_is_tlv_writable
snd_ctl_elem_info_is_tlv_commandable
snd_hctl_elem_tlv_read
snd_hctl_elem_tlv_write
snd_hctl_elem_tlv_command
This commit is contained in:
Jaroslav Kysela 2006-07-05 17:42:16 +02:00
parent 408697bfe2
commit c7a0708a23
7 changed files with 248 additions and 4 deletions

View file

@ -274,3 +274,17 @@ ALSA_1.0.11 {
snd_pcm_set_params;
snd_pcm_get_params;
} ALSA_1.0.10;
ALSA_1.0.12 {
global:
snd_ctl_elem_tlv_read;
snd_ctl_elem_tlv_write;
snd_ctl_elem_tlv_command;
snd_ctl_elem_info_is_tlv_readable;
snd_ctl_elem_info_is_tlv_writable;
snd_ctl_elem_info_is_tlv_commandable;
snd_hctl_elem_tlv_read;
snd_hctl_elem_tlv_write;
snd_hctl_elem_tlv_command;
} ALSA_1.0.11;

View file

@ -404,7 +404,9 @@ int snd_ctl_elem_read(snd_ctl_t *ctl, snd_ctl_elem_value_t *control)
* \brief Set CTL element value
* \param ctl CTL handle
* \param control CTL element id/value pointer
* \return 0 on success otherwise a negative error code
* \retval 0 on success
* \retval >0 on success when value was changed
* \retval <0 a negative error code
*/
int snd_ctl_elem_write(snd_ctl_t *ctl, snd_ctl_elem_value_t *control)
{
@ -412,6 +414,83 @@ int snd_ctl_elem_write(snd_ctl_t *ctl, snd_ctl_elem_value_t *control)
return ctl->ops->element_write(ctl, control);
}
static int snd_ctl_tlv_do(snd_ctl_t *ctl, int op_flag,
const snd_ctl_elem_id_t *id,
unsigned int *tlv, unsigned int tlv_size)
{
snd_ctl_elem_info_t *info = NULL;
int err;
if (id->numid == 0) {
info = calloc(1, sizeof(*info));
if (info == NULL)
return -ENOMEM;
info->id = *id;
id = &info->id;
err = snd_ctl_elem_info(ctl, info);
if (err < 0)
goto __err;
if (id->numid == 0) {
err = -ENOENT;
goto __err;
}
}
err = ctl->ops->element_tlv(ctl, op_flag, id->numid, tlv, tlv_size);
__err:
if (info)
free(info);
return err;
}
/**
* \brief Get CTL element TLV value
* \param ctl CTL handle
* \param id CTL element id pointer
* \param tlv TLV array pointer to store
* \param tlv_size TLV array size in bytes
* \return 0 on success otherwise a negative error code
*/
int snd_ctl_elem_tlv_read(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
unsigned int *tlv, unsigned int tlv_size)
{
assert(ctl && id && (id->name[0] || id->numid) && tlv);
return snd_ctl_tlv_do(ctl, 0, id, tlv, tlv_size);
}
/**
* \brief Set CTL element TLV value
* \param ctl CTL handle
* \param id CTL element id pointer
* \param tlv TLV array pointer to store
* \retval 0 on success
* \retval >0 on success when value was changed
* \retval <0 a negative error code
*/
int snd_ctl_elem_tlv_write(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
const unsigned int *tlv)
{
assert(ctl && id && (id->name[0] || id->numid) && tlv);
return snd_ctl_tlv_do(ctl, 1, id, (unsigned int *)tlv, tlv[1] + 2 * sizeof(unsigned int));
}
/**
* \brief Process CTL element TLV command
* \param ctl CTL handle
* \param id CTL element id pointer
* \param tlv TLV array pointer to process
* \retval 0 on success
* \retval >0 on success when value was changed
* \retval <0 a negative error code
*/
int snd_ctl_elem_tlv_command(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
const unsigned int *tlv)
{
assert(ctl && id && (id->name[0] || id->numid) && tlv);
return snd_ctl_tlv_do(ctl, -1, id, (unsigned int *)tlv, tlv[1] + 2 * sizeof(unsigned int));
}
/**
* \brief Lock CTL element
* \param ctl CTL handle
@ -1741,6 +1820,39 @@ int snd_ctl_elem_info_is_user(const snd_ctl_elem_info_t *obj)
return !!(obj->access & SNDRV_CTL_ELEM_ACCESS_USER);
}
/**
* \brief Get info about TLV readability from a CTL element id/info
* \param obj CTL element id/info
* \return 0 if element's TLV is not readable, 1 if element's TLV is readable
*/
int snd_ctl_elem_info_is_tlv_readable(const snd_ctl_elem_info_t *obj)
{
assert(obj);
return !!(obj->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ);
}
/**
* \brief Get info about TLV writeability from a CTL element id/info
* \param obj CTL element id/info
* \return 0 if element's TLV is not writable, 1 if element's TLV is writable
*/
int snd_ctl_elem_info_is_tlv_writable(const snd_ctl_elem_info_t *obj)
{
assert(obj);
return !!(obj->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE);
}
/**
* \brief Get info about TLV command possibility from a CTL element id/info
* \param obj CTL element id/info
* \return 0 if element's TLV command is not possible, 1 if element's TLV command is supported
*/
int snd_ctl_elem_info_is_tlv_commandable(const snd_ctl_elem_info_t *obj)
{
assert(obj);
return !!(obj->access & SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND);
}
/**
* \brief (DEPRECATED) Get info about values passing policy from a CTL element value
* \param obj CTL element id/info

View file

@ -200,6 +200,39 @@ static int snd_ctl_hw_elem_unlock(snd_ctl_t *handle, snd_ctl_elem_id_t *id)
return 0;
}
static int snd_ctl_hw_elem_tlv(snd_ctl_t *handle, int op_flag,
unsigned int numid,
unsigned int *tlv, unsigned int tlv_size)
{
int inum;
snd_ctl_hw_t *hw = handle->private_data;
struct sndrv_ctl_tlv *xtlv;
switch (op_flag) {
case -1: inum = SNDRV_CTL_IOCTL_TLV_COMMAND; break;
case 0: inum = SNDRV_CTL_IOCTL_TLV_READ; break;
case 1: inum = SNDRV_CTL_IOCTL_TLV_WRITE; break;
default: return -EINVAL;
}
xtlv = malloc(sizeof(struct sndrv_ctl_tlv) + tlv_size);
if (xtlv == NULL)
return -ENOMEM;
xtlv->numid = numid;
xtlv->length = tlv_size;
memcpy(xtlv->tlv, tlv, tlv_size);
if (ioctl(hw->fd, inum, xtlv) < 0) {
free(xtlv);
return -errno;
}
if (op_flag == 0) {
if (xtlv->tlv[1] + 2 * sizeof(unsigned int) > tlv_size)
return -EFAULT;
memcpy(tlv, xtlv->tlv, xtlv->tlv[1] + 2 * sizeof(unsigned int));
}
free(xtlv);
return 0;
}
static int snd_ctl_hw_hwdep_next_device(snd_ctl_t *handle, int * device)
{
snd_ctl_hw_t *hw = handle->private_data;
@ -305,6 +338,7 @@ snd_ctl_ops_t snd_ctl_hw_ops = {
.element_write = snd_ctl_hw_elem_write,
.element_lock = snd_ctl_hw_elem_lock,
.element_unlock = snd_ctl_hw_elem_unlock,
.element_tlv = snd_ctl_hw_elem_tlv,
.hwdep_next_device = snd_ctl_hw_hwdep_next_device,
.hwdep_info = snd_ctl_hw_hwdep_info,
.pcm_next_device = snd_ctl_hw_pcm_next_device,

View file

@ -36,6 +36,8 @@ typedef struct _snd_ctl_ops {
int (*element_write)(snd_ctl_t *handle, snd_ctl_elem_value_t *control);
int (*element_lock)(snd_ctl_t *handle, snd_ctl_elem_id_t *lock);
int (*element_unlock)(snd_ctl_t *handle, snd_ctl_elem_id_t *unlock);
int (*element_tlv)(snd_ctl_t *handle, int op_flag, unsigned int numid,
unsigned int *tlv, unsigned int tlv_size);
int (*hwdep_next_device)(snd_ctl_t *handle, int *device);
int (*hwdep_info)(snd_ctl_t *handle, snd_hwdep_info_t * info);
int (*pcm_next_device)(snd_ctl_t *handle, int *device);

View file

@ -821,7 +821,9 @@ int snd_hctl_elem_read(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value)
* \brief Set value for an HCTL element
* \param elem HCTL element
* \param value HCTL element value
* \return 0 otherwise a negative error code on failure
* \retval 0 on success
* \ratval >1 on success when value was changed
* \retval <0 a negative error code on failure
*/
int snd_hctl_elem_write(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value)
{
@ -832,6 +834,53 @@ int snd_hctl_elem_write(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value)
return snd_ctl_elem_write(elem->hctl->ctl, value);
}
/**
* \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);
}
/**
* \brief Set TLV value for an HCTL element
* \param elem HCTL element
* \param tlv TLV array for value
* \retval 0 on success
* \ratval >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);
}
/**
* \brief Set TLV value for an HCTL element
* \param elem HCTL element
* \param tlv TLV array for value
* \retval 0 on success
* \ratval >1 on success when value was changed
* \retval <0 a negative error code on failure
*/
int snd_hctl_elem_tlv_command(snd_hctl_elem_t *elem, const unsigned int *tlv)
{
assert(elem);
assert(tlv);
assert(tlv[1] >= 4);
return snd_ctl_elem_tlv_command(elem->hctl->ctl, &elem->id, tlv);
}
/**
* \brief Get HCTL handle for an HCTL element
* \param elem HCTL element