Bluetooth: Audio: Add PACS for broadcast sink

Add support for using PACS and/or capabilities for
the broadcast sink role. PACS and capabilities were
originally only supported for the unicast server
role, so the PACS callbacks were moved their own
struct, as if a device supports both the unicast
server role and the broadcast sink role, it will
only have a single PACS instance.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
diff --git a/include/zephyr/bluetooth/audio/audio.h b/include/zephyr/bluetooth/audio/audio.h
index 29c4998..ee2b16d 100644
--- a/include/zephyr/bluetooth/audio/audio.h
+++ b/include/zephyr/bluetooth/audio/audio.h
@@ -1367,7 +1367,15 @@
 	 *  @return 0 in case of success or negative value in case of error.
 	 */
 	int (*release)(struct bt_audio_stream *stream);
+};
 
+/**  @brief Callback structure for the Public Audio Capabilities Service (PACS)
+ *
+ * This is used for the Unicast Server
+ * (@kconfig{CONFIG_BT_AUDIO_UNICAST_SERVER}) and Broadcast Sink
+ * (@kconfig{CONFIG_BT_AUDIO_BROADCAST_SINK}) roles.
+ */
+struct bt_audio_pacs_cb {
 	/** @brief Get available audio contexts callback
 	 *
 	 *  Get available audio contexts callback is called whenever a remote client
@@ -1377,7 +1385,7 @@
 	 *  @param[in]  conn     The connection that requests the available audio
 	 *                       contexts. Will be NULL if requested for sending
 	 *                       a notification, as a result of calling
-	 *                       bt_audio_unicast_server_available_contexts_changed().
+	 *                       bt_pacs_available_contexts_changed().
 	 *  @param[in]  dir      Direction of the endpoint.
 	 *  @param[out] context  Pointer to the contexts that needs to be set.
 	 *
@@ -1422,8 +1430,7 @@
 	 *  @param[in]  conn      The connection that requests the location.
 	 *                        Will be NULL if the location is requested
 	 *                        for sending a notification, as a result of
-	 *                        calling
-	 *                        bt_audio_unicast_server_location_changed().
+	 *                        calling bt_audio_pacs_location_changed().
 	 *  @param[in]  dir       Direction of the endpoint.
 	 *  @param[out] location  Pointer to the location that needs to be set.
 	 *
@@ -1662,6 +1669,40 @@
  * @{
  */
 
+/** @brief Register Published Audio Capabilities Service callbacks.
+ *
+ *  Only one callback structure can be registered, and attempting to
+ *  registering more than one will result in an error.
+ *
+ *  This can only be done for the Unicast Server
+ *  (@kconfig{CONFIG_BT_AUDIO_UNICAST_SERVER}) and Broadcast Sink
+ *  (@kconfig{CONFIG_BT_AUDIO_BROADCAST_SINK}) roles.
+ *
+ *  Calling bt_audio_capability_register() will implicitly register the
+ *  callbacks.
+ *
+ *  @param cb  Unicast server callback structure.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_audio_pacs_register_cb(const struct bt_audio_pacs_cb *cb);
+
+/** @brief Notify that the location has changed
+ *
+ * @param dir Direction of the location changed.
+ *
+ * @return 0 in case of success or negative value in case of error.
+ */
+int bt_audio_pacs_location_changed(enum bt_audio_dir dir);
+
+/** @brief Notify available audio contexts changed
+ *
+ * Notify connected clients that the available audio contexts has changed
+ *
+ * @return 0 in case of success or negative value in case of error.
+ */
+int bt_pacs_available_contexts_changed(void);
+
 /** @brief Register unicast server callbacks.
  *
  *  Only one callback structure can be registered, and attempting to
@@ -1684,24 +1725,6 @@
  */
 int bt_audio_unicast_server_unregister_cb(const struct bt_audio_unicast_server_cb *cb);
 
-/** @brief Notify location changed
- *
- * Notify connected clients that the location has changed
- *
- * @param dir       Direction of the endpoint.
- *
- * @return 0 in case of success or negative value in case of error.
- */
-int bt_audio_unicast_server_location_changed(enum bt_audio_dir dir);
-
-/** @brief Notify available audio contexts changed
- *
- * Notify connected clients that the available audio contexts has changed
- *
- * @return 0 in case of success or negative value in case of error.
- */
-int bt_audio_unicast_server_available_contexts_changed(void);
-
 /** @} */ /* End of group bt_audio_server */
 
 /**
diff --git a/include/zephyr/bluetooth/audio/capabilities.h b/include/zephyr/bluetooth/audio/capabilities.h
index bbafbfe..6a4b587 100644
--- a/include/zephyr/bluetooth/audio/capabilities.h
+++ b/include/zephyr/bluetooth/audio/capabilities.h
@@ -232,10 +232,12 @@
 	enum bt_audio_dir dir;
 	/** Capability codec reference */
 	struct bt_codec *codec;
+#if defined(CONFIG_BT_AUDIO_UNICAST_SERVER)
 	/** Capability preferences */
 	struct bt_audio_capability_pref pref;
 	/** Capability operations reference */
 	struct bt_audio_capability_ops *ops;
+#endif /* CONFIG_BT_AUDIO_UNICAST_SERVER */
 	sys_snode_t node;
 };
 
