2023-10-20 18:09:07

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ v2 1/4] shared/util: Add util_debug_{tlv, bit} helpers

From: Luiz Augusto von Dentz <[email protected]>

This adds util_debug_tlv and util_debug_bit which can help to print
debug information in their respective formats.
---
src/shared/util.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++
src/shared/util.h | 30 ++++++++++++++++
2 files changed, 118 insertions(+)

diff --git a/src/shared/util.c b/src/shared/util.c
index e9c1c18f5ea7..bf37fce364ed 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -138,6 +138,94 @@ void util_hexdump(const char dir, const unsigned char *buf, size_t len,
}
}

+/* Helper to print debug information of bitfields */
+uint64_t util_debug_bit(uint64_t val, const struct util_bit_debugger *table,
+ util_debug_func_t function, void *user_data)
+{
+ uint64_t mask = val;
+ int i;
+
+ for (i = 0; table[i].str; i++) {
+ if (val & (((uint64_t) 1) << table[i].bit)) {
+ util_debug(function, user_data, "%s", table[i].str);
+ mask &= ~(((uint64_t) 1) << table[i].bit);
+ }
+ }
+
+ return mask;
+}
+
+static struct util_ltv_debugger*
+ltv_debugger(struct util_ltv_debugger *debugger, size_t num, uint8_t type)
+{
+ size_t i;
+
+ if (!debugger || !num)
+ return NULL;
+
+ for (i = 0; i < num; i++) {
+ struct util_ltv_debugger *debug = &debugger[i];
+
+ if (debug->type == type)
+ return debug;
+ }
+
+ return NULL;
+}
+
+/* Helper to print debug information of LTV entries */
+bool util_debug_ltv(const uint8_t *data, uint8_t len,
+ struct util_ltv_debugger *debugger, size_t num,
+ util_debug_func_t function, void *user_data)
+{
+ struct iovec iov;
+ int i;
+
+ iov.iov_base = (void *) data;
+ iov.iov_len = len;
+
+ for (i = 0; iov.iov_len; i++) {
+ uint8_t l, t, *v;
+ struct util_ltv_debugger *debug;
+
+ if (!util_iov_pull_u8(&iov, &l)) {
+ util_debug(function, user_data,
+ "Unable to pull length");
+ return false;
+ }
+
+ if (!l) {
+ util_debug(function, user_data, "#%d: len 0x%02x",
+ i, l);
+ continue;
+ }
+
+ if (!util_iov_pull_u8(&iov, &t)) {
+ util_debug(function, user_data, "Unable to pull type");
+ return false;
+ }
+
+ util_debug(function, user_data, "#%d: len 0x%02x type 0x%02x",
+ i, l, t);
+
+ l--;
+
+ v = util_iov_pull_mem(&iov, l);
+ if (!v) {
+ util_debug(function, user_data, "Unable to pull value");
+ return false;
+ }
+
+ debug = ltv_debugger(debugger, num, t);
+ if (debug)
+ debug->func(v, l, function, user_data);
+ else
+ util_hexdump(' ', (void *)v, l, function, user_data);
+ }
+
+ return true;
+}
+
/* Helper for getting the dirent type in case readdir returns DT_UNKNOWN */
unsigned char util_get_dt(const char *parent, const char *name)
{
diff --git a/src/shared/util.h b/src/shared/util.h
index c37b0f7296ab..28ae5c290071 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -107,6 +107,36 @@ void util_debug(util_debug_func_t function, void *user_data,
void util_hexdump(const char dir, const unsigned char *buf, size_t len,
util_debug_func_t function, void *user_data);

+#define UTIL_BIT_DEBUG(_bit, _str) \
+{ \
+ .bit = _bit, \
+ .str = _str, \
+}
+
+struct util_bit_debugger {
+ uint64_t bit;
+ const char *str;
+};
+
+uint64_t util_debug_bit(uint64_t val, const struct util_bit_debugger *table,
+ util_debug_func_t func, void *user_data);
+
+#define UTIL_LTV_DEBUG(_type, _func) \
+{ \
+ .type = _type, \
+ .func = _func, \
+}
+
+struct util_ltv_debugger {
+ uint8_t type;
+ void (*func)(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data);
+};
+
+bool util_debug_ltv(const uint8_t *data, uint8_t len,
+ struct util_ltv_debugger *debugger, size_t num,
+ util_debug_func_t function, void *user_data);
+
unsigned char util_get_dt(const char *parent, const char *name);

ssize_t util_getrandom(void *buf, size_t buflen, unsigned int flags);
--
2.41.0


2023-10-20 18:09:10

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ v2 2/4] monitor: Make use of util_debug_tlv to decode TLV entries

From: Luiz Augusto von Dentz <[email protected]>

This uses util_debug_tlv to decode TLV entries.
---
monitor/att.c | 101 +++++++++++++++++++++++++++++------------------
monitor/packet.c | 81 ++++++-------------------------------
monitor/packet.h | 14 -------
3 files changed, 75 insertions(+), 121 deletions(-)

diff --git a/monitor/att.c b/monitor/att.c
index 0e12ee352078..39ea5d6dac5a 100644
--- a/monitor/att.c
+++ b/monitor/att.c
@@ -675,8 +675,15 @@ static bool print_ase_codec(const struct l2cap_frame *frame)
return true;
}

+static void print_ltv(const char *str, void *user_data)
+{
+ const char *label = user_data;
+
+ print_field("%s: %s", label, str);
+}
+
static bool print_ase_lv(const struct l2cap_frame *frame, const char *label,
- struct packet_ltv_decoder *decoder, size_t decoder_len)
+ struct util_ltv_debugger *decoder, size_t decoder_len)
{
struct bt_hci_lv_data *lv;

@@ -691,13 +698,14 @@ static bool print_ase_lv(const struct l2cap_frame *frame, const char *label,
return false;
}

- packet_print_ltv(label, lv->data, lv->len, decoder, decoder_len);
+ util_debug_ltv(lv->data, lv->len, decoder, decoder_len, print_ltv,
+ (void *) label);

return true;
}

static bool print_ase_cc(const struct l2cap_frame *frame, const char *label,
- struct packet_ltv_decoder *decoder, size_t decoder_len)
+ struct util_ltv_debugger *decoder, size_t decoder_len)
{
return print_ase_lv(frame, label, decoder, decoder_len);
}
@@ -744,7 +752,8 @@ done:
print_hex_field(" Data", frame->data, frame->size);
}

