Skip to content

Commit cd92b7f

Browse files
committed
Bluetooth: CCP: Client: Add support for get bearer uci
Add support for getting the remote bearer UCI. Signed-off-by: Emil Gydesen <[email protected]>
1 parent 6f60423 commit cd92b7f

File tree

12 files changed

+372
-47
lines changed

12 files changed

+372
-47
lines changed

doc/connectivity/bluetooth/shell/audio/ccp.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,7 @@ Example Usage when connected
100100
Bearer 0x20046254 name: Generic TBS
101101
uart:~$ ccp_call_control_client read_bearer_name 1
102102
Bearer 0x20046256 name: Telephone Bearer #1
103+
uart:~$ ccp_call_control_client read_bearer_uci
104+
Bearer 0x20046254 UCI: un999
105+
uart:~$ ccp_call_control_client read_bearer_uci 1
106+
Bearer 0x20046256 name: skype

include/zephyr/bluetooth/audio/ccp.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,21 @@ struct bt_ccp_call_control_client_cb {
196196
const char *name);
197197
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME */
198198

199+
#if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)
200+
/**
201+
* @brief Callback function for bt_ccp_call_control_client_read_bearer_provider_name().
202+
*
203+
* This callback is called once the read bearer provider name procedure is completed.
204+
*
205+
* @param client Call Control Client instance pointer.
206+
* @param err Error value. 0 on success, GATT error on positive
207+
* value or errno on negative value.
208+
* @param uci The UCI of the bearer. NULL if @p err is not 0.
209+
*/
210+
void (*bearer_uci)(struct bt_ccp_call_control_client_bearer *bearer, int err,
211+
const char *uci);
212+
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME */
213+
199214
/** @internal Internally used field for list handling */
200215
sys_snode_t _node;
201216
};
@@ -252,6 +267,23 @@ int bt_ccp_call_control_client_get_bearers(struct bt_ccp_call_control_client *cl
252267
*/
253268
int bt_ccp_call_control_client_read_bearer_provider_name(
254269
struct bt_ccp_call_control_client_bearer *bearer);
270+
271+
/**
272+
* @brief Read the bearer Unicorm Caller Identifier (UCI) of a remote TBS bearer.
273+
*
274+
* @kconfig_dep{CONFIG_BT_TBS_CLIENT_BEARER_UCI}
275+
*
276+
* @param bearer The bearer to read the UCI from
277+
*
278+
* @retval 0 Success
279+
* @retval -EINVAL @p bearer is NULL
280+
* @retval -EFAULT @p bearer has not been discovered
281+
* @retval -EEXIST A @ref bt_ccp_call_control_client could not be identified for @p bearer
282+
* @retval -EBUSY The @ref bt_ccp_call_control_client identified by @p bearer is busy, or the TBS
283+
* instance of @p bearer is busy.
284+
* @retval -ENOTCONN The @ref bt_ccp_call_control_client identified by @p bearer is not connected
285+
*/
286+
int bt_ccp_call_control_client_read_bearer_uci(struct bt_ccp_call_control_client_bearer *bearer);
255287
/** @} */ /* End of group bt_ccp_call_control_client */
256288
#ifdef __cplusplus
257289
}

samples/bluetooth/ccp_call_control_client/prj.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ CONFIG_BT_TBS_CLIENT_GTBS=y
1717
CONFIG_BT_TBS_CLIENT_TBS=y
1818
CONFIG_BT_TBS_CLIENT_MAX_TBS_INSTANCES=1
1919
CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME=y
20+
CONFIG_BT_TBS_CLIENT_BEARER_UCI=y
2021
CONFIG_UTF8=y
2122

2223
# TBS Client may require up to 12 buffers

samples/bluetooth/ccp_call_control_client/src/main.c

Lines changed: 67 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,22 @@ static void ccp_call_control_client_read_bearer_provider_name_cb(
222222
}
223223
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME */
224224

225+
#if defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI)
226+
static void
227+
ccp_call_control_client_read_bearer_uci_cb(struct bt_ccp_call_control_client_bearer *bearer,
228+
int err, const char *name)
229+
{
230+
if (err != 0) {
231+
LOG_ERR("Failed to read bearer %p UCI: %d\n", (void *)bearer, err);
232+
return;
233+
}
234+
235+
LOG_INF("Bearer %p UCI: %s", (void *)bearer, name);
236+
237+
k_sem_give(&sem_ccp_action_completed);
238+
}
239+
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_UCI */
240+
225241
static int reset_ccp_call_control_client(void)
226242
{
227243
int err;
@@ -292,24 +308,62 @@ static int read_bearer_name(struct bt_ccp_call_control_client_bearer *bearer)
292308
return 0;
293309
}
294310

