From 688ca6b27ebb83cc3e735ca0b2bbd00a0f5e17ad Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 18 Nov 2019 13:22:44 +0900 Subject: [PATCH] ctl: card: add APIs to write/read/command Type-Length-Value data for element --- src/ctl/alsactl.map | 3 + src/ctl/card.c | 139 ++++++++++++++++++++++++++++++++++++++++++++ src/ctl/card.h | 12 ++++ tests/alsactl-card | 3 + 4 files changed, 157 insertions(+) diff --git a/src/ctl/alsactl.map b/src/ctl/alsactl.map index cb85df7..44585d6 100644 --- a/src/ctl/alsactl.map +++ b/src/ctl/alsactl.map @@ -18,6 +18,9 @@ ALSA_GOBJECT_0_0_0 { "alsactl_card_get_elem_id_list"; "alsactl_card_lock_elem"; "alsactl_card_get_elem_info"; + "alsactl_card_write_elem_tlv"; + "alsactl_card_read_elem_tlv"; + "alsactl_card_command_elem_tlv"; "alsactl_card_info_get_type"; diff --git a/src/ctl/card.c b/src/ctl/card.c index 061ab54..e0b4774 100644 --- a/src/ctl/card.c +++ b/src/ctl/card.c @@ -339,3 +339,142 @@ void alsactl_card_get_elem_info(ALSACtlCard *self, const ALSACtlElemId *elem_id, ctl_elem_info_refer_private(ALSACTL_ELEM_INFO(*elem_info), &info_ptr); *info_ptr = info; } + +/** + * alsactl_card_write_elem_tlv: + * @self: A #ALSACtlCard. + * @elem_id: A #ALSACtlElemId. + * @container: (array length=container_count): The array with qudalets for + * Type-Length-Value data. + * @container_count: The number of quadlets in the container. + * @error: A #GError. + */ +void alsactl_card_write_elem_tlv(ALSACtlCard *self, + const ALSACtlElemId *elem_id, + const gint32 *container, gsize container_count, + GError **error) +{ + ALSACtlCardPrivate *priv; + struct snd_ctl_tlv *packet; + size_t container_size; + + g_return_if_fail(ALSACTL_IS_CARD(self)); + g_return_if_fail(elem_id != NULL); + priv = alsactl_card_get_instance_private(self); + + // At least two quadlets should be included for type and length. + if (container == NULL || container_count < 2) { + generate_error(error, EINVAL); + return; + } + container_size = container_count * sizeof(*container); + + packet = g_malloc0(sizeof(*packet) + container_size); + if (packet == NULL) { + generate_error(error, ENOMEM); + return; + } + + packet->numid = elem_id->numid; + packet->length = container_size; + memcpy(packet->tlv, container, container_size); + + if (ioctl(priv->fd, SNDRV_CTL_IOCTL_TLV_WRITE, packet) < 0) + generate_error(error, errno); + + g_free(packet); +} + +/** + * alsactl_card_read_elem_tlv: + * @self: A #ALSACtlCard. + * @elem_id: A #ALSACtlElemId. + * @container: (array length=container_count)(inout): The array with qudalets + * for Type-Length-Value data. + * @container_count: The number of quadlets in the container. + * @error: A #GError. + */ +void alsactl_card_read_elem_tlv(ALSACtlCard *self, const ALSACtlElemId *elem_id, + gint32 *const *container, gsize *container_count, + GError **error) +{ + ALSACtlCardPrivate *priv; + struct snd_ctl_tlv *packet; + size_t container_size; + + g_return_if_fail(ALSACTL_IS_CARD(self)); + g_return_if_fail(elem_id != NULL); + priv = alsactl_card_get_instance_private(self); + + // At least two quadlets should be included for type and length. + if (*container == NULL || *container_count < 2) { + generate_error(error, EINVAL); + return; + } + container_size = *container_count * sizeof(**container); + + packet = g_malloc0(sizeof(*packet) + container_size); + if (packet == NULL) { + generate_error(error, ENOMEM); + return; + } + + packet->numid = elem_id->numid; + packet->length = container_size; + + if (ioctl(priv->fd, SNDRV_CTL_IOCTL_TLV_READ, packet) < 0) + generate_error(error, errno); + + memcpy(*container, packet->tlv, packet->length); + *container_count = packet->length / sizeof(**container); + + g_free(packet); +} + +/** + * alsactl_card_command_elem_tlv: + * @self: A #ALSACtlCard. + * @elem_id: A #ALSACtlElemId. + * @container: (array length=container_count)(inout): The array with qudalets + * for Type-Length-Value data. + * @container_count: The number of quadlets in the container. + * @error: A #GError. + */ +void alsactl_card_command_elem_tlv(ALSACtlCard *self, + const ALSACtlElemId *elem_id, + gint32 *const *container, gsize *container_count, + GError **error) +{ + ALSACtlCardPrivate *priv; + struct snd_ctl_tlv *packet; + size_t container_size; + + g_return_if_fail(ALSACTL_IS_CARD(self)); + g_return_if_fail(elem_id != NULL); + priv = alsactl_card_get_instance_private(self); + + // At least two quadlets should be included for type and length. + if (*container == NULL || *container_count < 2) { + generate_error(error, EINVAL); + return; + } + container_size = *container_count * sizeof(**container); + + packet = g_malloc0(sizeof(*packet) + container_size); + if (packet == NULL) { + generate_error(error, ENOMEM); + return; + } + + packet->numid = elem_id->numid; + packet->length = container_size; + memcpy(packet->tlv, *container, container_size); + + if (ioctl(priv->fd, SNDRV_CTL_IOCTL_TLV_COMMAND, packet) < 0) + generate_error(error, errno); + + memcpy(*container, packet->tlv, packet->length); + *container_count = packet->length / sizeof(**container); + + g_free(packet); +} diff --git a/src/ctl/card.h b/src/ctl/card.h index 8dacecb..c4c5681 100644 --- a/src/ctl/card.h +++ b/src/ctl/card.h @@ -65,6 +65,18 @@ void alsactl_card_lock_elem(ALSACtlCard *self, const ALSACtlElemId *elem_id, void alsactl_card_get_elem_info(ALSACtlCard *self, const ALSACtlElemId *elem_id, ALSACtlElemInfo **elem_info, GError **error); +void alsactl_card_write_elem_tlv(ALSACtlCard *self, + const ALSACtlElemId *elem_id, + const gint32 *container, gsize container_count, + GError **error); +void alsactl_card_read_elem_tlv(ALSACtlCard *self, const ALSACtlElemId *elem_id, + gint32 *const *container, gsize *container_count, + GError **error); +void alsactl_card_command_elem_tlv(ALSACtlCard *self, + const ALSACtlElemId *elem_id, + gint32 *const *container, gsize *container_count, + GError **error); + G_END_DECLS #endif diff --git a/tests/alsactl-card b/tests/alsactl-card index 12ca1c9..83b93ee 100644 --- a/tests/alsactl-card +++ b/tests/alsactl-card @@ -20,6 +20,9 @@ methods = ( 'get_elem_id_list', 'lock_elem', 'get_elem_info', + 'write_elem_tlv', + 'read_elem_tlv', + 'command_elem_tlv', ) signals = () -- 2.47.3