From c0fb7005d66171ae9bf97bb2a9f7d6ec622ad2a3 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 17 Sep 2024 21:00:19 -0700 Subject: [PATCH 1/6] tools: ctl: Add ABI header for kcontrol read This is necessary to pass the param ID for the data being requested. Signed-off-by: Ranjani Sridharan --- tools/ctl/ctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/ctl/ctl.c b/tools/ctl/ctl.c index 3f969635b4cc..1d89c2c15fd9 100644 --- a/tools/ctl/ctl.c +++ b/tools/ctl/ctl.c @@ -508,6 +508,8 @@ static int ctl_set_get(struct ctl_data *ctl_data) fprintf(stdout, "Retrieving configuration for "); fprintf(stdout, "device %s control %s.\n", ctl_data->dev, ctl_data->cname); + /* set the ABI header to pass the param ID */ + header_init(ctl_data); ctl_data->buffer[BUFFER_SIZE_OFFSET] = ctl_data->ctrl_size; ret = snd_ctl_elem_tlv_read(ctl_data->ctl, ctl_data->id, ctl_data->buffer, From f0334b66a7f4d95ca27d232260c18aaf7775e222 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 17 Sep 2024 21:06:57 -0700 Subject: [PATCH 2/6] tools: plugin: tplg_ctl: Set control type Set the type while parsing the controls. Signed-off-by: Ranjani Sridharan --- tools/plugin/alsaplug/tplg_ctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/plugin/alsaplug/tplg_ctl.c b/tools/plugin/alsaplug/tplg_ctl.c index db3248ed5b76..620c730f82a1 100644 --- a/tools/plugin/alsaplug/tplg_ctl.c +++ b/tools/plugin/alsaplug/tplg_ctl.c @@ -170,6 +170,7 @@ int plug_kcontrol_cb_new(struct snd_soc_tplg_ctl_hdr *tplg_ctl, void *_comp, voi ctl->instance_id = comp_info->instance_id; ctl->mixer_ctl = *tplg_mixer; ctl->index = index; + ctl->type = tplg_ctl->type; tlv = &tplg_ctl->tlv; scale = &tlv->scale; @@ -197,6 +198,7 @@ int plug_kcontrol_cb_new(struct snd_soc_tplg_ctl_hdr *tplg_ctl, void *_comp, voi ctl->instance_id = comp_info->instance_id; ctl->enum_ctl = *tplg_enum; ctl->index = index; + ctl->type = tplg_ctl->type; break; } case SND_SOC_TPLG_CTL_BYTES: From 1008ec07e77cc6743e7061e918940fe4b242c06f Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 17 Sep 2024 21:09:17 -0700 Subject: [PATCH 3/6] tool: plugin: tplg: Parse kcontrols for process type widgets Parse and set up the kcontrols during topology parsing. Signed-off-by: Ranjani Sridharan --- tools/plugin/alsaplug/tplg.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tools/plugin/alsaplug/tplg.c b/tools/plugin/alsaplug/tplg.c index 3b5cb7be8609..2d60bf90921d 100644 --- a/tools/plugin/alsaplug/tplg.c +++ b/tools/plugin/alsaplug/tplg.c @@ -312,7 +312,22 @@ static int plug_new_process(snd_sof_plug_t *plug) plug_setup_widget_ipc_msg(comp_info); - return 0; + tplg_ctl = calloc(ctx->hdr->payload_size, 1); + if (!tplg_ctl) { + free(comp_info->ipc_payload); + return -ENOMEM; + } + + /* set up kcontrols */ + ret = tplg_create_controls(ctx, ctx->widget->num_kcontrols, + tplg_ctl, ctx->hdr->payload_size, comp_info); + if (ret < 0) { + SNDERR("failed to create controls for process comp\n"); + free(comp_info->ipc_payload); + } + + free(tplg_ctl); + return ret; } static int plug_new_pipeline(snd_sof_plug_t *plug) From 248c51737969cf29e79eb5a094318c129d5513db Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 17 Sep 2024 21:13:09 -0700 Subject: [PATCH 4/6] tools: plugin: Move plug_mq_cmd_tx_rx() definition to common code It will be used by both the PCM and the control plugin. Signed-off-by: Ranjani Sridharan --- tools/plugin/alsaplug/plugin.c | 73 ---------------------------------- tools/plugin/common.c | 72 +++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 73 deletions(-) diff --git a/tools/plugin/alsaplug/plugin.c b/tools/plugin/alsaplug/plugin.c index c8fb86ce809c..be5ff0e69f2b 100644 --- a/tools/plugin/alsaplug/plugin.c +++ b/tools/plugin/alsaplug/plugin.c @@ -41,79 +41,6 @@ #include "plugin.h" #include "common.h" -int plug_mq_cmd_tx_rx(struct plug_mq_desc *ipc_tx, struct plug_mq_desc *ipc_rx, - void *msg, size_t len, void *reply, size_t rlen) -{ - struct timespec ts; - ssize_t ipc_size; - char mailbox[IPC3_MAX_MSG_SIZE]; - int err; - - if (len > IPC3_MAX_MSG_SIZE) { - SNDERR("ipc: message too big %d\n", len); - return -EINVAL; - } - memset(mailbox, 0, IPC3_MAX_MSG_SIZE); - memcpy(mailbox, msg, len); - - /* wait for sof-pipe reader to consume data or timeout */ - err = clock_gettime(CLOCK_REALTIME, &ts); - if (err == -1) { - SNDERR("ipc: cant get time: %s", strerror(errno)); - return -errno; - } - - /* IPCs should be read under 10ms */ - plug_timespec_add_ms(&ts, 10); - - /* now return message completion status */ - err = mq_timedsend(ipc_tx->mq, mailbox, IPC3_MAX_MSG_SIZE, 0, &ts); - if (err == -1) { - SNDERR("error: timeout can't send IPC message queue %s : %s\n", - ipc_tx->queue_name, strerror(errno)); - return -errno; - } - - /* wait for sof-pipe reader to consume data or timeout */ - err = clock_gettime(CLOCK_REALTIME, &ts); - if (err == -1) { - SNDERR("ipc: cant get time: %s", strerror(errno)); - return -errno; - } - - /* IPCs should be processed under 20ms, but wait longer as - * some can take longer especially in valgrind - */ - plug_timespec_add_ms(&ts, 20); - - ipc_size = mq_timedreceive(ipc_rx->mq, mailbox, IPC3_MAX_MSG_SIZE, NULL, &ts); - if (ipc_size == -1) { - //fprintf(stderr, "dbg: timeout can't read IPC message queue %s : %s retrying\n", - // ipc->queue_name, strerror(errno)); - - /* ok, its a long IPC or valgrind, wait longer */ - plug_timespec_add_ms(&ts, 800); - - ipc_size = mq_timedreceive(ipc_rx->mq, mailbox, IPC3_MAX_MSG_SIZE, NULL, &ts); - if (ipc_size == -1) { - SNDERR("error: timeout can't read IPC message queue %s : %s\n", - ipc_rx->queue_name, strerror(errno)); - return -errno; - } - - /* needed for valgrind to complete MQ op before next client IPC */ - ts.tv_nsec = 20 * 1000 * 1000; - ts.tv_sec = 0; - nanosleep(&ts, NULL); - } - - /* do the message work */ - if (rlen && reply) - memcpy(reply, mailbox, rlen); - - return 0; -} - int plug_mq_cmd(struct plug_mq_desc *ipc, void *msg, size_t len, void *reply, size_t rlen) { return plug_mq_cmd_tx_rx(ipc, ipc, msg, len, reply, rlen); diff --git a/tools/plugin/common.c b/tools/plugin/common.c index d9bb1c7bb6ba..91b6e5df5b58 100644 --- a/tools/plugin/common.c +++ b/tools/plugin/common.c @@ -178,3 +178,75 @@ int plug_shm_open(struct plug_shm_desc *shm) return 0; } +int plug_mq_cmd_tx_rx(struct plug_mq_desc *ipc_tx, struct plug_mq_desc *ipc_rx, + void *msg, size_t len, void *reply, size_t rlen) +{ + struct timespec ts; + ssize_t ipc_size; + char mailbox[IPC3_MAX_MSG_SIZE]; + int err; + + if (len > IPC3_MAX_MSG_SIZE) { + SNDERR("ipc: message too big %d\n", len); + return -EINVAL; + } + memset(mailbox, 0, IPC3_MAX_MSG_SIZE); + memcpy(mailbox, msg, len); + + /* wait for sof-pipe reader to consume data or timeout */ + err = clock_gettime(CLOCK_REALTIME, &ts); + if (err == -1) { + SNDERR("ipc: cant get time: %s", strerror(errno)); + return -errno; + } + + /* IPCs should be read under 10ms */ + plug_timespec_add_ms(&ts, 10); + + /* now return message completion status */ + err = mq_timedsend(ipc_tx->mq, mailbox, IPC3_MAX_MSG_SIZE, 0, &ts); + if (err == -1) { + SNDERR("error: timeout can't send IPC message queue %s : %s\n", + ipc_tx->queue_name, strerror(errno)); + return -errno; + } + + /* wait for sof-pipe reader to consume data or timeout */ + err = clock_gettime(CLOCK_REALTIME, &ts); + if (err == -1) { + SNDERR("ipc: cant get time: %s", strerror(errno)); + return -errno; + } + + /* IPCs should be processed under 20ms, but wait longer as + * some can take longer especially in valgrind + */ + plug_timespec_add_ms(&ts, 20); + + ipc_size = mq_timedreceive(ipc_rx->mq, mailbox, IPC3_MAX_MSG_SIZE, NULL, &ts); + if (ipc_size == -1) { + //fprintf(stderr, "dbg: timeout can't read IPC message queue %s : %s retrying\n", + // ipc->queue_name, strerror(errno)); + + /* ok, its a long IPC or valgrind, wait longer */ + plug_timespec_add_ms(&ts, 800); + + ipc_size = mq_timedreceive(ipc_rx->mq, mailbox, IPC3_MAX_MSG_SIZE, NULL, &ts); + if (ipc_size == -1) { + SNDERR("error: timeout can't read IPC message queue %s : %s\n", + ipc_rx->queue_name, strerror(errno)); + return -errno; + } + + /* needed for valgrind to complete MQ op before next client IPC */ + ts.tv_nsec = 20 * 1000 * 1000; + ts.tv_sec = 0; + nanosleep(&ts, NULL); + } + + /* do the message work */ + if (rlen && reply) + memcpy(reply, mailbox, rlen); + + return 0; +} From 03715b2034ff92953541ae0c171a71ef95719340 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 17 Sep 2024 21:17:43 -0700 Subject: [PATCH 5/6] tools: plugin: common: Move plug_ctl_ipc_message() definition to common code It will be used by both the PCM and the control plugin. Signed-off-by: Ranjani Sridharan --- tools/plugin/alsaplug/ctl.c | 14 -------------- tools/plugin/common.c | 14 ++++++++++++++ tools/plugin/common.h | 4 ++++ 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/tools/plugin/alsaplug/ctl.c b/tools/plugin/alsaplug/ctl.c index be38587135c0..c235591a5f1f 100644 --- a/tools/plugin/alsaplug/ctl.c +++ b/tools/plugin/alsaplug/ctl.c @@ -198,20 +198,6 @@ static int plug_ctl_get_integer_info(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, return err; } -static void plug_ctl_ipc_message(struct ipc4_module_large_config *config, int param_id, - size_t size, uint32_t module_id, uint32_t instance_id, - uint32_t type) -{ - config->primary.r.type = type; - config->primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_MODULE_MSG; - config->primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; - config->primary.r.module_id = module_id; - config->primary.r.instance_id = instance_id; - - config->extension.r.data_off_size = size; - config->extension.r.large_param_id = param_id; -} - static int plug_ctl_read_integer(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, long *value) { snd_sof_ctl_t *ctl = ext->private_data; diff --git a/tools/plugin/common.c b/tools/plugin/common.c index 91b6e5df5b58..1674dea5f787 100644 --- a/tools/plugin/common.c +++ b/tools/plugin/common.c @@ -250,3 +250,17 @@ int plug_mq_cmd_tx_rx(struct plug_mq_desc *ipc_tx, struct plug_mq_desc *ipc_rx, return 0; } + +void plug_ctl_ipc_message(struct ipc4_module_large_config *config, int param_id, + size_t size, uint32_t module_id, uint32_t instance_id, + uint32_t type) +{ + config->primary.r.type = type; + config->primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_MODULE_MSG; + config->primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + config->primary.r.module_id = module_id; + config->primary.r.instance_id = instance_id; + + config->extension.r.data_off_size = size; + config->extension.r.large_param_id = param_id; +} diff --git a/tools/plugin/common.h b/tools/plugin/common.h index 5297d7564302..f849676fbcc8 100644 --- a/tools/plugin/common.h +++ b/tools/plugin/common.h @@ -317,4 +317,8 @@ static inline void data_dump(void *vdata, size_t bytes) printf("\n"); } +void plug_ctl_ipc_message(struct ipc4_module_large_config *config, int param_id, + size_t size, uint32_t module_id, uint32_t instance_id, + uint32_t type); + #endif From d5ea317892257b7e69c146976e7eb33d9e38e430 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 17 Sep 2024 21:03:56 -0700 Subject: [PATCH 6/6] tools: plugin: ctl: Add support for bytes control Add a new field in struct plug_shm_ctl to save the bytes data from topology for bytes controls. This will be used to send the kcontrol data to the modules right after they are instantiated. Fix the tlv callback in the control to handle the tlv bytes read/write when using sof-ctl. Signed-off-by: Ranjani Sridharan --- tools/plugin/README.md | 16 +++- tools/plugin/alsaplug/ctl.c | 140 +++++++++++++++++++++++++++---- tools/plugin/alsaplug/tplg.c | 32 ++++++- tools/plugin/alsaplug/tplg_ctl.c | 13 +++ tools/plugin/common.c | 42 ++++++++++ tools/plugin/common.h | 6 ++ 6 files changed, 232 insertions(+), 17 deletions(-) diff --git a/tools/plugin/README.md b/tools/plugin/README.md index 368b0f499377..673cbceb08ff 100644 --- a/tools/plugin/README.md +++ b/tools/plugin/README.md @@ -79,7 +79,21 @@ or ``` amixer -Dsof:plugin cset numid=1 20 ``` -Right now, only volume controls are supported. Support for bytes and enum controls is pending. +Bytes control data can be set using sof-ctl as follows: + +``` +./sof-ctl -Dsof:plugin -n 4 -r -i 4 -p 2 -s ~/data.txt +``` +where -n is the numid of the kcontrol, -i is the IPC version, -p is the param ID and -s specifies +the data in csv format. + +Bytes control data can be read using sof-ctl as follows: +``` +./sof-ctl -Dsof:plugin -n 4 -i 4 -p 2 +``` +where -n is the numid of the kcontrol, -i is the IPC version and -p is the param ID. + +Note: Bytes controls must have tlv_read/tlv_write and tlv_callback access. # Instructions for testing OpenVino noise suppression model with the SOF plugin: 1. Fetch the model from the Open Model zoo repository ex: noise-suppression-poconetlike-0001.xml diff --git a/tools/plugin/alsaplug/ctl.c b/tools/plugin/alsaplug/ctl.c index c235591a5f1f..f45bf4f9b0e1 100644 --- a/tools/plugin/alsaplug/ctl.c +++ b/tools/plugin/alsaplug/ctl.c @@ -145,10 +145,9 @@ static int plug_ctl_get_attribute(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, // TODO: ?? break; case SND_SOC_TPLG_CTL_BYTES: - printf("%s %d\n", __func__, __LINE__); bytes_ctl = (struct snd_soc_tplg_bytes_control *)hdr; *type = SND_CTL_ELEM_TYPE_BYTES; - *count = bytes_ctl->size; // Not sure if size is correct + *count = bytes_ctl->max; break; } @@ -536,36 +535,147 @@ static int plug_ctl_write_enumerated(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, /* * Bytes ops */ +static int plug_ctl_get_bytes_data(snd_sof_ctl_t *ctl, snd_ctl_ext_key_t key, + struct sof_abi_hdr *abi, unsigned int max_bytes) +{ + struct snd_soc_tplg_bytes_control *bytes_ctl = CTL_GET_TPLG_BYTES(ctl, key); + struct ipc4_module_large_config config = {{ 0 }}; + struct ipc4_module_large_config_reply *reply; + char *reply_data, *data; + void *msg; + uint32_t data_size; + int size, reply_data_size; + int err; + + /* configure the IPC message */ + plug_ctl_ipc_message(&config, abi->type, 0, + ctl->glb->ctl[key].module_id, ctl->glb->ctl[key].instance_id, + SOF_IPC4_MOD_LARGE_CONFIG_GET); + + config.extension.r.final_block = 1; + config.extension.r.init_block = 1; + + size = sizeof(config); + msg = calloc(size, 1); + if (!msg) + return -ENOMEM; + + /* + * reply contains both the requested data and the reply status. Allocate enough memory + * for max data + */ + reply_data_size = sizeof(*reply) + sizeof(*data) + bytes_ctl->max; + reply_data = calloc(reply_data_size, 1); + if (!reply_data_size) { + free(msg); + return -ENOMEM; + } + + /* send the IPC message */ + memcpy(msg, &config, sizeof(config)); + err = plug_mq_cmd_tx_rx(&ctl->ipc_tx, &ctl->ipc_rx, + msg, size, reply_data, reply_data_size); + free(msg); + if (err < 0) { + SNDERR("failed to get bytes data for control %s\n", bytes_ctl->hdr.name); + goto out; + } + + reply = (struct ipc4_module_large_config_reply *)reply_data; + if (reply->primary.r.status != IPC4_SUCCESS) { + SNDERR("bytes control %s get failed with status %d\n", + bytes_ctl->hdr.name, reply->primary.r.status); + err = -EINVAL; + goto out; + } + + /* check data sanity */ + data = (char *)(reply_data + sizeof(*reply)); + data_size = reply->extension.r.data_off_size; + if (data_size > bytes_ctl->max) { + SNDERR("received data size %d is larger than max %d for bytes control %s\n", + data_size, bytes_ctl->max, bytes_ctl->hdr.name); + err = -EINVAL; + goto out; + } + + abi->size = data_size; + + if (data_size) + memcpy(abi->data, data, MIN(data_size, max_bytes)); + + err = data_size; +out: + free(reply_data); + return err; +} + static int plug_ctl_read_bytes(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, unsigned char *data, size_t max_bytes) { + snd_sof_ctl_t *ctl = ext->private_data; + struct sof_abi_hdr *abi = (struct sof_abi_hdr *)data; + int data_size; + + data_size = plug_ctl_get_bytes_data(ctl, key, abi, max_bytes); + if (data_size < 0) + return data_size; + return 0; } static int plug_ctl_write_bytes(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, unsigned char *data, size_t max_bytes) { + snd_sof_ctl_t *ctl = ext->private_data; + struct snd_soc_tplg_bytes_control *bytes_ctl = CTL_GET_TPLG_BYTES(ctl, key); + struct sof_abi_hdr *abi = (struct sof_abi_hdr *)data; + int err; + + /* send IPC with kcontrol data */ + err = plug_send_bytes_data(&ctl->ipc_tx, &ctl->ipc_rx, + ctl->glb->ctl[key].module_id, ctl->glb->ctl[key].instance_id, + abi); + if (err < 0) { + SNDERR("failed to set bytes data for control %s\n", bytes_ctl->hdr.name); + return err; + } + return 0; } -/* - * TLV ops - * - * The format of an array of \a tlv argument is: - * tlv[0]: Type. One of SND_CTL_TLVT_XXX. - * tlv[1]: Length. The length of value in units of byte. - * tlv[2..]: Value. Depending on the type. - */ +/* TLV ops used for TLV bytes control callback */ static int plug_tlv_rw(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, int op_flag, unsigned int numid, unsigned int *tlv, unsigned int tlv_size) { snd_sof_ctl_t *ctl = ext->private_data; - struct snd_soc_tplg_ctl_hdr *hdr = CTL_GET_TPLG_HDR(ctl, key); + struct snd_soc_tplg_bytes_control *bytes_ctl = CTL_GET_TPLG_BYTES(ctl, key); + struct sof_abi_hdr *abi = (struct sof_abi_hdr *)(tlv + 2); /* skip TLV header */ + int data_size; + + /* send IPC with kcontrol data if op_flag is > 0 else send IPC to get kcontrol data */ + if (op_flag) { + int err; + + err = plug_send_bytes_data(&ctl->ipc_tx, &ctl->ipc_rx, + ctl->glb->ctl[key].module_id, + ctl->glb->ctl[key].instance_id, abi); + if (err < 0) { + SNDERR("failed to set bytes data for control %s\n", bytes_ctl->hdr.name); + return err; + } + + return 0; + } + + /* read kcontrol data */ + data_size = plug_ctl_get_bytes_data(ctl, key, abi, tlv_size); + if (data_size < 0) + return data_size; - //TODO: alsamixer showing wrong dB scales - tlv[0] = hdr->tlv.type; - tlv[1] = hdr->tlv.size - sizeof(uint32_t) * 2; - memcpy(&tlv[2], hdr->tlv.data, hdr->tlv.size - sizeof(uint32_t) * 2); + /* set data size and numid */ + tlv[0] = numid; + tlv[1] = data_size + sizeof(*abi); return 0; } diff --git a/tools/plugin/alsaplug/tplg.c b/tools/plugin/alsaplug/tplg.c index 2d60bf90921d..f8f229f563d3 100644 --- a/tools/plugin/alsaplug/tplg.c +++ b/tools/plugin/alsaplug/tplg.c @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -1105,7 +1106,9 @@ static int plug_set_up_route(snd_sof_plug_t *plug, struct tplg_route_info *route static int plug_set_up_widget(snd_sof_plug_t *plug, struct tplg_comp_info *comp_info) { struct tplg_pipeline_info *pipe_info = comp_info->pipe_info; - int ret; + struct plug_shm_glb_state *glb = plug->glb_ctx.addr; + struct plug_shm_ctl *ctl; + int ret, i; pipe_info->usage_count++; @@ -1123,6 +1126,33 @@ static int plug_set_up_widget(snd_sof_plug_t *plug, struct tplg_comp_info *comp_ if (ret < 0) return ret; + /* send kcontrol bytes data */ + for (i = 0; i < glb->num_ctls; i++) { + struct snd_soc_tplg_bytes_control *tplg_bytes; + struct sof_abi_hdr *abi; + int priv_size; + + ctl = &glb->ctl[i]; + + /* send the bytes data from kcontrols associated with current widget */ + if (ctl->module_id != comp_info->module_id || + ctl->instance_id != comp_info->instance_id || + ctl->type != SND_SOC_TPLG_TYPE_BYTES) + continue; + + tplg_bytes = &ctl->bytes_ctl; + priv_size = tplg_bytes->priv.size; + abi = (struct sof_abi_hdr *)ctl->data; + + /* send IPC with kcontrol data */ + ret = plug_send_bytes_data(&plug->ipc_tx, &plug->ipc_rx, + comp_info->module_id, comp_info->instance_id, abi); + if (ret < 0) { + SNDERR("failed to set bytes data for widget %s\n", comp_info->name); + return ret; + } + } + tplg_debug("widget %s set up\n", comp_info->name); return 0; diff --git a/tools/plugin/alsaplug/tplg_ctl.c b/tools/plugin/alsaplug/tplg_ctl.c index 620c730f82a1..6424b54825ba 100644 --- a/tools/plugin/alsaplug/tplg_ctl.c +++ b/tools/plugin/alsaplug/tplg_ctl.c @@ -202,7 +202,20 @@ int plug_kcontrol_cb_new(struct snd_soc_tplg_ctl_hdr *tplg_ctl, void *_comp, voi break; } case SND_SOC_TPLG_CTL_BYTES: + { + struct snd_soc_tplg_bytes_control *tplg_bytes = + (struct snd_soc_tplg_bytes_control *)tplg_ctl; + + glb->size += sizeof(struct plug_shm_ctl); + ctl = &glb->ctl[glb->num_ctls++]; + ctl->module_id = comp_info->module_id; + ctl->instance_id = comp_info->instance_id; + ctl->bytes_ctl = *tplg_bytes; + ctl->index = index; + ctl->type = tplg_ctl->type; + memcpy(ctl->data, tplg_bytes->priv.data, tplg_bytes->priv.size); break; + } case SND_SOC_TPLG_CTL_RANGE: case SND_SOC_TPLG_CTL_STROBE: default: diff --git a/tools/plugin/common.c b/tools/plugin/common.c index 1674dea5f787..46629f061201 100644 --- a/tools/plugin/common.c +++ b/tools/plugin/common.c @@ -264,3 +264,45 @@ void plug_ctl_ipc_message(struct ipc4_module_large_config *config, int param_id, config->extension.r.data_off_size = size; config->extension.r.large_param_id = param_id; } + +int plug_send_bytes_data(struct plug_mq_desc *ipc_tx, struct plug_mq_desc *ipc_rx, + uint32_t module_id, uint32_t instance_id, struct sof_abi_hdr *abi) +{ + struct ipc4_module_large_config config = {{ 0 }}; + struct ipc4_message_reply reply; + void *msg; + int msg_size; + int err; + + /* configure the IPC message */ + plug_ctl_ipc_message(&config, abi->type, abi->size, module_id, instance_id, + SOF_IPC4_MOD_LARGE_CONFIG_SET); + + config.extension.r.final_block = 1; + config.extension.r.init_block = 1; + + /* allocate memory for IPC message */ + msg_size = sizeof(config) + abi->size; + msg = calloc(msg_size, 1); + if (!msg) + return -ENOMEM; + + /* set the IPC message data */ + memcpy(msg, &config, sizeof(config)); + memcpy(msg + sizeof(config), abi->data, abi->size); + + /* send the message and check status */ + err = plug_mq_cmd_tx_rx(ipc_tx, ipc_rx, msg, msg_size, &reply, sizeof(reply)); + free(msg); + if (err < 0) { + SNDERR("failed to send IPC to set bytes data\n"); + return err; + } + + if (reply.primary.r.status != IPC4_SUCCESS) { + SNDERR("IPC failed with status %d\n", reply.primary.r.status); + return -EINVAL; + } + + return 0; +} diff --git a/tools/plugin/common.h b/tools/plugin/common.h index f849676fbcc8..002f3843c3e7 100644 --- a/tools/plugin/common.h +++ b/tools/plugin/common.h @@ -12,6 +12,8 @@ #include #include #include +#include +#include /* temporary - current MAXLEN is not define in UAPI header - fix pending */ #ifndef SNDRV_CTL_ELEM_ID_NAME_MAXLEN @@ -52,6 +54,7 @@ #define SOF_MAGIC "sofpipe" #define MAX_VOLUME_SIZE 120 +#define MAX_DATA_SIZE 512 enum plugin_state { SOF_PLUGIN_STATE_INIT = 0, @@ -67,6 +70,7 @@ struct plug_shm_ctl { unsigned int type; unsigned int volume_table[MAX_VOLUME_SIZE]; unsigned int index; + char data[MAX_DATA_SIZE]; union { struct snd_soc_tplg_mixer_control mixer_ctl; struct snd_soc_tplg_enum_control enum_ctl; @@ -320,5 +324,7 @@ static inline void data_dump(void *vdata, size_t bytes) void plug_ctl_ipc_message(struct ipc4_module_large_config *config, int param_id, size_t size, uint32_t module_id, uint32_t instance_id, uint32_t type); +int plug_send_bytes_data(struct plug_mq_desc *ipc_tx, struct plug_mq_desc *ipc_rx, + uint32_t module_id, uint32_t instance_id, struct sof_abi_hdr *abi); #endif