295-
static int read_bearer_names(void)
311+
static int read_bearer_uci(struct bt_ccp_call_control_client_bearer *bearer)
296312
{
297313
int err;
298314

299-
#if defined(CONFIG_BT_TBS_CLIENT_GTBS)
300-
err = read_bearer_name(client_bearers.gtbs_bearer);
315+
err = bt_ccp_call_control_client_read_bearer_uci(bearer);
301316
if (err != 0) {
302-
LOG_ERR("Failed to read name for GTBS bearer: %d", err);
303317
return err;
304318
}
319+
320+
err = k_sem_take(&sem_ccp_action_completed, SEM_TIMEOUT);
321+
if (err != 0) {
322+
LOG_ERR("Failed to take sem_ccp_action_completed: %d", err);
323+
return err;
324+
}
325+
326+
return 0;
327+
}
328+
329+
static int read_bearer_values(void)
330+
{
331+
int err;
332+
333+
#if defined(CONFIG_BT_TBS_CLIENT_GTBS)
334+
if (IS_ENABLED(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)) {
335+
err = read_bearer_name(client_bearers.gtbs_bearer);
336+
if (err != 0) {
337+
LOG_ERR("Failed to read name for GTBS bearer: %d", err);
338+
return err;
339+
}
340+
}
341+
342+
if (IS_ENABLED(CONFIG_BT_TBS_CLIENT_BEARER_UCI)) {
343+
err = read_bearer_uci(client_bearers.gtbs_bearer);
344+
if (err != 0) {
345+
LOG_ERR("Failed to read UCI for GTBS bearer: %d", err);
346+
return err;
347+
}
348+
}
305349
#endif /* CONFIG_BT_TBS_CLIENT_GTBS */
306350

307351
#if defined(CONFIG_BT_TBS_CLIENT_TBS)
308352
for (size_t i = 0; i < client_bearers.tbs_count; i++) {
309-
err = read_bearer_name(client_bearers.tbs_bearers[i]);
310-
if (err != 0) {
311-
LOG_ERR("Failed to read name for bearer[%zu]: %d", i, err);
312-
return err;
353+
if (IS_ENABLED(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)) {
354+
err = read_bearer_name(client_bearers.tbs_bearers[i]);
355+
if (err != 0) {
356+
LOG_ERR("Failed to read name for bearer[%zu]: %d", i, err);
357+
return err;
358+
}
359+
}
360+
361+
if (IS_ENABLED(CONFIG_BT_TBS_CLIENT_BEARER_UCI)) {
362+
err = read_bearer_uci(client_bearers.tbs_bearers[i]);
363+
if (err != 0) {
364+
LOG_ERR("Failed to read UCI for bearer[%zu]: %d", i, err);
365+
return err;
366+
}
313367
}
314368
}
315369
#endif /* CONFIG_BT_TBS_CLIENT_TBS */
@@ -322,8 +376,11 @@ static int init_ccp_call_control_client(void)
322376
static struct bt_ccp_call_control_client_cb ccp_call_control_client_cbs = {
323377
.discover = ccp_call_control_client_discover_cb,
324378
#if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)
325-
.bearer_provider_name = ccp_call_control_client_read_bearer_provider_name_cb
379+
.bearer_provider_name = ccp_call_control_client_read_bearer_provider_name_cb,
326380
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME */
381+
#if defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI)
382+
.bearer_uci = ccp_call_control_client_read_bearer_uci_cb,
383+
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_UCI */
327384
};
328385
static struct bt_le_scan_cb scan_cbs = {
329386
.recv = scan_recv_cb,
@@ -384,12 +441,7 @@ int main(void)
384441
continue;
385442
}
386443

387-
if (IS_ENABLED(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)) {
388-
err = read_bearer_names();
389-
if (err != 0) {
390-
continue;
391-
}
392-
}
444+
read_bearer_values();
393445

394446
/* Reset if disconnected */
395447
err = k_sem_take(&sem_conn_state_change, K_FOREVER);

subsys/bluetooth/audio/ccp_call_control_client.c

Lines changed: 87 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -281,31 +281,7 @@ int bt_ccp_call_control_client_get_bearers(struct bt_ccp_call_control_client *cl
281281
return 0;
282282
}
283283

284-
#if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)
285-
static void tbs_client_read_bearer_provider_name_cb(struct bt_conn *conn, int err,
286-
uint8_t inst_index, const char *name)
287-
{
288-
struct bt_ccp_call_control_client *client = get_client_by_conn(conn);
289-
struct bt_ccp_call_control_client_cb *listener, *next;
290-
struct bt_ccp_call_control_client_bearer *bearer;
291-
292-
atomic_clear_bit(client->flags, CCP_CALL_CONTROL_CLIENT_FLAG_BUSY);
293-
294-
bearer = get_bearer_by_tbs_index(client, inst_index);
295-
if (bearer == NULL) {
296-
LOG_DBG("Could not lookup bearer for client %p and index 0x%02X", client,
297-
inst_index);
298-
299-
return;
300-
}
301-
302-
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&ccp_call_control_client_cbs, listener, next, _node) {
303-
if (listener->bearer_provider_name != NULL) {
304-
listener->bearer_provider_name(bearer, err, name);
305-
}
306-
}
307-
}
308-
284+
#if defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI) || defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)
309285
/**
310286
* @brief Validates a bearer and provides a client with ownership of the busy flag
311287
*
@@ -345,6 +321,32 @@ static int validate_bearer_and_get_client(const struct bt_ccp_call_control_clien
345321

346322
return 0;
347323
}
324+
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_UCI || CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME */
325+
326+
#if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)
327+
static void tbs_client_read_bearer_provider_name_cb(struct bt_conn *conn, int err,
328+
uint8_t inst_index, const char *name)
329+
{
330+
struct bt_ccp_call_control_client *client = get_client_by_conn(conn);
331+
struct bt_ccp_call_control_client_cb *listener, *next;
332+
struct bt_ccp_call_control_client_bearer *bearer;
333+
334+
atomic_clear_bit(client->flags, CCP_CALL_CONTROL_CLIENT_FLAG_BUSY);
335+
336+
bearer = get_bearer_by_tbs_index(client, inst_index);
337+
if (bearer == NULL) {
338+
LOG_DBG("Could not lookup bearer for client %p and index 0x%02X", client,
339+
inst_index);
340+
341+
return;
342+
}
343+
344+
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&ccp_call_control_client_cbs, listener, next, _node) {
345+
if (listener->bearer_provider_name != NULL) {
346+
listener->bearer_provider_name(bearer, err, name);
347+
}
348+
}
349+
}
348350

