Skip to content

Commit 035d86d

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 035d86d

4 files changed

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

414-
if (strncmp(line, sleep_cmd, sizeof(*sleep_cmd)) == 0) {
526+
if (strncmp(line, sleep_cmd, strlen(sleep_cmd)) == 0) {
415527
ret = tb_parse_sleep(line, sleep_ns);
416528
if (ret) {
417529
fprintf(stderr, "error: failed parse of sleep command.\n");
@@ -420,12 +532,22 @@ int tb_read_controls(struct testbench_prm *tp, int64_t *sleep_ns)
420532
break;
421533
}
422534

423-
if (strncmp(line, amixer_cmd, sizeof(*amixer_cmd)) == 0) {
535+
if (strncmp(line, amixer_cmd, strlen(amixer_cmd)) == 0) {
424536
ret = tb_parse_amixer(tp, line);
425537
if (ret) {
426538
fprintf(stderr, "error: failed parse of amixer command.\n");
427539
break;
428540
}
541+
continue;
542+
}
543+
544+
if (strncmp(line, sofctl_cmd, strlen(sofctl_cmd)) == 0) {
545+
ret = tb_parse_sofctl(tp, line);
546+
if (ret) {
547+
fprintf(stderr, "error: failed parse of sof-ctl command.\n");
548+
break;
549+
}
550+
continue;
429551
}
430552
}
431553

tools/testbench/utils_ipc3.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,4 +435,9 @@ int tb_set_mixer_control(struct testbench_prm *tp, struct tb_ctl *ctl, char *con
435435
return 0;
436436
}
437437

438+
int tb_set_bytes_control(struct testbench_prm *tp, struct tb_ctl *ctl, uint32_t *data)
439+
{
440+
return 0;
441+
}
442+
438443
#endif /* CONFIG_IPC_MAJOR_3 */

tools/testbench/utils_ipc4.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,4 +691,11 @@ 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+
return tb_send_bytes_data(&tp->ipc_tx, &tp->ipc_rx,
697+
ctl->module_id, ctl->instance_id,
698+
(struct sof_abi_hdr *)data);
699+
}
700+
694701
#endif /* CONFIG_IPC_MAJOR_4 */

0 commit comments

Comments
 (0)