Skip to content

Commit 6e7a254

Browse files
committed
Tools: Testbench: Add sof-ctl simulation to control scripts
With this change sof-ctl commands can be executed during sof-testbench4 simulation, e.g. sof-ctl -c name='Post Mixer Analog Playback IIR Eq bytes' \ -s tools/ctl/ipc4/eq_iir/loudness.txt No other than switches -c and -s are supported for simulated sof-ctl. The blob file must be in normal comma separated ASCII uint32_t numbers format with nothing else in it. With this change the SOF processing components can be tested extensively for their controls during simulated audio streaming. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent d6786df commit 6e7a254

3 files changed

Lines changed: 128 additions & 2 deletions

File tree

tools/testbench/include/testbench/utils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#define TB_MAX_CTL_NAME_CHARS 128
2424
#define TB_MAX_VOLUME_SIZE 120
2525
#define TB_MAX_BYTES_DATA_SIZE 8192
26+
#define TB_MAX_BLOB_NAME_CHARS 128
27+
#define TB_MAX_BLOB_CONTENT_CHARS 32768
2628

2729
/* number of widgets types supported in testbench */
2830
#define TB_NUM_WIDGETS_SUPPORTED 16
@@ -159,6 +161,7 @@ int tb_pipeline_reset(struct ipc *ipc, struct pipeline *p);
159161
int tb_pipeline_start(struct ipc *ipc, struct pipeline *p);
160162
int tb_pipeline_stop(struct ipc *ipc, struct pipeline *p);
161163
int tb_read_controls(struct testbench_prm *tp, int64_t *sleep_ns);
164+
int tb_set_bytes_control(struct testbench_prm *tp, struct tb_ctl *ctl, uint32_t *data);
162165
int tb_set_enum_control(struct testbench_prm *tp, struct tb_ctl *ctl, char *control_params);
163166
int tb_set_reset_state(struct testbench_prm *tp);
164167
int tb_set_mixer_control(struct testbench_prm *tp, struct tb_ctl *ctl, char *control_params);

tools/testbench/utils.c

Lines changed: 116 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <sof/lib/notifier.h>
1010

1111
#include <ctype.h>
12+
#include <errno.h>
1213
#include <stdint.h>
1314
#include <stdio.h>
1415
#include <stdlib.h>
@@ -388,10 +389,114 @@ static int tb_parse_amixer(struct testbench_prm *tp, char *line)
388389
return ret;
389390
}
390391