349351
int bt_ccp_call_control_client_read_bearer_provider_name(
350352
struct bt_ccp_call_control_client_bearer *bearer)
@@ -381,3 +383,63 @@ int bt_ccp_call_control_client_read_bearer_provider_name(
381383
return 0;
382384
}
383385
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME */
386+
387+
#if defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI)
388+
static void tbs_client_read_bearer_uci_cb(struct bt_conn *conn, int err, uint8_t inst_index,
389+
const char *uci)
390+
{
391+
struct bt_ccp_call_control_client *client = get_client_by_conn(conn);
392+
struct bt_ccp_call_control_client_cb *listener, *next;
393+
struct bt_ccp_call_control_client_bearer *bearer;
394+
395+
atomic_clear_bit(client->flags, CCP_CALL_CONTROL_CLIENT_FLAG_BUSY);
396+
397+
bearer = get_bearer_by_tbs_index(client, inst_index);
398+
if (bearer == NULL) {
399+
LOG_DBG("Could not lookup bearer for client %p and index 0x%02X", client,
400+
inst_index);
401+
402+
return;
403+
}
404+
405+
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&ccp_call_control_client_cbs, listener, next, _node) {
406+
if (listener->bearer_uci != NULL) {
407+
listener->bearer_uci(bearer, err, uci);
408+
}
409+
}
410+
}
411+
412+
int bt_ccp_call_control_client_read_bearer_uci(struct bt_ccp_call_control_client_bearer *bearer)
413+
{
414+
struct bt_ccp_call_control_client *client;
415+
int err;
416+
417+
err = validate_bearer_and_get_client(bearer, &client);
418+
if (err != 0) {
419+
return err;
420+
}
421+
422+
tbs_client_cbs.bearer_uci = tbs_client_read_bearer_uci_cb;
423+
424+
err = bt_tbs_client_read_bearer_uci(client->conn, bearer->tbs_index);
425+
if (err != 0) {
426+
atomic_clear_bit(client->flags, CCP_CALL_CONTROL_CLIENT_FLAG_BUSY);
427+
428+
/* Return expected return values directly */
429+
if (err == -ENOTCONN || err == -EBUSY) {
430+
LOG_DBG("bt_tbs_client_read_bearer_uci returned %d", err);
431+
432+
return err;
433+
}
434+
435+
/* Assert if the return value is -EINVAL as that means we are missing a check */
436+
__ASSERT(err != -EINVAL, "err shall not be -EINVAL");
437+
438+
LOG_DBG("Unexpected error from bt_tbs_client_read_bearer_uci: %d", err);
439+
440+
return -ENOEXEC;
441+
}
442+
443+
return 0;
444+
}
445+
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_UCI */

