Skip to content

Commit

Permalink
Tools: sof-ctl: Use same blob format as UCM2/cset-tlv
Browse files Browse the repository at this point in the history
This change aligns the blob formats with UCM2 and sof-ctl.
The binary blobs for UCM2 have an additional 8 byte header that
was internally generated inside sof-ctl. This patch changes
sof-ctl to expect the header to be in .txt and .bin format
in the data file.

The Octave scripts to export blobs for topology, sof-ctl, and
UCM2 are updated to match the change. The topology embedded blobs
remain as before without the header.

Signed-off-by: Seppo Ingalsuo <[email protected]>
  • Loading branch information
singalsu committed Dec 31, 2024
1 parent 97841f1 commit f1ccd88
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 44 deletions.
66 changes: 42 additions & 24 deletions tools/ctl/ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#define BUFFER_SIZE_OFFSET 1
#define BUFFER_ABI_OFFSET 2

#define BUFFER_TLV_HEADER_BYTES ((BUFFER_ABI_OFFSET) * sizeof(uint32_t))

/* Definitions for multiple IPCs */
enum sof_ipc_type {
SOF_IPC_TYPE_3,
Expand Down Expand Up @@ -103,6 +105,7 @@ static void header_init(struct ctl_data *ctl_data)
hdr->magic = ctl_data->magic;
hdr->type = ctl_data->type;
hdr->abi = SOF_ABI_VERSION;
ctl_data->buffer[BUFFER_TAG_OFFSET] = SOF_CTRL_CMD_BINARY;
}

/* Returns the number of bytes written to the control buffer */
Expand All @@ -117,7 +120,7 @@ static int read_setup(struct ctl_data *ctl_data)
int separator;
int n = 0;
FILE *fh;
int data_start_int_index = BUFFER_ABI_OFFSET;
int data_start_int_index = 0;
int data_int_index;

/* open input file */
Expand All @@ -131,7 +134,7 @@ static int read_setup(struct ctl_data *ctl_data)
if (ctl_data->no_abi) {
header_init(ctl_data);
abi_size = sizeof(struct sof_abi_hdr);
data_start_int_index += abi_size / sizeof(uint32_t);
data_start_int_index += abi_size / sizeof(uint32_t) + BUFFER_ABI_OFFSET;
}

if (ctl_data->binary) {
Expand Down Expand Up @@ -163,6 +166,8 @@ static int read_setup(struct ctl_data *ctl_data)
if (ctl_data->no_abi) {
hdr->size = n;
n += abi_size;
ctl_data->buffer[BUFFER_SIZE_OFFSET] = n;
n += BUFFER_TLV_HEADER_BYTES;
}

if (n > n_max) {
Expand Down Expand Up @@ -206,16 +211,16 @@ static void hex_data_dump(struct ctl_data *ctl_data)
int i;

/* calculate the dumping units */
n = ctl_data->buffer[BUFFER_SIZE_OFFSET] / sizeof(uint16_t);
n = (ctl_data->buffer[BUFFER_SIZE_OFFSET] + BUFFER_TLV_HEADER_BYTES) / sizeof(uint16_t);

/* exclude the type and size header */
int_offset = 2;
int_offset = 0;

/* exclude abi header if '-r' specified */
if (ctl_data->no_abi) {
int_offset += sizeof(struct sof_abi_hdr) /
int_offset += (sizeof(struct sof_abi_hdr) + BUFFER_TLV_HEADER_BYTES) /
sizeof(uint32_t);
n -= sizeof(struct sof_abi_hdr) /
n -= (sizeof(struct sof_abi_hdr) + BUFFER_TLV_HEADER_BYTES) /
sizeof(uint16_t);
}

Expand All @@ -242,11 +247,11 @@ static void csv_data_dump(struct ctl_data *ctl_data, FILE *fh)
int i;
int s = 0;

config = &ctl_data->buffer[BUFFER_ABI_OFFSET];
n = ctl_data->buffer[BUFFER_SIZE_OFFSET] / sizeof(uint32_t);
config = &ctl_data->buffer[0];
n = (ctl_data->buffer[BUFFER_SIZE_OFFSET] + BUFFER_TLV_HEADER_BYTES) / sizeof(uint32_t);

if (ctl_data->no_abi)
s = sizeof(struct sof_abi_hdr) / sizeof(uint32_t);
s = sizeof(struct sof_abi_hdr) / sizeof(uint32_t) + BUFFER_ABI_OFFSET;

/* Print out in CSV txt formal */
for (i = s; i < n; i++) {
Expand Down Expand Up @@ -298,10 +303,7 @@ static int buffer_alloc(struct ctl_data *ctl_data)
return -EINVAL;
}

ctl_data->buffer[BUFFER_TAG_OFFSET] = SOF_CTRL_CMD_BINARY;

ctl_data->buffer_size = buffer_size;

return 0;
}

Expand Down Expand Up @@ -429,7 +431,7 @@ static int ctl_free(struct ctl_data *ctl_data)
return ret;
}

