Skip to content

Bluetooth: CCP: Add read bearer provider name for the CCP client #79462

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion doc/connectivity/bluetooth/shell/audio/ccp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,18 @@ The Server can be controlled locally, or by a remote device (when in a call). Fo
example a remote device may initiate a call to the server,
or the Server may initiate a call to remote device, without a client.

For all commands that take an optional :code:`index`, if the index is not supplied then it defaults
to :code:`0` which is the GTBS bearer.

.. code-block:: console

ccp_call_control_server --help
ccp_call_control_server - Bluetooth CCP Call Control Server shell commands
Subcommands:
init : Initialize CCP Call Control Server
init : Initialize CCP Call Control Server
set_bearer_name : Set bearer name [index] <name>
get_bearer_name : Get bearer name [index]


Example Usage
=============
Expand All @@ -34,6 +40,25 @@ Setup
Registered bearer[1]
uart:~$ bt connect xx:xx:xx:xx:xx:xx public

Setting and getting the bearer name
-----------------------------------

.. code-block:: console

uart:~$ ccp_call_control_server get_bearer_name
Bearer[0] name: Generic TBS
uart:~$ ccp_call_control_server set_bearer_name "New name"
Bearer[0] name: New name
uart:~$ ccp_call_control_server get_bearer_name
Bearer[0] name: New name
uart:~$ ccp_call_control_server get_bearer_name 1
Bearer[1] name: Telephone Bearer #1
uart:~$ ccp_call_control_server set_bearer_name 1 "New TBS name"
Bearer[1] name: New TBS name
uart:~$ ccp_call_control_server get_bearer_name 1
Bearer[1] name: New TBS name


Call Control Client
*******************
The Call Control Client is a role that typically resides on resource constrained devices such as
Expand All @@ -58,3 +83,10 @@ Example Usage when connected

uart:~$ ccp_call_control_client discover
Discovery completed with GTBS and 1 TBS bearers

.. code-block:: console

uart:~$ ccp_call_control_client read_bearer_name
Bearer 0x20046254 name: Generic TBS
uart:~$ ccp_call_control_client read_bearer_name 1
Bearer 0x20046256 name: Telephone Bearer #1
59 changes: 59 additions & 0 deletions include/zephyr/bluetooth/audio/ccp.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,33 @@ int bt_ccp_call_control_server_register_bearer(const struct bt_tbs_register_para
*/
int bt_ccp_call_control_server_unregister_bearer(struct bt_ccp_call_control_server_bearer *bearer);

/**
* @brief Set a new bearer provider name.
*
* @param bearer The bearer to set the name for.
* @param name The new bearer provider name.
*
* @retval 0 Success
* @retval -EINVAL @p bearer or @p name is NULL, or @p name is the empty string or @p name is larger
* than @kconfig{CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH}
* @retval -EFAULT @p bearer is not registered
*/
int bt_ccp_call_control_server_set_bearer_provider_name(
struct bt_ccp_call_control_server_bearer *bearer, const char *name);

/**
* @brief Get the bearer provider name.
*
* @param[in] bearer The bearer to get the name for.
* @param[out] name Pointer that will be updated to be the bearer provider name.
*
* @retval 0 Success
* @retval -EINVAL @p bearer or @p name is NULL
* @retval -EFAULT @p bearer is not registered
*/
int bt_ccp_call_control_server_get_bearer_provider_name(
struct bt_ccp_call_control_server_bearer *bearer, const char **name);

/** @} */ /* End of group bt_ccp_call_control_server */

/**
Expand Down Expand Up @@ -142,6 +169,21 @@ struct bt_ccp_call_control_client_cb {
void (*discover)(struct bt_ccp_call_control_client *client, int err,
struct bt_ccp_call_control_client_bearers *bearers);

#if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)
/**
* @brief Callback function for bt_ccp_call_control_client_read_bearer_provider_name().
*
* This callback is called once the read bearer provider name procedure is completed.
*
* @param client Call Control Client instance pointer.
* @param err Error value. 0 on success, GATT error on positive
* value or errno on negative value.
* @param name The bearer provider name. NULL if @p err is not 0.
*/
void (*bearer_provider_name)(struct bt_ccp_call_control_client_bearer *bearer, int err,
const char *name);
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME */

/** @cond INTERNAL_HIDDEN */
/** Internally used field for list handling */
sys_snode_t _node;
Expand Down Expand Up @@ -203,6 +245,23 @@ int bt_ccp_call_control_client_unregister_cb(struct bt_ccp_call_control_client_c
int bt_ccp_call_control_client_get_bearers(struct bt_ccp_call_control_client *client,
struct bt_ccp_call_control_client_bearers *bearers);

/**
* @brief Read the bearer provider name of a remote TBS bearer.
*
* @kconfig_dep{CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME}
*
* @param bearer The bearer to read the name from
*
* @retval 0 Success
* @retval -EINVAL @p bearer is NULL
* @retval -EFAULT @p bearer has not been discovered
* @retval -EEXIST A @ref bt_ccp_call_control_client could not be identified for @p bearer
* @retval -EBUSY The @ref bt_ccp_call_control_client identified by @p bearer is busy, or the TBS
* instance of @p bearer is busy.
* @retval -ENOTCONN The @ref bt_ccp_call_control_client identified by @p bearer is not connected
*/
int bt_ccp_call_control_client_read_bearer_provider_name(
struct bt_ccp_call_control_client_bearer *bearer);
/** @} */ /* End of group bt_ccp_call_control_client */
#ifdef __cplusplus
}
Expand Down
1 change: 1 addition & 0 deletions samples/bluetooth/ccp_call_control_client/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ CONFIG_BT_CCP_CALL_CONTROL_CLIENT_BEARER_COUNT=2
CONFIG_BT_TBS_CLIENT_GTBS=y
CONFIG_BT_TBS_CLIENT_TBS=y
CONFIG_BT_TBS_CLIENT_MAX_TBS_INSTANCES=1
CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME=y
CONFIG_UTF8=y

# TBS Client may require up to 12 buffers
Expand Down
82 changes: 75 additions & 7 deletions samples/bluetooth/ccp_call_control_client/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ LOG_MODULE_REGISTER(ccp_call_control_client, CONFIG_LOG_DEFAULT_LEVEL);
#define SEM_TIMEOUT K_SECONDS(10)

static struct bt_conn *peer_conn;
/* client is not static as it is used for testing purposes */
struct bt_ccp_call_control_client *client;
/* call_control_client is not static as it is used for testing purposes */
struct bt_ccp_call_control_client *call_control_client;
static struct bt_ccp_call_control_client_bearers client_bearers;

static K_SEM_DEFINE(sem_conn_state_change, 0, 1);
Expand Down Expand Up @@ -61,7 +61,7 @@ static void disconnected_cb(struct bt_conn *conn, uint8_t reason)

bt_conn_unref(peer_conn);
peer_conn = NULL;
client = NULL;
call_control_client = NULL;
memset(&client_bearers, 0, sizeof(client_bearers));
k_sem_give(&sem_conn_state_change);
}
Expand Down Expand Up @@ -207,6 +207,21 @@ static void ccp_call_control_client_discover_cb(struct bt_ccp_call_control_clien
k_sem_give(&sem_ccp_action_completed);
}