subsys/bluetooth/audio/shell/ccp_call_control_client.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,27 @@ ccp_call_control_client_bearer_provider_name_cb(struct bt_ccp_call_control_clien
6464
}
6565
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME */
6666

67+
#if defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI)
68+
static void ccp_call_control_client_bearer_uci_cb(struct bt_ccp_call_control_client_bearer *bearer,
69+
int err, const char *name)
70+
{
71+
if (err != 0) {
72+
bt_shell_error("Failed to read bearer %p UCI: %d", (void *)bearer, err);
73+
return;
74+
}
75+
76+
bt_shell_info("Bearer %p UCI: %s", (void *)bearer, name);
77+
}
78+
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_UCI */
79+
6780
static struct bt_ccp_call_control_client_cb ccp_call_control_client_cbs = {
6881
.discover = ccp_call_control_client_discover_cb,
6982
#if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)
7083
.bearer_provider_name = ccp_call_control_client_bearer_provider_name_cb,
7184
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME */
85+
#if defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI)
86+
.bearer_uci = ccp_call_control_client_bearer_uci_cb,
87+
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_UCI */
7288
};
7389

7490
static int cmd_ccp_call_control_client_discover(const struct shell *sh, size_t argc, char *argv[])
@@ -186,6 +202,37 @@ static int cmd_ccp_call_control_client_read_bearer_name(const struct shell *sh,
186202
return 0;
187203
}
188204

205+
static int cmd_ccp_call_control_client_read_bearer_uci(const struct shell *sh, size_t argc,
206+
char *argv[])
207+
{
208+
struct bt_ccp_call_control_client_bearer *bearer;
209+
unsigned long index = 0;
210+
int err;
211+
212+
if (argc > 1) {
213+
index = validate_and_get_index(sh, argv[1]);
214+
if (index < 0) {
215+
return index;
216+
}
217+
}
218+
219+
bearer = get_bearer_by_index(index);
220+
if (bearer == NULL) {
221+
shell_error(sh, "Failed to get bearer for index %lu", index);
222+
223+
return -ENOEXEC;
224+
}
225+
226+
err = bt_ccp_call_control_client_read_bearer_uci(bearer);
227+
if (err != 0) {
228+
shell_error(sh, "Failed to read bearer[%lu] UCI: %d", index, err);
229+
230+
return -ENOEXEC;
231+
}
232+
233+
return 0;
234+
}
235+
189236
static int cmd_ccp_call_control_client(const struct shell *sh, size_t argc, char **argv)
190237
{
191238
if (argc > 1) {
@@ -203,6 +250,8 @@ SHELL_STATIC_SUBCMD_SET_CREATE(ccp_call_control_client_cmds,
203250
cmd_ccp_call_control_client_discover, 1, 0),
204251
SHELL_CMD_ARG(read_bearer_name, NULL, "Get bearer name [index]",
205252
cmd_ccp_call_control_client_read_bearer_name, 1, 1),
253+
SHELL_CMD_ARG(read_bearer_name, NULL, "Get bearer UCI [index]",
254+
cmd_ccp_call_control_client_read_bearer_uci, 1, 1),
206255
SHELL_SUBCMD_SET_END);
207256

208257
SHELL_CMD_ARG_REGISTER(ccp_call_control_client, &ccp_call_control_client_cmds,

tests/bluetooth/audio/ccp_call_control_client/include/ccp_call_control_client.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,7 @@ DECLARE_FAKE_VOID_FUNC(mock_ccp_call_control_client_discover_cb,
2323
struct bt_ccp_call_control_client_bearers *);
2424
DECLARE_FAKE_VOID_FUNC(mock_ccp_call_control_client_bearer_provider_name_cb,
2525
struct bt_ccp_call_control_client_bearer *, int, const char *);
26+
DECLARE_FAKE_VOID_FUNC(mock_ccp_call_control_client_bearer_uci_cb,
27+
struct bt_ccp_call_control_client_bearer *, int, const char *);
2628

2729
#endif /* MOCKS_CCP_CALL_CONTROL_CLIENT_H_ */

0 commit comments

Comments
 (0)