static void ctl_dump(struct ctl_data *ctl_data)
static void ctl_dump(struct ctl_data *ctl_data, size_t dump_size)
{
FILE *fh;
int offset = 0;
Expand All @@ -445,13 +447,16 @@ static void ctl_dump(struct ctl_data *ctl_data)
return;
}

offset = BUFFER_ABI_OFFSET;
n = ctl_data->buffer[BUFFER_SIZE_OFFSET];
if (dump_size)
n = dump_size;
else
n = ctl_data->buffer[BUFFER_SIZE_OFFSET] + BUFFER_TLV_HEADER_BYTES;

if (ctl_data->no_abi) {
offset += sizeof(struct sof_abi_hdr) /
sizeof(int);
offset = sizeof(struct sof_abi_hdr) / sizeof(int) +
BUFFER_ABI_OFFSET;
n -= sizeof(struct sof_abi_hdr);
n -= BUFFER_ABI_OFFSET * sizeof(uint32_t);
}
n = fwrite(&ctl_data->buffer[offset],
1, n, fh);
Expand All @@ -476,7 +481,7 @@ static void ctl_dump(struct ctl_data *ctl_data)
static int ctl_set_get(struct ctl_data *ctl_data)
{
int ret;
size_t n;
size_t read_size, ref_size;

if (!ctl_data->buffer) {
fprintf(stderr, "Error: No buffer for set/get!\n");
Expand All @@ -488,14 +493,22 @@ static int ctl_set_get(struct ctl_data *ctl_data)
ctl_data->input_file);
fprintf(stdout, "into device %s control %s.\n",
ctl_data->dev, ctl_data->cname);
n = read_setup(ctl_data);
if (n < 1) {
read_size = read_setup(ctl_data);
if (read_size < 1) {
fprintf(stderr, "Error: failed data read from %s.\n",
ctl_data->input_file);
return -EINVAL;
}

ctl_data->buffer[BUFFER_SIZE_OFFSET] = n;
ref_size = ctl_data->buffer[BUFFER_SIZE_OFFSET] + BUFFER_TLV_HEADER_BYTES;
if (read_size != ref_size) {
fprintf(stderr,
"Error: Blob TLV header size %u (plus %lu) does not match with read bytes count %zu.\n",
ctl_data->buffer[BUFFER_SIZE_OFFSET], BUFFER_TLV_HEADER_BYTES,
read_size);
return -EINVAL;
}

ret = snd_ctl_elem_tlv_write(ctl_data->ctl, ctl_data->id,
ctl_data->buffer);
if (ret < 0) {
Expand All @@ -518,6 +531,11 @@ static int ctl_set_get(struct ctl_data *ctl_data)
fprintf(stderr, "Error: failed TLV read.\n");
return ret;
}
/* Replace the numid value (scontrol->comp_id) with SOF_CTRL_CMD_BINARY
* to get similar blob as in set command. Helps to compare the received
* blob to sent blobs. The comp_id is not useful.
*/
ctl_data->buffer[BUFFER_TAG_OFFSET] = SOF_CTRL_CMD_BINARY;
fprintf(stdout, "Success.\n");
}

Expand Down Expand Up @@ -629,8 +647,8 @@ int main(int argc, char *argv[])
hdr = (struct sof_abi_hdr *)
&ctl_data->buffer[BUFFER_ABI_OFFSET];
hdr->size = ctl_data->print_abi_size;
ctl_data->buffer[BUFFER_SIZE_OFFSET] = ctl_data->ctrl_size;
ctl_dump(ctl_data);
ctl_data->buffer[BUFFER_SIZE_OFFSET] = ctl_data->ctrl_size + hdr->size;
ctl_dump(ctl_data, sizeof(struct sof_abi_hdr) + BUFFER_TLV_HEADER_BYTES);
buffer_free(ctl_data);
goto out_fd_close;
}
Expand Down Expand Up @@ -668,7 +686,7 @@ int main(int argc, char *argv[])
}

/* dump the tlv buffer to a file or stdout */
ctl_dump(ctl_data);
ctl_dump(ctl_data, 0);

data_free:
ret = ctl_free(ctl_data);
Expand Down
3 changes: 3 additions & 0 deletions tools/tune/common/sof_alsactl_write.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
function sof_alsactl_write(fn, blob8)

