Bluetooth: Audio: Add Telephone Bearer Service server

Add the telephone bearer service server implementation.
This support multiple service instances as well as the
generic telephone bearer service, but is still a work in
progress and should be treated as such.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2021-11-26 20:01:29 +01:00 committed by Carles Cufí
commit 2a08b9e73c
7 changed files with 3408 additions and 0 deletions

View file

@ -0,0 +1,331 @@
/** @file
* @brief Public APIs for Bluetooth Telephone Bearer Service.
*
* Copyright (c) 2020 Bose Corporation
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_TBS_H_
#define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_TBS_H_
#include <zephyr/types.h>
#include <bluetooth/conn.h>
/* Call States */
#define BT_TBS_CALL_STATE_INCOMING 0x00
#define BT_TBS_CALL_STATE_DIALING 0x01
#define BT_TBS_CALL_STATE_ALERTING 0x02
#define BT_TBS_CALL_STATE_ACTIVE 0x03
#define BT_TBS_CALL_STATE_LOCALLY_HELD 0x04
#define BT_TBS_CALL_STATE_REMOTELY_HELD 0x05
#define BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD 0x06
/* Terminate Reason */
#define BT_TBS_REASON_BAD_REMOTE_URI 0x00
#define BT_TBS_REASON_CALL_FAILED 0x01
#define BT_TBS_REASON_REMOTE_ENDED_CALL 0x02
#define BT_TBS_REASON_SERVER_ENDED_CALL 0x03
#define BT_TBS_REASON_LINE_BUSY 0x04
#define BT_TBS_REASON_NETWORK_CONGESTED 0x05
#define BT_TBS_REASON_CLIENT_TERMINATED 0x06
#define BT_TBS_REASON_UNSPECIFIED 0x07
/* Application error codes */
#define BT_TBS_RESULT_CODE_SUCCESS 0x00
#define BT_TBS_RESULT_CODE_OPCODE_NOT_SUPPORTED 0x01
#define BT_TBS_RESULT_CODE_OPERATION_NOT_POSSIBLE 0x02
#define BT_TBS_RESULT_CODE_INVALID_CALL_INDEX 0x03
#define BT_TBS_RESULT_CODE_STATE_MISMATCH 0x04
#define BT_TBS_RESULT_CODE_OUT_OF_RESOURCES 0x05
#define BT_TBS_RESULT_CODE_INVALID_URI 0x06
#define BT_TBS_FEATURE_HOLD BIT(0)
#define BT_TBS_FEATURE_JOIN BIT(1)
#define BT_TBS_CALL_FLAG_SET_INCOMING(flag) (flag &= ~BIT(0))
#define BT_TBS_CALL_FLAG_SET_OUTGOING(flag) (flag |= BIT(0))
#define BT_TBS_SIGNAL_STRENGTH_NO_SERVICE 0
#define BT_TBS_SIGNAL_STRENGTH_MAX 100
#define BT_TBS_SIGNAL_STRENGTH_UNKNOWN 255
/* Bearer Technology */
#define BT_TBS_TECHNOLOGY_3G 0x01
#define BT_TBS_TECHNOLOGY_4G 0x02
#define BT_TBS_TECHNOLOGY_LTE 0x03
#define BT_TBS_TECHNOLOGY_WIFI 0x04
#define BT_TBS_TECHNOLOGY_5G 0x05
#define BT_TBS_TECHNOLOGY_GSM 0x06
#define BT_TBS_TECHNOLOGY_CDMA 0x07
#define BT_TBS_TECHNOLOGY_2G 0x08
#define BT_TBS_TECHNOLOGY_WCDMA 0x09
#define BT_TBS_TECHNOLOGY_IP 0x0a
/**
* @brief The GTBS index denotes whenever a callback is from a
* Generic Telephone Bearer Service (GTBS) instance, or
* whenever the client should perform on action on the GTBS instance of the
* server, rather than any of the specific Telephone Bearer Service instances.
*/
#define BT_TBS_GTBS_INDEX 0xFF
/**
* @brief Callback function for client originating a call.
*
* @param conn The connection used.
* @param call_index The call index.
* @param uri The URI. The value may change, so should be
* copied if persistence is wanted.
*
* @return true if the call request was accepted and remote party is alerted.
*/
typedef bool (*bt_tbs_originate_call_cb)(struct bt_conn *conn,
uint8_t call_index,
const char *uri);
/**
* @brief Callback function for client terminating a call.
*
* The call may be either terminated by the client or the server.
*
* @param conn The connection used.
* @param call_index The call index.
* @param reason The termination BT_TBS_REASON_* reason.
*/
typedef void (*bt_tbs_terminate_call_cb)(struct bt_conn *conn,
uint8_t call_index,
uint8_t reason);
/**
* @brief Callback function for client joining calls.
*
* @param conn The connection used.
* @param call_index_count The number of call indexes to join.
* @param call_indexes The call indexes.
*/
typedef void (*bt_tbs_join_calls_cb)(struct bt_conn *conn,
uint8_t call_index_count,
const uint8_t *call_indexes);
/**
* @brief Callback function for client request call state change
*
* @param conn The connection used.
* @param call_index The call index.
*/
typedef void (*bt_tbs_call_change_cb)(struct bt_conn *conn,
uint8_t call_index);
/**
* @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
*/
typedef bool (*bt_tbs_authorize_cb)(struct bt_conn *conn);
struct bt_tbs_cb {
bt_tbs_originate_call_cb originate_call;
bt_tbs_terminate_call_cb terminate_call;
bt_tbs_call_change_cb hold_call;
bt_tbs_call_change_cb accept_call;
bt_tbs_call_change_cb retrieve_call;
bt_tbs_join_calls_cb join_calls;
bt_tbs_authorize_cb authorize;
};
/**
* @brief Accept an alerting call.
*
* @param call_index The index of the call that will be accepted.
*
* @return int BT_TBS_RESULT_CODE_* if positive or 0,
* errno value if negative.
*/
int bt_tbs_accept(uint8_t call_index);
/**
* @brief Hold a call.
*
* @param call_index The index of the call that will be held.
*
* @return int BT_TBS_RESULT_CODE_* if positive or 0,
* errno value if negative.
*/
int bt_tbs_hold(uint8_t call_index);
/**
* @brief Retrieve a call.
*
* @param call_index The index of the call that will be retrieved.
*
* @return int BT_TBS_RESULT_CODE_* if positive or 0,
* errno value if negative.
*/
int bt_tbs_retrieve(uint8_t call_index);
/**
* @brief Terminate a call.
*
* @param call_index The index of the call that will be terminated.
*
* @return int BT_TBS_RESULT_CODE_* if positive or 0,
* errno value if negative.
*/
int bt_tbs_terminate(uint8_t call_index);
/**
* @brief Originate a call
*
* @param[in] bearer_index The index of the Telephone Bearer.
* @param[in] uri The remote URI.
* @param[out] call_index Pointer to a value where the new call_index will be
* stored.
*
* @return int A call index on success (positive value),
* errno value on fail.
*/
int bt_tbs_originate(uint8_t bearer_index, char *uri, uint8_t *call_index);
/**
* @brief Join calls
*
* @param call_index_cnt The number of call indexes to join
* @param call_indexes Array of call indexes to join.
*
* @return int BT_TBS_RESULT_CODE_* if positive or 0,
* errno value if negative.
*/
int bt_tbs_join(uint8_t call_index_cnt, uint8_t *call_indexes);
/**
* @brief Notify the server that the remote party answered the call.
*
* @param call_index The index of the call that was answered.
*
* @return int BT_TBS_RESULT_CODE_* if positive or 0,
* errno value if negative.
*/
int bt_tbs_remote_answer(uint8_t call_index);
/**
* @brief Notify the server that the remote party held the call.
*
* @param call_index The index of the call that was held.
*
* @return int BT_TBS_RESULT_CODE_* if positive or 0,
* errno value if negative.
*/
int bt_tbs_remote_hold(uint8_t call_index);
/**
* @brief Notify the server that the remote party retrieved the call.
*
* @param call_index The index of the call that was retrieved.
*
* @return int BT_TBS_RESULT_CODE_* if positive or 0,
* errno value if negative.
*/
int bt_tbs_remote_retrieve(uint8_t call_index);
/**
* @brief Notify the server that the remote party terminated the call.
*
* @param call_index The index of the call that was terminated.
*
* @return int BT_TBS_RESULT_CODE_* if positive or 0,
* errno value if negative.
*/
int bt_tbs_remote_terminate(uint8_t call_index);
/**
* @brief Notify the server of an incoming call.
*
* @param bearer_index The index of the Telephone Bearer.
* @param to The URI that is receiving the call.
* @param from The URI of the remote caller.
* @param friendly_name The friendly name of the remote caller.
*
* @return int New call index if positive or 0,
* errno value if negative.
*/
int bt_tbs_remote_incoming(uint8_t bearer_index, const char *to,
const char *from, const char *friendly_name);
/**
* @brief Set a new bearer provider.
*
* @param bearer_index The index of the Telephone Bearer or BT_TBS_GTBS_INDEX
* for GTBS.
* @param name The new bearer provider name.
*
* @return int BT_TBS_RESULT_CODE_* if positive or 0,
* errno value if negative.
*/
int bt_tbs_set_bearer_provider_name(uint8_t bearer_index, const char *name);
/**
* @brief Set a new bearer technology.
*
* @param bearer_index The index of the Telephone Bearer or BT_TBS_GTBS_INDEX
* for GTBS.
* @param new_technology The new bearer technology.
*
* @return int BT_TBS_RESULT_CODE_* if positive or 0,
* errno value if negative.
*/
int bt_tbs_set_bearer_technology(uint8_t bearer_index, uint8_t new_technology);
/**
* @brief Update the signal strength reported by the server.
*
* @param bearer_index The index of the Telephone Bearer or
* BT_TBS_GTBS_INDEX for GTBS.
* @param new_signal_strength The new signal strength.
*
* @return int BT_TBS_RESULT_CODE_* if positive or 0,
* errno value if negative.
*/
int bt_tbs_set_signal_strength(uint8_t bearer_index,
uint8_t new_signal_strength);
/**
* @brief Sets the feature and status value.
*
* @param bearer_index The index of the Telephone Bearer or BT_TBS_GTBS_INDEX
* for GTBS.
* @param status_flags The new feature and status value.
*
* @return int BT_TBS_RESULT_CODE_* if positive or 0,
* errno value if negative.
*/
int bt_tbs_set_status_flags(uint8_t bearer_index, uint16_t status_flags);
/** @brief Sets the URI scheme list of a bearer.
*
* @param bearer_index The index of the Telephone Bearer.
* @param uri_list List of URI prefixes (e.g. {"skype", "tel"}).
* @param uri_count Number of URI prefixies in @p uri_list.
*
* @return BT_TBS_RESULT_CODE_* if positive or 0, errno value if negative.
*/
int bt_tbs_set_uri_scheme_list(uint8_t bearer_index, const char **uri_list,
uint8_t uri_count);
/**
* @brief Register the callbacks for TBS.
*
* @param cbs Pointer to the callback structure.
*/
void bt_tbs_register_cb(struct bt_tbs_cb *cbs);
#if defined(CONFIG_BT_DEBUG_TBS)
/** @brief Prints all calls of all services to the debug log */
void bt_tbs_dbg_print_calls(void);
#endif /* defined(CONFIG_BT_DEBUG_TBS) */
#endif /* ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_TBS_H_ */