392+
static int tb_parse_sofctl(struct testbench_prm *tp, char *line)
393+
{
394+
char control_name[TB_MAX_CTL_NAME_CHARS] = {0};
395+
char blob_name[TB_MAX_BLOB_NAME_CHARS] = {0};
396+
struct tb_ctl *ctl;
397+
uint32_t *blob_bin;
398+
char *line_end;
399+
char *name_str;
400+
char *end_str;
401+
char *blob_str;
402+
char *token;
403+
char *rest;
404+
char *find_ctl_name_str = "-c name=\"";
405+
char *find_end_str = "\" ";
406+
char *find_set_switch_str = "-s";
407+
int find_len = strlen(find_ctl_name_str);
408+
int len;
409+
FILE *fh;
410+
int n = 0;
411+
int ret = 0;
412+
413+
name_str = strstr(line, find_ctl_name_str);
414+
if (!name_str) {
415+
fprintf(stderr, "error: no control name in script line: %s\n", line);
416+
return -EINVAL;
417+
}
418+
419+
end_str = strstr(&name_str[find_len], find_end_str);
420+
if (!end_str) {
421+
fprintf(stderr, "error: no control name end quote in script line: %s\n", line);
422+
return -EINVAL;
423+
}
424+
425+
len = end_str - name_str - find_len;
426+
memcpy(control_name, name_str + find_len, len);
427+
428+
name_str = strstr(line, find_set_switch_str);
429+
if (!name_str) {
430+
fprintf(stderr, "error: no sof-ctl control set switch in command: %s.\n",
431+
line);
432+
return -EINVAL;
433+
}
434+
435+
name_str += strlen(find_set_switch_str) + 1;
436+
line_end = line + strlen(line);
437+
memcpy(blob_name, name_str, line_end - name_str);
438+
439+
ctl = tb_find_control_by_name(tp, control_name);
440+
if (!ctl) {
441+
fprintf(stderr, "error: control %s not found in topology.\n", control_name);
442+
return -EINVAL;
443+
}
444+
445+
if (ctl->type != SND_SOC_TPLG_TYPE_BYTES) {
446+
fprintf(stderr, "error: control %s type %d is not supported.\n",
447+
control_name, ctl->type);
448+
return -EINVAL;
449+
}
450+
451+
blob_str = malloc(TB_MAX_BLOB_CONTENT_CHARS);
452+
if (!blob_str) {
453+
fprintf(stderr, "error: failed to allocate memory for blob file content.\n");
454+
return -ENOMEM;
455+
}
456+
457+
blob_bin = malloc(TB_MAX_BYTES_DATA_SIZE);
458+
if (!blob_bin) {
459+
fprintf(stderr, "error: failed to allocate memory for blob data.\n");
460+
return -ENOMEM;
461+
}
462+
463+
printf("Info: Setting control name '%s' to blob '%s'\n", control_name, blob_name);
464+
fh = fopen(blob_name, "r");
465+
if (!fh) {
466+
fprintf(stderr, "error: could not open file.\n");
467+
free(blob_str);
468+
return errno;
469+
}
470+
471+
fgets(blob_str, TB_MAX_BLOB_CONTENT_CHARS, fh);
472+
fclose(fh);
473+
474+
rest = blob_str;
475+
while ((token = strtok_r(rest, ",", &rest))) {
476+
if (n == TB_MAX_BYTES_DATA_SIZE) {
477+
fprintf(stderr, "error: data read exceeds max control data size.\n");
478+
ret = -EINVAL;
479+
goto err;
480+
}
481+
482+
blob_bin[n] = atoi(token);
483+
n++;
484+
}
485+
486+
/* Ignore TLV header from beginning. */
487+
ret = tb_set_bytes_control(tp, ctl, &blob_bin[2]);
488+
489+
err:
490+
free(blob_str);
491+
free(blob_bin);
492+
return ret;
493+
}
494+
391495
int tb_read_controls(struct testbench_prm *tp, int64_t *sleep_ns)
392496
{
393497
char *sleep_cmd = "sleep ";
394498
char *amixer_cmd = "amixer ";
499+
char *sofctl_cmd = "sof-ctl ";
395500
char *raw_line;
396501
char *line;
397502
int ret = 0;
@@ -411,7 +516,7 @@ int tb_read_controls(struct testbench_prm *tp, int64_t *sleep_ns)
411516
if (line[0] == '#' || strlen(line) == 0)
412517
continue;
413518

414-
if (strncmp(line, sleep_cmd, sizeof(*sleep_cmd)) == 0) {
519+
if (strncmp(line, sleep_cmd, strlen(sleep_cmd)) == 0) {
415520
ret = tb_parse_sleep(line, sleep_ns);
416521
if (ret) {
417522
fprintf(stderr, "error: failed parse of sleep command.\n");
@@ -420,12 +525,21 @@ int tb_read_controls(struct testbench_prm *tp, int64_t *sleep_ns)
420525
break;
421526
}
422527

423-
if (strncmp(line, amixer_cmd, sizeof(*amixer_cmd)) == 0) {
528+
if (strncmp(line, amixer_cmd, strlen(amixer_cmd)) == 0) {
424529
ret = tb_parse_amixer(tp, line);
425530
if (ret) {
426531
fprintf(stderr, "error: failed parse of amixer command.\n");
427532
break;
428533
}
534+
continue;
535+
}
536+
537+
if (strncmp(line, sofctl_cmd, strlen(sofctl_cmd)) == 0) {
538+
ret = tb_parse_sofctl(tp, line);
539+
if (ret) {
540+
fprintf(stderr, "error: failed parse of sof-ctl command.\n");
541+
break;
542+
}
429543
}
430544
}
431545

tools/testbench/utils_ipc4.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,4 +691,13 @@ int tb_set_mixer_control(struct testbench_prm *tp, struct tb_ctl *ctl, char *con
691691
return ret;
692692
}
693693

694+
int tb_set_bytes_control(struct testbench_prm *tp, struct tb_ctl *ctl, uint32_t *data)
695+
{
696+
int ret;
697+
698+
ret = tb_send_bytes_data(&tp->ipc_tx, &tp->ipc_rx, ctl->module_id, ctl->instance_id,
699+
(struct sof_abi_hdr *)data);
700+
return ret;
701+
}
702+
694703
#endif /* CONFIG_IPC_MAJOR_4 */

0 commit comments

Comments
 (0)