Bluetooth: BAP: Move pac record discovery to new callback
Add a new pac_record callback that is used to report the found
PAC records during BAP discovery, rather than calling
the discovery callback with optional values.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
diff --git a/include/zephyr/bluetooth/audio/bap.h b/include/zephyr/bluetooth/audio/bap.h
index b8ee64b..f034c94 100644
--- a/include/zephyr/bluetooth/audio/bap.h
+++ b/include/zephyr/bluetooth/audio/bap.h
@@ -1210,24 +1210,37 @@
enum bt_bap_ascs_reason reason);
/**
- * @brief Discover Audio capabilities and endpoints callback function.
+ * @brief Remote Published Audio Capability (PAC) record discovered
*
- * If discovery procedure has complete both cap and ep are set to NULL.
+ * Called when a PAC record has been discovered as part of the discovery procedure.
*
* The @p codec is only valid while in the callback, so the values must be stored by the
* receiver if future use is wanted.
*
* @param conn Connection to the remote unicast server.
+ * @param dir The type of remote endpoints and capabilities discovered.
+ * @param codec Remote capabilities.
+ *
+ * If discovery procedure has complete both @p codec and @p ep are set to NULL.
+ */
+ void (*pac_record)(struct bt_conn *conn, enum bt_audio_dir dir,
+ const struct bt_codec *codec);
+
+ /**
+ * @brief BAP discovery callback function.
+ *
+ * If discovery procedure has completed @p ep is set to NULL and @p err is 0.
+ *
+ * @param conn Connection to the remote unicast server.
* @param err Error value. 0 on success, GATT error on positive value or errno on
* negative value.
* @param dir The type of remote endpoints and capabilities discovered.
- * @param codec Remote capabilities.
* @param ep Remote endpoint.
*
* If discovery procedure has complete both @p codec and @p ep are set to NULL.
*/
void (*discover)(struct bt_conn *conn, int err, enum bt_audio_dir dir,
- struct bt_codec *codec, struct bt_bap_ep *ep);
+ struct bt_bap_ep *ep);
};
/**
diff --git a/samples/bluetooth/unicast_audio_client/src/main.c b/samples/bluetooth/unicast_audio_client/src/main.c
index 32e7813..949eb12 100644
--- a/samples/bluetooth/unicast_audio_client/src/main.c
+++ b/samples/bluetooth/unicast_audio_client/src/main.c
@@ -576,7 +576,7 @@
printk("Could not add sink ep\n");
}
-static void print_remote_codec(struct bt_codec *codec_capabilities, enum bt_audio_dir dir)
+static void print_remote_codec(const struct bt_codec *codec_capabilities, enum bt_audio_dir dir)
{
printk("codec_capabilities %p dir 0x%02x\n", codec_capabilities, dir);
@@ -584,18 +584,13 @@
}
static void discover_sinks_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir,
- struct bt_codec *codec, struct bt_bap_ep *ep)
+ struct bt_bap_ep *ep)
{
if (err != 0 && err != BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) {
printk("Discovery failed: %d\n", err);
return;
}
- if (codec != NULL) {
- print_remote_codec(codec, dir);
- return;
- }
-
if (ep != NULL) {
add_remote_sink(ep);
@@ -612,18 +607,13 @@
}
static void discover_sources_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir,
- struct bt_codec *codec, struct bt_bap_ep *ep)
+ struct bt_bap_ep *ep)
{
if (err != 0 && err != BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) {
printk("Discovery failed: %d\n", err);
return;
}
- if (codec != NULL) {
- print_remote_codec(codec, dir);
- return;
- }
-
if (ep != NULL) {
add_remote_source(ep);
@@ -721,9 +711,15 @@
printk("snk ctx %u src ctx %u\n", snk_ctx, src_ctx);
}
+static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir, const struct bt_codec *codec)
+{
+ print_remote_codec(codec, dir);
+}
+
static struct bt_bap_unicast_client_cb unicast_client_cbs = {
.location = unicast_client_location_cb,
.available_contexts = available_contexts_cb,
+ .pac_record = pac_record_cb,
};
static int init(void)
diff --git a/subsys/bluetooth/audio/bap_unicast_client.c b/subsys/bluetooth/audio/bap_unicast_client.c
index 0f6f6a3..c3e8a76 100644
--- a/subsys/bluetooth/audio/bap_unicast_client.c
+++ b/subsys/bluetooth/audio/bap_unicast_client.c
@@ -1450,12 +1450,26 @@
return bt_gatt_subscribe(conn, &client_ep->subscribe);
}
-static void discover_cb(struct bt_conn *conn, int err, struct bt_codec *codec, struct bt_bap_ep *ep)
+static void pac_record_cb(struct bt_conn *conn, const struct bt_codec *codec)
+{
+ if (unicast_client_cbs != NULL && unicast_client_cbs->pac_record != NULL) {
+ struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
+ const enum bt_audio_dir dir = client->dir;
+
+ /* TBD: Since the PAC records are optionally notifyable we may want to supply the
+ * index and total count of records in the callback, so that it easier for the
+ * upper layers to determine when a new set of PAC records is being reported.
+ */
+ unicast_client_cbs->pac_record(conn, dir, codec);
+ }
+}
+
+static void discover_cb(struct bt_conn *conn, int err, struct bt_bap_ep *ep)
{
struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
const enum bt_audio_dir dir = client->dir;
- if (err != 0 || (codec == NULL && ep == NULL)) {
+ if (err != 0 || ep == NULL) {
/* Discover complete - Reset discovery values */
client->dir = 0U;
client->busy = false;
@@ -1464,7 +1478,7 @@
}
if (unicast_client_cbs != NULL && unicast_client_cbs->discover != NULL) {
- unicast_client_cbs->discover(conn, err, dir, codec, ep);
+ unicast_client_cbs->discover(conn, err, dir, ep);
}
}
@@ -1474,7 +1488,7 @@
LOG_DBG("conn %p err %u", conn, err);
- discover_cb(conn, err, NULL, NULL);
+ discover_cb(conn, err, NULL);
}
static void unicast_client_ep_set_cp(struct bt_conn *conn, uint16_t handle)
@@ -1519,12 +1533,12 @@
if (err != 0) {
LOG_DBG("Failed to subscribe: %d", err);
- discover_cb(conn, BT_ATT_ERR_UNLIKELY, NULL, NULL);
+ discover_cb(conn, BT_ATT_ERR_UNLIKELY, NULL);
return;
}
} else { /* already subscribed */
- discover_cb(conn, 0, NULL, NULL);
+ discover_cb(conn, 0, NULL);
}
}
@@ -2836,7 +2850,7 @@
if (!attr) {
LOG_ERR("Unable to find ASE Control Point");
- discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND, NULL, NULL);
+ discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND, NULL);
return BT_GATT_ITER_STOP;
}
@@ -2927,19 +2941,19 @@
unicast_client_ep_set_status(ep, buf);
unicast_client_ep_subscribe(conn, ep);
- discover_cb(conn, 0, NULL, ep);
+ discover_cb(conn, 0, ep);
err = unicast_client_ase_discover(conn, handle);
if (err != 0) {
LOG_DBG("Failed to read ASE: %d", err);
- discover_cb(conn, err, NULL, NULL);
+ discover_cb(conn, err, NULL);
}
return BT_GATT_ITER_STOP;
fail:
- discover_cb(conn, err, NULL, NULL);
+ discover_cb(conn, err, NULL);
return BT_GATT_ITER_STOP;
}
@@ -2957,7 +2971,7 @@
if (err != 0) {
LOG_ERR("Unable to discover ASE Control Point");
- discover_cb(conn, BT_ATT_ERR_UNLIKELY, NULL, NULL);
+ discover_cb(conn, BT_ATT_ERR_UNLIKELY, NULL);
}
return BT_GATT_ITER_STOP;
@@ -2984,7 +2998,7 @@
if (err != 0) {
LOG_DBG("Failed to read PAC records: %d", err);
- discover_cb(conn, err, NULL, NULL);
+ discover_cb(conn, err, NULL);
}
return BT_GATT_ITER_STOP;
@@ -3031,7 +3045,7 @@
err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
}
- discover_cb(conn, err, NULL, NULL);
+ discover_cb(conn, err, NULL);
return BT_GATT_ITER_STOP;
}
@@ -3051,7 +3065,7 @@
if (cb_err != 0) {
LOG_ERR("Unable to read ASE: %d", cb_err);
- discover_cb(conn, err, NULL, NULL);
+ discover_cb(conn, err, NULL);
}
return BT_GATT_ITER_STOP;
@@ -3126,7 +3140,7 @@
* the characteristic is mandatory
*/
- discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND, NULL, NULL);
+ discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND, NULL);
return BT_GATT_ITER_STOP;
}
@@ -3162,7 +3176,7 @@
/* If the characteristic is not subscribable we terminate the
* discovery as BT_GATT_CHRC_NOTIFY is mandatory
*/
- discover_cb(conn, BT_ATT_ERR_NOT_SUPPORTED, NULL, NULL);
+ discover_cb(conn, BT_ATT_ERR_NOT_SUPPORTED, NULL);
return BT_GATT_ITER_STOP;
}
@@ -3171,7 +3185,7 @@
if (err != 0) {
LOG_DBG("Failed to read PACS avail_ctx: %d", err);
- discover_cb(conn, err, NULL, NULL);
+ discover_cb(conn, err, NULL);
}
return BT_GATT_ITER_STOP;
@@ -3215,7 +3229,7 @@
err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
}
- discover_cb(conn, err, NULL, NULL);
+ discover_cb(conn, err, NULL);
return BT_GATT_ITER_STOP;
}
@@ -3234,7 +3248,7 @@
if (cb_err != 0) {
LOG_ERR("Unable to read available contexts: %d", cb_err);
- discover_cb(conn, cb_err, NULL, NULL);
+ discover_cb(conn, cb_err, NULL);
}
return BT_GATT_ITER_STOP;
@@ -3321,7 +3335,7 @@
if (err != 0) {
LOG_ERR("Unable to read available contexts: %d", err);
- discover_cb(conn, err, NULL, NULL);
+ discover_cb(conn, err, NULL);
}
return BT_GATT_ITER_STOP;
@@ -3360,7 +3374,7 @@
if (err != 0) {
LOG_DBG("Failed to read PACS location: %d", err);
- discover_cb(conn, err, NULL, NULL);
+ discover_cb(conn, err, NULL);
}
return BT_GATT_ITER_STOP;
@@ -3416,7 +3430,7 @@
if (cb_err != 0) {
LOG_ERR("Unable to read PACS location: %d", cb_err);
- discover_cb(conn, cb_err, NULL, NULL);
+ discover_cb(conn, cb_err, NULL);
}
return BT_GATT_ITER_STOP;
@@ -3434,7 +3448,7 @@
if (attr == NULL) {
LOG_ERR("Unable to find %s PAC context", bt_audio_dir_str(client->dir));
- discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND, NULL, NULL);
+ discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND, NULL);
return BT_GATT_ITER_STOP;
}
@@ -3457,7 +3471,7 @@
if (err != 0) {
LOG_DBG("Failed to read PAC records: %d", err);
- discover_cb(conn, err, NULL, NULL);
+ discover_cb(conn, err, NULL);
}
return BT_GATT_ITER_STOP;
@@ -3594,7 +3608,7 @@
LOG_DBG("codec 0x%02x config count %u meta count %u ", codec.id, codec.data_count,
codec.meta_count);
- discover_cb(conn, 0, &codec, NULL);
+ pac_record_cb(conn, &codec);
}
if (i != rsp->num_pac) {
@@ -3613,7 +3627,7 @@
return BT_GATT_ITER_STOP;
fail:
- discover_cb(conn, cb_err, NULL, NULL);
+ discover_cb(conn, cb_err, NULL);
return BT_GATT_ITER_STOP;
}
@@ -3629,7 +3643,7 @@
if (attr == NULL) {
LOG_ERR("Unable to find %s PAC", bt_audio_dir_str(client->dir));
- discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND, NULL, NULL);
+ discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND, NULL);
return BT_GATT_ITER_STOP;
}
@@ -3655,7 +3669,7 @@
if (err != 0) {
LOG_DBG("Failed to read PAC records: %d", err);
- discover_cb(conn, err, NULL, NULL);
+ discover_cb(conn, err, NULL);
}
return BT_GATT_ITER_STOP;
diff --git a/subsys/bluetooth/audio/shell/bap.c b/subsys/bluetooth/audio/shell/bap.c
index b2f3573..70d49a8 100644
--- a/subsys/bluetooth/audio/shell/bap.c
+++ b/subsys/bluetooth/audio/shell/bap.c
@@ -703,7 +703,7 @@
return 0;
}
-static void print_remote_codec(const struct bt_conn *conn, struct bt_codec *codec,
+static void print_remote_codec(const struct bt_conn *conn, const struct bt_codec *codec,
enum bt_audio_dir dir)
{
shell_print(ctx_shell, "conn %p: codec %p dir 0x%02x", conn, codec, dir);
@@ -747,13 +747,13 @@
}
#endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
-static void discover_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir,
- struct bt_codec *codec, struct bt_bap_ep *ep)
+static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir, const struct bt_codec *codec)
{
- if (codec != NULL) {
- print_remote_codec(conn, codec, dir);
- return;
- }
+ print_remote_codec(conn, codec, dir);
+}
+
+static void discover_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir, struct bt_bap_ep *ep)
+{
if (ep) {
#if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
@@ -774,13 +774,8 @@
shell_print(ctx_shell, "Discover complete: err %d", err);
}
-static void discover_all(struct bt_conn *conn, int err, enum bt_audio_dir dir,
- struct bt_codec *codec, struct bt_bap_ep *ep)
+static void discover_all(struct bt_conn *conn, int err, enum bt_audio_dir dir, struct bt_bap_ep *ep)
{
- if (codec != NULL) {
- print_remote_codec(conn, codec, dir);
- return;
- }
if (ep) {
#if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
@@ -806,7 +801,7 @@
err = bt_bap_unicast_client_discover(default_conn, dir);
if (err) {
shell_error(ctx_shell, "bt_bap_unicast_client_discover err %d", err);
- discover_cb(conn, err, dir, NULL, NULL);
+ discover_cb(conn, err, dir, NULL);
}
}
}
@@ -892,6 +887,7 @@
.disable = disable_cb,
.metadata = metadata_cb,
.release = release_cb,
+ .pac_record = pac_record_cb,
};
static int cmd_discover(const struct shell *sh, size_t argc, char *argv[])
diff --git a/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c b/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c
index 7894449..ba6dbd0 100644
--- a/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c
+++ b/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c
@@ -30,6 +30,7 @@
CREATE_FLAG(flag_mtu_exchanged);
CREATE_FLAG(flag_sink_discovered);
CREATE_FLAG(flag_source_discovered);
+CREATE_FLAG(flag_codec_found);
CREATE_FLAG(flag_stream_codec_configured);
static atomic_t flag_stream_qos_configured;
CREATE_FLAG(flag_stream_enabled);
@@ -224,7 +225,7 @@
FAIL("Could not add source ep\n");
}
-static void print_remote_codec(struct bt_codec *codec, enum bt_audio_dir dir)
+static void print_remote_codec(const struct bt_codec *codec, enum bt_audio_dir dir)
{
printk("codec %p dir 0x%02x\n", codec, dir);
@@ -232,9 +233,8 @@
}
static void discover_sinks_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir,
- struct bt_codec *codec, struct bt_bap_ep *ep)
+ struct bt_bap_ep *ep)
{
- static bool codec_found;
static bool endpoint_found;
if (err != 0) {
@@ -242,12 +242,6 @@
return;
}
- if (codec != NULL) {
- print_remote_codec(codec, dir);
- codec_found = true;
- return;
- }
-
if (ep != NULL) {
if (dir == BT_AUDIO_DIR_SINK) {
add_remote_sink(ep);
@@ -261,7 +255,7 @@
printk("Sinks discover complete\n");
- if (endpoint_found && codec_found) {
+ if (endpoint_found) {
SET_FLAG(flag_sink_discovered);
} else {
FAIL("Did not discover endpoint and codec\n");
@@ -269,9 +263,8 @@
}
static void discover_sources_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir,
- struct bt_codec *codec, struct bt_bap_ep *ep)
+ struct bt_bap_ep *ep)
{
- static bool codec_found;
static bool endpoint_found;
if (err != 0) {
@@ -279,12 +272,6 @@
return;
}
- if (codec != NULL) {
- print_remote_codec(codec, dir);
- codec_found = true;
- return;
- }
-
if (ep != NULL) {
if (dir == BT_AUDIO_DIR_SOURCE) {
add_remote_source(ep);
@@ -298,13 +285,19 @@
printk("Sources discover complete\n");
- if (endpoint_found && codec_found) {
+ if (endpoint_found) {
SET_FLAG(flag_source_discovered);
} else {
FAIL("Did not discover endpoint and codec\n");
}
}
+static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir, const struct bt_codec *codec)
+{
+ print_remote_codec(codec, dir);
+ SET_FLAG(flag_codec_found);
+}
+
static struct bt_bap_unicast_client_cb unicast_client_cbs = {
.location = unicast_client_location_cb,
.available_contexts = available_contexts_cb,
@@ -316,6 +309,7 @@
.disable = disable_cb,
.metadata = metadata_cb,
.release = release_cb,
+ .pac_record = pac_record_cb,
};
static void att_mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
@@ -376,6 +370,7 @@
unicast_client_cbs.discover = discover_sinks_cb;
+ UNSET_FLAG(flag_codec_found);
UNSET_FLAG(flag_sink_discovered);
err = bt_bap_unicast_client_discover(default_conn, BT_AUDIO_DIR_SINK);
@@ -386,6 +381,7 @@
memset(g_sinks, 0, sizeof(g_sinks));
+ WAIT_FOR_FLAG(flag_codec_found);
WAIT_FOR_FLAG(flag_sink_discovered);
}
@@ -395,6 +391,7 @@
unicast_client_cbs.discover = discover_sources_cb;
+ UNSET_FLAG(flag_codec_found);
UNSET_FLAG(flag_source_discovered);
err = bt_bap_unicast_client_discover(default_conn, BT_AUDIO_DIR_SOURCE);
@@ -405,6 +402,7 @@
memset(g_sources, 0, sizeof(g_sources));
+ WAIT_FOR_FLAG(flag_codec_found);
WAIT_FOR_FLAG(flag_source_discovered);
}
diff --git a/tests/bsim/bluetooth/audio/src/cap_initiator_test.c b/tests/bsim/bluetooth/audio/src/cap_initiator_test.c
index d129ccb..b4f4368 100644
--- a/tests/bsim/bluetooth/audio/src/cap_initiator_test.c
+++ b/tests/bsim/bluetooth/audio/src/cap_initiator_test.c
@@ -52,6 +52,7 @@
static K_SEM_DEFINE(sem_broadcast_stopped, 0U, ARRAY_SIZE(broadcast_streams));
CREATE_FLAG(flag_discovered);
+CREATE_FLAG(flag_codec_found);
CREATE_FLAG(flag_started);
CREATE_FLAG(flag_updated);
CREATE_FLAG(flag_stopped);
@@ -255,17 +256,22 @@
FAIL("Could not add source ep\n");
}
-static void print_remote_codec(struct bt_codec *codec, enum bt_audio_dir dir)
+static void print_remote_codec(const struct bt_codec *codec, enum bt_audio_dir dir)
{
printk("codec %p dir 0x%02x\n", codec, dir);
print_codec(codec);
}
-static void discover_sink_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir,
- struct bt_codec *codec, struct bt_bap_ep *ep)
+static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir, const struct bt_codec *codec)
{
- static bool codec_found;
+ print_remote_codec(codec, dir);
+ SET_FLAG(flag_codec_found);
+}
+
+static void discover_sink_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir,
+ struct bt_bap_ep *ep)
+{
static bool endpoint_found;
if (err != 0) {
@@ -273,13 +279,6 @@
return;
}
- if (codec != NULL) {
- print_remote_codec(codec, dir);
- codec_found = true;
-
- return;
- }
-
if (ep != NULL) {
if (dir == BT_AUDIO_DIR_SINK) {
add_remote_sink(ep);
@@ -293,7 +292,7 @@
printk("Sink discover complete\n");
- if (endpoint_found && codec_found) {
+ if (endpoint_found) {
SET_FLAG(flag_sink_discovered);
} else {
FAIL("Did not discover endpoint and codec\n");
@@ -302,6 +301,7 @@
static const struct bt_bap_unicast_client_cb unicast_client_cbs = {
.discover = discover_sink_cb,
+ .pac_record = pac_record_cb,
};
static void att_mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
@@ -375,6 +375,9 @@
{
int err;
+ UNSET_FLAG(flag_sink_discovered);
+ UNSET_FLAG(flag_codec_found);
+
err = bt_bap_unicast_client_discover(default_conn, BT_AUDIO_DIR_SINK);
if (err != 0) {
printk("Failed to discover sink: %d\n", err);
@@ -384,6 +387,7 @@
memset(unicast_sink_eps, 0, sizeof(unicast_sink_eps));
WAIT_FOR_FLAG(flag_sink_discovered);
+ WAIT_FOR_FLAG(flag_codec_found);
}
static void discover_cas_inval(void)