diff --git a/doc/releases/migration-guide-4.1.rst b/doc/releases/migration-guide-4.1.rst index 5395efdb1f16..29969e1df4eb 100644 --- a/doc/releases/migration-guide-4.1.rst +++ b/doc/releases/migration-guide-4.1.rst @@ -385,6 +385,12 @@ Bluetooth Audio * :kconfig:option:`CONFIG_BT_PAC_SNK` * :kconfig:option:`CONFIG_BT_PAC_SRC` +* PACS have been changed to support dynamic, runtime configuration. This means that PACS now has + to be registered with :c:func:`bt_pacs_register` before it can be used. In addition, + :c:func:`bt_pacs_register` also have to be called before :c:func:`bt_ascs_register` can be + be called. All Kconfig options still remain. Runtime configuration cannot override a disabled + Kconfig option. (:github:`83730`) + Bluetooth Classic ================= diff --git a/include/zephyr/bluetooth/audio/pacs.h b/include/zephyr/bluetooth/audio/pacs.h index e956e0da7f47..9aece47ed88b 100644 --- a/include/zephyr/bluetooth/audio/pacs.h +++ b/include/zephyr/bluetooth/audio/pacs.h @@ -45,6 +45,43 @@ struct bt_pacs_cap { sys_snode_t _node; }; +/** Structure for registering PACS */ +struct bt_bap_pacs_register_param { +#if defined(CONFIG_BT_PAC_SNK) + /** + * @brief Enables or disables registration of Sink PAC Characteristic. + */ + bool snk_pac; +#endif /* CONFIG_BT_PAC_SNK */ + +#if defined(CONFIG_BT_PAC_SNK_LOC) + /** + * @brief Enables or disables registration of Sink Location Characteristic. + * + * Registration of Sink Location is dependent on @ref bt_bap_pacs_register_param.snk_pac + * also being set. + */ + bool snk_loc; +#endif /* CONFIG_BT_PAC_SNK_LOC */ + +#if defined(CONFIG_BT_PAC_SRC) + /** + * @brief Enables or disables registration of Source PAC Characteristic. + */ + bool src_pac; +#endif /* CONFIG_BT_PAC_SRC */ + +#if defined(CONFIG_BT_PAC_SRC_LOC) + /** + * @brief Enables or disables registration of Source Location Characteristic. + * + * Registration of Source Location is dependent on @ref bt_bap_pacs_register_param.src_pac + * also being set. + */ + bool src_loc; +#endif /* CONFIG_BT_PAC_SRC_LOC */ +}; + /** * @typedef bt_pacs_cap_foreach_func_t * @brief Published Audio Capability iterator callback. @@ -71,6 +108,22 @@ void bt_pacs_cap_foreach(enum bt_audio_dir dir, bt_pacs_cap_foreach_func_t func, void *user_data); +/** + * @brief Register the Published Audio Capability Service instance. + * + * @param param PACS register parameters. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_pacs_register(const struct bt_bap_pacs_register_param *param); + +/** + * @brief Unregister the Published Audio Capability Service instance. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_pacs_unregister(void); + /** * @brief Register Published Audio Capability. * diff --git a/samples/bluetooth/bap_broadcast_sink/src/main.c b/samples/bluetooth/bap_broadcast_sink/src/main.c index 902670aaee56..c9bfc62ffca3 100644 --- a/samples/bluetooth/bap_broadcast_sink/src/main.c +++ b/samples/bluetooth/bap_broadcast_sink/src/main.c @@ -1272,8 +1272,13 @@ static struct bt_le_per_adv_sync_cb bap_pa_sync_cb = { .term = bap_pa_sync_terminated_cb, }; + static int init(void) { + const struct bt_bap_pacs_register_param pacs_param = { + .snk_pac = true, + .snk_loc = true, + }; int err; err = bt_enable(NULL); @@ -1284,6 +1289,12 @@ static int init(void) printk("Bluetooth initialized\n"); + err = bt_pacs_register(&pacs_param); + if (err) { + printk("Could not register PACS (err %d)\n", err); + return err; + } + err = bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap); if (err) { printk("Capability register failed (err %d)\n", err); diff --git a/samples/bluetooth/bap_unicast_server/src/main.c b/samples/bluetooth/bap_unicast_server/src/main.c index af31df408a12..c7e1c3ff4c92 100644 --- a/samples/bluetooth/bap_unicast_server/src/main.c +++ b/samples/bluetooth/bap_unicast_server/src/main.c @@ -721,9 +721,16 @@ static int set_available_contexts(void) return 0; } + int main(void) { struct bt_le_ext_adv *adv; + const struct bt_bap_pacs_register_param pacs_param = { + .snk_pac = true, + .snk_loc = true, + .src_pac = true, + .src_loc = true + }; int err; err = bt_enable(NULL); @@ -734,6 +741,12 @@ int main(void) printk("Bluetooth initialized\n"); + err = bt_pacs_register(&pacs_param); + if (err) { + printk("Could not register PACS (err %d)\n", err); + return 0; + } + bt_bap_unicast_server_register(¶m); bt_bap_unicast_server_register_cb(&unicast_server_cb); diff --git a/samples/bluetooth/cap_acceptor/src/main.c b/samples/bluetooth/cap_acceptor/src/main.c index 37ba41d32ec8..cd07ed08eb99 100644 --- a/samples/bluetooth/cap_acceptor/src/main.c +++ b/samples/bluetooth/cap_acceptor/src/main.c @@ -256,6 +256,12 @@ static int init_cap_acceptor(void) static const struct bt_audio_codec_cap lc3_codec_cap = BT_AUDIO_CODEC_CAP_LC3( SUPPORTED_FREQ, SUPPORTED_DURATION, MAX_CHAN_PER_STREAM, MIN_SDU, MAX_SDU, FRAMES_PER_SDU, (SINK_CONTEXT | SOURCE_CONTEXT)); + const struct bt_bap_pacs_register_param pacs_param = { + .snk_pac = true, + .snk_loc = true, + .src_pac = true, + .src_loc = true + }; int err; err = bt_enable(NULL); @@ -267,6 +273,12 @@ static int init_cap_acceptor(void) LOG_INF("Bluetooth initialized"); + err = bt_pacs_register(&pacs_param); + if (err) { + LOG_ERR("Could not register PACS (err %d)", err); + return 0; + } + if (IS_ENABLED(CONFIG_BT_PAC_SNK)) { static struct bt_pacs_cap sink_cap = { .codec_cap = &lc3_codec_cap, diff --git a/samples/bluetooth/hap_ha/src/bap_unicast_sr.c b/samples/bluetooth/hap_ha/src/bap_unicast_sr.c index 6c8cd6fd862a..4e486ac1190f 100644 --- a/samples/bluetooth/hap_ha/src/bap_unicast_sr.c +++ b/samples/bluetooth/hap_ha/src/bap_unicast_sr.c @@ -405,6 +405,20 @@ static struct bt_pacs_cap cap_source = { int bap_unicast_sr_init(void) { + const struct bt_bap_pacs_register_param pacs_param = { + .snk_pac = true, + .snk_loc = true, + .src_pac = true, + .src_loc = true + }; + int err; + + err = bt_pacs_register(&pacs_param); + if (err) { + printk("Could not register PACS (err %d)\n", err); + return err; + } + bt_bap_unicast_server_register(¶m); bt_bap_unicast_server_register_cb(&unicast_server_cb); diff --git a/samples/bluetooth/tmap_bmr/src/bap_broadcast_sink.c b/samples/bluetooth/tmap_bmr/src/bap_broadcast_sink.c index 9c2994f99976..1f18e5834fc7 100644 --- a/samples/bluetooth/tmap_bmr/src/bap_broadcast_sink.c +++ b/samples/bluetooth/tmap_bmr/src/bap_broadcast_sink.c @@ -313,8 +313,18 @@ static int reset(void) int bap_broadcast_sink_init(void) { + const struct bt_bap_pacs_register_param pacs_param = { + .snk_pac = true, + .snk_loc = true, + }; int err; + err = bt_pacs_register(&pacs_param); + if (err) { + printk("Could not register PACS (err %d)\n", err); + return err; + } + bt_bap_broadcast_sink_register_cb(&broadcast_sink_cbs); bt_le_per_adv_sync_cb_register(&broadcast_sync_cb); diff --git a/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c b/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c index 0aea8794f294..aa53b2a8e8ff 100644 --- a/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c +++ b/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c @@ -367,8 +367,23 @@ static struct bt_pacs_cap cap = { .codec_cap = &lc3_codec_cap, }; + int bap_unicast_sr_init(void) { + const struct bt_bap_pacs_register_param pacs_param = { + .snk_pac = true, + .snk_loc = true, + .src_pac = true, + .src_loc = true + }; + int err; + + err = bt_pacs_register(&pacs_param); + if (err) { + printk("Could not register PACS (err %d)\n", err); + return err; + } + bt_bap_unicast_server_register(¶m); bt_bap_unicast_server_register_cb(&unicast_server_cb); diff --git a/subsys/bluetooth/audio/pacs.c b/subsys/bluetooth/audio/pacs.c index d664c2051401..6fe080fca779 100644 --- a/subsys/bluetooth/audio/pacs.c +++ b/subsys/bluetooth/audio/pacs.c @@ -53,13 +53,13 @@ LOG_MODULE_REGISTER(bt_pacs, CONFIG_BT_PACS_LOG_LEVEL); #if defined(CONFIG_BT_PAC_SRC) static uint32_t pacs_src_location; -static sys_slist_t src_pacs_list = SYS_SLIST_STATIC_INIT(&src_pacs_list); +static sys_slist_t src_pac_list = SYS_SLIST_STATIC_INIT(&src_pac_list); static uint16_t src_supported_contexts; #endif /* CONFIG_BT_PAC_SRC */ #if defined(CONFIG_BT_PAC_SNK) static uint32_t pacs_snk_location; -static sys_slist_t snk_pacs_list = SYS_SLIST_STATIC_INIT(&snk_pacs_list); +static sys_slist_t snk_pac_list = SYS_SLIST_STATIC_INIT(&snk_pac_list); static uint16_t snk_supported_contexts; #endif /* CONFIG_BT_PAC_SNK */ @@ -77,7 +77,18 @@ enum { FLAG_NUM, }; -static struct pacs_client { +enum { + PACS_FLAG_REGISTERED, + PACS_FLAG_SVC_CHANGING, + PACS_FLAG_NOTIFY_RDY, + PACS_FLAG_SNK_PAC, + PACS_FLAG_SNK_LOC, + PACS_FLAG_SRC_PAC, + PACS_FLAG_SRC_LOC, + PACS_FLAG_NUM, +}; + +struct pacs_client { bt_addr_le_t addr; #if defined(CONFIG_BT_PAC_SNK) @@ -92,9 +103,14 @@ static struct pacs_client { /* Pending notification flags */ ATOMIC_DEFINE(flags, FLAG_NUM); -} clients[CONFIG_BT_MAX_PAIRED]; +}; + +static struct pacs { + atomic_t flags; + + struct pacs_client clients[CONFIG_BT_MAX_PAIRED]; +} pacs; -static atomic_t notify_rdy; static K_SEM_DEFINE(read_buf_sem, 1, 1); NET_BUF_SIMPLE_DEFINE_STATIC(read_buf, BT_ATT_MAX_ATTRIBUTE_LEN); @@ -117,10 +133,10 @@ static struct pacs_client *client_lookup_conn(const struct bt_conn *conn) { __ASSERT_NO_MSG(conn != NULL); - for (size_t i = 0; i < ARRAY_SIZE(clients); i++) { - if (atomic_test_bit(clients[i].flags, FLAG_ACTIVE) && - bt_addr_le_eq(&clients[i].addr, bt_conn_get_dst(conn))) { - return &clients[i]; + for (size_t i = 0; i < ARRAY_SIZE(pacs.clients); i++) { + if (atomic_test_bit(pacs.clients[i].flags, FLAG_ACTIVE) && + bt_addr_le_eq(&pacs.clients[i].addr, bt_conn_get_dst(conn))) { + return &pacs.clients[i]; } } @@ -129,9 +145,9 @@ static struct pacs_client *client_lookup_conn(const struct bt_conn *conn) static void pacs_set_notify_bit(int bit) { - for (size_t i = 0U; i < ARRAY_SIZE(clients); i++) { - if (atomic_test_bit(clients[i].flags, FLAG_ACTIVE)) { - atomic_set_bit(clients[i].flags, bit); + for (size_t i = 0U; i < ARRAY_SIZE(pacs.clients); i++) { + if (atomic_test_bit(pacs.clients[i].flags, FLAG_ACTIVE)) { + atomic_set_bit(pacs.clients[i].flags, bit); } } } @@ -226,14 +242,16 @@ static enum bt_audio_context pacs_get_available_contexts_for_conn(struct bt_conn switch (dir) { case BT_AUDIO_DIR_SINK: #if defined(CONFIG_BT_PAC_SNK) - if (client->snk_available_contexts != NULL) { + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SNK_PAC) && + client->snk_available_contexts != NULL) { return POINTER_TO_UINT(client->snk_available_contexts); } #endif /* CONFIG_BT_PAC_SNK */ break; case BT_AUDIO_DIR_SOURCE: #if defined(CONFIG_BT_PAC_SRC) - if (client->src_available_contexts != NULL) { + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SRC_PAC) && + client->src_available_contexts != NULL) { return POINTER_TO_UINT(client->src_available_contexts); } #endif /* CONFIG_BT_PAC_SRC */ @@ -273,11 +291,15 @@ static uint16_t supported_context_get(enum bt_audio_dir dir) switch (dir) { #if defined(CONFIG_BT_PAC_SNK) case BT_AUDIO_DIR_SINK: - return snk_supported_contexts | BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED; + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SNK_PAC)) { + return snk_supported_contexts | BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED; + } #endif /* CONFIG_BT_PAC_SNK */ #if defined(CONFIG_BT_PAC_SRC) case BT_AUDIO_DIR_SOURCE: - return src_supported_contexts | BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED; + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SRC_PAC)) { + return src_supported_contexts | BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED; + } #endif /* CONFIG_BT_PAC_SRC */ default: break; @@ -371,7 +393,7 @@ static ssize_t snk_read(struct bt_conn *conn, const struct bt_gatt_attr *attr, return BT_GATT_ERR(BT_ATT_ERR_INSUFFICIENT_RESOURCES); } - get_pac_records(&snk_pacs_list, &read_buf); + get_pac_records(&snk_pac_list, &read_buf); ret_val = bt_gatt_attr_read(conn, attr, buf, len, offset, read_buf.data, read_buf.len); @@ -415,15 +437,17 @@ static void snk_loc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value) static void set_snk_location(enum bt_audio_location audio_location) { - if (audio_location == pacs_snk_location) { - return; - } + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SNK_LOC)) { + if (audio_location == pacs_snk_location) { + return; + } - pacs_snk_location = audio_location; + pacs_snk_location = audio_location; - if (IS_ENABLED(CONFIG_BT_PAC_SNK_LOC_NOTIFIABLE)) { - pacs_set_notify_bit(FLAG_SINK_AUDIO_LOCATIONS_CHANGED); - k_work_submit(&deferred_nfy_work); + if (IS_ENABLED(CONFIG_BT_PAC_SNK_LOC_NOTIFIABLE)) { + pacs_set_notify_bit(FLAG_SINK_AUDIO_LOCATIONS_CHANGED); + k_work_submit(&deferred_nfy_work); + } } } #else @@ -476,7 +500,7 @@ static ssize_t src_read(struct bt_conn *conn, const struct bt_gatt_attr *attr, return BT_GATT_ERR(BT_ATT_ERR_INSUFFICIENT_RESOURCES); } - get_pac_records(&src_pacs_list, &read_buf); + get_pac_records(&src_pac_list, &read_buf); ret_val = bt_gatt_attr_read(conn, attr, buf, len, offset, read_buf.data, read_buf.len); @@ -520,15 +544,17 @@ static void src_loc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value) static void set_src_location(enum bt_audio_location audio_location) { - if (audio_location == pacs_src_location) { - return; - } + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SRC_LOC)) { + if (audio_location == pacs_src_location) { + return; + } - pacs_src_location = audio_location; + pacs_src_location = audio_location; - if (IS_ENABLED(CONFIG_BT_PAC_SRC_LOC_NOTIFIABLE)) { - pacs_set_notify_bit(FLAG_SOURCE_AUDIO_LOCATIONS_CHANGED); - k_work_submit(&deferred_nfy_work); + if (IS_ENABLED(CONFIG_BT_PAC_SRC_LOC_NOTIFIABLE)) { + pacs_set_notify_bit(FLAG_SOURCE_AUDIO_LOCATIONS_CHANGED); + k_work_submit(&deferred_nfy_work); + } } } #else @@ -566,22 +592,29 @@ static ssize_t src_loc_write(struct bt_conn *conn, #endif /* CONFIG_BT_PAC_SRC_LOC_WRITEABLE */ -static sys_slist_t *pacs_get(enum bt_audio_dir dir) +static sys_slist_t *pacs_get_pac(enum bt_audio_dir dir) { switch (dir) { #if defined(CONFIG_BT_PAC_SNK) case BT_AUDIO_DIR_SINK: - return &snk_pacs_list; + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SNK_PAC)) { + return &snk_pac_list; + } + return NULL; #endif /* CONFIG_BT_PAC_SNK */ #if defined(CONFIG_BT_PAC_SRC) case BT_AUDIO_DIR_SOURCE: - return &src_pacs_list; + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SRC_PAC)) { + return &src_pac_list; + } + return NULL; #endif /* CONFIG_BT_PAC_SRC */ default: return NULL; } } +#if defined(CONFIG_BT_PAC_SNK) #define BT_PACS_SNK_PROP \ BT_GATT_CHRC_READ \ IF_ENABLED(CONFIG_BT_PAC_SNK_LOC_NOTIFIABLE, (|BT_GATT_CHRC_NOTIFY)) @@ -609,7 +642,12 @@ static sys_slist_t *pacs_get(enum bt_audio_dir dir) COND_CODE_1(CONFIG_BT_PAC_SNK_LOC_WRITEABLE, (snk_loc_write), (NULL)), \ NULL), \ IF_ENABLED(CONFIG_BT_PAC_SNK_LOC_NOTIFIABLE, (BT_AUDIO_CCC(snk_loc_cfg_changed),)) +#else +#define BT_PAC_SNK(_read) +#define BT_PACS_SNK_LOC(_read) +#endif +#if defined(CONFIG_BT_PAC_SRC) #define BT_PACS_SRC_PROP \ BT_GATT_CHRC_READ \ IF_ENABLED(CONFIG_BT_PAC_SRC_LOC_NOTIFIABLE, (|BT_GATT_CHRC_NOTIFY)) @@ -637,6 +675,10 @@ static sys_slist_t *pacs_get(enum bt_audio_dir dir) COND_CODE_1(CONFIG_BT_PAC_SRC_LOC_WRITEABLE, (src_loc_write), (NULL)), \ NULL), \ IF_ENABLED(CONFIG_BT_PAC_SRC_LOC_NOTIFIABLE, (BT_AUDIO_CCC(src_loc_cfg_changed),)) +#else +#define BT_PAC_SRC(_read) +#define BT_PACS_SRC_LOC(_read) +#endif #define BT_PAC_AVAILABLE_CONTEXT(_read) \ BT_AUDIO_CHRC(BT_UUID_PACS_AVAILABLE_CONTEXT, \ @@ -657,23 +699,165 @@ static sys_slist_t *pacs_get(enum bt_audio_dir dir) IF_ENABLED(CONFIG_BT_PACS_SUPPORTED_CONTEXT_NOTIFIABLE, \ (BT_AUDIO_CCC(supported_context_cfg_changed),)) -BT_GATT_SERVICE_DEFINE(pacs_svc, - BT_GATT_PRIMARY_SERVICE(BT_UUID_PACS), +#define BT_PACS_SERVICE_DEFINITION() { \ + BT_GATT_PRIMARY_SERVICE(BT_UUID_PACS), \ + BT_PAC_SNK(snk_read) \ + BT_PACS_SNK_LOC(snk_loc_read) \ + BT_PAC_SRC(src_read) \ + BT_PACS_SRC_LOC(src_loc_read) \ + BT_PAC_AVAILABLE_CONTEXT(available_contexts_read) \ + BT_PAC_SUPPORTED_CONTEXT(supported_context_read) \ +} + +static struct bt_gatt_attr pacs_attrs[] = BT_PACS_SERVICE_DEFINITION(); +static struct bt_gatt_service pacs_svc = (struct bt_gatt_service)BT_GATT_SERVICE(pacs_attrs); + + + + +#if defined(BT_PAC_SNK_NOTIFIABLE) +#define PACS_SINK_PAC_CHAR_ATTR_COUNT 3 /* declaration + value + cccd */ +#else +#define PACS_SINK_PAC_CHAR_ATTR_COUNT 2 /* declaration + value */ +#endif /* BT_PAC_SNK_NOTIFIABLE */ + +#if defined(BT_PAC_SNK_LOC_NOTIFIABLE) +#define PACS_SINK_PAC_LOC_CHAR_ATTR_COUNT 3 /* declaration + value + cccd */ +#else +#define PACS_SINK_PAC_LOC_CHAR_ATTR_COUNT 2 /* declaration + value*/ +#endif /* BT_PAC_SNK_LOC_NOTIFIABLE */ + +#if defined(BT_PAC_SRC_NOTIFIABLE) +#define PACS_SOURCE_PAC_CHAR_ATTR_COUNT 3 /* declaration + value + cccd */ +#else +#define PACS_SOURCE_PAC_CHAR_ATTR_COUNT 2 /* declaration + value */ +#endif /* BT_PAC_SRC_NOTIFIABLE */ + +#if defined(BT_PAC_SRC_LOC_NOTIFIABLE) +#define PACS_SOURCE_PAC_LOC_CHAR_ATTR_COUNT 3 /* declaration + value + cccd */ +#else +#define PACS_SOURCE_PAC_LOC_CHAR_ATTR_COUNT 2 /* declaration + value*/ +#endif /* BT_PAC_SRC_LOC_NOTIFIABLE */ + +static void configure_pacs_char(const struct bt_bap_pacs_register_param *param) +{ + size_t attrs_to_rem; + uint8_t first_to_rem; + + /* Remove the Sink PAC and Location */ + if (!param->snk_pac) { + first_to_rem = 0; + attrs_to_rem = PACS_SINK_PAC_CHAR_ATTR_COUNT + PACS_SINK_PAC_LOC_CHAR_ATTR_COUNT; + } else if (!param->snk_loc) { + first_to_rem = PACS_SINK_PAC_CHAR_ATTR_COUNT; + attrs_to_rem = PACS_SINK_PAC_LOC_CHAR_ATTR_COUNT; + } else { + first_to_rem = pacs_svc.attr_count; + attrs_to_rem = 0; + } + + for (size_t i = first_to_rem + attrs_to_rem; i < pacs_svc.attr_count; i++) { + pacs_svc.attrs[i - attrs_to_rem] = pacs_svc.attrs[i]; + } + pacs_svc.attr_count -= attrs_to_rem; + + /* Set first_to_rem to the start of Source PAC Char, for cleaner offset calc */ + first_to_rem = PACS_SINK_PAC_CHAR_ATTR_COUNT + PACS_SINK_PAC_LOC_CHAR_ATTR_COUNT; + + /* Remove the Source PAC and Location */ + if (!param->snk_pac) { + first_to_rem -= attrs_to_rem; + attrs_to_rem = PACS_SOURCE_PAC_CHAR_ATTR_COUNT + + PACS_SOURCE_PAC_LOC_CHAR_ATTR_COUNT; + } else if (!param->snk_loc) { + first_to_rem = first_to_rem + PACS_SOURCE_PAC_CHAR_ATTR_COUNT - attrs_to_rem; + attrs_to_rem = PACS_SINK_PAC_LOC_CHAR_ATTR_COUNT; + } else { + return; + } + + for (size_t i = first_to_rem; i < pacs_svc.attr_count; i++) { + pacs_svc.attrs[i - attrs_to_rem] = pacs_svc.attrs[i]; + } + pacs_svc.attr_count -= attrs_to_rem; +} + +int bt_pacs_register(const struct bt_bap_pacs_register_param *param) +{ + int err = 0; + + if (atomic_test_and_set_bit(&pacs.flags, PACS_FLAG_REGISTERED)) { + LOG_DBG("PACS already registered"); + + return -EALREADY; + } + + /* Save registration param so we can guard functions accordingly */ #if defined(CONFIG_BT_PAC_SNK) - BT_PAC_SNK(snk_read) + atomic_set_bit_to(&pacs.flags, PACS_FLAG_SNK_PAC, param->snk_pac); +#endif /* CONFIG_BT_PAC_SNK */ #if defined(CONFIG_BT_PAC_SNK_LOC) - BT_PACS_SNK_LOC(snk_loc_read) + atomic_set_bit_to(&pacs.flags, PACS_FLAG_SNK_LOC, param->snk_loc); #endif /* CONFIG_BT_PAC_SNK_LOC */ -#endif /* CONFIG_BT_PAC_SNK */ #if defined(CONFIG_BT_PAC_SRC) - BT_PAC_SRC(src_read) + atomic_set_bit_to(&pacs.flags, PACS_FLAG_SRC_PAC, param->src_pac); +#endif /* CONFIG_BT_PAC_SRC */ #if defined(CONFIG_BT_PAC_SRC_LOC) - BT_PACS_SRC_LOC(src_loc_read) + atomic_set_bit_to(&pacs.flags, PACS_FLAG_SRC_LOC, param->src_loc); #endif /* CONFIG_BT_PAC_SRC_LOC */ -#endif /* CONFIG_BT_PAC_SRC */ - BT_PAC_AVAILABLE_CONTEXT(available_contexts_read) - BT_PAC_SUPPORTED_CONTEXT(supported_context_read) -); + + /* Remove characteristics if necessary */ + configure_pacs_char(param); + + err = bt_gatt_service_register(&pacs_svc); + if (err != 0) { + LOG_DBG("Failed to register ASCS in gatt DB"); + atomic_clear_bit(&pacs.flags, PACS_FLAG_REGISTERED); + + return err; + } + + return 0; +} + +int bt_pacs_unregister(void) +{ + int err; + struct bt_gatt_attr _pacs_attrs[] = BT_PACS_SERVICE_DEFINITION(); + + if (!atomic_test_bit(&pacs.flags, PACS_FLAG_REGISTERED)) { + LOG_DBG("No pacs instance registered"); + + return -EALREADY; + } + + if (atomic_test_and_set_bit(&pacs.flags, PACS_FLAG_SVC_CHANGING)) { + LOG_DBG("Service change already in progress"); + atomic_clear_bit(&pacs.flags, PACS_FLAG_SVC_CHANGING); + + return -EBUSY; + } + + err = bt_gatt_service_unregister(&pacs_svc); + + /* If unregistration was succesful, make sure to reset pacs_attrs so it can be used for + * new registrations + */ + if (err != 0) { + LOG_DBG("Failed to unregister PACS"); + atomic_clear_bit(&pacs.flags, PACS_FLAG_SVC_CHANGING); + + return err; + } + + memcpy(pacs_svc.attrs, &_pacs_attrs, sizeof(struct bt_gatt_attr)); + pacs_svc.attr_count = ARRAY_SIZE(pacs_attrs); + + atomic_clear_bit(&pacs.flags, PACS_FLAG_REGISTERED); + atomic_clear_bit(&pacs.flags, PACS_FLAG_SVC_CHANGING); + + return err; +} #if defined(CONFIG_BT_PAC_SNK_LOC_NOTIFIABLE) || defined(CONFIG_BT_PAC_SRC_LOC_NOTIFIABLE) static int pac_notify_loc(struct bt_conn *conn, enum bt_audio_dir dir) @@ -713,7 +897,7 @@ static int pac_notify_loc(struct bt_conn *conn, enum bt_audio_dir dir) static int pac_notify(struct bt_conn *conn, enum bt_audio_dir dir) { int err = 0; - sys_slist_t *pacs; + sys_slist_t *pac; const struct bt_uuid *uuid; switch (dir) { @@ -738,9 +922,9 @@ static int pac_notify(struct bt_conn *conn, enum bt_audio_dir dir) return err; } - pacs = pacs_get(dir); - __ASSERT(pacs, "Failed to get pacs.\n"); - get_pac_records(pacs, &read_buf); + pac = pacs_get_pac(dir); + __ASSERT(pac, "Failed to get pacs.\n"); + get_pac_records(pac, &read_buf); err = pacs_gatt_notify(conn, uuid, pacs_svc.attrs, read_buf.data, read_buf.len); @@ -799,7 +983,7 @@ static int supported_contexts_notify(struct bt_conn *conn) void pacs_gatt_notify_complete_cb(struct bt_conn *conn, void *user_data) { /* Notification done, clear bit and reschedule work */ - atomic_clear(¬ify_rdy); + atomic_clear_bit(&pacs.flags, PACS_FLAG_NOTIFY_RDY); k_work_submit(&deferred_nfy_work); } @@ -820,11 +1004,16 @@ static int pacs_gatt_notify(struct bt_conn *conn, params.func = pacs_gatt_notify_complete_cb; /* Mark notification in progress */ - atomic_set(¬ify_rdy, 1); + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SVC_CHANGING) || + !atomic_test_bit(&pacs.flags, PACS_FLAG_REGISTERED)) { + return 0; + } + + atomic_set_bit(&pacs.flags, PACS_FLAG_NOTIFY_RDY); err = bt_gatt_notify_cb(conn, ¶ms); if (err != 0) { - atomic_clear(¬ify_rdy); + atomic_clear_bit(&pacs.flags, PACS_FLAG_NOTIFY_RDY); } if (err && err != -ENOTCONN) { @@ -859,7 +1048,7 @@ static void notify_cb(struct bt_conn *conn, void *data) } /* Check if we have unverified notifications in progress */ - if (atomic_get(¬ify_rdy)) { + if (atomic_test_bit(&pacs.flags, PACS_FLAG_NOTIFY_RDY)) { return; } @@ -936,18 +1125,18 @@ static void pacs_auth_pairing_complete(struct bt_conn *conn, bool bonded) } /* Check if already in list, and do nothing if it is */ - for (size_t i = 0U; i < ARRAY_SIZE(clients); i++) { - if (atomic_test_bit(clients[i].flags, FLAG_ACTIVE) && - bt_addr_le_eq(bt_conn_get_dst(conn), &clients[i].addr)) { + for (size_t i = 0U; i < ARRAY_SIZE(pacs.clients); i++) { + if (atomic_test_bit(pacs.clients[i].flags, FLAG_ACTIVE) && + bt_addr_le_eq(bt_conn_get_dst(conn), &pacs.clients[i].addr)) { return; } } /* Else add the device */ - for (size_t i = 0U; i < ARRAY_SIZE(clients); i++) { - if (!atomic_test_bit(clients[i].flags, FLAG_ACTIVE)) { - atomic_set_bit(clients[i].flags, FLAG_ACTIVE); - memcpy(&clients[i].addr, bt_conn_get_dst(conn), sizeof(bt_addr_le_t)); + for (size_t i = 0U; i < ARRAY_SIZE(pacs.clients); i++) { + if (!atomic_test_bit(pacs.clients[i].flags, FLAG_ACTIVE)) { + atomic_set_bit(pacs.clients[i].flags, FLAG_ACTIVE); + memcpy(&pacs.clients[i].addr, bt_conn_get_dst(conn), sizeof(bt_addr_le_t)); /* Send out all pending notifications */ k_work_submit(&deferred_nfy_work); @@ -959,14 +1148,14 @@ static void pacs_auth_pairing_complete(struct bt_conn *conn, bool bonded) static void pacs_bond_deleted(uint8_t id, const bt_addr_le_t *peer) { /* Find the device entry to delete */ - for (size_t i = 0U; i < ARRAY_SIZE(clients); i++) { + for (size_t i = 0U; i < ARRAY_SIZE(pacs.clients); i++) { /* Check if match, and if active, if so, reset */ - if (atomic_test_bit(clients[i].flags, FLAG_ACTIVE) && - bt_addr_le_eq(peer, &clients[i].addr)) { + if (atomic_test_bit(pacs.clients[i].flags, FLAG_ACTIVE) && + bt_addr_le_eq(peer, &pacs.clients[i].addr)) { for (size_t j = 0U; j < FLAG_NUM; j++) { - atomic_clear_bit(clients[i].flags, j); + atomic_clear_bit(pacs.clients[i].flags, j); } - (void)memset(&clients[i].addr, 0, sizeof(bt_addr_le_t)); + (void)memset(&pacs.clients[i].addr, 0, sizeof(bt_addr_le_t)); return; } } @@ -985,9 +1174,9 @@ static void pacs_security_changed(struct bt_conn *conn, bt_security_t level, return; } - for (size_t i = 0U; i < ARRAY_SIZE(clients); i++) { + for (size_t i = 0U; i < ARRAY_SIZE(pacs.clients); i++) { for (size_t j = 0U; j < FLAG_NUM; j++) { - if (atomic_test_bit(clients[i].flags, j)) { + if (atomic_test_bit(pacs.clients[i].flags, j)) { /** * It's enough that one flag is set, as the defer work will go @@ -1010,7 +1199,8 @@ static void pacs_disconnected(struct bt_conn *conn, uint8_t reason) } #if defined(CONFIG_BT_PAC_SNK) - if (client->snk_available_contexts != NULL) { + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SNK_PAC) && + client->snk_available_contexts != NULL) { uint16_t old = POINTER_TO_UINT(client->snk_available_contexts); uint16_t new; @@ -1022,7 +1212,8 @@ static void pacs_disconnected(struct bt_conn *conn, uint8_t reason) #endif /* CONFIG_BT_PAC_SNK */ #if defined(CONFIG_BT_PAC_SRC) - if (client->src_available_contexts != NULL) { + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SRC_PAC) && + client->src_available_contexts != NULL) { uint16_t old = POINTER_TO_UINT(client->src_available_contexts); uint16_t new; @@ -1053,7 +1244,7 @@ void bt_pacs_cap_foreach(enum bt_audio_dir dir, bt_pacs_cap_foreach_func_t func, return; } - pac = pacs_get(dir); + pac = pacs_get_pac(dir); if (!pac) { return; } @@ -1063,14 +1254,14 @@ void bt_pacs_cap_foreach(enum bt_audio_dir dir, bt_pacs_cap_foreach_func_t func, static void add_bonded_addr_to_client_list(const struct bt_bond_info *info, void *data) { - for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) { + for (uint8_t i = 0; i < ARRAY_SIZE(pacs.clients); i++) { /* Check if device is registered, it not, add it */ - if (!atomic_test_bit(clients[i].flags, FLAG_ACTIVE)) { + if (!atomic_test_bit(pacs.clients[i].flags, FLAG_ACTIVE)) { char addr_str[BT_ADDR_LE_STR_LEN]; - atomic_set_bit(clients[i].flags, FLAG_ACTIVE); - memcpy(&clients[i].addr, &info->addr, sizeof(bt_addr_le_t)); - bt_addr_le_to_str(&clients[i].addr, addr_str, sizeof(addr_str)); + atomic_set_bit(pacs.clients[i].flags, FLAG_ACTIVE); + memcpy(&pacs.clients[i].addr, &info->addr, sizeof(bt_addr_le_t)); + bt_addr_le_to_str(&pacs.clients[i].addr, addr_str, sizeof(addr_str)); LOG_DBG("Added %s to bonded list\n", addr_str); return; } @@ -1090,7 +1281,7 @@ int bt_pacs_cap_register(enum bt_audio_dir dir, struct bt_pacs_cap *cap) codec_cap = cap->codec_cap; - pac = pacs_get(dir); + pac = pacs_get_pac(dir); if (!pac) { return -EINVAL; } @@ -1132,7 +1323,7 @@ int bt_pacs_cap_unregister(enum bt_audio_dir dir, struct bt_pacs_cap *cap) return -EINVAL; } - pac = pacs_get(dir); + pac = pacs_get_pac(dir); if (!pac) { return -EINVAL; } @@ -1181,13 +1372,22 @@ int bt_pacs_set_location(enum bt_audio_dir dir, enum bt_audio_location location) int bt_pacs_set_available_contexts(enum bt_audio_dir dir, enum bt_audio_context contexts) { + if (!atomic_test_bit(&pacs.flags, PACS_FLAG_REGISTERED)) { + return -EINVAL; + } switch (dir) { case BT_AUDIO_DIR_SINK: - return set_available_contexts(contexts, &snk_available_contexts, - supported_context_get(dir)); + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SNK_PAC)) { + return set_available_contexts(contexts, &snk_available_contexts, + supported_context_get(dir)); + } + return -EINVAL; case BT_AUDIO_DIR_SOURCE: - return set_available_contexts(contexts, &src_available_contexts, - supported_context_get(dir)); + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SRC_PAC)) { + return set_available_contexts(contexts, &src_available_contexts, + supported_context_get(dir)); + } + return -EINVAL; } return -EINVAL; @@ -1215,23 +1415,29 @@ int bt_pacs_conn_set_available_contexts_for_conn(struct bt_conn *conn, enum bt_a switch (dir) { #if defined(CONFIG_BT_PAC_SNK) case BT_AUDIO_DIR_SINK: - if (contexts != NULL) { - client->snk_available_contexts = UINT_TO_POINTER(*contexts); - } else { - client->snk_available_contexts = NULL; + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SNK_PAC)) { + if (contexts != NULL) { + client->snk_available_contexts = UINT_TO_POINTER(*contexts); + } else { + client->snk_available_contexts = NULL; + } + break; } - break; + return -EINVAL; #endif /* CONFIG_BT_PAC_SNK */ #if defined(CONFIG_BT_PAC_SRC) case BT_AUDIO_DIR_SOURCE: - if (contexts != NULL) { - client->src_available_contexts = UINT_TO_POINTER(*contexts); - } else { - client->src_available_contexts = NULL; + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SRC_PAC)) { + if (contexts != NULL) { + client->src_available_contexts = UINT_TO_POINTER(*contexts); + } else { + client->src_available_contexts = NULL; + } + break; } - break; + return -EINVAL; #endif /* CONFIG_BT_PAC_SRC */ default: return -EINVAL; @@ -1260,16 +1466,22 @@ int bt_pacs_set_supported_contexts(enum bt_audio_dir dir, enum bt_audio_context switch (dir) { case BT_AUDIO_DIR_SINK: #if defined(CONFIG_BT_PAC_SNK) - supported_contexts = &snk_supported_contexts; - available_contexts = &snk_available_contexts; - break; + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SNK_PAC)) { + supported_contexts = &snk_supported_contexts; + available_contexts = &snk_available_contexts; + break; + } + return -EINVAL; #endif /* CONFIG_BT_PAC_SNK */ return -ENOTSUP; case BT_AUDIO_DIR_SOURCE: #if defined(CONFIG_BT_PAC_SRC) - supported_contexts = &src_supported_contexts; - available_contexts = &src_available_contexts; - break; + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SRC_PAC)) { + supported_contexts = &src_supported_contexts; + available_contexts = &src_available_contexts; + break; + } + return -EINVAL; #endif /* CONFIG_BT_PAC_SRC */ return -ENOTSUP; default: @@ -1287,9 +1499,15 @@ enum bt_audio_context bt_pacs_get_available_contexts(enum bt_audio_dir dir) { switch (dir) { case BT_AUDIO_DIR_SINK: - return snk_available_contexts; + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SNK_PAC)) { + return snk_available_contexts; + } + return -EINVAL; case BT_AUDIO_DIR_SOURCE: - return src_available_contexts; + if (atomic_test_bit(&pacs.flags, PACS_FLAG_SRC_PAC)) { + return src_available_contexts; + } + return -EINVAL; } return BT_AUDIO_CONTEXT_TYPE_PROHIBITED; diff --git a/subsys/bluetooth/audio/shell/bap.c b/subsys/bluetooth/audio/shell/bap.c index 492c90e9024e..89d4f30b6205 100644 --- a/subsys/bluetooth/audio/shell/bap.c +++ b/subsys/bluetooth/audio/shell/bap.c @@ -3768,7 +3768,20 @@ static int cmd_init(const struct shell *sh, size_t argc, char *argv[]) CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT, CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT }; - + const struct bt_bap_pacs_register_param pacs_param = { +#if defined(CONFIG_BT_PAC_SNK) + .snk_pac = true, +#endif /* CONFIG_BT_PAC_SNK */ +#if defined(CONFIG_BT_PAC_SNK_LOC) + .snk_loc = true, +#endif /* CONFIG_BT_PAC_SNK_LOC */ +#if defined(CONFIG_BT_PAC_SRC) + .src_pac = true, +#endif /* CONFIG_BT_PAC_SRC */ +#if defined(CONFIG_BT_PAC_SRC_LOC) + .src_loc = true +#endif /* CONFIG_BT_PAC_SRC_LOC */ + }; if (argc == 3) { snk_cnt = shell_strtoul(argv[1], 0, &err); @@ -3795,8 +3808,14 @@ static int cmd_init(const struct shell *sh, size_t argc, char *argv[]) src_cnt = CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT; } - bt_bap_unicast_server_register(&unicast_server_param); - bt_bap_unicast_server_register_cb(&unicast_server_cb); + err = bt_pacs_register(&pacs_param); + __ASSERT(err == 0, "Failed to register PACS: %d", err); + + err = bt_bap_unicast_server_register(&unicast_server_param); + __ASSERT(err == 0, "Failed to register Unicast Server: %d", err); + + err = bt_bap_unicast_server_register_cb(&unicast_server_cb); + __ASSERT(err == 0, "Failed to register Unicast Server Callbacks: %d", err); #endif /* CONFIG_BT_BAP_UNICAST_SERVER */ #if defined(CONFIG_BT_PAC_SNK) diff --git a/tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c b/tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c index 27ec575e56b9..8cd470999503 100644 --- a/tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c @@ -627,6 +627,12 @@ static int init(void) static struct bt_pacs_cap vs_cap = { .codec_cap = &vs_codec_cap, }; + const struct bt_bap_pacs_register_param pacs_param = { + .snk_pac = true, + .snk_loc = true, + .src_pac = true, + .src_loc = true + }; int err; err = bt_enable(NULL); @@ -637,6 +643,12 @@ static int init(void) printk("Bluetooth initialized\n"); + err = bt_pacs_register(&pacs_param); + if (err) { + FAIL("Could not register PACS (err %d)\n", err); + return err; + } + err = bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap); if (err) { FAIL("Capability register failed (err %d)\n", err); diff --git a/tests/bsim/bluetooth/audio/src/bap_unicast_server_test.c b/tests/bsim/bluetooth/audio/src/bap_unicast_server_test.c index 406a1ce822cf..5cd7f74285bc 100644 --- a/tests/bsim/bluetooth/audio/src/bap_unicast_server_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_unicast_server_test.c @@ -407,6 +407,20 @@ static void init(void) static struct bt_pacs_cap cap = { .codec_cap = &lc3_codec_cap, }; + const struct bt_bap_pacs_register_param pacs_param = { +#if defined(CONFIG_BT_PAC_SNK) + .snk_pac = true, +#endif /* CONFIG_BT_PAC_SNK */ +#if defined(CONFIG_BT_PAC_SNK_LOC) + .snk_loc = true, +#endif /* CONFIG_BT_PAC_SNK_LOC */ +#if defined(CONFIG_BT_PAC_SRC) + .src_pac = true, +#endif /* CONFIG_BT_PAC_SRC */ +#if defined(CONFIG_BT_PAC_SRC_LOC) + .src_loc = true +#endif /* CONFIG_BT_PAC_SRC_LOC */ + }; int err; err = bt_enable(NULL); @@ -416,6 +430,13 @@ static void init(void) } printk("Bluetooth initialized\n"); + + err = bt_pacs_register(&pacs_param); + if (err) { + FAIL("Could not register PACS (err %d)\n", err); + return; + } + bap_stream_tx_init(); err = bt_bap_unicast_server_register(¶m); diff --git a/tests/bsim/bluetooth/audio/src/cap_acceptor_test.c b/tests/bsim/bluetooth/audio/src/cap_acceptor_test.c index f33a34b9f3b2..79f6a38940b8 100644 --- a/tests/bsim/bluetooth/audio/src/cap_acceptor_test.c +++ b/tests/bsim/bluetooth/audio/src/cap_acceptor_test.c @@ -648,6 +648,20 @@ static void init(void) BT_AUDIO_CODEC_CAP_FREQ_ANY, BT_AUDIO_CODEC_CAP_DURATION_ANY, BT_AUDIO_CODEC_CAP_CHAN_COUNT_SUPPORT(1, 2), 30, 240, 2, (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); + const struct bt_bap_pacs_register_param pacs_param = { +#if defined(CONFIG_BT_PAC_SNK) + .snk_pac = true, +#endif /* CONFIG_BT_PAC_SNK */ +#if defined(CONFIG_BT_PAC_SNK_LOC) + .snk_loc = true, +#endif /* CONFIG_BT_PAC_SNK_LOC */ +#if defined(CONFIG_BT_PAC_SRC) + .src_pac = true, +#endif /* CONFIG_BT_PAC_SRC */ +#if defined(CONFIG_BT_PAC_SRC_LOC) + .src_loc = true +#endif /* CONFIG_BT_PAC_SRC_LOC */ + }; int err; err = bt_enable(NULL); @@ -658,6 +672,12 @@ static void init(void) printk("Bluetooth initialized\n"); + err = bt_pacs_register(&pacs_param); + if (err) { + FAIL("Could not register PACS (err %d)\n", err); + return; + } + if (IS_ENABLED(CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER)) { err = bt_cap_acceptor_register(&csip_set_member_param, &csip_set_member); if (err != 0) { diff --git a/tests/bsim/bluetooth/audio/src/gmap_ugt_test.c b/tests/bsim/bluetooth/audio/src/gmap_ugt_test.c index d8c259199cab..330ca116b476 100644 --- a/tests/bsim/bluetooth/audio/src/gmap_ugt_test.c +++ b/tests/bsim/bluetooth/audio/src/gmap_ugt_test.c @@ -363,6 +363,20 @@ static void test_main(void) .codec_cap = &codec_cap, }; struct bt_le_ext_adv *ext_adv; + const struct bt_bap_pacs_register_param pacs_param = { +#if defined(CONFIG_BT_PAC_SNK) + .snk_pac = true, +#endif /* CONFIG_BT_PAC_SNK */ +#if defined(CONFIG_BT_PAC_SNK_LOC) + .snk_loc = true, +#endif /* CONFIG_BT_PAC_SNK_LOC */ +#if defined(CONFIG_BT_PAC_SRC) + .src_pac = true, +#endif /* CONFIG_BT_PAC_SRC */ +#if defined(CONFIG_BT_PAC_SRC_LOC) + .src_loc = true +#endif /* CONFIG_BT_PAC_SRC_LOC */ + }; int err; err = bt_enable(NULL); @@ -373,6 +387,12 @@ static void test_main(void) printk("Bluetooth initialized\n"); + err = bt_pacs_register(&pacs_param); + if (err) { + FAIL("Could not register PACS (err %d)\n", err); + return; + } + if (IS_ENABLED(CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER)) { const struct bt_csip_set_member_register_param csip_set_member_param = { .set_size = 2, diff --git a/tests/bsim/bluetooth/audio/src/pacs_notify_server_test.c b/tests/bsim/bluetooth/audio/src/pacs_notify_server_test.c index a9ebce0e73d5..58064823652f 100644 --- a/tests/bsim/bluetooth/audio/src/pacs_notify_server_test.c +++ b/tests/bsim/bluetooth/audio/src/pacs_notify_server_test.c @@ -159,6 +159,12 @@ static void test_main(void) int err; enum bt_audio_context available, available_for_conn; struct bt_le_ext_adv *ext_adv; + const struct bt_bap_pacs_register_param pacs_param = { + .snk_pac = true, + .snk_loc = true, + .src_pac = true, + .src_loc = true + }; LOG_DBG("Enabling Bluetooth"); err = bt_enable(NULL); @@ -167,6 +173,12 @@ static void test_main(void) return; } + err = bt_pacs_register(&pacs_param); + if (err) { + FAIL("Could not register PACS (err %d)\n", err); + return; + } + bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SINK, BT_AUDIO_CONTEXT_TYPE_ANY); bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SOURCE, BT_AUDIO_CONTEXT_TYPE_ANY); bt_pacs_set_available_contexts(BT_AUDIO_DIR_SINK, BT_AUDIO_CONTEXT_TYPE_ANY); diff --git a/tests/bsim/bluetooth/audio/src/pbp_public_broadcast_sink_test.c b/tests/bsim/bluetooth/audio/src/pbp_public_broadcast_sink_test.c index 0df8ae7c6099..fb7306895b08 100644 --- a/tests/bsim/bluetooth/audio/src/pbp_public_broadcast_sink_test.c +++ b/tests/bsim/bluetooth/audio/src/pbp_public_broadcast_sink_test.c @@ -197,6 +197,12 @@ static int reset(void) static int init(void) { + const struct bt_bap_pacs_register_param pacs_param = { + .snk_pac = true, + .snk_loc = true, + .src_pac = true, + .src_loc = true + }; int err; err = bt_enable(NULL); @@ -208,6 +214,12 @@ static int init(void) printk("Bluetooth initialized\n"); + err = bt_pacs_register(&pacs_param); + if (err) { + FAIL("Could not register PACS (err %d)\n", err); + return err; + } + bt_bap_broadcast_sink_register_cb(&broadcast_sink_cbs); bt_le_per_adv_sync_cb_register(&broadcast_sync_cb);