#if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)
static void ccp_call_control_client_read_bearer_provider_name_cb(
struct bt_ccp_call_control_client_bearer *bearer, int err, const char *name)
{
if (err != 0) {
LOG_ERR("Failed to read bearer %p provider name: %d\n", (void *)bearer, err);
return;
}

LOG_INF("Bearer %p provider name: %s", (void *)bearer, name);

k_sem_give(&sem_ccp_action_completed);
}
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME */

static int reset_ccp_call_control_client(void)
{
int err;
Expand Down Expand Up @@ -244,7 +259,7 @@ static int discover_services(void)

LOG_INF("Discovering GTBS and TBS");

err = bt_ccp_call_control_client_discover(peer_conn, &client);
err = bt_ccp_call_control_client_discover(peer_conn, &call_control_client);
if (err != 0) {
LOG_ERR("Failed to discover: %d", err);
return err;
Expand All @@ -259,13 +274,59 @@ static int discover_services(void)
return 0;
}

static int read_bearer_name(struct bt_ccp_call_control_client_bearer *bearer)
{
int err;

err = bt_ccp_call_control_client_read_bearer_provider_name(bearer);
if (err != 0) {
return err;
}

err = k_sem_take(&sem_ccp_action_completed, SEM_TIMEOUT);
if (err != 0) {
LOG_ERR("Failed to take sem_ccp_action_completed: %d", err);
return err;
}

return 0;
}

static int read_bearer_names(void)
{
int err;

#if defined(CONFIG_BT_TBS_CLIENT_GTBS)
err = read_bearer_name(client_bearers.gtbs_bearer);
if (err != 0) {
LOG_ERR("Failed to read name for GTBS bearer: %d", err);
return err;
}
#endif /* CONFIG_BT_TBS_CLIENT_GTBS */

#if defined(CONFIG_BT_TBS_CLIENT_TBS)
for (size_t i = 0; i < client_bearers.tbs_count; i++) {
err = read_bearer_name(client_bearers.tbs_bearers[i]);
if (err != 0) {
LOG_ERR("Failed to read name for bearer[%zu]: %d", i, err);
return err;
}
}
#endif /* CONFIG_BT_TBS_CLIENT_TBS */

return 0;
}

static int init_ccp_call_control_client(void)
{
static struct bt_le_scan_cb scan_cbs = {
.recv = scan_recv_cb,
};
static struct bt_ccp_call_control_client_cb ccp_call_control_client_cbs = {
.discover = ccp_call_control_client_discover_cb,
#if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)
.bearer_provider_name = ccp_call_control_client_read_bearer_provider_name_cb
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME */
};
static struct bt_le_scan_cb scan_cbs = {
.recv = scan_recv_cb,
};
int err;

Expand Down Expand Up @@ -323,6 +384,13 @@ int main(void)
continue;
}

if (IS_ENABLED(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)) {
err = read_bearer_names();
if (err != 0) {
continue;
}
}

/* Reset if disconnected */
err = k_sem_take(&sem_conn_state_change, K_FOREVER);
if (err != 0) {
Expand Down
7 changes: 7 additions & 0 deletions subsys/bluetooth/audio/Kconfig.ccp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ config BT_CCP_CALL_CONTROL_SERVER_BEARER_COUNT
help
The number of supported telephone bearers on the CCP Call Control Server

config BT_CCP_CALL_CONTROL_SERVER_PROVIDER_NAME_MAX_LENGTH
int "The maximum length of the bearer provider name excluding null terminator"
default BT_TBS_MAX_PROVIDER_NAME_LENGTH
range 1 BT_TBS_MAX_PROVIDER_NAME_LENGTH
help
Sets the maximum length of the bearer provider name.

module = BT_CCP_CALL_CONTROL_SERVER
module-str = "Call Control Profile Call Control Server"
source "subsys/logging/Kconfig.template.log_config"
Expand Down
2 changes: 1 addition & 1 deletion subsys/bluetooth/audio/Kconfig.tbs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ config BT_TBS_MAX_URI_LENGTH
config BT_TBS_MAX_PROVIDER_NAME_LENGTH
int "The maximum length of the bearer provider name"
default 30
range 0 512
range 1 512
help
Sets the maximum length of the bearer provider name.

Expand Down
Loading