diff --git a/samples/bluetooth/broadcast_audio_sink/prj.conf b/samples/bluetooth/broadcast_audio_sink/prj.conf
index 22e4e99..1dd1fd1 100644
--- a/samples/bluetooth/broadcast_audio_sink/prj.conf
+++ b/samples/bluetooth/broadcast_audio_sink/prj.conf
@@ -1,6 +1,9 @@
 CONFIG_BT=y
 CONFIG_BT_DEBUG_LOG=y
 CONFIG_BT_AUDIO=y
+CONFIG_BT_SMP=y
+CONFIG_BT_PAC_SNK=y
+CONFIG_BT_PERIPHERAL=y
 CONFIG_BT_AUDIO_BROADCAST_SINK=y
 
 CONFIG_BT_DEVICE_NAME="Broadcast Audio Sink"
diff --git a/samples/bluetooth/broadcast_audio_sink/src/main.c b/samples/bluetooth/broadcast_audio_sink/src/main.c
index 117da94..7a74620 100644
--- a/samples/bluetooth/broadcast_audio_sink/src/main.c
+++ b/samples/bluetooth/broadcast_audio_sink/src/main.c
@@ -5,6 +5,7 @@
  */
 #include <zephyr/bluetooth/bluetooth.h>
 #include <zephyr/bluetooth/audio/audio.h>
+#include <zephyr/bluetooth/audio/capabilities.h>
 
 #define SEM_TIMEOUT K_SECONDS(10)
 
@@ -147,6 +148,11 @@
 	.pa_sync_lost = pa_sync_lost_cb
 };
 
+static struct bt_audio_capability capabilities = {
+	.dir = BT_AUDIO_DIR_SINK,
+	.codec = &preset_16_2_1.codec,
+};
+
 static int init(void)
 {
 	int err;
@@ -159,6 +165,12 @@
 
 	printk("Bluetooth initialized\n");
 
+	err = bt_audio_capability_register(&capabilities);
+	if (err) {
+		printk("Capability register failed (err %d)\n", err);
+		return err;
+	}
+
 	bt_audio_broadcast_sink_register_cb(&broadcast_sink_cbs);
 
 	for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) {
diff --git a/subsys/bluetooth/audio/Kconfig.baps b/subsys/bluetooth/audio/Kconfig.baps
index 0a91bd8..2de9e05 100644
--- a/subsys/bluetooth/audio/Kconfig.baps
+++ b/subsys/bluetooth/audio/Kconfig.baps
@@ -153,6 +153,8 @@
 	bool "Bluetooth Broadcast Sink Audio Support [EXPERIMENTAL]"
 	select EXPERIMENTAL
 	select BT_ISO_SYNC_RECEIVER
+	depends on BT_PERIPHERAL
+	depends on BT_PAC_SNK
 	help
 	  This option enables support for Bluetooth Broadcast Sink Audio using
 	  Isochronous channels.
@@ -243,7 +245,7 @@
 config BT_AUDIO_CAPABILITY
 	# Virtual/hidden option
 	bool
-	default y if BT_ASCS || BT_AUDIO_BROADCAST_SINK
+	default y if BT_PACS
 
 rsource "Kconfig.pacs"
 rsource "Kconfig.ascs"
diff --git a/subsys/bluetooth/audio/capabilities.c b/subsys/bluetooth/audio/capabilities.c
index c578d90..9311e52 100644
--- a/subsys/bluetooth/audio/capabilities.c
+++ b/subsys/bluetooth/audio/capabilities.c
@@ -230,6 +230,19 @@
 	return cap->ops->release(stream);
 }
 