%% Check that blob header is sane
sof_check_blob_header(blob8);

%% Write blob
sof_check_create_dir(fn);
fh = fopen(fn, 'w');
Expand Down
2 changes: 2 additions & 0 deletions tools/tune/common/sof_blob_write.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
function sof_blob_write(fn, blob8)

%% Check that blob header is sane
sof_check_blob_header(blob8);

%% Write blob
check_create_dir(fn);
Expand Down
37 changes: 37 additions & 0 deletions tools/tune/common/sof_check_blob_header.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
% sof_check_blob_header(blob)
%
% Check for correct header in bytes data. The function
% errors if header is not correct.
%
% Input
% blob - int8 type numbers data
%
% Output
% <none>

function sof_check_blob_header(blob8)

% Correct size in header?
blob_bytes = length(blob8);
header_bytes = b2w(blob8(5:8));
if blob_bytes ~= header_bytes + 8
fprintf(1, "Error: blob header size %d does not math blob size %d\n", header_bytes, blob_bytes);
fprintf(1, "Is installed sof-ctl up-to-date?\n");
error("Failed.");
end

% Correct command?
SOF_CTRL_CMD_BINARY = 3;
value = b2w(blob8(1:4));
if value ~= SOF_CTRL_CMD_BINARY
fprintf(1, "Error: blob control command is not set to SOF_CTRL_CMD_BINARY.\n");
fprintf(1, "Is installed sof-ctl up-to-date?\n");
error("Failed.");
end

end

function word =b2w(bytes)
tmp = int32(bytes);
word = tmp(1) + bitshift(tmp(2), 8) + bitshift(tmp(3), 16) + bitshift(tmp(4), 24);
end
6 changes: 6 additions & 0 deletions tools/tune/common/sof_tplg2_write.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ function sof_tplg2_write(fn, blob8, component, comment, howto)
howto = [];
end

%% Check that blob header is sane
sof_check_blob_header(blob8);

%% Drop the 8 bytes TLV header from topology embedded blop
blob8 = blob8(9:end);

%% Check that blob length is multiple of 32 bits
n_blob = length(blob8);
n_test = ceil(n_blob/4)*4;
Expand Down
6 changes: 6 additions & 0 deletions tools/tune/common/sof_tplg_write.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ function sof_tplg_write(fn, blob8, name, comment, howto)
howto = [];
end

%% Check that blob header is sane
sof_check_blob_header(blob8);

%% Drop the 8 bytes TLV header from topology embedded blop
blob8 = blob8(9:end);

%% Pad blob length to multiple of four bytes
n_orig = length(blob8);
n_new = ceil(n_orig/4)*4;
Expand Down
25 changes: 5 additions & 20 deletions tools/tune/common/sof_ucm_blob_write.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,8 @@ function sof_ucm_blob_write(fn, blob8)
%
% Copyright (c) 2024, Intel Corporation. All rights reserved.

% Export for UCM cset-tlv with additional 8 bytes header
SOF_CTRL_CMD_BINARY = 3;
nh = 8;
nb = length(blob8);
ublob8 = zeros(nb + nh, 1, 'uint8');
ublob8(1:4) = w32b(SOF_CTRL_CMD_BINARY);
ublob8(5:8) = w32b(nb);
ublob8(9:end) = blob8;
%% Check that blob header is sane
sof_check_blob_header(blob8);

%% Write blob
sof_check_create_dir(fn);
Expand All @@ -30,28 +24,19 @@ function sof_ucm_blob_write(fn, blob8)
error("Failed.");
end

fwrite(fh, ublob8, 'uint8');
fwrite(fh, blob8, 'uint8');
fclose(fh);

%% Print as 8 bit hex
nb = length(ublob8);
nb = length(blob8);
nl = ceil(nb/16);
for i = 1:nl
m = min(16, nb-(i-1)*16);
for j = 1:m
fprintf(1, "%02x ", ublob8((i-1)*16 + j));
fprintf(1, "%02x ", blob8((i-1)*16 + j));
end
fprintf(1, "\n");
end

fprintf(1, "\n");
end

function bytes = w32b(word)
sh = [0 -8 -16 -24];
bytes = uint8(zeros(1,4));
bytes(1) = bitand(bitshift(word, sh(1)), 255);
bytes(2) = bitand(bitshift(word, sh(2)), 255);
bytes(3) = bitand(bitshift(word, sh(3)), 255);
bytes(4) = bitand(bitshift(word, sh(4)), 255);
end

0 comments on commit f1ccd88

Please sign in to comment.