Skip to content
Open
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
10 changes: 10 additions & 0 deletions doc/connectivity/bluetooth/shell/audio/ccp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ to :code:`0` which is the GTBS bearer.
init : Initialize CCP Call Control Server
set_bearer_name : Set bearer name [index] <name>
get_bearer_name : Get bearer name [index]
get_bearer_name : Get bearer UCI [index]
Example Usage
Expand Down Expand Up @@ -58,6 +59,15 @@ Setting and getting the bearer name
uart:~$ ccp_call_control_server get_bearer_name 1
Bearer[1] name: New TBS name
Getting the bearer UCI
----------------------

.. code-block:: console
uart:~$ ccp_call_control_server get_bearer_uci
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we normally assume that omitting index will default the index to 0, instead of the whole list?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now at least we always default to bearer[0] if no index is provided.

Do you think it makes more sense to perform the action on all bearers if index is omitted?

It could work, especially for all "get/read" operations, but probably doesn't make sense for "set/write" operations.

It's following the implementation of the TBS shell, but we can change that no problem.

We can also just modify it so that index is a mandatory argument

Bearer[0] UCI: un999
uart:~$ ccp_call_control_server get_bearer_name 1
Bearer[1] UCI: skype
Call Control Client
*******************
Expand Down
13 changes: 13 additions & 0 deletions include/zephyr/bluetooth/audio/ccp.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,19 @@ int bt_ccp_call_control_server_set_bearer_provider_name(
int bt_ccp_call_control_server_get_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] uci Pointer that will be updated to be the bearer uci.
*
* @retval 0 Success
* @retval -EINVAL @p bearer or @p uci is NULL
* @retval -EFAULT @p bearer is not registered
*/
int bt_ccp_call_control_server_get_bearer_uci(struct bt_ccp_call_control_server_bearer *bearer,
const char **uci);

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

/**
Expand Down
9 changes: 8 additions & 1 deletion include/zephyr/bluetooth/audio/tbs.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,14 @@ extern "C" {
* 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
#define BT_TBS_GTBS_INDEX 0xFF

/** Maximum size of bearer uniform caller identifier (UCI)
*
* Includes the NULL terminator.
* Allowed values are defined by Bluetooth Assigned Numbers.
*/
#define BT_TBS_MAX_UCI_SIZE 6

/** @brief Opaque Telephone Bearer Service instance. */
struct bt_tbs_instance;
Expand Down
28 changes: 28 additions & 0 deletions subsys/bluetooth/audio/ccp_call_control_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,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];
char uci[BT_TBS_MAX_UCI_SIZE];
uint8_t tbs_index;
bool registered;
};
Expand Down Expand Up @@ -75,6 +76,7 @@ int bt_ccp_call_control_server_register_bearer(const struct bt_tbs_register_para
free_bearer->tbs_index = (uint8_t)ret;
(void)utf8_lcpy(free_bearer->provider_name, param->provider_name,
sizeof(free_bearer->provider_name));
(void)utf8_lcpy(free_bearer->uci, param->uci, sizeof(free_bearer->uci));
*bearer = free_bearer;

return 0;
Expand Down Expand Up @@ -175,3 +177,29 @@ int bt_ccp_call_control_server_get_bearer_provider_name(

return 0;
}

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

return -EINVAL;
}

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

return -EINVAL;
}

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

return -EFAULT;
}

*uci = bearer->uci;

return 0;
}
28 changes: 28 additions & 0 deletions subsys/bluetooth/audio/shell/ccp_call_control_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,32 @@
return 0;
}

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

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

Check failure on line 167 in subsys/bluetooth/audio/shell/ccp_call_control_server.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

result of comparison of unsigned expression < 0 is always false

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZbn2ZDo_c7DdQvTOPCr&open=AZbn2ZDo_c7DdQvTOPCr&pullRequest=79642
return index;
}
}

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

return -ENOEXEC;
}

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

return 0;
}