-static void ase_decode_preferred_context(const uint8_t *data, uint8_t len)
+static void ase_debug_preferred_context(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
{
struct l2cap_frame frame;

@@ -753,7 +762,8 @@ static void ase_decode_preferred_context(const uint8_t *data, uint8_t len)
print_context(&frame, " Preferred Context");
}

-static void ase_decode_context(const uint8_t *data, uint8_t len)
+static void ase_debug_context(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
{
struct l2cap_frame frame;

@@ -762,7 +772,8 @@ static void ase_decode_context(const uint8_t *data, uint8_t len)
print_context(&frame, " Context");
}

-static void ase_decode_program_info(const uint8_t *data, uint8_t len)
+static void ase_debug_program_info(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
{
struct l2cap_frame frame;
const char *str;
@@ -782,7 +793,8 @@ done:
print_hex_field(" Data", frame.data, frame.size);
}

-static void ase_decode_language(const uint8_t *data, uint8_t len)
+static void ase_debug_language(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
{
struct l2cap_frame frame;
uint32_t value;
@@ -801,16 +813,17 @@ done:
print_hex_field(" Data", frame.data, frame.size);
}

-struct packet_ltv_decoder ase_metadata_table[] = {
- LTV_DEC(0x01, ase_decode_preferred_context),
- LTV_DEC(0x02, ase_decode_context),
- LTV_DEC(0x03, ase_decode_program_info),
- LTV_DEC(0x04, ase_decode_language)
+struct util_ltv_debugger ase_metadata_table[] = {
+ UTIL_LTV_DEBUG(0x01, ase_debug_preferred_context),
+ UTIL_LTV_DEBUG(0x02, ase_debug_context),
+ UTIL_LTV_DEBUG(0x03, ase_debug_program_info),
+ UTIL_LTV_DEBUG(0x04, ase_debug_language)
};

static bool print_ase_metadata(const struct l2cap_frame *frame)
{
- return print_ase_lv(frame, " Metadata", NULL, 0);
+ return print_ase_lv(frame, " Metadata", ase_metadata_table,
+ ARRAY_SIZE(ase_metadata_table));
}

static const struct bitfield_data pac_freq_table[] = {
@@ -833,7 +846,8 @@ static const struct bitfield_data pac_freq_table[] = {
{ }
};

-static void pac_decode_freq(const uint8_t *data, uint8_t len)
+static void pac_decode_freq(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
{
struct l2cap_frame frame;
uint16_t value;
@@ -870,7 +884,8 @@ static const struct bitfield_data pac_duration_table[] = {
{ }
};

-static void pac_decode_duration(const uint8_t *data, uint8_t len)
+static void pac_decode_duration(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
{
struct l2cap_frame frame;
uint8_t value;
@@ -907,7 +922,8 @@ static const struct bitfield_data pac_channel_table[] = {
{ }
};

-static void pac_decode_channels(const uint8_t *data, uint8_t len)
+static void pac_decode_channels(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
{
struct l2cap_frame frame;
uint8_t value;
@@ -932,7 +948,8 @@ done:
print_hex_field(" Data", frame.data, frame.size);
}

-static void pac_decode_frame_length(const uint8_t *data, uint8_t len)
+static void pac_decode_frame_length(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
{
struct l2cap_frame frame;
uint16_t min, max;
@@ -957,7 +974,8 @@ done:
print_hex_field(" Data", frame.data, frame.size);
}

-static void pac_decode_sdu(const uint8_t *data, uint8_t len)
+static void pac_decode_sdu(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
{
struct l2cap_frame frame;
uint8_t value;
@@ -976,12 +994,12 @@ done:
print_hex_field(" Data", frame.data, frame.size);
}

-struct packet_ltv_decoder pac_cap_table[] = {
- LTV_DEC(0x01, pac_decode_freq),
- LTV_DEC(0x02, pac_decode_duration),
- LTV_DEC(0x03, pac_decode_channels),
- LTV_DEC(0x04, pac_decode_frame_length),
- LTV_DEC(0x05, pac_decode_sdu)
+struct util_ltv_debugger pac_cap_table[] = {
+ UTIL_LTV_DEBUG(0x01, pac_decode_freq),
+ UTIL_LTV_DEBUG(0x02, pac_decode_duration),
+ UTIL_LTV_DEBUG(0x03, pac_decode_channels),
+ UTIL_LTV_DEBUG(0x04, pac_decode_frame_length),
+ UTIL_LTV_DEBUG(0x05, pac_decode_sdu)
};

static void print_pac(const struct l2cap_frame *frame)
@@ -1117,7 +1135,8 @@ static bool print_ase_pd(const struct l2cap_frame *frame, const char *label)
return true;
}

-static void ase_decode_freq(const uint8_t *data, uint8_t len)
+static void ase_debug_freq(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
{
struct l2cap_frame frame;
uint8_t value;
@@ -1179,7 +1198,8 @@ done:
print_hex_field(" Data", frame.data, frame.size);
}

-static void ase_decode_duration(const uint8_t *data, uint8_t len)
+static void ase_debug_duration(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
{
struct l2cap_frame frame;
uint8_t value;
@@ -1266,7 +1286,8 @@ done:
print_hex_field(" Data", frame->data, frame->size);
}

-static void ase_decode_location(const uint8_t *data, uint8_t len)
+static void ase_debug_location(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
{
struct l2cap_frame frame;

@@ -1275,7 +1296,8 @@ static void ase_decode_location(const uint8_t *data, uint8_t len)
print_location(&frame);
}

-static void ase_decode_frame_length(const uint8_t *data, uint8_t len)
+static void ase_debug_frame_length(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
{
struct l2cap_frame frame;
uint16_t value;
@@ -1294,7 +1316,8 @@ done:
print_hex_field(" Data", frame.data, frame.size);
}

-static void ase_decode_blocks(const uint8_t *data, uint8_t len)
+static void ase_debug_blocks(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
{
struct l2cap_frame frame;
uint8_t value;
@@ -1313,12 +1336,12 @@ done:
print_hex_field(" Data", frame.data, frame.size);
}

-struct packet_ltv_decoder ase_cc_table[] = {
- LTV_DEC(0x01, ase_decode_freq),
- LTV_DEC(0x02, ase_decode_duration),
- LTV_DEC(0x03, ase_decode_location),
- LTV_DEC(0x04, ase_decode_frame_length),
- LTV_DEC(0x05, ase_decode_blocks)
+struct util_ltv_debugger ase_cc_table[] = {
+ UTIL_LTV_DEBUG(0x01, ase_debug_freq),
+ UTIL_LTV_DEBUG(0x02, ase_debug_duration),
+ UTIL_LTV_DEBUG(0x03, ase_debug_location),
+ UTIL_LTV_DEBUG(0x04, ase_debug_frame_length),
+ UTIL_LTV_DEBUG(0x05, ase_debug_blocks)
};

static void print_ase_config(const struct l2cap_frame *frame)
@@ -2745,8 +2768,9 @@ static const struct big_enc_decoder {
};

static bool print_subgroup_lv(const struct l2cap_frame *frame,
- const char *label, struct packet_ltv_decoder *decoder,
- size_t decoder_len)
+ const char *label,
+ struct util_ltv_debugger *debugger,
+ size_t debugger_len)
{
struct bt_hci_lv_data *lv;

@@ -2761,7 +2785,8 @@ static bool print_subgroup_lv(const struct l2cap_frame *frame,
return false;
}

- packet_print_ltv(label, lv->data, lv->len, decoder, decoder_len);
+ util_debug_ltv(lv->data, lv->len, debugger, debugger_len,
+ print_ltv, (void *)label);

return true;
}
diff --git a/monitor/packet.c b/monitor/packet.c
index 30ffe79c6c09..87805be0122a 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -3419,72 +3419,11 @@ static void *iov_pull(struct iovec *iov, size_t len)
return data;
}

-static struct packet_ltv_decoder*
-get_ltv_decoder(struct packet_ltv_decoder *decoder, size_t num, uint8_t type)
+static void print_ltv(const char *str, void *user_data)
{
- size_t i;
+ const char *label = user_data;

- if (!decoder || !num)
- return NULL;
-
- for (i = 0; i < num; i++) {
- struct packet_ltv_decoder *dec = &decoder[i];
-
- if (dec->type == type)
- return dec;
- }
-
- return NULL;
-}
-
-static void print_ltv(const char *label, const uint8_t *data, uint8_t len,
- struct packet_ltv_decoder *decoder, size_t num)
-{
- struct iovec iov;
- int i;
-
- iov.iov_base = (void *) data;
- iov.iov_len = len;
-
- for (i = 0; iov.iov_len; i++) {
- uint8_t l, t, *v;
- struct packet_ltv_decoder *dec;
-
- l = get_u8(iov_pull(&iov, sizeof(l)));
- if (!l) {
- print_field("%s #%d: len 0x%02x", label, i, l);
- break;
- }
-
- v = iov_pull(&iov, sizeof(*v));
- if (!v)
- break;
-
- t = get_u8(v);
-
- print_field("%s #%d: len 0x%02x type 0x%02x", label, i, l, t);
-
- l -= 1;
-
- v = iov_pull(&iov, l);
- if (!v)
- break;
-
- dec = get_ltv_decoder(decoder, num, t);
- if (dec)
- dec->func(v, l);
- else
- print_hex_field(label, v, l);
- }
-
- if (iov.iov_len)
- print_hex_field(label, iov.iov_base, iov.iov_len);
-}
-
-void packet_print_ltv(const char *label, const uint8_t *data, uint8_t len,
- struct packet_ltv_decoder *decoder, size_t decoder_len)
-{
- print_ltv(label, data, len, decoder, decoder_len);
+ print_field("%s: %s", label, str);
}

static void print_base_annoucement(const uint8_t *data, uint8_t data_len)
@@ -3510,6 +3449,7 @@ static void print_base_annoucement(const uint8_t *data, uint8_t data_len)
struct bt_hci_lv_data *codec_cfg;
struct bt_hci_lv_data *metadata;
uint8_t j;
+ const char *label;

print_field(" Subgroup #%u:", i);

@@ -3537,9 +3477,10 @@ static void print_base_annoucement(const uint8_t *data, uint8_t data_len)
if (!iov_pull(&iov, codec_cfg->len))
goto done;

- print_ltv(" Codec Specific Configuration",
- codec_cfg->data, codec_cfg->len,
- NULL, 0);
+ label = " Codec Specific Configuration";
+
+ util_debug_ltv(codec_cfg->data, codec_cfg->len, NULL, 0,
+ print_ltv, (void *)label);

metadata = iov_pull(&iov, sizeof(*metadata));
if (!metadata)
@@ -3548,8 +3489,10 @@ static void print_base_annoucement(const uint8_t *data, uint8_t data_len)
if (!iov_pull(&iov, metadata->len))
goto done;

- print_ltv(" Metadata", metadata->data, metadata->len,
- NULL, 0);
+ label = " Metadata";
+
+ util_debug_ltv(metadata->data, metadata->len, NULL, 0,
+ print_ltv, (void *)label);

/* Level 3 - BIS(s)*/
for (j = 0; j < subgroup->num_bis; j++) {
diff --git a/monitor/packet.h b/monitor/packet.h
index 384f460d2f58..856f74f4db16 100644
--- a/monitor/packet.h
+++ b/monitor/packet.h
@@ -84,20 +84,6 @@ void packet_print_io_capability(uint8_t capability);
void packet_print_io_authentication(uint8_t authentication);
void packet_print_codec_id(const char *label, uint8_t codec);

-#define LTV_DEC(_type, _func) \
-{ \
- .type = _type, \
- .func = _func, \
-}
-
-struct packet_ltv_decoder {
- uint8_t type;
- void (*func)(const uint8_t *data, uint8_t len);
-};
-
-void packet_print_ltv(const char *label, const uint8_t *data, uint8_t len,
- struct packet_ltv_decoder *decoder, size_t num);
-
void packet_control(struct timeval *tv, struct ucred *cred,
uint16_t index, uint16_t opcode,
const void *data, uint16_t size);
--
2.41.0

2023-10-20 18:09:11

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ v2 3/4] shared/bap: Add debug helpers

From: Luiz Augusto von Dentz <[email protected]>

This adds bap-debug.{c.h} that implements function helpers that can be
used to print BAP/ASCS/PACS TLV entries.
---
Makefile.am | 1 +
profiles/audio/media.c | 7 +-
src/shared/bap-debug.c | 539 +++++++++++++++++++++++++++++++++++++++++
src/shared/bap-debug.h | 14 ++
src/shared/bap.c | 60 +----
src/shared/bap.h | 3 -
6 files changed, 564 insertions(+), 60 deletions(-)
create mode 100644 src/shared/bap-debug.c
create mode 100644 src/shared/bap-debug.h

diff --git a/Makefile.am b/Makefile.am
index 6187f298e81a..e9a952e72d69 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -231,6 +231,7 @@ shared_sources = src/shared/io.h src/shared/timeout.h \
src/shared/gap.h src/shared/gap.c \
src/shared/log.h src/shared/log.c \
src/shared/bap.h src/shared/bap.c src/shared/ascs.h \
+ src/shared/bap-debug.h src/shared/bap-debug.c \
src/shared/mcs.h src/shared/mcp.h src/shared/mcp.c \
src/shared/vcp.c src/shared/vcp.h \
src/shared/micp.c src/shared/micp.h \
diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index 1d98ac5a1a70..825f3cf97f5f 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -42,6 +42,7 @@
#include "src/shared/queue.h"
#include "src/shared/att.h"
#include "src/shared/bap.h"
+#include "src/shared/bap-debug.h"

#include "avdtp.h"
#include "media.h"
@@ -1217,13 +1218,13 @@ static bool endpoint_init_pac(struct media_endpoint *endpoint, uint8_t type,
return false;
}

- if (!bap_print_cc(endpoint->capabilities, endpoint->size, bap_debug,
- NULL)) {
+ if (!bt_bap_debug_caps(endpoint->capabilities, endpoint->size,
+ bap_debug, NULL)) {
error("Unable to parse endpoint capabilities");
return false;
}

- if (!bap_print_cc(endpoint->metadata, endpoint->metadata_size,
+ if (!bt_bap_debug_metadata(endpoint->metadata, endpoint->metadata_size,
bap_debug, NULL)) {
error("Unable to parse endpoint metadata");
return false;
diff --git a/src/shared/bap-debug.c b/src/shared/bap-debug.c
new file mode 100644
index 000000000000..20dc3a1419c0
--- /dev/null
+++ b/src/shared/bap-debug.c
@@ -0,0 +1,539 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2023 Intel Corporation.
+ */
+
+#define _GNU_SOURCE
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "src/shared/util.h"
+#include "src/shared/bap-debug.h"
+
+static const struct util_bit_debugger pac_freq_table[] = {
+ UTIL_BIT_DEBUG(0, "\t8 Khz (0x0001)"),
+ UTIL_BIT_DEBUG(1, "\t11.25 Khz (0x0002)"),
+ UTIL_BIT_DEBUG(2, "\t16 Khz (0x0004)"),
+ UTIL_BIT_DEBUG(3, "\t22.05 Khz (0x0008)"),
+ UTIL_BIT_DEBUG(4, "\t24 Khz (0x0010)"),
+ UTIL_BIT_DEBUG(5, "\t32 Khz (0x0020)"),
+ UTIL_BIT_DEBUG(6, "\t44.1 Khz (0x0040)"),
+ UTIL_BIT_DEBUG(7, "\t48 Khz (0x0080)"),
+ UTIL_BIT_DEBUG(8, "\t88.2 Khz (0x0100)"),
+ UTIL_BIT_DEBUG(9, "\t96 Khz (0x0200)"),
+ UTIL_BIT_DEBUG(10, "\t176.4 Khz (0x0400)"),
+ UTIL_BIT_DEBUG(11, "\t192 Khz (0x0800)"),
+ UTIL_BIT_DEBUG(12, "\t384 Khz (0x1000)"),
+ UTIL_BIT_DEBUG(13, "\tRFU (0x2000)"),
+ UTIL_BIT_DEBUG(14, "\tRFU (0x4000)"),
+ UTIL_BIT_DEBUG(15, "\tRFU (0x8000)"),
+ { }
+};
+
+static void pac_debug_freq(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
+{
+ struct iovec frame = { (void *)data, len };
+ uint16_t value;
+ uint16_t mask;
+
+ if (!util_iov_pull_le16(&frame, &value)) {
+ util_debug(func, user_data, "value: invalid size");
+ goto done;
+ }
+
+ util_debug(func, user_data, "Sampling Frequencies: 0x%4.4x", value);
+
+ mask = util_debug_bit(value, pac_freq_table, func, user_data);
+ if (mask)
+ util_debug(func, user_data, "Unknown fields (0x%4.4x)",
+ mask);
+
+done:
+ if (frame.iov_len)
+ util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+ user_data);
+}
+
+static const struct util_bit_debugger pac_duration_table[] = {
+ UTIL_BIT_DEBUG(0, "\t7.5 ms (0x01)"),
+ UTIL_BIT_DEBUG(1, "\t10 ms (0x02)"),
+ UTIL_BIT_DEBUG(2, "\tRFU (0x04)"),
+ UTIL_BIT_DEBUG(3, "\tRFU (0x08)"),
+ UTIL_BIT_DEBUG(4, "\t7.5 ms preferred (0x10)"),
+ UTIL_BIT_DEBUG(5, "\t10 ms preferred (0x20)"),
+ UTIL_BIT_DEBUG(6, "\tRFU (0x40)"),
+ UTIL_BIT_DEBUG(7, "\tRFU (0x80)"),
+ { }
+};
+
+static void pac_debug_duration(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
+{
+ struct iovec frame = { (void *)data, len };
+ uint8_t value;
+ uint8_t mask;
+
+ if (!util_iov_pull_u8(&frame, &value)) {
+ util_debug(func, user_data, "value: invalid size");
+ goto done;
+ }
+
+ util_debug(func, user_data, "Frame Duration: 0x%2.2x", value);
+
+ mask = util_debug_bit(value, pac_duration_table, func, user_data);
+ if (mask)
+ util_debug(func, user_data, "Unknown fields (0x%2.2x)",
+ mask);
+
+done:
+ if (frame.iov_len)
+ util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+ user_data);
+}
+
+static const struct util_bit_debugger pac_channel_table[] = {
+ UTIL_BIT_DEBUG(0, "\t1 channel (0x01)"),
+ UTIL_BIT_DEBUG(1, "\t2 channel (0x02)"),
+ UTIL_BIT_DEBUG(2, "\t3 channel (0x04)"),
+ UTIL_BIT_DEBUG(3, "\t4 channel (0x08)"),
+ UTIL_BIT_DEBUG(4, "\t5 channel (0x10)"),
+ UTIL_BIT_DEBUG(5, "\t6 channel (0x20)"),
+ UTIL_BIT_DEBUG(6, "\t7 channel (0x40)"),
+ UTIL_BIT_DEBUG(7, "\t8 channel (0x80)"),
+ { }
+};
+
+static void pac_debug_channels(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
+{
+ struct iovec frame = { (void *)data, len };
+ uint8_t value;
+ uint8_t mask;
+
+ if (!util_iov_pull_u8(&frame, &value)) {
+ util_debug(func, user_data, "value: invalid size");
+ goto done;
+ }
+
+ util_debug(func, user_data, "Audio Channel Count: 0x%2.2x", value);
+
+ mask = util_debug_bit(value, pac_channel_table, func, user_data);
+ if (mask)
+ util_debug(func, user_data, "Unknown fields (0x%2.2x)",
+ mask);
+
+done:
+ if (frame.iov_len)
+ util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+ user_data);
+}
+
+static void pac_debug_frame_length(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
+{
+ struct iovec frame = { (void *)data, len };
+ uint16_t min, max;
+
+ if (!util_iov_pull_le16(&frame, &min)) {
+ util_debug(func, user_data, "min: invalid size");
+ goto done;
+ }
+
+ if (!util_iov_pull_le16(&frame, &max)) {
+ util_debug(func, user_data, "max: invalid size");
+ goto done;
+ }
+
+ util_debug(func, user_data,
+ "Frame Length: %u (0x%4.4x) - %u (0x%4.4x)",
+ min, min, max, max);
+
+done:
+ if (frame.iov_len)
+ util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+ user_data);
+}
+
+static void pac_debug_sdu(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
+{
+ struct iovec frame = { (void *)data, len };
+ uint8_t value;
+
+ if (!util_iov_pull_u8(&frame, &value)) {
+ util_debug(func, user_data, "value: invalid size");
+ goto done;
+ }
+
+ util_debug(func, user_data, "Max SDU: %u (0x%2.2x)", value, value);
+
+done:
+ if (frame.iov_len)
+ util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+ user_data);
+}
+
+struct util_ltv_debugger pac_cap_table[] = {
+ UTIL_LTV_DEBUG(0x01, pac_debug_freq),
+ UTIL_LTV_DEBUG(0x02, pac_debug_duration),
+ UTIL_LTV_DEBUG(0x03, pac_debug_channels),
+ UTIL_LTV_DEBUG(0x04, pac_debug_frame_length),
+ UTIL_LTV_DEBUG(0x05, pac_debug_sdu)
+};
+
+bool bt_bap_debug_caps(void *data, size_t len, util_debug_func_t func,
+ void *user_data)
+{
+ return util_debug_ltv(data, len, pac_cap_table,
+ ARRAY_SIZE(pac_cap_table),
+ func, user_data);
+}
+
+static void ase_debug_freq(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
+{
+ struct iovec frame = { (void *)data, len };
+ uint8_t value;
+
+ if (!util_iov_pull_u8(&frame, &value)) {
+ util_debug(func, user_data, "value: invalid size");
+ goto done;
+ }
+
+ switch (value) {
+ case 0x01:
+ util_debug(func, user_data, "Sampling Frequency: 8 Khz (0x01)");
+ break;
+ case 0x02:
+ util_debug(func, user_data,
+ "Sampling Frequency: 11.25 Khz (0x02)");
+ break;
+ case 0x03:
+ util_debug(func, user_data,
+ "Sampling Frequency: 16 Khz (0x03)");
+ break;
+ case 0x04:
+ util_debug(func, user_data,
+ "Sampling Frequency: 22.05 Khz (0x04)");
+ break;
+ case 0x05:
+ util_debug(func, user_data,
+ "Sampling Frequency: 24 Khz (0x05)");
+ break;
+ case 0x06:
+ util_debug(func, user_data,
+ "Sampling Frequency: 32 Khz (0x06)");
+ break;
+ case 0x07:
+ util_debug(func, user_data,
+ "Sampling Frequency: 44.1 Khz (0x07)");
+ break;
+ case 0x08:
+ util_debug(func, user_data,
+ "Sampling Frequency: 48 Khz (0x08)");
+ break;
+ case 0x09:
+ util_debug(func, user_data,
+ "Sampling Frequency: 88.2 Khz (0x09)");
+ break;
+ case 0x0a:
+ util_debug(func, user_data,
+ "Sampling Frequency: 96 Khz (0x0a)");
+ break;
+ case 0x0b:
+ util_debug(func, user_data,
+ "Sampling Frequency: 176.4 Khz (0x0b)");
+ break;
+ case 0x0c:
+ util_debug(func, user_data,
+ "Sampling Frequency: 192 Khz (0x0c)");
+ break;
+ case 0x0d:
+ util_debug(func, user_data,
+ "Sampling Frequency: 384 Khz (0x0d)");
+ break;
+ default:
+ util_debug(func, user_data,
+ "Sampling Frequency: RFU (0x%2.2x)", value);
+ break;
+ }
+
+done:
+ if (frame.iov_len)
+ util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+ user_data);
+}
+
+static void ase_debug_duration(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
+{
+ struct iovec frame = { (void *)data, len };
+ uint8_t value;
+
+ if (!util_iov_pull_u8(&frame, &value)) {
+ util_debug(func, user_data, "\tvalue: invalid size\n");
+ goto done;
+ }
+
+ switch (value) {
+ case 0x00:
+ util_debug(func, user_data, "Frame Duration: 7.5 ms (0x00)");
+ break;
+ case 0x01:
+ util_debug(func, user_data, "Frame Duration: 10 ms (0x01)");
+ break;
+ default:
+ util_debug(func, user_data, "Frame Duration: RFU (0x%2.2x)",
+ value);
+ break;
+ }
+
+done:
+ if (frame.iov_len)
+ util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+ user_data);
+}
+
+static const struct util_bit_debugger channel_location_table[] = {
+ UTIL_BIT_DEBUG(0, "\tFront Left (0x00000001)"),
+ UTIL_BIT_DEBUG(1, "\tFront Right (0x00000002)"),
+ UTIL_BIT_DEBUG(2, "\tFront Center (0x00000004)"),
+ UTIL_BIT_DEBUG(3, "\tLow Frequency Effects 1 (0x00000008)"),
+ UTIL_BIT_DEBUG(4, "\tBack Left (0x00000010)"),
+ UTIL_BIT_DEBUG(5, "\tBack Right (0x00000020)"),
+ UTIL_BIT_DEBUG(6, "\tFront Left of Center (0x00000040)"),
+ UTIL_BIT_DEBUG(7, "\tFront Right of Center (0x00000080)"),
+ UTIL_BIT_DEBUG(8, "\tBack Center (0x00000100)"),
+ UTIL_BIT_DEBUG(9, "\tLow Frequency Effects 2 (0x00000200)"),
+ UTIL_BIT_DEBUG(10, "\tSide Left (0x00000400)"),
+ UTIL_BIT_DEBUG(11, "\tSide Right (0x00000800)"),
+ UTIL_BIT_DEBUG(12, "\tTop Front Left (0x00001000)"),
+ UTIL_BIT_DEBUG(13, "\tTop Front Right (0x00002000)"),
+ UTIL_BIT_DEBUG(14, "\tTop Front Center (0x00004000)"),
+ UTIL_BIT_DEBUG(15, "\tTop Center (0x00008000)"),
+ UTIL_BIT_DEBUG(16, "\tTop Back Left (0x00010000)"),
+ UTIL_BIT_DEBUG(17, "\tTop Back Right (0x00020000)"),
+ UTIL_BIT_DEBUG(18, "\tTop Side Left (0x00040000)"),
+ UTIL_BIT_DEBUG(19, "\tTop Side Right (0x00080000)"),
+ UTIL_BIT_DEBUG(20, "\tTop Back Center (0x00100000)"),
+ UTIL_BIT_DEBUG(21, "\tBottom Front Center (0x00200000)"),
+ UTIL_BIT_DEBUG(22, "\tBottom Front Left (0x00400000)"),
+ UTIL_BIT_DEBUG(23, "\tBottom Front Right (0x00800000)"),
+ UTIL_BIT_DEBUG(24, "\tFront Left Wide (0x01000000)"),
+ UTIL_BIT_DEBUG(25, "\tFront Right Wide (0x02000000)"),
+ UTIL_BIT_DEBUG(26, "\tLeft Surround (0x04000000)"),
+ UTIL_BIT_DEBUG(27, "\tRight Surround (0x08000000)"),
+ UTIL_BIT_DEBUG(28, "\tRFU (0x10000000)"),
+ UTIL_BIT_DEBUG(29, "\tRFU (0x20000000)"),
+ UTIL_BIT_DEBUG(30, "\tRFU (0x40000000)"),
+ UTIL_BIT_DEBUG(31, "\tRFU (0x80000000)"),
+ { }
+};
+
+static void debug_location(const struct iovec *frame, util_debug_func_t func,
+ void *user_data)
+{
+ uint32_t value;
+ uint32_t mask;
+
+ if (!util_iov_pull_le32((void *)frame, &value)) {
+ util_debug(func, user_data, "value: invalid size");
+ goto done;
+ }
+
+ util_debug(func, user_data, "Location: 0x%8.8x", value);
+
+ mask = util_debug_bit(value, channel_location_table, func, user_data);
+ if (mask)
+ util_debug(func, user_data, "Unknown fields (0x%8.8x)", mask);
+
+done:
+ if (frame->iov_len)
+ util_hexdump(' ', frame->iov_base, frame->iov_len, func,
+ user_data);
+}
+
+static void ase_debug_location(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
+{
+ struct iovec frame = { (void *)data, len };
+
+ debug_location(&frame, func, user_data);
+}
+
+static void ase_debug_frame_length(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
+{
+ struct iovec frame = { (void *)data, len };
+ uint16_t value;
+
+ if (!util_iov_pull_le16(&frame, &value)) {
+ util_debug(func, user_data, "\tvalue: invalid size\n");
+ goto done;
+ }
+
+ util_debug(func, user_data, "Frame Length: %u (0x%4.4x)",
+ value, value);
+
+done:
+ if (frame.iov_len)
+ util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+ user_data);
+}
+
+static void ase_debug_blocks(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
+{
+ struct iovec frame = { (void *)data, len };
+ uint8_t value;
+
+ if (!util_iov_pull_u8(&frame, &value)) {
+ util_debug(func, user_data, "value: invalid size");
+ goto done;
+ }
+
+ util_debug(func, user_data, "Frame Blocks per SDU: %u (0x%2.2x)",
+ value, value);
+
+done:
+ if (frame.iov_len)
+ util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+ user_data);
+}
+
+struct util_ltv_debugger ase_cc_table[] = {
+ UTIL_LTV_DEBUG(0x01, ase_debug_freq),
+ UTIL_LTV_DEBUG(0x02, ase_debug_duration),
+ UTIL_LTV_DEBUG(0x03, ase_debug_location),
+ UTIL_LTV_DEBUG(0x04, ase_debug_frame_length),
+ UTIL_LTV_DEBUG(0x05, ase_debug_blocks)
+};
+
+bool bt_bap_debug_config(void *data, size_t len, util_debug_func_t func,
+ void *user_data)
+{
+ return util_debug_ltv(data, len, ase_cc_table,
+ ARRAY_SIZE(ase_cc_table),
+ func, user_data);
+}
+
+static const struct util_bit_debugger pac_context_table[] = {
+ UTIL_BIT_DEBUG(0, "\tUnspecified (0x0001)"),
+ UTIL_BIT_DEBUG(1, "\tConversational (0x0002)"),
+ UTIL_BIT_DEBUG(2, "\tMedia (0x0004)"),
+ UTIL_BIT_DEBUG(3, "\tGame (0x0008)"),
+ UTIL_BIT_DEBUG(4, "\tInstructional (0x0010)"),
+ UTIL_BIT_DEBUG(5, "\tVoice Assistants (0x0020)"),
+ UTIL_BIT_DEBUG(6, "\tLive (0x0040)"),
+ UTIL_BIT_DEBUG(7, "\tSound Effects (0x0080)"),
+ UTIL_BIT_DEBUG(8, "\tNotifications (0x0100)"),
+ UTIL_BIT_DEBUG(9, "\tRingtone (0x0200)"),
+ UTIL_BIT_DEBUG(10, "\tAlerts (0x0400)"),
+ UTIL_BIT_DEBUG(11, "\tEmergency alarm (0x0800)"),
+ UTIL_BIT_DEBUG(12, "\tRFU (0x1000)"),
+ UTIL_BIT_DEBUG(13, "\tRFU (0x2000)"),
+ UTIL_BIT_DEBUG(14, "\tRFU (0x4000)"),
+ UTIL_BIT_DEBUG(15, "\tRFU (0x8000)"),
+ { }
+};
+
+static void debug_context(const struct iovec *frame, const char *label,
+ util_debug_func_t func, void *user_data)
+{
+ uint16_t value;
+ uint16_t mask;
+
+ if (!util_iov_pull_le16((void *)frame, &value)) {
+ util_debug(func, user_data, "value: invalid size");
+ goto done;
+ }
+
+ util_debug(func, user_data, "%s: 0x%4.4x", label, value);
+
+ mask = util_debug_bit(value, pac_context_table, func, user_data);
+ if (mask)
+ util_debug(func, user_data, "Unknown fields (0x%4.4x)", mask);
+
+done:
+ if (frame->iov_len)
+ util_hexdump(' ', frame->iov_base, frame->iov_len, func,
+ user_data);
+}
+
+static void ase_debug_preferred_context(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
+{
+ struct iovec frame = { (void *)data, len };
+
+ debug_context(&frame, "Preferred Context", func, user_data);
+}
+
+static void ase_debug_context(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
+{
+ struct iovec frame = { (void *)data, len };
+
+ debug_context(&frame, "Context", func, user_data);
+}
+
+static void ase_debug_program_info(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
+{
+ struct iovec frame = { (void *)data, len };
+ const char *str;
+
+ str = util_iov_pull_mem(&frame, len);
+ if (!str) {
+ util_debug(func, user_data, "value: invalid size");
+ goto done;
+ }
+
+ util_debug(func, user_data, "Program Info: %*s", len, str);
+
+done:
+ if (frame.iov_len)
+ util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+ user_data);
+}
+
+static void ase_debug_language(const uint8_t *data, uint8_t len,
+ util_debug_func_t func, void *user_data)
+{
+ struct iovec frame = { (void *)data, len };
+ uint32_t value;
+
+ if (!util_iov_pull_le24(&frame, &value)) {
+ util_debug(func, user_data, "value: invalid size");
+ goto done;
+ }
+
+ util_debug(func, user_data, "Language: 0x%6.6x\n", value);
+
+done:
+ if (frame.iov_len)
+ util_hexdump(' ', frame.iov_base, frame.iov_len, func,
+ user_data);
+}
+
+struct util_ltv_debugger ase_metadata_table[] = {
+ UTIL_LTV_DEBUG(0x01, ase_debug_preferred_context),
+ UTIL_LTV_DEBUG(0x02, ase_debug_context),
+ UTIL_LTV_DEBUG(0x03, ase_debug_program_info),
+ UTIL_LTV_DEBUG(0x04, ase_debug_language)
+};
+
+bool bt_bap_debug_metadata(void *data, size_t len, util_debug_func_t func,
+ void *user_data)
+{
+ return util_debug_ltv(data, len, ase_metadata_table,
+ ARRAY_SIZE(ase_metadata_table),
+ func, user_data);
+}
diff --git a/src/shared/bap-debug.h b/src/shared/bap-debug.h
new file mode 100644
index 000000000000..93f3b18e17c4
--- /dev/null
+++ b/src/shared/bap-debug.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2023 Intel Corporation.
+ */
+
+bool bt_bap_debug_caps(void *data, size_t len, util_debug_func_t func,
+ void *user_data);
+bool bt_bap_debug_config(void *data, size_t len, util_debug_func_t func,
+ void *user_data);
+bool bt_bap_debug_metadata(void *data, size_t len, util_debug_func_t func,
+ void *user_data);
diff --git a/src/shared/bap.c b/src/shared/bap.c
index 925501c48d98..85460a813108 100644
--- a/src/shared/bap.c
+++ b/src/shared/bap.c
@@ -29,6 +29,7 @@
#include "src/shared/gatt-client.h"
#include "src/shared/bap.h"
#include "src/shared/ascs.h"
+#include "src/shared/bap-debug.h"

/* Maximum number of ASE(s) */
#define NUM_SINKS 2
@@ -1568,7 +1569,7 @@ static uint8_t ep_config(struct bt_bap_endpoint *ep, struct bt_bap *bap,
cc.iov_base = util_iov_pull_mem(iov, req->cc_len);
cc.iov_len = req->cc_len;

- if (!bap_print_cc(cc.iov_base, cc.iov_len, bap->debug_func,
+ if (!bt_bap_debug_caps(cc.iov_base, cc.iov_len, bap->debug_func,
bap->debug_data)) {
ascs_ase_rsp_add(rsp, req->ase,
BT_ASCS_RSP_CONF_INVALID,
@@ -1735,49 +1736,6 @@ static uint8_t stream_enable(struct bt_bap_stream *stream, struct iovec *meta,
return 0;
}

-static bool bap_print_ltv(const char *label, void *data, size_t len,
- util_debug_func_t func, void *user_data)
-{
- struct iovec iov = {
- .iov_base = data,
- .iov_len = len,
- };
- int i;
-
- util_debug(func, user_data, "Length %zu", iov.iov_len);
-
- for (i = 0; iov.iov_len > 1; i++) {
- struct bt_ltv *ltv = util_iov_pull_mem(&iov, sizeof(*ltv));
- uint8_t *data;
-
- if (!ltv) {
- util_debug(func, user_data, "Unable to parse %s",
- label);
- return false;
- }
-
- util_debug(func, user_data, "%s #%u: len %u type %u",
- label, i, ltv->len, ltv->type);
-
- data = util_iov_pull_mem(&iov, ltv->len - 1);
- if (!data) {
- util_debug(func, user_data, "Unable to parse %s",
- label);
- return false;
- }
-
- util_hexdump(' ', ltv->value, ltv->len - 1, func, user_data);
- }
-
- return true;
-}
-
-static bool bap_print_metadata(void *data, size_t len, util_debug_func_t func,
- void *user_data)
-{
- return bap_print_ltv("Metadata", data, len, func, user_data);
-}
-
static uint8_t ep_enable(struct bt_bap_endpoint *ep, struct bt_bap *bap,
struct bt_ascs_enable *req, struct iovec *iov,
struct iovec *rsp)
@@ -1801,8 +1759,8 @@ static uint8_t ep_enable(struct bt_bap_endpoint *ep, struct bt_bap *bap,
meta.iov_base = util_iov_pull_mem(iov, req->meta.len);
meta.iov_len = req->meta.len;

- if (!bap_print_metadata(meta.iov_base, meta.iov_len, bap->debug_func,
- bap->debug_data)) {
+ if (!bt_bap_debug_metadata(meta.iov_base, meta.iov_len,
+ bap->debug_func, bap->debug_data)) {
ascs_ase_rsp_add(rsp, ep->id,
BT_ASCS_RSP_METADATA_INVALID,
BT_ASCS_REASON_NONE);
@@ -3175,12 +3133,6 @@ static void bap_notify_ready(struct bt_bap *bap)
bt_bap_unref(bap);
}

-bool bap_print_cc(void *data, size_t len, util_debug_func_t func,
- void *user_data)
-{
- return bap_print_ltv("CC", data, len, func, user_data);
-}
-
static void bap_parse_pacs(struct bt_bap *bap, uint8_t type,
struct queue *queue,
const uint8_t *value,
@@ -3221,7 +3173,7 @@ static void bap_parse_pacs(struct bt_bap *bap, uint8_t type,

pac = NULL;

- if (!bap_print_cc(iov.iov_base, p->cc_len, bap->debug_func,
+ if (!bt_bap_debug_caps(iov.iov_base, p->cc_len, bap->debug_func,
bap->debug_data))
return;

@@ -4632,7 +4584,7 @@ unsigned int bt_bap_stream_config(struct bt_bap_stream *stream,
iov[0].iov_len = sizeof(config);

if (data) {
- if (!bap_print_cc(data->iov_base, data->iov_len,
+ if (!bt_bap_debug_config(data->iov_base, data->iov_len,
stream->bap->debug_func,
stream->bap->debug_data))
return 0;
diff --git a/src/shared/bap.h b/src/shared/bap.h
index ebe4dbf7d858..23edbf4c6953 100644
--- a/src/shared/bap.h
+++ b/src/shared/bap.h
@@ -201,9 +201,6 @@ void bt_bap_detach(struct bt_bap *bap);
bool bt_bap_set_debug(struct bt_bap *bap, bt_bap_debug_func_t cb,
void *user_data, bt_bap_destroy_func_t destroy);

-bool bap_print_cc(void *data, size_t len, util_debug_func_t func,
- void *user_data);
-
unsigned int bt_bap_pac_register(struct bt_bap *bap, bt_bap_pac_func_t added,
bt_bap_pac_func_t removed, void *user_data,
bt_bap_destroy_func_t destroy);
--
2.41.0

2023-10-20 18:09:15

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ v2 4/4] client: Make use of bap-debug functions

From: Luiz Augusto von Dentz <[email protected]>

This make use of bap-debug functions to decode Capabilities,
Configuration and Metadata.
---
client/player.c | 124 ++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 116 insertions(+), 8 deletions(-)

diff --git a/client/player.c b/client/player.c
index d1809f24fd27..603447a9df46 100644
--- a/client/player.c
+++ b/client/player.c
@@ -42,6 +42,7 @@
#include "src/shared/shell.h"
#include "src/shared/io.h"
#include "src/shared/queue.h"
+#include "src/shared/bap-debug.h"
#include "print.h"
#include "player.h"

@@ -1451,6 +1452,34 @@ static struct codec_preset lc3_presets[] = {
LC3_10_UNFRAMED(155u, 13u, 100u, 40000u)),
};

+static void print_ltv(const char *str, void *user_data)
+{
+ const char *label = user_data;
+
+ bt_shell_printf("\t%s.%s\n", label, str);
+}
+
+static void print_lc3_caps(uint8_t *data, int len)
+{
+ const char *label = "Capabilities";
+
+ bt_bap_debug_caps(data, len, print_ltv, (void *)label);
+}
+
+static void print_lc3_cfg(void *data, int len)
+{
+ const char *label = "Configuration";
+
+ bt_bap_debug_config(data, len, print_ltv, (void *)label);
+}
+
+static void print_lc3_meta(void *data, int len)
+{
+ const char *label = "Metadata";
+
+ bt_bap_debug_metadata(data, len, print_ltv, (void *)label);
+}
+
#define PRESET(_uuid, _codec, _presets, _default_index) \
{ \
.uuid = _uuid, \
@@ -1941,8 +1970,12 @@ static void append_properties(DBusMessageIter *iter,

dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &dict);

- bt_shell_printf("Capabilities: ");
- bt_shell_hexdump(cfg->caps->iov_base, cfg->caps->iov_len);
+ if (cfg->ep->codec == LC3_ID) {
+ print_lc3_cfg(cfg->caps->iov_base, cfg->caps->iov_len);
+ } else {
+ bt_shell_printf("Capabilities: ");
+ bt_shell_hexdump(cfg->caps->iov_base, cfg->caps->iov_len);
+ }

g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &key,
DBUS_TYPE_BYTE, &cfg->caps->iov_base,
@@ -1955,8 +1988,13 @@ static void append_properties(DBusMessageIter *iter,
DBUS_TYPE_BYTE, &cfg->meta->iov_base,
cfg->meta->iov_len);

- bt_shell_printf("Metadata:\n");
- bt_shell_hexdump(cfg->meta->iov_base, cfg->meta->iov_len);
+ if (cfg->ep->codec == LC3_ID) {
+ print_lc3_meta(cfg->meta->iov_base, cfg->meta->iov_len);
+ } else {
+ bt_shell_printf("Metadata:\n");
+ bt_shell_hexdump(cfg->meta->iov_base,
+ cfg->meta->iov_len);
+ }
}

append_qos(&dict, cfg);
@@ -2124,6 +2162,42 @@ static struct endpoint *endpoint_find(const char *pattern)
return NULL;
}

+static void print_capabilities(GDBusProxy *proxy)
+{
+ DBusMessageIter iter, subiter;
+ uint8_t codec;
+ uint8_t *data;
+ int len;
+
+ if (!g_dbus_proxy_get_property(proxy, "Codec", &iter))
+ return;
+
+ dbus_message_iter_get_basic(&iter, &codec);
+
+ if (codec != LC3_ID) {
+ print_property(proxy, "Capabilities");
+ return;
+ }
+
+ if (!g_dbus_proxy_get_property(proxy, "Capabilities", &iter))
+ return;
+
+ dbus_message_iter_recurse(&iter, &subiter);
+
+ dbus_message_iter_get_fixed_array(&subiter, &data, &len);
+
+ print_lc3_caps(data, len);
+
+ if (!g_dbus_proxy_get_property(proxy, "Metadata", &iter))
+ return;
+
+ dbus_message_iter_recurse(&iter, &subiter);
+
+ dbus_message_iter_get_fixed_array(&subiter, &data, &len);
+
+ print_lc3_meta(data, len);
+}
+
static void cmd_show_endpoint(int argc, char *argv[])
{
GDBusProxy *proxy;
@@ -2139,7 +2213,7 @@ static void cmd_show_endpoint(int argc, char *argv[])

print_property(proxy, "UUID");
print_property(proxy, "Codec");
- print_property(proxy, "Capabilities");
+ print_capabilities(proxy);
print_property(proxy, "Device");
print_property(proxy, "DelayReporting");
print_property(proxy, "Locations");
@@ -3817,6 +3891,42 @@ static void cmd_list_transport(int argc, char *argv[])
return bt_shell_noninteractive_quit(EXIT_SUCCESS);
}

+static void print_configuration(GDBusProxy *proxy)
+{
+ DBusMessageIter iter, subiter;
+ uint8_t codec;
+ uint8_t *data;
+ int len;
+
+ if (!g_dbus_proxy_get_property(proxy, "Codec", &iter))
+ return;
+
+ dbus_message_iter_get_basic(&iter, &codec);
+
+ if (codec != LC3_ID) {
+ print_property(proxy, "Configuration");
+ return;
+ }
+
+ if (!g_dbus_proxy_get_property(proxy, "Configuration", &iter))
+ return;
+
+ dbus_message_iter_recurse(&iter, &subiter);
+
+ dbus_message_iter_get_fixed_array(&subiter, &data, &len);
+
+ print_lc3_cfg(data, len);
+
+ if (!g_dbus_proxy_get_property(proxy, "Metadata", &iter))
+ return;
+
+ dbus_message_iter_recurse(&iter, &subiter);
+
+ dbus_message_iter_get_fixed_array(&subiter, &data, &len);
+
+ print_lc3_meta(data, len);
+}
+
static void cmd_show_transport(int argc, char *argv[])
{
GDBusProxy *proxy;
@@ -3832,16 +3942,14 @@ static void cmd_show_transport(int argc, char *argv[])

print_property(proxy, "UUID");
print_property(proxy, "Codec");
- print_property(proxy, "Configuration");
+ print_configuration(proxy);
print_property(proxy, "Device");
print_property(proxy, "State");
print_property(proxy, "Delay");
print_property(proxy, "Volume");
print_property(proxy, "Endpoint");
-
print_property(proxy, "QoS");
print_property(proxy, "Location");
- print_property(proxy, "Metadata");
print_property(proxy, "Links");

return bt_shell_noninteractive_quit(EXIT_SUCCESS);
--
2.41.0

2023-10-20 20:12:35

by bluez.test.bot

[permalink] [raw]
Subject: RE: [BlueZ,v2,1/4] shared/util: Add util_debug_{tlv, bit} helpers

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=795210

---Test result---

Test Summary:
CheckPatch PASS 2.89 seconds
GitLint PASS 1.37 seconds
BuildEll PASS 29.71 seconds
BluezMake PASS 1085.10 seconds
MakeCheck PASS 12.59 seconds
MakeDistcheck PASS 185.35 seconds
CheckValgrind PASS 284.84 seconds
CheckSmatch WARNING 377.39 seconds
bluezmakeextell PASS 122.42 seconds
IncrementalBuild PASS 3643.09 seconds
ScanBuild WARNING 1170.95 seconds

Details
##############################
Test: CheckSmatch - WARNING
Desc: Run smatch tool with source
Output:
monitor/att.c: note: in included file:monitor/display.h:82:26: warning: Variable length array is used.monitor/packet.c: note: in included file:monitor/display.h:82:26: warning: Variable length array is used.monitor/packet.c:1859:26: warning: Variable length array is used.monitor/packet.c: note: in included file:monitor/bt.h:3606:52: warning: array of flexible structuresmonitor/bt.h:3594:40: warning: array of flexible structures
##############################
Test: ScanBuild - WARNING
Desc: Run Scan Build
Output:
In file included from tools/mesh-gatt/crypto.c:32:
./src/shared/util.h:221:9: warning: 1st function call argument is an uninitialized value
return be32_to_cpu(get_unaligned((const uint32_t *) ptr));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./src/shared/util.h:33:26: note: expanded from macro 'be32_to_cpu'
#define be32_to_cpu(val) bswap_32(val)
^~~~~~~~~~~~~
/usr/include/byteswap.h:34:21: note: expanded from macro 'bswap_32'
#define bswap_32(x) __bswap_32 (x)
^~~~~~~~~~~~~~
In file included from tools/mesh-gatt/crypto.c:32:
./src/shared/util.h:231:9: warning: 1st function call argument is an uninitialized value
return be64_to_cpu(get_unaligned((const uint64_t *) ptr));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./src/shared/util.h:34:26: note: expanded from macro 'be64_to_cpu'
#define be64_to_cpu(val) bswap_64(val)
^~~~~~~~~~~~~
/usr/include/byteswap.h:37:21: note: expanded from macro 'bswap_64'
#define bswap_64(x) __bswap_64 (x)
^~~~~~~~~~~~~~
2 warnings generated.



---
Regards,
Linux Bluetooth

2023-10-20 20:51:31

by patchwork-bot+bluetooth

[permalink] [raw]
Subject: Re: [PATCH BlueZ v2 1/4] shared/util: Add util_debug_{tlv, bit} helpers

Hello:

This series was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <[email protected]>:

On Fri, 20 Oct 2023 11:08:31 -0700 you wrote:
> From: Luiz Augusto von Dentz <[email protected]>
>
> This adds util_debug_tlv and util_debug_bit which can help to print
> debug information in their respective formats.
> ---
> src/shared/util.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++
> src/shared/util.h | 30 ++++++++++++++++
> 2 files changed, 118 insertions(+)

Here is the summary with links:
- [BlueZ,v2,1/4] shared/util: Add util_debug_{tlv, bit} helpers
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=ffc5819ce412
- [BlueZ,v2,2/4] monitor: Make use of util_debug_tlv to decode TLV entries
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=e1ec08661422
- [BlueZ,v2,3/4] shared/bap: Add debug helpers
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=6d4491649e06
- [BlueZ,v2,4/4] client: Make use of bap-debug functions
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=8a335099bc1b

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html