+static struct bt_audio_unicast_server_cb unicast_server_cb = {
+	.config = unicast_server_config_cb,
+	.reconfig = unicast_server_reconfig_cb,
+	.qos = unicast_server_qos_cb,
+	.enable = unicast_server_enable_cb,
+	.start = unicast_server_start_cb,
+	.metadata = unicast_server_metadata_cb,
+	.disable = unicast_server_disable_cb,
+	.stop = unicast_server_stop_cb,
+	.release = unicast_server_release_cb
+};
+#endif /* CONFIG_BT_AUDIO_UNICAST_SERVER && CONFIG_BT_ASCS */
+
 static int publish_capability_cb(struct bt_conn *conn, uint8_t dir,
 				 uint8_t index, struct bt_codec *codec)
 {
@@ -309,18 +322,9 @@
 	return get_available_contexts(dir, contexts);
 }
 
-static struct bt_audio_unicast_server_cb unicast_server_cb = {
-	.config = unicast_server_config_cb,
-	.reconfig = unicast_server_reconfig_cb,
-	.qos = unicast_server_qos_cb,
-	.enable = unicast_server_enable_cb,
-	.start = unicast_server_start_cb,
-	.metadata = unicast_server_metadata_cb,
-	.disable = unicast_server_disable_cb,
-	.stop = unicast_server_stop_cb,
-	.release = unicast_server_release_cb,
-	.get_available_contexts = get_available_contexts_cb,
+static struct bt_audio_pacs_cb pacs_cb = {
 	.publish_capability = publish_capability_cb,
+	.get_available_contexts = get_available_contexts_cb,
 #if defined(CONFIG_BT_PAC_SNK_LOC) || defined(CONFIG_BT_PAC_SRC_LOC)
 	.publish_location = publish_location_cb,
 #if defined(CONFIG_BT_PAC_SNK_LOC_WRITEABLE) || defined(CONFIG_BT_PAC_SRC_LOC_WRITEABLE)
@@ -328,7 +332,6 @@
 #endif /* CONFIG_BT_PAC_SNK_LOC_WRITEABLE || CONFIG_BT_PAC_SRC_LOC_WRITEABLE */
 #endif /* CONFIG_BT_PAC_SNK_LOC || CONFIG_BT_PAC_SRC_LOC */
 };
-#endif /* CONFIG_BT_AUDIO_UNICAST_SERVER && CONFIG_BT_ASCS */
 
 sys_slist_t *bt_audio_capability_get(enum bt_audio_dir dir)
 {
@@ -345,6 +348,7 @@
 /* Register Audio Capability */
 int bt_audio_capability_register(struct bt_audio_capability *cap)
 {
+	static bool pacs_cb_registered;
 	sys_slist_t *lst;
 
 	if (!cap || !cap->codec) {
@@ -360,6 +364,19 @@
 	       "codec vid 0x%04x", cap, cap->dir, cap->codec->id,
 	       cap->codec->cid, cap->codec->vid);
 
+	if (!pacs_cb_registered) {
+		int err;
+
+		err = bt_audio_pacs_register_cb(&pacs_cb);
+		if (err != 0) {
+			BT_DBG("Failed to register PACS callbacks: %d",
+			       err);
+			return err;
+		}
+
+		pacs_cb_registered = true;
+	}
+
 #if defined(CONFIG_BT_AUDIO_UNICAST_SERVER) && defined(CONFIG_BT_ASCS)
 	/* Using the capabilities instead of the unicast server directly will
 	 * require the capabilities to register the callbacks, which not only
@@ -438,8 +455,6 @@
 int bt_audio_capability_set_location(enum bt_audio_dir dir,
 				     enum bt_audio_location location)
 {
-	int err;
-
 	if (0) {
 #if defined(CONFIG_BT_PAC_SNK_LOC)
 	} else if (dir == BT_AUDIO_DIR_SINK) {
@@ -455,11 +470,16 @@
 		return -EINVAL;
 	}
 
-	if (IS_ENABLED(CONFIG_BT_AUDIO_UNICAST_SERVER)) {
-		err = bt_audio_unicast_server_location_changed(dir);
+	if (IS_ENABLED(CONFIG_BT_PAC_SNK_LOC) ||
+	    IS_ENABLED(CONFIG_BT_PAC_SRC_LOC)) {
+		int err;
+
+		err = bt_audio_pacs_location_changed(dir);
 		if (err) {
 			BT_DBG("Location for dir %d wasn't notified: %d",
 			       dir, err);
+
+			return err;
 		}
 	}
 
@@ -537,8 +557,8 @@
 		return err;
 	}
 
-	if (IS_ENABLED(CONFIG_BT_AUDIO_UNICAST_SERVER)) {
-		err = bt_audio_unicast_server_available_contexts_changed();
+	if (IS_ENABLED(CONFIG_BT_PACS)) {
+		err = bt_pacs_available_contexts_changed();
 		if (err) {
 			BT_DBG("Available contexts weren't notified: %d", err);
 			return err;
diff --git a/subsys/bluetooth/audio/pacs.c b/subsys/bluetooth/audio/pacs.c
index f2b5c0a..dab9e14 100644
--- a/subsys/bluetooth/audio/pacs.c
+++ b/subsys/bluetooth/audio/pacs.c
@@ -11,6 +11,7 @@
 
 #include <zephyr/zephyr.h>
 #include <zephyr/sys/byteorder.h>
+#include <zephyr/sys/check.h>
 
 #include <zephyr/device.h>
 #include <zephyr/init.h>
@@ -33,6 +34,8 @@
 
 NET_BUF_SIMPLE_DEFINE_STATIC(read_buf, CONFIG_BT_L2CAP_TX_MTU);
 
+static const struct bt_audio_pacs_cb *pacs_cb;
+
 static void pac_data_add(struct net_buf_simple *buf, uint8_t num,
 			 struct bt_codec_data *data)
 {
@@ -60,8 +63,8 @@
 	rsp = net_buf_simple_add(&read_buf, sizeof(*rsp));
 	rsp->num_pac = 0;
 
-	if (unicast_server_cb == NULL ||
-	    unicast_server_cb->publish_capability == NULL) {
+	if (pacs_cb == NULL ||
+	    pacs_cb->publish_capability == NULL) {
 		return;
 	}
 
@@ -71,9 +74,8 @@
 		struct bt_pac *pac;
 		int err;
 
-		err = unicast_server_cb->publish_capability(conn, dir,
-							    rsp->num_pac,
-							    &codec);
+		err = pacs_cb->publish_capability(conn, dir, rsp->num_pac,
+						  &codec);
 		if (err != 0) {
 			break;
 		}
@@ -133,16 +135,15 @@
 	enum bt_audio_context context_snk, context_src;
 	int err;
 
-	if (unicast_server_cb == NULL ||
-	    unicast_server_cb->get_available_contexts == NULL) {
+	if (pacs_cb == NULL ||
+	    pacs_cb->get_available_contexts == NULL) {
 		BT_WARN("No callback for get_available_contexts");
 		return -ENODATA;
 	}
 
 	if (IS_ENABLED(CONFIG_BT_PAC_SNK)) {
-		err = unicast_server_cb->get_available_contexts(conn,
-								BT_AUDIO_DIR_SINK,
-								&context_snk);
+		err = pacs_cb->get_available_contexts(conn, BT_AUDIO_DIR_SINK,
+						      &context_snk);
 		if (err) {
 			return err;
 		}
@@ -152,9 +153,8 @@
 	}
 
 	if (IS_ENABLED(CONFIG_BT_PAC_SRC)) {
-		err = unicast_server_cb->get_available_contexts(conn,
-								BT_AUDIO_DIR_SOURCE,
-								&context_src);
+		err = pacs_cb->get_available_contexts(conn, BT_AUDIO_DIR_SOURCE,
+						      &context_src);
 		if (err) {
 			return err;
 		}
@@ -226,13 +226,13 @@
 {
 	int err;
 
-	if (unicast_server_cb == NULL ||
-	    unicast_server_cb->publish_location == NULL) {
+	if (pacs_cb == NULL ||
+	    pacs_cb->publish_location == NULL) {
 		BT_WARN("No callback for publish_location");
 		return -ENODATA;
 	}
 
-	err = unicast_server_cb->publish_location(conn, dir, location);
+	err = pacs_cb->publish_location(conn, dir, location);
 	if (err != 0 || *location == 0) {
 		BT_DBG("err (%d) or invalid location value (%u)",
 		       err, *location);
@@ -309,8 +309,8 @@
 		return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
 	}
 
-	if (unicast_server_cb == NULL ||
-	    unicast_server_cb->write_location == NULL) {
+	if (pacs_cb == NULL ||
+	    pacs_cb->write_location == NULL) {
 		BT_WARN("No callback for write_location");
 		return BT_GATT_ERR(BT_ATT_ERR_UNLIKELY);
 	}
@@ -321,8 +321,7 @@
 		return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED);
 	}
 
-	err = unicast_server_cb->write_location(conn, BT_AUDIO_DIR_SINK,
-						location);
+	err = pacs_cb->write_location(conn, BT_AUDIO_DIR_SINK, location);
 	if (err != 0) {
 		BT_DBG("write_location returned %d", err);
 		return BT_GATT_ERR(BT_ATT_ERR_AUTHORIZATION);
@@ -406,8 +405,8 @@
 		return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
 	}
 
-	if (unicast_server_cb == NULL ||
-	    unicast_server_cb->write_location == NULL) {
+	if (pacs_cb == NULL ||
+	    pacs_cb->write_location == NULL) {
 		BT_WARN("No callback for write_location");
 		return BT_GATT_ERR(BT_ATT_ERR_UNLIKELY);
 	}
@@ -418,8 +417,7 @@
 		return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED);
 	}
 
-	err = unicast_server_cb->write_location(conn, BT_AUDIO_DIR_SOURCE,
-						location);
+	err = pacs_cb->write_location(conn, BT_AUDIO_DIR_SOURCE, location);
 	if (err != 0) {
 		BT_DBG("write_location returned %d", err);
 		return BT_GATT_ERR(BT_ATT_ERR_AUTHORIZATION);
@@ -630,7 +628,8 @@
 }
 
 #if defined(CONFIG_BT_PAC_SNK_LOC) || defined(CONFIG_BT_PAC_SRC_LOC)
-int bt_pacs_location_changed(enum bt_audio_dir dir)
+/******* PUBLIC API *******/
+int bt_audio_pacs_location_changed(enum bt_audio_dir dir)
 {
 	struct k_work_delayable *work;
 
@@ -681,3 +680,18 @@
 
 	return 0;
 }
+
+int bt_audio_pacs_register_cb(const struct bt_audio_pacs_cb *cb)
+{
+	CHECKIF(cb == NULL) {
+		return -EINVAL;
+	}
+
+	if (pacs_cb != NULL) {
+		return -EALREADY;
+	}
+
+	pacs_cb = cb;
+
+	return 0;
+}
diff --git a/subsys/bluetooth/audio/pacs_internal.h b/subsys/bluetooth/audio/pacs_internal.h
index 54880d7..7383412 100644
--- a/subsys/bluetooth/audio/pacs_internal.h
+++ b/subsys/bluetooth/audio/pacs_internal.h
@@ -52,5 +52,3 @@
 
 void bt_pacs_add_capability(enum bt_audio_dir dir);
 void bt_pacs_remove_capability(enum bt_audio_dir dir);
-int bt_pacs_location_changed(enum bt_audio_dir dir);
-int bt_pacs_available_contexts_changed(void);
diff --git a/subsys/bluetooth/audio/unicast_server.c b/subsys/bluetooth/audio/unicast_server.c
index de80bb3..b37e566 100644
--- a/subsys/bluetooth/audio/unicast_server.c
+++ b/subsys/bluetooth/audio/unicast_server.c
@@ -51,15 +51,3 @@
 
 	return 0;
 }
-
-#if defined(CONFIG_BT_PAC_SNK_LOC) || defined(CONFIG_BT_PAC_SRC_LOC)
-int bt_audio_unicast_server_location_changed(enum bt_audio_dir dir)
-{
-	return bt_pacs_location_changed(dir);
-}
-#endif /* CONFIG_BT_PAC_SNK_LOC || CONFIG_BT_PAC_SRC_LOC */
-
-int bt_audio_unicast_server_available_contexts_changed(void)
-{
-	return bt_pacs_available_contexts_changed();
-}
diff --git a/subsys/bluetooth/shell/audio.c b/subsys/bluetooth/shell/audio.c
index 9e5ba2f..1de6aca 100644
--- a/subsys/bluetooth/shell/audio.c
+++ b/subsys/bluetooth/shell/audio.c
@@ -437,8 +437,11 @@
 	.stop = lc3_stop,
 	.release = lc3_release,
 };
+#endif /* CONFIG_BT_AUDIO_UNICAST */
 
+#if defined(CONFIG_BT_AUDIO_UNICAST_SERVER) || defined(CONFIG_BT_AUDIO_BROADCAST_SINK)
 static struct bt_audio_capability caps[MAX_PAC] = {
+#if defined(CONFIG_BT_AUDIO_UNICAST_SERVER)
 	{
 		.dir = BT_AUDIO_DIR_SOURCE,
 		.pref = BT_AUDIO_CAPABILITY_PREF(
@@ -448,17 +451,20 @@
 		.codec = &lc3_codec,
 		.ops = &lc3_ops,
 	},
+#endif /* CONFIG_BT_AUDIO_UNICAST_SERVER */
 	{
 		.dir = BT_AUDIO_DIR_SINK,
+		.codec = &lc3_codec,
+#if defined(CONFIG_BT_AUDIO_UNICAST_SERVER)
 		.pref = BT_AUDIO_CAPABILITY_PREF(
 				BT_AUDIO_CAPABILITY_UNFRAMED_SUPPORTED,
 				BT_GAP_LE_PHY_2M, 0u, 60u, 20000u, 40000u,
 				20000u, 40000u),
-		.codec = &lc3_codec,
 		.ops = &lc3_ops,
+#endif /* CONFIG_BT_AUDIO_UNICAST_SERVER */
 	},
 };
-#endif /* CONFIG_BT_AUDIO_UNICAST */
+#endif /* CONFIG_BT_AUDIO_UNICAST_SERVER || CONFIG_BT_AUDIO_BROADCAST_SINK */
 
 #if defined(CONFIG_BT_AUDIO_UNICAST_CLIENT)
 static uint8_t stream_dir(const struct bt_audio_stream *stream)
@@ -1355,10 +1361,11 @@
 		return err;
 	}
 
-#if defined(CONFIG_BT_AUDIO_UNICAST)
+#if defined(CONFIG_BT_AUDIO_UNICAST_SERVER) || defined(CONFIG_BT_AUDIO_BROADCAST_SINK)
 	for (i = 0; i < ARRAY_SIZE(caps); i++) {
 		bt_audio_capability_register(&caps[i]);
 	}
+#endif /* CONFIG_BT_AUDIO_UNICAST || CONFIG_BT_AUDIO_BROADCAST_SOURCE */
 
 	/* Mark all supported contexts as available */
 	bt_audio_capability_set_available_contexts(BT_AUDIO_DIR_SINK,
@@ -1366,6 +1373,7 @@
 	bt_audio_capability_set_available_contexts(BT_AUDIO_DIR_SOURCE,
 						   BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED);
 
+#if defined(CONFIG_BT_AUDIO_UNICAST)
 	for (i = 0; i < ARRAY_SIZE(streams); i++) {
 		bt_audio_stream_cb_register(&streams[i], &stream_ops);
 	}
diff --git a/tests/bluetooth/bsim_bt/bsim_test_audio/src/broadcast_sink_test.c b/tests/bluetooth/bsim_bt/bsim_test_audio/src/broadcast_sink_test.c
index 3e5759e..7d186b9 100644
--- a/tests/bluetooth/bsim_bt/bsim_test_audio/src/broadcast_sink_test.c
+++ b/tests/bluetooth/bsim_bt/bsim_test_audio/src/broadcast_sink_test.c
@@ -8,6 +8,7 @@
 
 #include <zephyr/bluetooth/bluetooth.h>
 #include <zephyr/bluetooth/audio/audio.h>
+#include <zephyr/bluetooth/audio/capabilities.h>
 #include "common.h"
 
 extern enum bst_result_t bst_result;
@@ -19,6 +20,9 @@
 
 static struct bt_audio_broadcast_sink *g_sink;
 
+/* Mandatory support preset by both source and sink */
+static struct bt_audio_lc3_preset preset = BT_AUDIO_LC3_BROADCAST_PRESET_16_2_1;
+
 static bool scan_recv_cb(const struct bt_le_scan_recv_info *info,
 			 uint32_t broadcast_id)
 {
@@ -90,6 +94,11 @@
 	.pa_sync_lost = pa_sync_lost_cb
 };
 
+static struct bt_audio_capability capabilities = {
+	.dir = BT_AUDIO_DIR_SINK,
+	.codec = &preset.codec,
+};
+
 static int init(void)
 {
 	int err;
@@ -102,6 +111,12 @@
 
 	printk("Bluetooth initialized\n");
 
+	err = bt_audio_capability_register(&capabilities);
+	if (err) {
+		FAIL("Capability register failed (err %d)\n", err);
+		return err;
+	}
+
 	bt_audio_broadcast_sink_register_cb(&broadcast_sink_cbs);
 
 	UNSET_FLAG(broadcaster_found);