diff --git a/tests/bluetooth/tester/CMakeLists.txt b/tests/bluetooth/tester/CMakeLists.txt index ace7b33162..c49357db3b 100644 --- a/tests/bluetooth/tester/CMakeLists.txt +++ b/tests/bluetooth/tester/CMakeLists.txt @@ -86,3 +86,7 @@ endif() if(CONFIG_BT_CAP_INITIATOR) target_sources(app PRIVATE src/btp_cap.c) endif() + +if(CONFIG_BT_TBS OR CONFIG_BT_GTBS) + target_sources(app PRIVATE src/btp_ccp.c) +endif() diff --git a/tests/bluetooth/tester/overlay-le-audio.conf b/tests/bluetooth/tester/overlay-le-audio.conf index cb82a76533..2751787a40 100644 --- a/tests/bluetooth/tester/overlay-le-audio.conf +++ b/tests/bluetooth/tester/overlay-le-audio.conf @@ -18,7 +18,7 @@ CONFIG_BT_BUF_CMD_TX_SIZE=255 # When initiating Codec Config by server for 3 ASEs one by one, MTU buffers # were freed too slow. The bt_bap_stream_ops.configured callback comes earlier. -CONFIG_BT_L2CAP_TX_BUF_COUNT=4 +CONFIG_BT_L2CAP_TX_BUF_COUNT=10 # CAP CONFIG_BT_CAP_INITIATOR=y @@ -134,3 +134,9 @@ CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS=y CONFIG_MCTL_REMOTE_PLAYER_CONTROL=y CONFIG_BT_MPL=y CONFIG_UTF8=y + +#TBS +CONFIG_BT_GTBS=y +CONFIG_BT_TBS=y +CONFIG_BT_TBS_MAX_CALLS=10 +CONFIG_BT_TBS_SUPPORTED_FEATURES=3 diff --git a/tests/bluetooth/tester/src/btp/btp.h b/tests/bluetooth/tester/src/btp/btp.h index 3d8a7dc93f..adbaa3dee6 100644 --- a/tests/bluetooth/tester/src/btp/btp.h +++ b/tests/bluetooth/tester/src/btp/btp.h @@ -35,6 +35,7 @@ #include "btp_hap.h" #include "btp_csip.h" #include "btp_cap.h" +#include "btp_tbs.h" #define BTP_MTU 1024 #define BTP_DATA_MAX_SIZE (BTP_MTU - sizeof(struct btp_hdr)) @@ -69,8 +70,9 @@ #define BTP_SERVICE_ID_HAP 24 #define BTP_SERVICE_ID_CSIP 25 #define BTP_SERVICE_ID_CAP 26 +#define BTP_SERVICE_ID_TBS 27 -#define BTP_SERVICE_ID_MAX BTP_SERVICE_ID_CAP +#define BTP_SERVICE_ID_MAX BTP_SERVICE_ID_TBS #define BTP_STATUS_SUCCESS 0x00 #define BTP_STATUS_FAILED 0x01 diff --git a/tests/bluetooth/tester/src/btp/btp_tbs.h b/tests/bluetooth/tester/src/btp/btp_tbs.h new file mode 100644 index 0000000000..8f0adc3606 --- /dev/null +++ b/tests/bluetooth/tester/src/btp/btp_tbs.h @@ -0,0 +1,73 @@ +/* btp_mics.h - Bluetooth tester headers */ + +/* + * Copyright (c) 2024 Codecoup + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* TBS commands */ +#define BTP_TBS_READ_SUPPORTED_COMMANDS 0x01 +struct btp_tbs_read_supported_commands_rp { + uint8_t data[0]; +} __packed; + +#define BTP_TBS_REMOTE_INCOMING 0x02 +struct btp_tbs_remote_incoming_cmd { + uint8_t index; + uint8_t recv_len; + uint8_t caller_len; + uint8_t fn_len; + uint8_t data_len; + uint8_t data[0]; +} __packed; + +#define BTP_TBS_HOLD 0x03 +struct btp_tbs_hold_cmd { + uint8_t index; +} __packed; + +#define BTP_TBS_SET_BEARER_NAME 0x04 +struct btp_tbs_set_bearer_name_cmd { + uint8_t index; + uint8_t name_len; + uint8_t name[0]; +} __packed; + +#define BTP_TBS_SET_TECHNOLOGY 0x05 +struct btp_tbs_set_technology_cmd { + uint8_t index; + uint8_t tech; +} __packed; + +#define BTP_TBS_SET_URI_SCHEME 0x06 +struct btp_tbs_set_uri_schemes_list_cmd { + uint8_t index; + uint8_t uri_len; + uint8_t uri_count; + uint8_t uri_list[0]; +} __packed; + +#define BTP_TBS_SET_STATUS_FLAGS 0x07 +struct btp_tbs_set_status_flags_cmd { + uint8_t index; + uint16_t flags; +} __packed; + +#define BTP_TBS_REMOTE_HOLD 0x08 +struct btp_tbs_remote_hold_cmd { + uint8_t index; +} __packed; + +#define BTP_TBS_ORIGINATE 0x09 +struct btp_tbs_originate_cmd { + uint8_t index; + uint8_t uri_len; + uint8_t uri[0]; +} __packed; + +#define BTP_TBS_SET_SIGNAL_STRENGTH 0x0a +struct btp_tbs_set_signal_strength_cmd { + uint8_t index; + uint8_t strength; +} __packed; diff --git a/tests/bluetooth/tester/src/btp/bttester.h b/tests/bluetooth/tester/src/btp/bttester.h index bce0e10ed9..6b1c971a46 100644 --- a/tests/bluetooth/tester/src/btp/bttester.h +++ b/tests/bluetooth/tester/src/btp/bttester.h @@ -129,3 +129,6 @@ uint8_t tester_unregister_mcs(void); uint8_t tester_init_hap(void); uint8_t tester_unregister_hap(void); + +uint8_t tester_init_tbs(void); +uint8_t tester_unregister_tbs(void); diff --git a/tests/bluetooth/tester/src/btp_ccp.c b/tests/bluetooth/tester/src/btp_ccp.c index aad1431a88..bd58dea341 100644 --- a/tests/bluetooth/tester/src/btp_ccp.c +++ b/tests/bluetooth/tester/src/btp_ccp.c @@ -17,6 +17,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL); struct btp_ccp_chrc_handles_ev tbs_handles; struct bt_tbs_instance *tbs_inst; +static uint8_t call_index; static uint8_t inst_ccid; static bool send_ev; @@ -871,3 +872,300 @@ uint8_t tester_unregister_ccp(void) { return BTP_STATUS_SUCCESS; } + +/* Telephone Bearer Service */ +static uint8_t tbs_supported_commands(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + struct btp_tbs_read_supported_commands_rp *rp = rsp; + + /* octet 0 */ + tester_set_bit(rp->data, BTP_TBS_READ_SUPPORTED_COMMANDS); + tester_set_bit(rp->data, BTP_TBS_REMOTE_INCOMING); + tester_set_bit(rp->data, BTP_TBS_HOLD); + tester_set_bit(rp->data, BTP_TBS_SET_BEARER_NAME); + tester_set_bit(rp->data, BTP_TBS_SET_TECHNOLOGY); + tester_set_bit(rp->data, BTP_TBS_SET_URI_SCHEME); + tester_set_bit(rp->data, BTP_TBS_SET_STATUS_FLAGS); + + /* octet 1 */ + tester_set_bit(rp->data, BTP_TBS_REMOTE_HOLD); + tester_set_bit(rp->data, BTP_TBS_ORIGINATE); + tester_set_bit(rp->data, BTP_TBS_SET_SIGNAL_STRENGTH); + + *rsp_len = sizeof(*rp) + 2; + + return BTP_STATUS_SUCCESS; +} + +static uint8_t tbs_remote_incoming(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_tbs_remote_incoming_cmd *cp = cmd; + char friendly_name[CONFIG_BT_TBS_MAX_URI_LENGTH]; + char caller_uri[CONFIG_BT_TBS_MAX_URI_LENGTH]; + char recv_uri[CONFIG_BT_TBS_MAX_URI_LENGTH]; + int err; + + LOG_DBG(""); + + if ((cp->recv_len >= sizeof(recv_uri) || cp->caller_len >= sizeof(caller_uri)) || + cp->fn_len >= sizeof(friendly_name)) { + return BTP_STATUS_FAILED; + } + + memcpy(recv_uri, cp->data, cp->recv_len); + memcpy(caller_uri, cp->data + cp->recv_len, cp->caller_len); + memcpy(friendly_name, cp->data + cp->recv_len + cp->caller_len, cp->fn_len); + + recv_uri[cp->recv_len] = '\0'; + caller_uri[cp->caller_len] = '\0'; + friendly_name[cp->fn_len] = '\0'; + + err = bt_tbs_remote_incoming(cp->index, recv_uri, caller_uri, friendly_name); + if (err < 0) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t tbs_originate(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_tbs_originate_cmd *cp = cmd; + char uri[CONFIG_BT_TBS_MAX_URI_LENGTH]; + int err; + + LOG_DBG("TBS Originate Call"); + + if (cp->uri_len >= sizeof(uri)) { + return BTP_STATUS_FAILED; + } + + memcpy(uri, cp->uri, cp->uri_len); + uri[cp->uri_len] = '\0'; + + err = bt_tbs_originate(cp->index, uri, &call_index); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t tbs_hold(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_tbs_hold_cmd *cp = cmd; + int err; + + LOG_DBG("TBS Hold Call"); + + err = bt_tbs_hold(cp->index); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t tbs_remote_hold(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_tbs_remote_hold_cmd *cp = cmd; + int err; + + LOG_DBG("TBS Remote Hold Call"); + + err = bt_tbs_remote_hold(cp->index); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t tbs_set_bearer_name(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_tbs_set_bearer_name_cmd *cp = cmd; + char bearer_name[CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH]; + int err; + + LOG_DBG("TBS Set Bearer Provider Name"); + + if (cp->name_len >= sizeof(bearer_name)) { + return BTP_STATUS_FAILED; + } + + memcpy(bearer_name, cp->name, cp->name_len); + bearer_name[cp->name_len] = '\0'; + + err = bt_tbs_set_bearer_provider_name(cp->index, bearer_name); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t tbs_set_bearer_technology(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_tbs_set_technology_cmd *cp = cmd; + int err; + + LOG_DBG("TBS Set bearer technology"); + + err = bt_tbs_set_bearer_technology(cp->index, cp->tech); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t tbs_set_uri_scheme_list(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_tbs_set_uri_schemes_list_cmd *cp = cmd; + char uri_list[CONFIG_BT_TBS_MAX_SCHEME_LIST_LENGTH]; + char *uri_ptr = (char *)&uri_list; + int err; + + LOG_DBG("TBS Set Uri Scheme list"); + + if (cp->uri_len >= sizeof(uri_list)) { + return BTP_STATUS_FAILED; + } + + memcpy(uri_list, cp->uri_list, cp->uri_len); + uri_list[cp->uri_len] = '\0'; + + if (cp->uri_count > 1) { + /* TODO: currently supporting only one uri*/ + return BTP_STATUS_FAILED; + } + + err = bt_tbs_set_uri_scheme_list(cp->index, (const char **)&uri_ptr, cp->uri_count); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t tbs_set_status_flags(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_tbs_set_status_flags_cmd *cp = cmd; + uint16_t flags = sys_le16_to_cpu(cp->flags); + int err; + + LOG_DBG("TBS Set Status Flags"); + + err = bt_tbs_set_status_flags(cp->index, flags); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t tbs_set_signal_strength(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_tbs_set_signal_strength_cmd *cp = cmd; + int err; + + LOG_DBG("TBS Set Signal Strength"); + + err = bt_tbs_set_signal_strength(cp->index, cp->strength); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static bool btp_tbs_originate_call_cb(struct bt_conn *conn, uint8_t call_index, const char *uri) +{ + LOG_DBG("TBS Originate Call cb"); + + return true; +} + +static void btp_tbs_call_change_cb(struct bt_conn *conn, uint8_t call_index) +{ + LOG_DBG("TBS Call Status Changed cb"); +} + +static struct bt_tbs_cb tbs_cbs = { + .originate_call = btp_tbs_originate_call_cb, + .hold_call = btp_tbs_call_change_cb, +}; + +static const struct btp_handler tbs_handlers[] = { + { + .opcode = BTP_TBS_READ_SUPPORTED_COMMANDS, + .index = BTP_INDEX_NONE, + .expect_len = 0, + .func = tbs_supported_commands, + }, + { + .opcode = BTP_TBS_REMOTE_INCOMING, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = tbs_remote_incoming, + }, + { + .opcode = BTP_TBS_HOLD, + .expect_len = sizeof(struct btp_tbs_hold_cmd), + .func = tbs_hold, + }, + { + .opcode = BTP_TBS_SET_BEARER_NAME, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = tbs_set_bearer_name, + }, + { + .opcode = BTP_TBS_SET_TECHNOLOGY, + .expect_len = sizeof(struct btp_tbs_set_technology_cmd), + .func = tbs_set_bearer_technology, + }, + { + .opcode = BTP_TBS_SET_URI_SCHEME, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = tbs_set_uri_scheme_list, + }, + { + .opcode = BTP_TBS_SET_STATUS_FLAGS, + .expect_len = sizeof(struct btp_tbs_set_status_flags_cmd), + .func = tbs_set_status_flags, + }, + { + .opcode = BTP_TBS_REMOTE_HOLD, + .expect_len = sizeof(struct btp_tbs_remote_hold_cmd), + .func = tbs_remote_hold, + }, + { + .opcode = BTP_TBS_ORIGINATE, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = tbs_originate, + }, + { + .opcode = BTP_TBS_SET_SIGNAL_STRENGTH, + .expect_len = sizeof(struct btp_tbs_set_signal_strength_cmd), + .func = tbs_set_signal_strength, + }, +}; + +uint8_t tester_init_tbs(void) +{ + bt_tbs_register_cb(&tbs_cbs); + + tester_register_command_handlers(BTP_SERVICE_ID_TBS, tbs_handlers, + ARRAY_SIZE(tbs_handlers)); + + return BTP_STATUS_SUCCESS; +} + +uint8_t tester_unregister_tbs(void) +{ + return BTP_STATUS_SUCCESS; +} diff --git a/tests/bluetooth/tester/src/btp_core.c b/tests/bluetooth/tester/src/btp_core.c index 60a47d34bd..cb66fec9d3 100644 --- a/tests/bluetooth/tester/src/btp_core.c +++ b/tests/bluetooth/tester/src/btp_core.c @@ -101,6 +101,9 @@ static uint8_t supported_services(const void *cmd, uint16_t cmd_len, #if defined(CONFIG_BT_HAS) tester_set_bit(rp->data, BTP_SERVICE_ID_HAP); #endif /* CONFIG_BT_HAS */ +#if defined(CONFIG_BT_TBS) || defined(CONFIG_BT_GTBS) + tester_set_bit(rp->data, BTP_SERVICE_ID_TBS); +#endif /*CONFIG_BT_TBS */ *rsp_len = sizeof(*rp) + 2; @@ -229,6 +232,11 @@ static uint8_t register_service(const void *cmd, uint16_t cmd_len, status = tester_init_hap(); break; #endif /* CONFIG_BT_HAS */ +#if defined(CONFIG_BT_TBS) || defined(CONFIG_BT_GTBS) + case BTP_SERVICE_ID_TBS: + status = tester_init_tbs(); + break; +#endif /* CONFIG_BT_TBS */ default: LOG_WRN("unknown id: 0x%02x", cp->id); status = BTP_STATUS_FAILED; @@ -361,6 +369,11 @@ static uint8_t unregister_service(const void *cmd, uint16_t cmd_len, status = tester_unregister_hap(); break; #endif /* CONFIG_BT_HAS */ +#if defined(CONFIG_BT_TBS) + case BTP_SERVICE_ID_TBS: + status = tester_unregister_tbs(); + break; +#endif /* CONFIG_BT_TBS */ default: LOG_WRN("unknown id: 0x%x", cp->id); status = BTP_STATUS_FAILED;