diff --git a/include/zephyr/bluetooth/audio/tbs.h b/include/zephyr/bluetooth/audio/tbs.h index 7e64c34592bec0..6f408ff8174682 100644 --- a/include/zephyr/bluetooth/audio/tbs.h +++ b/include/zephyr/bluetooth/audio/tbs.h @@ -126,6 +126,8 @@ extern "C" { #define BT_TBS_FEATURE_HOLD BIT(0) /** Join Call Control Point Opcode supported */ #define BT_TBS_FEATURE_JOIN BIT(1) +/** All Control Point Opcodes supported */ +#define BT_TBS_FEATURE_ALL (BT_TBS_FEATURE_HOLD | BT_TBS_FEATURE_JOIN) /** @} */ /** @@ -247,8 +249,6 @@ typedef void (*bt_tbs_call_change_cb)(struct bt_conn *conn, /** * @brief Callback function for authorizing a client. * - * Only used if BT_TBS_AUTHORIZATION is enabled. - * * @param conn The connection used. * * @return true if authorized, false otherwise @@ -462,6 +462,98 @@ int bt_tbs_set_uri_scheme_list(uint8_t bearer_index, const char **uri_list, */ void bt_tbs_register_cb(struct bt_tbs_cb *cbs); +struct bt_tbs_register_param { + /** The name of the provider, for example a cellular service provider */ + char *provider_name; + + /** + * @brief The Uniform Caller Identifier of the bearer + * + * See the Uniform Caller Identifiers table in Bluetooth Assigned Numbers + */ + char *uci; + + /** + * The Uniform Resource Identifiers schemes supported by this bearer as an UTF-8 string + * + * See https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml for possible values. + * If multiple values are used, these shall be comma separated, e.g. "tel,skype". + */ + char *uri_schemes_supported; + + /** + * @brief Whether this bearer shall be registered as a Generic Telephone Bearer server + * + * A GTBS shall be registered before any non-GTBS services. There can only be a single GTBS + * registered. + */ + bool gtbs; + + /** + * @brief Whether the application will need to authorize changes to calls + * + * If set to false then the service will automatically accept write requests from clients. + */ + bool authorization_required; + + /** + * @brief The technology of the bearer + * + * See the BT_TBS_TECHNOLOGY_* values. + */ + uint8_t technology; + + /** + * @brief The optional supported features of the bearer + * + * See the BT_TBS_FEATURE_* values. + */ + uint8_t supported_features; +}; + +/** + * @brief Register a Telephone Bearer + * + * This will register a Telephone Bearer Service (TBS) (or a Generic Telephone Bearer service + * (GTBS)) with the provided parameters. + * + * As per the TBS specification, the GTBS shall be instantiated for the feature, and as such a GTBS + * shall always be registered before any TBS can be registered. + * Similarly, all TBS shall be unregistered before the GTBS can be unregistered with + * bt_tbs_unregister_bearer(). + * + * @param param The parameters to initialize the bearer. + + * @retval index The bearer index if return value is >= 0 + * @retval -EINVAL @p param contains invalid data + * @retval -EALREADY @p param.gtbs is true and GTBS has already been registered + * @retval -EAGAIN @p param.gtbs is false and GTBS has not been registered + * @retval -ENOMEM @p param.gtbs is false and no more TBS can be registered (see + * @kconfig{CONFIG_BT_TBS_BEARER_COUNT}) + * @retval -ENOEXEC The service failed to be registered + */ +int bt_tbs_register_bearer(const struct bt_tbs_register_param *param); + +/** + * @brief Unregister a Telephone Bearer + * + * This will unregister a Telephone Bearer Service (TBS) (or a Generic Telephone Bearer service + * (GTBS)) with the provided parameters. The bearer shall be registered first by + * bt_tbs_register_bearer() before it can be unregistered. + * + * Similarly, all TBS shall be unregistered before the GTBS can be unregistered with. + * + * @param bearer_index The index of the bearer to unregister. + * + * @retval 0 Success + * @retval -EINVAL @p bearer_index is invalid + * @retval -EALREADY The bearer identified by @p bearer_index is not registered + * @retval -EAGAIN The bearer identified by @p bearer_index is GTBS and there are TBS instances + * registered. + * @retval -ENOEXEC The service failed to be unregistered + */ +int bt_tbs_unregister_bearer(uint8_t bearer_index); + /** @brief Prints all calls of all services to the debug log */ void bt_tbs_dbg_print_calls(void); diff --git a/subsys/bluetooth/audio/Kconfig.tbs b/subsys/bluetooth/audio/Kconfig.tbs index 01de630df7631e..54275efa970230 100644 --- a/subsys/bluetooth/audio/Kconfig.tbs +++ b/subsys/bluetooth/audio/Kconfig.tbs @@ -22,70 +22,14 @@ config BT_TBS if BT_TBS -config BT_TBS_PROVIDER_NAME - string "Telephone Bearer Service Provider Name" - default "Unknown" - help - Sets the name of the service provider for the bearer. - -config BT_TBS_UCI - string "Telephone Bearer Service Uniform Caller Identifier (UCI)" - default "un000" - help - Sets the UCI of the bearer. See - https://www.bluetooth.com/specifications/assigned-numbers/uniform-caller-identifiers/ - for a table of valid UCIs. - -config BT_TBS_TECHNOLOGY - int "Telephone Bearer Service Technology" - range 1 10 - help - Sets the technology used for the bearer, e.g. GSM, LTE and 5G. - 1 : 3G - 2 : 4G - 3 : LTE - 4 : Wi-Fi - 5 : 5G - 6 : GSM - 7 : CDMA - 8 : 2G - 9 : WCDMA - 10: IP - -config BT_TBS_URI_SCHEMES_LIST - string "Telephone Bearer Service URI schemes Supported List" - default "tel,skype" - help - Sets a list of URI schemes that are supported by the bearer, - e.g. "tel" or "skype". - Multiple values shall be comma (,) separated, e.g. "tel,skype". - -config BT_TBS_SIGNAL_STRENGTH_INTERVAL - int "Telephone Bearer Service Signal Strength Reporting Interval" - default 0 - range 0 $(UINT8_MAX) - help - Sets the interval of reporting the signal strength in seconds. - If the value is 0, the signal will not be reported. - -config BT_TBS_STATUS_FLAGS - int "Telephone Bearer Service Features and Status value" - default 0 - range 0 3 - help - Bitfield to set feature and status flags. - Bit 0: In-band ringtone - Bit 1: Silent mode - Bits 2-15: Reserved for future use - config BT_TBS_SUPPORTED_FEATURES int "Telephone Bearer Service Supported Features" default 1 range 0 3 help Bitfield to set supported features of the bearer. - Bit 0: Local Hold and Retrieve - Bit 1: Join calls within Telephone Bearer Service + Bit 0: Local Hold and Retrieve + Bit 1: Join calls within Telephone Bearer Service config BT_TBS_MAX_CALLS int "Telephone Bearer Service Maximum Number Of Calls Supported" @@ -108,12 +52,6 @@ config BT_TBS_MAX_SCHEME_LIST_LENGTH help Sets the maximum length of the URI scheme list. -config BT_TBS_AUTHORIZATION - bool "TBS authorization requirement" - help - If set to true, then any writable characteristics will require - authorization per connection. - endif # BT_TBS diff --git a/subsys/bluetooth/audio/shell/tbs.c b/subsys/bluetooth/audio/shell/tbs.c index 6ea78cb61e03b5..eaafb16f249c31 100644 --- a/subsys/bluetooth/audio/shell/tbs.c +++ b/subsys/bluetooth/audio/shell/tbs.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -26,7 +27,6 @@ #include "host/shell/bt.h" static struct bt_conn *tbs_authorized_conn; -static bool cbs_registered; static bool tbs_authorize_cb(struct bt_conn *conn) { @@ -59,13 +59,64 @@ static int cmd_tbs_authorize(const struct shell *sh, size_t argc, char *argv[]) return 0; } -static int cmd_tbs_init(void) +static int cmd_tbs_init(const struct shell *sh, size_t argc, char *argv[]) { - if (!cbs_registered) { - bt_tbs_register_cb(&tbs_cbs); - cbs_registered = true; + static bool registered; + + if (registered) { + shell_info(sh, "Already initialized"); + + return -ENOEXEC; + } + + const struct bt_tbs_register_param gtbs_param = { + .provider_name = "Generic TBS", + .uci = "un000", + .uri_schemes_supported = "tel,skype", + .gtbs = true, + .authorization_required = false, + .technology = BT_TBS_TECHNOLOGY_3G, + .supported_features = CONFIG_BT_TBS_SUPPORTED_FEATURES, + }; + int err; + + err = bt_tbs_register_bearer(>bs_param); + if (err < 0) { + shell_error(sh, "Failed to register GTBS: %d", err); + + return -ENOEXEC; + } + + shell_info(sh, "Registered GTBS"); + + for (int i = 0; i < CONFIG_BT_TBS_BEARER_COUNT; i++) { + char prov_name[22]; /* Enough to store "Telephone Bearer #255" */ + const struct bt_tbs_register_param tbs_param = { + .provider_name = prov_name, + .uci = "un000", + .uri_schemes_supported = "tel,skype", + .gtbs = false, + .authorization_required = false, + /* Set different technologies per bearer */ + .technology = (i % BT_TBS_TECHNOLOGY_WCDMA) + 1, + .supported_features = CONFIG_BT_TBS_SUPPORTED_FEATURES, + }; + + snprintf(prov_name, sizeof(prov_name), "Telephone Bearer #%d", i); + + err = bt_tbs_register_bearer(&tbs_param); + if (err < 0) { + shell_error(sh, "Failed to register TBS[%d]: %d", i, err); + + return -ENOEXEC; + } + + shell_info(sh, "Registered TBS[%d] with index %u", i, (uint8_t)err); } + bt_tbs_register_cb(&tbs_cbs); + registered = true; + return 0; } diff --git a/subsys/bluetooth/audio/tbs.c b/subsys/bluetooth/audio/tbs.c index af958bd0462f2e..a978ab212dfc83 100644 --- a/subsys/bluetooth/audio/tbs.c +++ b/subsys/bluetooth/audio/tbs.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -65,6 +66,8 @@ struct tbs_inst { const struct bt_gatt_attr *attrs; /** Service Attribute count */ size_t attr_count; + + bool authorization_required; }; static struct tbs_inst svc_insts[CONFIG_BT_TBS_BEARER_COUNT]; @@ -82,6 +85,11 @@ static uint8_t held_calls_cnt; static struct bt_tbs_cb *tbs_cbs; +static bool inst_is_registered(const struct tbs_inst *inst) +{ + return inst->attrs != NULL; +} + static bool inst_is_gtbs(const struct tbs_inst *inst) { if (CONFIG_BT_TBS_BEARER_COUNT > 0) { @@ -109,15 +117,19 @@ static uint8_t inst_index(const struct tbs_inst *inst) static struct tbs_inst *inst_lookup_index(uint8_t index) { + struct tbs_inst *inst = NULL; + if (index == BT_TBS_GTBS_INDEX) { - return >bs_inst; + inst = >bs_inst; + } else if (ARRAY_SIZE(svc_insts) > 0U && index < ARRAY_SIZE(svc_insts)) { + inst = &svc_insts[index]; } - if (ARRAY_SIZE(svc_insts) > 0U && index < ARRAY_SIZE(svc_insts)) { - return &svc_insts[index]; + if (inst == NULL || !inst_is_registered(inst)) { + return NULL; } - return NULL; + return inst; } static struct bt_tbs_call *lookup_call_in_inst(struct tbs_inst *inst, uint8_t call_index) @@ -213,9 +225,9 @@ static struct tbs_inst *lookup_inst_by_call_index(uint8_t call_index) return NULL; } -static bool is_authorized(struct bt_conn *conn) +static bool is_authorized(const struct tbs_inst *inst, struct bt_conn *conn) { - if (IS_ENABLED(CONFIG_BT_TBS_AUTHORIZATION)) { + if (inst->authorization_required) { if (tbs_cbs != NULL && tbs_cbs->authorize != NULL) { return tbs_cbs->authorize(conn); } else { @@ -636,12 +648,8 @@ static ssize_t read_signal_strength_interval(struct bt_conn *conn, const struct { const struct tbs_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr); - if (!is_authorized(conn)) { - return BT_GATT_ERR(BT_ATT_ERR_AUTHORIZATION); - } - - LOG_DBG("Index %u: Signal strength interval 0x%02x", inst_index(inst), - inst->signal_strength_interval); + LOG_DBG("Index %u: Signal strength interval 0x%02x", + inst_index(inst), inst->signal_strength_interval); return bt_gatt_attr_read(conn, attr, buf, len, offset, &inst->signal_strength_interval, sizeof(inst->signal_strength_interval)); @@ -655,7 +663,7 @@ static ssize_t write_signal_strength_interval(struct bt_conn *conn, const struct struct net_buf_simple net_buf; uint8_t signal_strength_interval; - if (!is_authorized(conn)) { + if (!is_authorized(inst, conn)) { return BT_GATT_ERR(BT_ATT_ERR_AUTHORIZATION); } @@ -1115,7 +1123,7 @@ static ssize_t write_call_cp(struct bt_conn *conn, const struct bt_gatt_attr *at uint8_t call_index = 0; const bool is_gtbs = inst_is_gtbs(inst); - if (!is_authorized(conn)) { + if (!is_authorized(inst, conn)) { return BT_GATT_ERR(BT_ATT_ERR_AUTHORIZATION); } @@ -1474,7 +1482,8 @@ static void in_call_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value) BT_TBS_SERVICE_DEFINE(BT_UUID_TBS, &(_inst)) \ } -BT_GATT_SERVICE_DEFINE(gtbs_svc, BT_TBS_SERVICE_DEFINE(BT_UUID_GTBS, >bs_inst)); +static struct bt_gatt_service gtbs_svc = + BT_GATT_SERVICE(((struct bt_gatt_attr[]){BT_TBS_SERVICE_DEFINE(BT_UUID_GTBS, >bs_inst)})); BT_GATT_SERVICE_INSTANCE_DEFINE(tbs_service_list, svc_insts, CONFIG_BT_TBS_BEARER_COUNT, BT_TBS_SERVICE_DEFINITION); @@ -1499,58 +1508,220 @@ static void signal_interval_timeout(struct k_work *work) inst->pending_signal_strength_notification = false; } -static void tbs_inst_init(struct tbs_inst *inst, const struct bt_gatt_attr *attrs, - size_t attr_count, const char *provider_name) +static int tbs_inst_init_and_register(struct tbs_inst *inst, struct bt_gatt_service *svc, + const struct bt_tbs_register_param *param) { - LOG_DBG("inst %p index 0x%02x provider_name %s", inst, inst_index(inst), provider_name); + int err; + + LOG_DBG("inst %p index 0x%02x", inst, inst_index(inst)); inst->ccid = bt_ccid_get_value(); - (void)utf8_lcpy(inst->provider_name, provider_name, sizeof(inst->provider_name)); - (void)utf8_lcpy(inst->uci, CONFIG_BT_TBS_UCI, sizeof(inst->uci)); - inst->optional_opcodes = CONFIG_BT_TBS_SUPPORTED_FEATURES; - inst->technology = CONFIG_BT_TBS_TECHNOLOGY; - inst->signal_strength_interval = CONFIG_BT_TBS_SIGNAL_STRENGTH_INTERVAL; - inst->status_flags = CONFIG_BT_TBS_STATUS_FLAGS; - inst->attrs = attrs; - inst->attr_count = attr_count; + (void)utf8_lcpy(inst->provider_name, param->provider_name, sizeof(inst->provider_name)); + (void)utf8_lcpy(inst->uci, param->uci, sizeof(inst->uci)); + (void)utf8_lcpy(inst->uri_scheme_list, param->uri_schemes_supported, + sizeof(inst->uri_scheme_list)); + inst->optional_opcodes = param->supported_features; + inst->technology = param->technology; + inst->attrs = svc->attrs; + inst->attr_count = svc->attr_count; + inst->authorization_required = param->authorization_required; k_work_init_delayable(&inst->reporting_interval_work, signal_interval_timeout); + + err = bt_gatt_service_register(svc); + if (err != 0) { + LOG_DBG("Could not register %sTBS: %d", param->gtbs ? "G" : "", err); + memset(inst, 0, sizeof(*inst)); + + return err; + } + + return inst_index(inst); } -static void gtbs_service_inst_init(struct tbs_inst *inst, - const struct bt_gatt_service_static *service) +static int gtbs_service_inst_register(const struct bt_tbs_register_param *param) { - tbs_inst_init(inst, service->attrs, service->attr_count, "Generic TBS"); + return tbs_inst_init_and_register(>bs_inst, >bs_svc, param); } -static void tbs_service_inst_init(struct tbs_inst *inst, struct bt_gatt_service *service) +static int tbs_service_inst_register(const struct bt_tbs_register_param *param) { - tbs_inst_init(inst, service->attrs, service->attr_count, CONFIG_BT_TBS_PROVIDER_NAME); - (void)utf8_lcpy(inst->uri_scheme_list, CONFIG_BT_TBS_URI_SCHEMES_LIST, - sizeof(inst->uri_scheme_list)); + for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) { + struct tbs_inst *inst = &svc_insts[i]; + + if (!(inst_is_registered(inst))) { + return tbs_inst_init_and_register(inst, &tbs_service_list[i], param); + } + } + + return -ENOMEM; } -static int bt_tbs_init(void) +static bool valid_register_param(const struct bt_tbs_register_param *param) { - gtbs_service_inst_init(>bs_inst, >bs_svc); + size_t str_len; - for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) { - int err; + if (param == NULL) { + LOG_DBG("param is NULL"); - err = bt_gatt_service_register(&tbs_service_list[i]); - if (err != 0) { - LOG_ERR("Could not register TBS[%d]: %d", i, err); + return false; + } + + if (param->provider_name == NULL) { + LOG_DBG("provider_name is NULL"); + + return false; + } + + str_len = strlen(param->provider_name); + if (str_len > CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH) { + LOG_DBG("Provider name length (%zu) larger than " + "CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH %d", + str_len, CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH); + + return false; + } + + if (param->uci == NULL) { + LOG_DBG("uci is NULL"); + + return false; + } + + if (param->uri_schemes_supported == NULL) { + LOG_DBG("uri_schemes_supported is NULL"); + + return false; + } + + if (!IN_RANGE(param->technology, BT_TBS_TECHNOLOGY_3G, BT_TBS_TECHNOLOGY_WCDMA)) { + LOG_DBG("Invalid technology: %u", param->technology); + + return false; + } + + if (param->supported_features > BT_TBS_FEATURE_ALL) { + LOG_DBG("Invalid supported_features: %u", param->supported_features); + + return false; + } + + if (CONFIG_BT_TBS_BEARER_COUNT == 0 && !param->gtbs) { + LOG_DBG("Cannot register TBS when CONFIG_BT_TBS_BEARER_COUNT=0"); + + return false; + } + + return true; +} + +int bt_tbs_register_bearer(const struct bt_tbs_register_param *param) +{ + int ret; + + CHECKIF(!valid_register_param(param)) { + LOG_DBG("Invalid parameters"); + + return -EINVAL; + } + + if (param->gtbs && inst_is_registered(>bs_inst)) { + LOG_DBG("GTBS already registered"); + + return -EALREADY; + } + + if (!param->gtbs && !inst_is_registered(>bs_inst)) { + LOG_DBG("GTBS not yet registered"); + + return -EAGAIN; + } + + if (param->gtbs) { + ret = gtbs_service_inst_register(param); + if (ret < 0) { + LOG_DBG("Failed to register GTBS: %d", ret); + + return -ENOEXEC; } + } else if (CONFIG_BT_TBS_BEARER_COUNT > 0) { + ret = tbs_service_inst_register(param); + if (ret < 0) { + LOG_DBG("Failed to register GTBS: %d", ret); + + if (ret == -ENOMEM) { + return -ENOMEM; + } - tbs_service_inst_init(&svc_insts[i], &tbs_service_list[i]); + return -ENOEXEC; + } } - return 0; + /* ret will contain the index of the registered service */ + return ret; } -SYS_INIT(bt_tbs_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); +int bt_tbs_unregister_bearer(uint8_t bearer_index) +{ + struct tbs_inst *inst = inst_lookup_index(bearer_index); + struct bt_gatt_service *svc; + struct k_work_sync sync; + bool restart_reporting_interval; + int err; + + if (inst == NULL) { + LOG_DBG("Could not find inst by index %u", bearer_index); + + return -EINVAL; + } + + if (!inst_is_registered(inst)) { + LOG_DBG("Instance from index %u is not registered", bearer_index); + + return -EALREADY; + } + + if (inst_is_gtbs(inst)) { + for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) { + struct tbs_inst *tbs = &svc_insts[i]; + + if (inst_is_registered(tbs)) { + LOG_DBG("TBS[%u] is registered, please unregister all TBS first", + bearer_index); + return -EAGAIN; + } + } + svc = >bs_svc; + } else { + svc = &tbs_service_list[bearer_index]; + } + + restart_reporting_interval = + k_work_cancel_delayable_sync(&inst->reporting_interval_work, &sync); + + err = bt_gatt_service_unregister(svc); + if (err != 0) { + LOG_DBG("Failed to unregister service %p: %d", svc, err); + + if (restart_reporting_interval && inst->signal_strength_interval != 0U) { + /* In this unlikely scenario we may report interval later than expected if + * the k_work was cancelled right before it was set to trigger. It is not a + * big deal and not worth trying to reschedule in a way that it would + * trigger at the same time again, as specific timing over GATT is a wishful + * dream anyways + */ + k_work_schedule(&inst->reporting_interval_work, + K_SECONDS(inst->signal_strength_interval)); + } + + return -ENOEXEC; + } + + memset(inst, 0, sizeof(*inst)); + + return 0; +} -/***************************** Profile API *****************************/ int bt_tbs_accept(uint8_t call_index) { struct tbs_inst *inst = lookup_inst_by_call_index(call_index); diff --git a/tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c b/tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c index eebffc06a734e2..724623240372ec 100644 --- a/tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c +++ b/tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #include #include "bap_common.h" @@ -194,6 +196,27 @@ static void init(void) cap_stream_from_audio_test_stream(&broadcast_source_streams[i]); bt_cap_stream_ops_register(broadcast_streams[i], &broadcast_stream_ops); } + + if (IS_ENABLED(CONFIG_BT_TBS)) { + const struct bt_tbs_register_param gtbs_param = { + .provider_name = "Generic TBS", + .uci = "un000", + .uri_schemes_supported = "tel,skype", + .gtbs = true, + .authorization_required = false, + .technology = BT_TBS_TECHNOLOGY_3G, + .supported_features = CONFIG_BT_TBS_SUPPORTED_FEATURES, + }; + + err = bt_tbs_register_bearer(>bs_param); + if (err < 0) { + FAIL("Failed to register GTBS (err %d)\n", err); + + return; + } + + printk("Registered GTBS\n"); + } } static void setup_extended_adv(struct bt_le_ext_adv **adv) @@ -449,14 +472,15 @@ static void test_broadcast_audio_start(struct bt_cap_broadcast_source *broadcast static void test_broadcast_audio_update_inval(struct bt_cap_broadcast_source *broadcast_source) { - const uint16_t mock_ccid = 0xAB; const uint8_t new_metadata[] = { BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT, BT_BYTES_LIST_LE16(BT_AUDIO_CONTEXT_TYPE_MEDIA)), - BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_CCID_LIST, mock_ccid), + BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PARENTAL_RATING, + BT_AUDIO_PARENTAL_RATING_AGE_ANY), }; const uint8_t invalid_metadata[] = { - BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_CCID_LIST, mock_ccid), + BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PARENTAL_RATING, + BT_AUDIO_PARENTAL_RATING_AGE_ANY), }; int err; diff --git a/tests/bsim/bluetooth/audio/src/tbs_test.c b/tests/bsim/bluetooth/audio/src/tbs_test.c index e76d1ab4234111..ea96241db136c8 100644 --- a/tests/bsim/bluetooth/audio/src/tbs_test.c +++ b/tests/bsim/bluetooth/audio/src/tbs_test.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -327,22 +328,85 @@ static void test_tbs_server_only(void) test_set_status_flags(); } -static void test_main(void) +static void init(void) { + const struct bt_tbs_register_param gtbs_param = { + .provider_name = "Generic TBS", + .uci = "un000", + .uri_schemes_supported = "tel,skype", + .gtbs = true, + .authorization_required = false, + .technology = BT_TBS_TECHNOLOGY_3G, + .supported_features = CONFIG_BT_TBS_SUPPORTED_FEATURES, + }; int err; err = bt_enable(NULL); if (err != 0) { - printk("Bluetooth init failed (err %d)\n", err); + FAIL("Bluetooth enable failed (err %d)\n", err); + return; } - printk("Audio Client: Bluetooth initialized\n"); + printk("Bluetooth initialized\n"); + + err = bt_conn_cb_register(&conn_callbacks); + if (err != 0) { + FAIL("Failed to register conn CBs (err %d)\n", err); + + return; + } + + err = bt_le_scan_cb_register(&common_scan_cb); + if (err != 0) { + FAIL("Failed to register scan CBs (err %d)\n", err); + + return; + } - bt_conn_cb_register(&conn_callbacks); - bt_le_scan_cb_register(&common_scan_cb); bt_tbs_register_cb(&tbs_cbs); + err = bt_tbs_register_bearer(>bs_param); + if (err < 0) { + FAIL("Failed to register GTBS (err %d)\n", err); + + return; + } + + printk("Registered GTBS\n"); + + for (int i = 0; i < CONFIG_BT_TBS_BEARER_COUNT; i++) { + char prov_name[22]; /* Enough to store "Telephone Bearer #255" */ + const struct bt_tbs_register_param tbs_param = { + .provider_name = prov_name, + .uci = "un000", + .uri_schemes_supported = "tel,skype", + .gtbs = false, + .authorization_required = false, + /* Set different technologies per bearer */ + .technology = (i % BT_TBS_TECHNOLOGY_WCDMA) + 1, + .supported_features = CONFIG_BT_TBS_SUPPORTED_FEATURES, + }; + + snprintf(prov_name, sizeof(prov_name), "Telephone Bearer #%d", i); + + err = bt_tbs_register_bearer(&tbs_param); + if (err < 0) { + FAIL("Failed to register TBS[%d]: %d", i, err); + + return; + } + + printk("Registered TBS[%d] with index %u\n", i, (uint8_t)err); + } +} + +static void test_main(void) +{ + int err; + + init(); + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); if (err != 0) { FAIL("Scanning failed to start (err %d)\n", err); @@ -382,14 +446,7 @@ static void test_main(void) static void tbs_test_server_only(void) { - int err; - - err = bt_enable(NULL); - - if (err != 0) { - FAIL("Bluetooth init failed (err %d)\n", err); - return; - } + init(); test_tbs_server_only();