View file

@ -473,6 +473,24 @@ struct bt_uuid_128 {
*/ */
#define BT_UUID_GMCS \ #define BT_UUID_GMCS \
BT_UUID_DECLARE_16(BT_UUID_GMCS_VAL) BT_UUID_DECLARE_16(BT_UUID_GMCS_VAL)
/** @def BT_UUID_TBS_VAL
* @brief Telephone Bearer Service value
*/
#define BT_UUID_TBS_VAL 0x184B
/** @def BT_UUID_TBS
* @brief Telephone Bearer Service
*/
#define BT_UUID_TBS \
BT_UUID_DECLARE_16(BT_UUID_TBS_VAL)
/** @def BT_UUID_GTBS_VAL
* @brief Generic Telephone Bearer Service value
*/
#define BT_UUID_GTBS_VAL 0x184C
/** @def BT_UUID_GTBS
* @brief Generic Telephone Bearer Service
*/
#define BT_UUID_GTBS \
BT_UUID_DECLARE_16(BT_UUID_GTBS_VAL)
/** @def BT_UUID_MICS_VAL /** @def BT_UUID_MICS_VAL
* @brief Microphone Input Control Service value * @brief Microphone Input Control Service value
*/ */
@ -1826,6 +1844,69 @@ struct bt_uuid_128 {
*/ */
#define BT_UUID_OTS_TYPE_GROUP \ #define BT_UUID_OTS_TYPE_GROUP \
BT_UUID_DECLARE_16(BT_UUID_OTS_TYPE_GROUP_VAL) BT_UUID_DECLARE_16(BT_UUID_OTS_TYPE_GROUP_VAL)
/** @def BT_UUID_TBS_PROVIDER_NAME_VAL
* @brief Bearer Provider Name value
*/
#define BT_UUID_TBS_PROVIDER_NAME_VAL 0x2BB3
/** @def BT_UUID_TBS_PROVIDER_NAME
* @brief Bearer Provider Name
*/
#define BT_UUID_TBS_PROVIDER_NAME \
BT_UUID_DECLARE_16(BT_UUID_TBS_PROVIDER_NAME_VAL)
/** @def BT_UUID_TBS_UCI_VAL
* @brief Bearer UCI value
*/
#define BT_UUID_TBS_UCI_VAL 0x2BB4
/** @def BT_UUID_TBS_UCI
* @brief Bearer UCI
*/
#define BT_UUID_TBS_UCI \
BT_UUID_DECLARE_16(BT_UUID_TBS_UCI_VAL)
/** @def BT_UUID_TBS_TECHNOLOGY_VAL
* @brief Bearer Technology value
*/
#define BT_UUID_TBS_TECHNOLOGY_VAL 0x2BB5
/** @def BT_UUID_TBS_TECHNOLOGY
* @brief Bearer Technology
*/
#define BT_UUID_TBS_TECHNOLOGY \
BT_UUID_DECLARE_16(BT_UUID_TBS_TECHNOLOGY_VAL)
/** @def BT_UUID_TBS_URI_LIST_VAL
* @brief Bearer URI Prefixes Supported List value
*/
#define BT_UUID_TBS_URI_LIST_VAL 0x2BB6
/** @def BT_UUID_TBS_URI_LIST
* @brief Bearer URI Prefixes Supported List
*/
#define BT_UUID_TBS_URI_LIST \
BT_UUID_DECLARE_16(BT_UUID_TBS_URI_LIST_VAL)
/** @def BT_UUID_TBS_SIGNAL_STRENGTH_VAL
* @brief Bearer Signal Strength value
*/
#define BT_UUID_TBS_SIGNAL_STRENGTH_VAL 0x2BB7
/** @def BT_UUID_TBS_SIGNAL_STRENGTH
* @brief Bearer Signal Strength
*/
#define BT_UUID_TBS_SIGNAL_STRENGTH \
BT_UUID_DECLARE_16(BT_UUID_TBS_SIGNAL_STRENGTH_VAL)
/** @def BT_UUID_TBS_SIGNAL_INTERVAL_VAL
* @brief Bearer Signal Strength Reporting Interval value
*/
#define BT_UUID_TBS_SIGNAL_INTERVAL_VAL 0x2BB8
/** @def BT_UUID_TBS_SIGNAL_INTERVAL
* @brief Bearer Signal Strength Reporting Interval
*/
#define BT_UUID_TBS_SIGNAL_INTERVAL \
BT_UUID_DECLARE_16(BT_UUID_TBS_SIGNAL_INTERVAL_VAL)
/** @def BT_UUID_TBS_LIST_CURRENT_CALLS_VAL
* @brief Bearer List Current Calls value
*/
#define BT_UUID_TBS_LIST_CURRENT_CALLS_VAL 0x2BB9
/** @def BT_UUID_TBS_LIST_CURRENT_CALLS
* @brief Bearer List Current Calls
*/
#define BT_UUID_TBS_LIST_CURRENT_CALLS \
BT_UUID_DECLARE_16(BT_UUID_TBS_LIST_CURRENT_CALLS_VAL)
/** @def BT_UUID_CCID_VAL /** @def BT_UUID_CCID_VAL
* @brief Content Control ID value * @brief Content Control ID value
*/ */
@ -1835,6 +1916,78 @@ struct bt_uuid_128 {
*/ */
#define BT_UUID_CCID \ #define BT_UUID_CCID \
BT_UUID_DECLARE_16(BT_UUID_CCID_VAL) BT_UUID_DECLARE_16(BT_UUID_CCID_VAL)
/** @def BT_UUID_TBS_STATUS_FLAGS_VAL
* @brief Status flags value
*/
#define BT_UUID_TBS_STATUS_FLAGS_VAL 0x2BBB
/** @def BT_UUID_TBS_STATUS_FLAGS
* @brief Status flags
*/
#define BT_UUID_TBS_STATUS_FLAGS \
BT_UUID_DECLARE_16(BT_UUID_TBS_STATUS_FLAGS_VAL)
/** @def BT_UUID_TBS_INCOMING_URI_VAL
* @brief Incoming Call Target Caller ID value
*/
#define BT_UUID_TBS_INCOMING_URI_VAL 0x2BBC
/** @def BT_UUID_TBS_INCOMING_URI
* @brief Incoming Call Target Caller ID
*/
#define BT_UUID_TBS_INCOMING_URI \
BT_UUID_DECLARE_16(BT_UUID_TBS_INCOMING_URI_VAL)
/** @def BT_UUID_TBS_CALL_STATE_VAL
* @brief Call State value
*/
#define BT_UUID_TBS_CALL_STATE_VAL 0x2BBD
/** @def BT_UUID_TBS_CALL_STATE
* @brief Call State
*/
#define BT_UUID_TBS_CALL_STATE \
BT_UUID_DECLARE_16(BT_UUID_TBS_CALL_STATE_VAL)
/** @def BT_UUID_TBS_CALL_CONTROL_POINT_VAL
* @brief Call Control Point value
*/
#define BT_UUID_TBS_CALL_CONTROL_POINT_VAL 0x2BBE
/** @def BT_UUID_TBS_CALL_CONTROL_POINT
* @brief Call Control Point
*/
#define BT_UUID_TBS_CALL_CONTROL_POINT \
BT_UUID_DECLARE_16(BT_UUID_TBS_CALL_CONTROL_POINT_VAL)
/** @def BT_UUID_TBS_OPTIONAL_OPCODES_VAL
* @brief Optional Opcodes value
*/
#define BT_UUID_TBS_OPTIONAL_OPCODES_VAL 0x2BBF
/** @def BT_UUID_TBS_OPTIONAL_OPCODES
* @brief Optional Opcodes
*/
#define BT_UUID_TBS_OPTIONAL_OPCODES \
BT_UUID_DECLARE_16(BT_UUID_TBS_OPTIONAL_OPCODES_VAL)
/** BT_UUID_TBS_TERMINATE_REASON_VAL
* @brief Terminate reason value
*/
#define BT_UUID_TBS_TERMINATE_REASON_VAL 0x2BC0
/** BT_UUID_TBS_TERMINATE_REASON
* @brief Terminate reason
*/
#define BT_UUID_TBS_TERMINATE_REASON \
BT_UUID_DECLARE_16(BT_UUID_TBS_TERMINATE_REASON_VAL)
/** @def BT_UUID_TBS_INCOMING_CALL_VAL
* @brief Incoming Call value
*/
#define BT_UUID_TBS_INCOMING_CALL_VAL 0x2BC1
/** @def BT_UUID_TBS_INCOMING_CALL
* @brief Incoming Call
*/
#define BT_UUID_TBS_INCOMING_CALL \
BT_UUID_DECLARE_16(BT_UUID_TBS_INCOMING_CALL_VAL)
/** @def BT_UUID_TBS_FRIENDLY_NAME_VAL
* @brief Incoming Call Friendly name value
*/
#define BT_UUID_TBS_FRIENDLY_NAME_VAL 0x2BC2
/** @def BT_UUID_TBS_FRIENDLY_NAME
* @brief Incoming Call Friendly name
*/
#define BT_UUID_TBS_FRIENDLY_NAME \
BT_UUID_DECLARE_16(BT_UUID_TBS_FRIENDLY_NAME_VAL)
/** @def BT_UUID_MICS_MUTE_VAL /** @def BT_UUID_MICS_MUTE_VAL
* @brief Microphone Input Control Service Mute value * @brief Microphone Input Control Service Mute value
*/ */

View file

@ -32,6 +32,8 @@ if (CONFIG_BT_CSIS OR CONFIG_BT_CSIS_CLIENT)
zephyr_library_sources(csis_crypto.c) zephyr_library_sources(csis_crypto.c)
endif() endif()
zephyr_library_sources_ifdef(CONFIG_BT_TBS tbs.c)
zephyr_library_sources_ifdef(CONFIG_BT_MCC mcc.c) zephyr_library_sources_ifdef(CONFIG_BT_MCC mcc.c)
zephyr_library_sources_ifdef(CONFIG_BT_MCS mcs.c) zephyr_library_sources_ifdef(CONFIG_BT_MCS mcs.c)

View file

@ -31,6 +31,7 @@ rsource "Kconfig.aics"
rsource "Kconfig.vcs" rsource "Kconfig.vcs"
rsource "Kconfig.mics" rsource "Kconfig.mics"
rsource "Kconfig.csis" rsource "Kconfig.csis"
rsource "Kconfig.tbs"
rsource "Kconfig.mcs" rsource "Kconfig.mcs"
rsource "Kconfig.bass" rsource "Kconfig.bass"
rsource "Kconfig.has" rsource "Kconfig.has"

View file

@ -0,0 +1,154 @@
# Bluetooth Audio - Call control configuration options
#
# Copyright (c) 2020 Bose Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
if BT_AUDIO
##################### Telephone Bearer Service #####################
config BT_TBS
bool "Telephone Bearer Service Support"
select BT_CCID
help
This option enables support for Telephone Bearer Service.
if BT_TBS
# TODO: BT_GTBS is mandatory if you support the call control server role.
# Need to enforce this.
config BT_GTBS
bool "Generic Telephone Bearer Service Support"
default y
help
This option enables support for Generic Telephone Bearer Service.
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 255
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
config BT_TBS_MAX_CALLS
int "Telephone Bearer Service Maximum Number Of Calls Supported"
default 3
range 1 16
help
Sets the maximum number of calls the service supports per bearer.
config BT_TBS_BEARER_COUNT
int "How many bearer instances the device instantiates"
default 1
range 1 255
help
Sets the number of TBS instances that are instantiated
config BT_TBS_SERVICE_COUNT
int "Number of instantiated bearer service instances"
default BT_TBS_BEARER_COUNT
range 0 BT_TBS_BEARER_COUNT if BT_GTBS
range BT_TBS_BEARER_COUNT BT_TBS_BEARER_COUNT
help
Sets the number of TBS service instances that are instantiated
config BT_TBS_MAX_SCHEME_LIST_LENGTH
int "The maximum length of the URI scheme list"
default 30
range 0 512
help
Sets the maximum length of the URI scheme list. If BT_GTBS is enabled,
then the maximum length should be maximum 512 / BT_TBS_BEARER_COUNT.
config BT_TBS_AUTHORIZATION
bool "TBS authorization requirement"
help
If set to true, then any writable characteristics will require
authorization per connection.
config BT_TBS_MAX_URI_LENGTH
int "The maximum length of the call URI supported"
default 30
range 4 253
help
Sets the maximum length of the call URI supported. Note that if this
value is lower than a call URI, the call request will be rejected.
config BT_TBS_MAX_PROVIDER_NAME_LENGTH
int "The maximum length of the bearer provider name"
default 30
range 0 512
help
Sets the maximum length of the bearer provider name.
############# DEBUG #############
config BT_DEBUG_TBS
bool "Telephone Bearer Service debug"
help
Use this option to enable Telephone Bearer Service debug logs for the
Bluetooth Audio functionality.
endif # BT_TBS
endif # BT_AUDIO

2484
subsys/bluetooth/audio/tbs.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,283 @@
/** @file
* @brief Internal APIs for Bluetooth TBS.
*/
/*
* Copyright (c) 2019 Bose Corporation
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/types.h>
#include <bluetooth/audio/tbs.h>
#define BT_TBS_MAX_UCI_SIZE 6
#define BT_TBS_MIN_URI_LEN 3 /* a:b */
#define BT_TBS_FREE_CALL_INDEX 0
/* Call Control Point Opcodes */
#define BT_TBS_CALL_OPCODE_ACCEPT 0x00
#define BT_TBS_CALL_OPCODE_TERMINATE 0x01
#define BT_TBS_CALL_OPCODE_HOLD 0x02
#define BT_TBS_CALL_OPCODE_RETRIEVE 0x03
#define BT_TBS_CALL_OPCODE_ORIGINATE 0x04
#define BT_TBS_CALL_OPCODE_JOIN 0x05
/* Local Control Points - Used to do local control operations but still being
* able to determine if it is a local or remote operation
*/
#define BT_TBS_LOCAL_OPCODE_ANSWER 0x80
#define BT_TBS_LOCAL_OPCODE_HOLD 0x81
#define BT_TBS_LOCAL_OPCODE_RETRIEVE 0x82
#define BT_TBS_LOCAL_OPCODE_TERMINATE 0x83
#define BT_TBS_LOCAL_OPCODE_INCOMING 0x84
#define BT_TBS_LOCAL_OPCODE_SERVER_TERMINATE 0x85
#define FIRST_PRINTABLE_ASCII_CHAR ' ' /* space */
static inline const char *bt_tbs_state_str(uint8_t state)
{
switch (state) {
case BT_TBS_CALL_STATE_INCOMING:
return "incoming";
case BT_TBS_CALL_STATE_DIALING:
return "dialing";
case BT_TBS_CALL_STATE_ALERTING:
return "alerting";
case BT_TBS_CALL_STATE_ACTIVE:
return "active";
case BT_TBS_CALL_STATE_LOCALLY_HELD:
return "locally held";
case BT_TBS_CALL_STATE_REMOTELY_HELD:
return "remote held";
case BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD:
return "locally and remotely held";
default:
return "unknown";
}
}
static inline const char *bt_tbs_opcode_str(uint8_t opcode)
{
switch (opcode) {
case BT_TBS_CALL_OPCODE_ACCEPT:
return "accept";
case BT_TBS_CALL_OPCODE_TERMINATE:
return "terminate";
case BT_TBS_CALL_OPCODE_HOLD:
return "hold";
case BT_TBS_CALL_OPCODE_RETRIEVE:
return "retrieve";
case BT_TBS_CALL_OPCODE_ORIGINATE:
return "originate";
case BT_TBS_CALL_OPCODE_JOIN:
return "join";
case BT_TBS_LOCAL_OPCODE_ANSWER:
return "remote answer";
case BT_TBS_LOCAL_OPCODE_HOLD:
return "remote hold";
case BT_TBS_LOCAL_OPCODE_RETRIEVE:
return "remote retrieve";
case BT_TBS_LOCAL_OPCODE_TERMINATE:
return "remote terminate";
case BT_TBS_LOCAL_OPCODE_INCOMING:
return "remote incoming";
case BT_TBS_LOCAL_OPCODE_SERVER_TERMINATE:
return "server terminate";
default:
return "unknown";
}
}
static inline const char *bt_tbs_status_str(uint8_t status)
{
switch (status) {
case BT_TBS_RESULT_CODE_SUCCESS:
return "success";
case BT_TBS_RESULT_CODE_OPCODE_NOT_SUPPORTED:
return "opcode not supported";
case BT_TBS_RESULT_CODE_OPERATION_NOT_POSSIBLE:
return "operation not possible";
case BT_TBS_RESULT_CODE_INVALID_CALL_INDEX:
return "invalid call index";
case BT_TBS_RESULT_CODE_STATE_MISMATCH:
return "state mismatch";
case BT_TBS_RESULT_CODE_OUT_OF_RESOURCES:
return "out of resources";
case BT_TBS_RESULT_CODE_INVALID_URI:
return "invalid URI";
default:
return "ATT err";
}
}
static inline const char *bt_tbs_technology_str(uint8_t status)
{
switch (status) {
case BT_TBS_TECHNOLOGY_3G:
return "3G";
case BT_TBS_TECHNOLOGY_4G:
return "4G";
case BT_TBS_TECHNOLOGY_LTE:
return "LTE";
case BT_TBS_TECHNOLOGY_WIFI:
return "WIFI";
case BT_TBS_TECHNOLOGY_5G:
return "5G";
case BT_TBS_TECHNOLOGY_GSM:
return "GSM";
case BT_TBS_TECHNOLOGY_CDMA:
return "CDMA";
case BT_TBS_TECHNOLOGY_2G:
return "2G";
case BT_TBS_TECHNOLOGY_WCDMA:
return "WCDMA";
case BT_TBS_TECHNOLOGY_IP:
return "IP";
default:
return "unknown technology";
}
}
static inline const char *bt_tbs_term_reason_str(uint8_t reason)
{
switch (reason) {
case BT_TBS_REASON_BAD_REMOTE_URI:
return "bad remote URI";
case BT_TBS_REASON_CALL_FAILED:
return "call failed";
case BT_TBS_REASON_REMOTE_ENDED_CALL:
return "remote ended call";
case BT_TBS_REASON_SERVER_ENDED_CALL:
return "server ended call";
case BT_TBS_REASON_LINE_BUSY:
return "line busy";
case BT_TBS_REASON_NETWORK_CONGESTED:
return "network congested";
case BT_TBS_REASON_CLIENT_TERMINATED:
return "client terminated";
case BT_TBS_REASON_UNSPECIFIED:
return "unspecified";
default:
return "unknown reason";
}
}
/**
* @brief Checks if a string contains a colon (':') followed by a printable
* character. Minimal uri is "a:b".
*
* @param uri The uri "scheme:id"
* @return true If the above is true
* @return false If the above is not true
*/
static inline bool bt_tbs_valid_uri(const char *uri)
{
size_t len;
if (!uri) {
return false;
}
len = strlen(uri);
if (len > CONFIG_BT_TBS_MAX_URI_LENGTH ||
len < BT_TBS_MIN_URI_LEN) {
return false;
} else if (uri[0] < FIRST_PRINTABLE_ASCII_CHAR) {
/* Invalid first char */
return false;
}
for (int i = 1; i < len; i++) {
if (uri[i] == ':' && uri[i + 1] >= FIRST_PRINTABLE_ASCII_CHAR) {
return true;
}
}
return false;
}
/* TODO: The bt_tbs_call could use the bt_tbs_call_state struct for the first
* 3 fields
*/
struct bt_tbs_call {
uint8_t index;
uint8_t state;
uint8_t flags;
char remote_uri[CONFIG_BT_TBS_MAX_URI_LENGTH + 1];
} __packed;
struct bt_tbs_call_state {
uint8_t index;
uint8_t state;
uint8_t flags;
} __packed;
struct bt_tbs_call_cp_acc {
uint8_t opcode;
uint8_t call_index;
} __packed;
struct bt_tbs_call_cp_term {
uint8_t opcode;
uint8_t call_index;
} __packed;
struct bt_tbs_call_cp_hold {
uint8_t opcode;
uint8_t call_index;
} __packed;
struct bt_tbs_call_cp_retrieve {
uint8_t opcode;
uint8_t call_index;
} __packed;
struct bt_tbs_call_cp_originate {
uint8_t opcode;
uint8_t uri[0];
} __packed;
struct bt_tbs_call_cp_join {
uint8_t opcode;
uint8_t call_indexes[0];
} __packed;
union bt_tbs_call_cp_t {
uint8_t opcode;
struct bt_tbs_call_cp_acc accept;
struct bt_tbs_call_cp_term terminate;
struct bt_tbs_call_cp_hold hold;
struct bt_tbs_call_cp_retrieve retrieve;
struct bt_tbs_call_cp_originate originate;
struct bt_tbs_call_cp_join join;
} __packed;
struct bt_tbs_call_cp_notify {
uint8_t opcode;
uint8_t call_index;
uint8_t status;
} __packed;
struct bt_tbs_call_state_notify {
uint8_t call_index;
uint8_t state;
} __packed;
struct bt_tbs_terminate_reason {
uint8_t call_index;
uint8_t reason;
} __packed;
struct bt_tbs_current_call_item {
uint8_t length;
uint8_t call_index;
uint8_t call_state;
uint8_t uri[CONFIG_BT_TBS_MAX_URI_LENGTH];
} __packed;
struct bt_tbs_in_uri {
uint8_t call_index;
char uri[CONFIG_BT_TBS_MAX_URI_LENGTH + 1];
} __packed;