static int cmd_ccp_call_control_server(const struct shell *sh, size_t argc, char **argv)
{
if (argc > 1) {
Expand All @@ -174,6 +200,8 @@
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_CMD_ARG(get_bearer_uci, NULL, "Get bearer UCI [index]",
cmd_ccp_call_control_server_get_bearer_uci, 1, 1),
SHELL_SUBCMD_SET_END);

SHELL_CMD_ARG_REGISTER(ccp_call_control_server, &ccp_call_control_server_cmds,
Expand Down
1 change: 0 additions & 1 deletion subsys/bluetooth/audio/tbs_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include <zephyr/sys/atomic.h>
#include <zephyr/types.h>

#define BT_TBS_MAX_UCI_SIZE 6
#define BT_TBS_MIN_URI_LEN 3 /* a:b */
#define BT_TBS_FREE_CALL_INDEX 0

Expand Down
55 changes: 54 additions & 1 deletion tests/bluetooth/audio/ccp_call_control_server/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
DEFINE_FFF_GLOBALS;

#define DEFAULT_BEARER_NAME "test"
#define DEFAULT_BEARER_UCI "un999"

struct ccp_call_control_server_test_suite_fixture {
/** Need 1 additional bearer than the max to trigger some corner cases */
Expand Down Expand Up @@ -83,7 +84,7 @@ static void register_default_bearer(struct ccp_call_control_server_test_suite_fi
{
const struct bt_tbs_register_param register_param = {
.provider_name = DEFAULT_BEARER_NAME,
.uci = "un999",
.uci = DEFAULT_BEARER_UCI,
.uri_schemes_supported = "tel",
.gtbs = true,
.authorization_required = false,
Expand Down Expand Up @@ -408,3 +409,55 @@ static ZTEST_F(ccp_call_control_server_test_suite,
err = bt_ccp_call_control_server_get_bearer_provider_name(fixture->bearers[0], NULL);
zassert_equal(err, -EINVAL, "Unexpected return value %d", err);
}

static ZTEST_F(ccp_call_control_server_test_suite, test_bt_ccp_call_control_server_get_bearer_uci)
{
const char *res_bearer_name;
int err;

register_default_bearer(fixture);

err = bt_ccp_call_control_server_get_bearer_uci(fixture->bearers[0], &res_bearer_name);
zassert_equal(err, 0, "Unexpected return value %d", err);

zassert_str_equal(DEFAULT_BEARER_UCI, res_bearer_name, "%s != %s", DEFAULT_BEARER_UCI,
res_bearer_name);
}

static ZTEST_F(ccp_call_control_server_test_suite,
test_bt_ccp_call_control_server_get_bearer_uci_inval_not_registered)
{
const char *res_bearer_name;
int err;

/* Register and unregister bearer to get a valid pointer but where it is unregistered*/
register_default_bearer(fixture);
err = bt_ccp_call_control_server_unregister_bearer(fixture->bearers[0]);
zassert_equal(err, 0, "Unexpected return value %d", err);

err = bt_ccp_call_control_server_get_bearer_uci(fixture->bearers[0], &res_bearer_name);
zassert_equal(err, -EFAULT, "Unexpected return value %d", err);
}

static ZTEST_F(ccp_call_control_server_test_suite,
test_bt_ccp_call_control_server_get_bearer_uci_inval_null_bearer)
{
const char *res_bearer_name;
int err;

register_default_bearer(fixture);

err = bt_ccp_call_control_server_get_bearer_uci(NULL, &res_bearer_name);
zassert_equal(err, -EINVAL, "Unexpected return value %d", err);
}

static ZTEST_F(ccp_call_control_server_test_suite,
test_bt_ccp_call_control_server_get_bearer_uci_inval_null_name)
{
int err;

register_default_bearer(fixture);

err = bt_ccp_call_control_server_get_bearer_uci(fixture->bearers[0], NULL);
zassert_equal(err, -EINVAL, "Unexpected return value %d", err);
}