Skip to content

Commit

Permalink
Bluetooth: CCP: Add support for set/get provider name
Browse files Browse the repository at this point in the history
Add support for setting and getting the bearer provider
name. For now the name will be duplicated by the TBS
implementation, but will be optimizied in the future
so only one copy of the name exists.

Signed-off-by: Emil Gydesen <[email protected]>
  • Loading branch information
Thalley committed Nov 29, 2024
1 parent dd80064 commit 878f797
Show file tree
Hide file tree
Showing 8 changed files with 363 additions and 3 deletions.
27 changes: 26 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 contrained devices such as
Expand Down
27 changes: 27 additions & 0 deletions include/zephyr/bluetooth/audio/ccp.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,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
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 @@ -250,7 +250,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
69 changes: 69 additions & 0 deletions subsys/bluetooth/audio/ccp_call_control_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>

#include <zephyr/autoconf.h>
#include <zephyr/bluetooth/audio/tbs.h>
Expand All @@ -19,6 +20,7 @@ LOG_MODULE_REGISTER(bt_ccp_call_control_server, CONFIG_BT_CCP_CALL_CONTROL_SERVE

/* A service instance can either be a GTBS or a TBS instance */
struct bt_ccp_call_control_server_bearer {
char provider_name[CONFIG_BT_ccp_call_control_server_PROVIDER_NAME_MAX_LENGTH + 1];
uint8_t tbs_index;
bool registered;
};
Expand Down Expand Up @@ -69,6 +71,8 @@ int bt_ccp_call_control_server_register_bearer(const struct bt_tbs_register_para

free_bearer->registered = true;
free_bearer->tbs_index = (uint8_t)ret;
(void)utf8_lcpy(free_bearer->provider_name, param->provider_name,
sizeof(free_bearer->provider_name));
*bearer = free_bearer;

return 0;
Expand Down Expand Up @@ -104,3 +108,68 @@ int bt_ccp_call_control_server_unregister_bearer(struct bt_ccp_call_control_serv

return 0;
}

int bt_ccp_call_control_server_set_bearer_provider_name(
struct bt_ccp_call_control_server_bearer *bearer, const char *name)
{
size_t len;

CHECKIF(bearer == NULL) {
LOG_DBG("bearer is NULL");

return -EINVAL;
}

CHECKIF(name == NULL) {
LOG_DBG("name is NULL");

return -EINVAL;
}

if (!bearer->registered) {
LOG_DBG("Bearer %p not registered", bearer);

return -EFAULT;
}

len = strlen(name);
if (len > CONFIG_BT_ccp_call_control_server_PROVIDER_NAME_MAX_LENGTH || len == 0) {
LOG_DBG("Invalid name length: %zu", len);

return -EINVAL;
}

if (strcmp(bearer->provider_name, name) == 0) {
return 0;
}

(void)utf8_lcpy(bearer->provider_name, name, sizeof(bearer->provider_name));

return bt_tbs_set_bearer_provider_name(bearer->tbs_index, name);
}

int bt_ccp_call_control_server_get_bearer_provider_name(
struct bt_ccp_call_control_server_bearer *bearer, const char **name)
{
CHECKIF(bearer == NULL) {
LOG_DBG("bearer is NULL");

return -EINVAL;
}

CHECKIF(name == NULL) {
LOG_DBG("name is NULL");

return -EINVAL;
}

if (!bearer->registered) {
LOG_DBG("Bearer %p not registered", bearer);

return -EFAULT;
}

*name = bearer->provider_name;

return 0;
}
81 changes: 81 additions & 0 deletions subsys/bluetooth/audio/shell/ccp_call_control_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <zephyr/bluetooth/audio/tbs.h>
#include <zephyr/bluetooth/audio/ccp.h>
#include <zephyr/shell/shell.h>
#include <zephyr/shell/shell_string_conv.h>

static struct bt_ccp_call_control_server_bearer
*bearers[CONFIG_BT_CCP_CALL_CONTROL_SERVER_BEARER_COUNT];
Expand Down Expand Up @@ -79,6 +80,81 @@ static int cmd_ccp_call_control_server_init(const struct shell *sh, size_t argc,
return 0;
}

static int validate_and_get_index(const struct shell *sh, const char *index_arg)
{
unsigned long index;
int err = 0;

index = shell_strtoul(index_arg, 0, &err);
if (err != 0) {
shell_error(sh, "Could not parse index: %d", err);

return -ENOEXEC;
}

if (index > CONFIG_BT_TBS_BEARER_COUNT) {
shell_error(sh, "Invalid index: %lu", index);

return -ENOEXEC;
}

return (int)index;
}

static int cmd_ccp_call_control_server_set_bearer_name(const struct shell *sh, size_t argc,
char *argv[])
{
unsigned long index = 0;
const char *name;
int err = 0;

if (argc > 2) {
index = validate_and_get_index(sh, argv[1]);
if (index < 0) {
return index;
}
}

name = argv[argc - 1];

err = bt_ccp_call_control_server_set_bearer_provider_name(bearers[index], name);
if (err != 0) {
shell_error(sh, "Failed to set bearer[%lu] name: %d", index, err);

return -ENOEXEC;
}

shell_print(sh, "Bearer[%lu] name: %s", index, name);

return 0;
}

static int cmd_ccp_call_control_server_get_bearer_name(const struct shell *sh, size_t argc,
char *argv[])
{
unsigned long index = 0;
const char *name;
int err = 0;

if (argc > 1) {
index = validate_and_get_index(sh, argv[1]);
if (index < 0) {
return index;
}
}

err = bt_ccp_call_control_server_get_bearer_provider_name(bearers[index], &name);
if (err != 0) {
shell_error(sh, "Failed to get bearer[%lu] name: %d", index, err);

return -ENOEXEC;
}

shell_print(sh, "Bearer[%lu] name: %s", index, name);

return 0;
}

static int cmd_ccp_call_control_server(const struct shell *sh, size_t argc, char **argv)
{
if (argc > 1) {
Expand All @@ -93,6 +169,11 @@ static int cmd_ccp_call_control_server(const struct shell *sh, size_t argc, char
SHELL_STATIC_SUBCMD_SET_CREATE(ccp_call_control_server_cmds,
SHELL_CMD_ARG(init, NULL, "Initialize CCP Call Control Server",
cmd_ccp_call_control_server_init, 1, 0),
SHELL_CMD_ARG(set_bearer_name, NULL,
"Set bearer name [index] <name>",
cmd_ccp_call_control_server_set_bearer_name, 2, 1),
SHELL_CMD_ARG(get_bearer_name, NULL, "Get bearer name [index]",
cmd_ccp_call_control_server_get_bearer_name, 1, 1),
SHELL_SUBCMD_SET_END);

SHELL_CMD_ARG_REGISTER(ccp_call_control_server, &ccp_call_control_server_cmds,
Expand Down
4 changes: 4 additions & 0 deletions subsys/bluetooth/audio/tbs.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ LOG_MODULE_REGISTER(bt_tbs, CONFIG_BT_TBS_LOG_LEVEL);
/* A service instance can either be a GTBS or a TBS instance */
struct tbs_inst {
/* Attribute values */
/* TODO: The provider name should be removed from the tbs_inst and instead by stored by the
* user of TBS. This will be done once the CCP API is complete as the CCP Server will own
* all the data instead of the TBS
*/
char provider_name[CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH];
char uci[BT_TBS_MAX_UCI_SIZE];
uint8_t technology;
Expand Down
Loading

0 comments on commit 878f797

Please sign in to comment.