1 /* Bluetooth TBS - Telephone Bearer Service
2 *
3 * Copyright (c) 2020 Bose Corporation
4 * Copyright (c) 2021-2024 Nordic Semiconductor ASA
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <errno.h>
10 #include <stdbool.h>
11 #include <stddef.h>
12 #include <stdint.h>
13 #include <string.h>
14 #include <sys/types.h>
15
16 #include <zephyr/autoconf.h>
17 #include <zephyr/bluetooth/att.h>
18 #include <zephyr/bluetooth/audio/ccid.h>
19 #include <zephyr/bluetooth/audio/tbs.h>
20 #include <zephyr/bluetooth/bluetooth.h>
21 #include <zephyr/bluetooth/conn.h>
22 #include <zephyr/bluetooth/gatt.h>
23 #include <zephyr/bluetooth/uuid.h>
24 #include <zephyr/init.h>
25 #include <zephyr/kernel.h>
26 #include <zephyr/logging/log.h>
27 #include <zephyr/net_buf.h>
28 #include <zephyr/sys/__assert.h>
29 #include <zephyr/sys/atomic.h>
30 #include <zephyr/sys/byteorder.h>
31 #include <zephyr/sys/check.h>
32 #include <zephyr/sys/util.h>
33 #include <zephyr/sys/util_macro.h>
34 #include <zephyr/types.h>
35
36 #include "audio_internal.h"
37 #include "tbs_internal.h"
38 #include "common/bt_str.h"
39
40 LOG_MODULE_REGISTER(bt_tbs, CONFIG_BT_TBS_LOG_LEVEL);
41
42 #define BT_TBS_VALID_STATUS_FLAGS(val) ((val) <= (BIT(0) | BIT(1)))
43 #define MUTEX_TIMEOUT K_MSEC(CONFIG_BT_TBS_LOCK_TIMEOUT)
44
45 struct tbs_flags {
46 bool bearer_provider_name_changed: 1;
47 bool bearer_technology_changed: 1;
48 bool bearer_uri_schemes_supported_list_changed: 1;
49 bool bearer_signal_strength_changed: 1;
50 bool bearer_list_current_calls_changed: 1;
51 bool status_flags_changed: 1;
52 bool incoming_call_target_bearer_uri_changed: 1;
53 bool call_state_changed: 1;
54 bool termination_reason_changed: 1;
55 bool incoming_call_changed: 1;
56 bool call_friendly_name_changed: 1;
57 };
58
59 /* A service instance can either be a GTBS or a TBS instance */
60 struct tbs_inst {
61 /* Attribute values */
62 char provider_name[CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH];
63 char uci[BT_TBS_MAX_UCI_SIZE];
64 uint8_t technology;
65 uint8_t signal_strength;
66 uint8_t signal_strength_interval;
67 uint8_t ccid;
68 uint16_t optional_opcodes;
69 uint16_t status_flags;
70 struct bt_tbs_in_uri incoming_uri;
71 struct bt_tbs_in_uri friendly_name;
72 struct bt_tbs_in_uri in_call;
73 char uri_scheme_list[CONFIG_BT_TBS_MAX_SCHEME_LIST_LENGTH];
74 struct bt_tbs_terminate_reason terminate_reason;
75 struct bt_tbs_call calls[CONFIG_BT_TBS_MAX_CALLS];
76
77 bool pending_signal_strength_notification;
78 struct k_work_delayable reporting_interval_work;
79
80 /** Service Attributes */
81 const struct bt_gatt_attr *attrs;
82 /** Service Attribute count */
83 size_t attr_count;
84
85 bool authorization_required;
86
87 struct k_mutex mutex;
88 /* Flags for each client. Access and modification of these shall be guarded by the mutex */
89 struct tbs_flags flags[CONFIG_BT_MAX_CONN];
90
91 /* Control point notifications are handled separately from other notifications - We will not
92 * accept any new control point operations while a notification is pending
93 */
94 struct cp_ntf {
95 struct bt_tbs_call_cp_notify notification;
96
97 uint8_t conn_index; /* The conn index that triggered the request */
98 bool pending: 1;
99 } cp_ntf;
100
101 struct k_work_delayable notify_work;
102 };
103
104 static struct tbs_inst svc_insts[CONFIG_BT_TBS_BEARER_COUNT];
105 static struct tbs_inst gtbs_inst;
106
107 #define READ_BUF_SIZE \
108 MAX(BT_ATT_MAX_ATTRIBUTE_LEN, \
109 (CONFIG_BT_TBS_MAX_CALLS * sizeof(struct bt_tbs_current_call_item) * \
110 (1U + ARRAY_SIZE(svc_insts))))
111 NET_BUF_SIMPLE_DEFINE_STATIC(read_buf, READ_BUF_SIZE);
112
113 /* Used to notify app with held calls in case of join */
114 static struct bt_tbs_call *held_calls[CONFIG_BT_TBS_MAX_CALLS];
115 static uint8_t held_calls_cnt;
116
117 static struct bt_tbs_cb *tbs_cbs;
118
inst_is_registered(const struct tbs_inst * inst)119 static bool inst_is_registered(const struct tbs_inst *inst)
120 {
121 return inst->attrs != NULL;
122 }
123
inst_is_gtbs(const struct tbs_inst * inst)124 static bool inst_is_gtbs(const struct tbs_inst *inst)
125 {
126 if (CONFIG_BT_TBS_BEARER_COUNT > 0) {
127 return inst == >bs_inst;
128 } else {
129 return true;
130 }
131 }
132
inst_index(const struct tbs_inst * inst)133 static uint8_t inst_index(const struct tbs_inst *inst)
134 {
135 ptrdiff_t index = 0;
136
137 __ASSERT_NO_MSG(inst);
138
139 if (inst_is_gtbs(inst)) {
140 return BT_TBS_GTBS_INDEX;
141 }
142
143 index = inst - svc_insts;
144 __ASSERT(index >= 0 && index < ARRAY_SIZE(svc_insts), "Invalid tbs_inst pointer");
145
146 return (uint8_t)index;
147 }
148
inst_lookup_index(uint8_t index)149 static struct tbs_inst *inst_lookup_index(uint8_t index)
150 {
151 struct tbs_inst *inst = NULL;
152
153 if (index == BT_TBS_GTBS_INDEX) {
154 inst = >bs_inst;
155 } else if (ARRAY_SIZE(svc_insts) > 0U && index < ARRAY_SIZE(svc_insts)) {
156 inst = &svc_insts[index];
157 }
158
159 if (inst == NULL || !inst_is_registered(inst)) {
160 return NULL;
161 }
162
163 return inst;
164 }
165
lookup_call_in_inst(struct tbs_inst * inst,uint8_t call_index)166 static struct bt_tbs_call *lookup_call_in_inst(struct tbs_inst *inst, uint8_t call_index)
167 {
168 if (call_index == BT_TBS_FREE_CALL_INDEX) {
169 return NULL;
170 }
171
172 for (int i = 0; i < ARRAY_SIZE(svc_insts[i].calls); i++) {
173 if (inst->calls[i].index == call_index) {
174 return &inst->calls[i];
175 }
176 }
177
178 return NULL;
179 }
180
181 /**
182 * @brief Finds and returns a call
183 *
184 * @param call_index The ID of the call
185 * @return struct bt_tbs_call* Pointer to the call. NULL if not found
186 */
lookup_call(uint8_t call_index)187 static struct bt_tbs_call *lookup_call(uint8_t call_index)
188 {
189 struct bt_tbs_call *call;
190
191 if (call_index == BT_TBS_FREE_CALL_INDEX) {
192 return NULL;
193 }
194
195 call = lookup_call_in_inst(>bs_inst, call_index);
196 if (call != NULL) {
197 return call;
198 }
199
200 for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) {
201 call = lookup_call_in_inst(&svc_insts[i], call_index);
202 if (call != NULL) {
203 return call;
204 }
205 }
206
207 return NULL;
208 }
209
inst_check_attr(struct tbs_inst * inst,const struct bt_gatt_attr * attr)210 static bool inst_check_attr(struct tbs_inst *inst, const struct bt_gatt_attr *attr)
211 {
212 for (size_t j = 0; j < inst->attr_count; j++) {
213 if (&inst->attrs[j] == attr) {
214 return true;
215 }
216 }
217
218 return false;
219 }
220
lookup_inst_by_attr(const struct bt_gatt_attr * attr)221 static struct tbs_inst *lookup_inst_by_attr(const struct bt_gatt_attr *attr)
222 {
223 if (attr == NULL) {
224 return NULL;
225 }
226
227 for (int i = 0; i < ARRAY_SIZE(svc_insts); i++) {
228 if (inst_check_attr(&svc_insts[i], attr)) {
229 return &svc_insts[i];
230 }
231 }
232
233 if (inst_check_attr(>bs_inst, attr)) {
234 return >bs_inst;
235 }
236
237 return NULL;
238 }
239
lookup_inst_by_call_index(uint8_t call_index)240 static struct tbs_inst *lookup_inst_by_call_index(uint8_t call_index)
241 {
242 if (call_index == BT_TBS_FREE_CALL_INDEX) {
243 return NULL;
244 }
245
246 if (lookup_call_in_inst(>bs_inst, call_index) != NULL) {
247 return >bs_inst;
248 }
249
250 for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) {
251 if (lookup_call_in_inst(&svc_insts[i], call_index) != NULL) {
252 return &svc_insts[i];
253 }
254 }
255
256 return NULL;
257 }
258
is_authorized(const struct tbs_inst * inst,struct bt_conn * conn)259 static bool is_authorized(const struct tbs_inst *inst, struct bt_conn *conn)
260 {
261 if (inst->authorization_required) {
262 if (tbs_cbs != NULL && tbs_cbs->authorize != NULL) {
263 return tbs_cbs->authorize(conn);
264 } else {
265 return false;
266 }
267 }
268
269 return true;
270 }
271
uri_scheme_in_list(const char * uri_scheme,const char * uri_scheme_list)272 static bool uri_scheme_in_list(const char *uri_scheme, const char *uri_scheme_list)
273 {
274 const size_t scheme_len = strlen(uri_scheme);
275 const size_t scheme_list_len = strlen(uri_scheme_list);
276 const char *uri_scheme_cand = uri_scheme_list;
277 size_t uri_scheme_cand_len;
278 size_t start_idx = 0;
279
280 for (size_t i = 0; i < scheme_list_len; i++) {
281 if (uri_scheme_list[i] == ',') {
282 uri_scheme_cand_len = i - start_idx;
283 if (uri_scheme_cand_len != scheme_len) {
284 continue;
285 }
286
287 if (memcmp(uri_scheme, uri_scheme_cand, scheme_len) == 0) {
288 return true;
289 }
290
291 if (i + 1 < scheme_list_len) {
292 uri_scheme_cand = &uri_scheme_list[i + 1];
293 }
294 }
295 }
296
297 return false;
298 }
299
lookup_inst_by_uri_scheme(const uint8_t * uri,uint8_t uri_len)300 static struct tbs_inst *lookup_inst_by_uri_scheme(const uint8_t *uri, uint8_t uri_len)
301 {
302 char uri_scheme[CONFIG_BT_TBS_MAX_URI_LENGTH] = {0};
303
304 if (uri_len == 0) {
305 return NULL;
306 }
307
308 /* Look for ':' between the first and last char */
309 for (uint8_t i = 1U; i < uri_len - 1U; i++) {
310 if (uri[i] == ':') {
311 (void)memcpy(uri_scheme, uri, i);
312 break;
313 }
314 }
315
316 if (uri_scheme[0] == '\0') {
317 /* No URI scheme found */
318 return NULL;
319 }
320
321 for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) {
322 for (size_t j = 0; j < ARRAY_SIZE(svc_insts[i].calls); j++) {
323 if (uri_scheme_in_list(uri_scheme, svc_insts[i].uri_scheme_list)) {
324 return &svc_insts[i];
325 }
326 }
327 }
328
329 /* If not found in any TBS instance, check GTBS */
330 if (uri_scheme_in_list(uri_scheme, gtbs_inst.uri_scheme_list)) {
331 return >bs_inst;
332 }
333
334 return NULL;
335 }
336
disconnected(struct bt_conn * conn,uint8_t reason)337 static void disconnected(struct bt_conn *conn, uint8_t reason)
338 {
339 /* Clear pending notifications */
340 for (size_t i = 0U; i < ARRAY_SIZE(svc_insts); i++) {
341 const uint8_t conn_index = bt_conn_index(conn);
342 int err;
343
344 err = k_mutex_lock(&svc_insts[i].mutex, MUTEX_TIMEOUT);
345 if (err != 0) {
346 LOG_WRN("Failed to take mutex: %d", err);
347 /* In this case we still need to clear the data, so continue and hope for
348 * the best
349 */
350 }
351
352 if (svc_insts[i].cp_ntf.pending && conn_index == svc_insts[i].cp_ntf.conn_index) {
353 memset(&svc_insts[i].cp_ntf, 0, sizeof(svc_insts[i].cp_ntf));
354 }
355
356 memset(&svc_insts[i].flags[conn_index], 0, sizeof(svc_insts[i].flags[conn_index]));
357
358 if (err == 0) { /* if mutex was locked */
359 err = k_mutex_unlock(&svc_insts[i].mutex);
360 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
361 }
362 }
363 }
364
365 BT_CONN_CB_DEFINE(conn_cb) = {
366 .disconnected = disconnected,
367 };
368
notify(struct bt_conn * conn,const struct bt_uuid * uuid,const struct bt_gatt_attr * attrs,const void * value,size_t value_len)369 static int notify(struct bt_conn *conn, const struct bt_uuid *uuid,
370 const struct bt_gatt_attr *attrs, const void *value, size_t value_len)
371 {
372 const uint8_t att_header_size = 3; /* opcode + handle */
373 const uint16_t att_mtu = bt_gatt_get_mtu(conn);
374
375 __ASSERT(att_mtu > att_header_size, "Could not get valid ATT MTU");
376 const uint16_t maxlen = att_mtu - att_header_size; /* Subtract opcode and handle */
377
378 if (maxlen < value_len) {
379 LOG_DBG("Truncating notification to %u (was %u)", maxlen, value_len);
380 value_len = maxlen;
381 }
382
383 /* Send notification potentially truncated to the MTU */
384 return bt_gatt_notify_uuid(conn, uuid, attrs, value, value_len);
385 }
386
387 struct tbs_notify_cb_info {
388 struct tbs_inst *inst;
389 const struct bt_gatt_attr *attr;
390 void (*value_cb)(struct tbs_flags *flags);
391 };
392
set_value_changed_cb(struct bt_conn * conn,void * data)393 static void set_value_changed_cb(struct bt_conn *conn, void *data)
394 {
395 struct tbs_notify_cb_info *cb_info = data;
396 struct tbs_inst *inst = cb_info->inst;
397 struct tbs_flags *flags = &inst->flags[bt_conn_index(conn)];
398 const struct bt_gatt_attr *attr = cb_info->attr;
399 struct bt_conn_info info;
400 int err;
401
402 err = bt_conn_get_info(conn, &info);
403 __ASSERT(err == 0, "Failed to get conn info: %d", err);
404
405 if (info.state != BT_CONN_STATE_CONNECTED) {
406 /* Not connected */
407 return;
408 }
409
410 if (!bt_gatt_is_subscribed(conn, attr, BT_GATT_CCC_NOTIFY)) {
411 /* Not subscribed */
412 return;
413 }
414
415 /* Set the specific flag based on the provided callback */
416 cb_info->value_cb(flags);
417
418 /* We may schedule the same work multiple times, but that is OK as scheduling the same work
419 * multiple times is a no-op
420 */
421 err = k_work_schedule(&inst->notify_work, K_NO_WAIT);
422 __ASSERT(err >= 0, "Failed to schedule work: %d", err);
423 }
424
set_value_changed(struct tbs_inst * inst,void (* value_cb)(struct tbs_flags * flags),const struct bt_uuid * uuid)425 static void set_value_changed(struct tbs_inst *inst, void (*value_cb)(struct tbs_flags *flags),
426 const struct bt_uuid *uuid)
427 {
428 struct tbs_notify_cb_info cb_info = {
429 .inst = inst,
430 .value_cb = value_cb,
431 .attr = bt_gatt_find_by_uuid(inst->attrs, 0, uuid),
432 };
433
434 __ASSERT(cb_info.attr != NULL, "Failed to look attribute for %s", bt_uuid_str(uuid));
435 bt_conn_foreach(BT_CONN_TYPE_LE, set_value_changed_cb, &cb_info);
436 }
437
set_terminate_reason_changed_cb(struct tbs_flags * flags)438 static void set_terminate_reason_changed_cb(struct tbs_flags *flags)
439 {
440 if (flags->termination_reason_changed) {
441 LOG_DBG("pending notification replaced");
442 }
443
444 flags->termination_reason_changed = true;
445 }
446
tbs_set_terminate_reason(struct tbs_inst * inst,uint8_t call_index,uint8_t reason)447 static void tbs_set_terminate_reason(struct tbs_inst *inst, uint8_t call_index, uint8_t reason)
448 {
449 inst->terminate_reason.call_index = call_index;
450 inst->terminate_reason.reason = reason;
451 LOG_DBG("Index %u: call index 0x%02x, reason %s", inst_index(inst), call_index,
452 bt_tbs_term_reason_str(reason));
453
454 set_value_changed(inst, set_terminate_reason_changed_cb, BT_UUID_TBS_TERMINATE_REASON);
455 }
456
457 /**
458 * @brief Gets the next free call_index
459 *
460 * For each new call, the call index should be incremented and wrap at 255.
461 * However, the index = 0 is reserved for outgoing calls
462 *
463 * Call indexes are shared among all bearers, so there is always a 1:1 between a call index and a
464 * bearer
465 *
466 * @return uint8_t The next free call index
467 */
next_free_call_index(void)468 static uint8_t next_free_call_index(void)
469 {
470 for (int i = 0; i < CONFIG_BT_TBS_MAX_CALLS; i++) {
471 static uint8_t next_call_index;
472 const struct bt_tbs_call *call;
473
474 /* For each new call, the call index should be incremented */
475 next_call_index++;
476
477 if (next_call_index == BT_TBS_FREE_CALL_INDEX) {
478 /* call_index = 0 reserved for outgoing calls */
479 next_call_index = 1;
480 }
481
482 call = lookup_call(next_call_index);
483 if (call == NULL) {
484 return next_call_index;
485 }
486 }
487
488 LOG_DBG("No more free call spots");
489
490 return BT_TBS_FREE_CALL_INDEX;
491 }
492
call_alloc(struct tbs_inst * inst,uint8_t state,const uint8_t * uri,uint16_t uri_len)493 static struct bt_tbs_call *call_alloc(struct tbs_inst *inst, uint8_t state, const uint8_t *uri,
494 uint16_t uri_len)
495 {
496 struct bt_tbs_call *free_call = NULL;
497
498 for (size_t i = 0; i < ARRAY_SIZE(inst->calls); i++) {
499 if (inst->calls[i].index == BT_TBS_FREE_CALL_INDEX) {
500 free_call = &inst->calls[i];
501 break;
502 }
503 }
504
505 if (free_call == NULL) {
506 return NULL;
507 }
508
509 __ASSERT_NO_MSG(uri_len < sizeof(free_call->remote_uri));
510
511 memset(free_call, 0, sizeof(*free_call));
512
513 /* Get the next free call_index */
514 free_call->index = next_free_call_index();
515 __ASSERT_NO_MSG(free_call->index != BT_TBS_FREE_CALL_INDEX);
516
517 free_call->state = state;
518 (void)memcpy(free_call->remote_uri, uri, uri_len);
519 free_call->remote_uri[uri_len] = '\0';
520
521 return free_call;
522 }
523
call_free(struct bt_tbs_call * call)524 static void call_free(struct bt_tbs_call *call)
525 {
526 call->index = BT_TBS_FREE_CALL_INDEX;
527 }
528
net_buf_put_call_states_by_inst(const struct tbs_inst * inst,struct net_buf_simple * buf)529 static void net_buf_put_call_states_by_inst(const struct tbs_inst *inst, struct net_buf_simple *buf)
530 {
531 const struct bt_tbs_call *call;
532 const struct bt_tbs_call *calls;
533 size_t call_count;
534
535 calls = inst->calls;
536 call_count = ARRAY_SIZE(inst->calls);
537
538 for (size_t i = 0; i < call_count; i++) {
539 call = &calls[i];
540 if (call->index == BT_TBS_FREE_CALL_INDEX) {
541 continue;
542 }
543
544 if (buf->len + 3U > buf->size) {
545 LOG_WRN("Not able to store all call states in buffer");
546 return;
547 }
548
549 net_buf_simple_add_u8(buf, call->index);
550 net_buf_simple_add_u8(buf, call->state);
551 net_buf_simple_add_u8(buf, call->flags);
552 }
553 }
554
net_buf_put_call_states(const struct tbs_inst * inst,struct net_buf_simple * buf)555 static void net_buf_put_call_states(const struct tbs_inst *inst, struct net_buf_simple *buf)
556 {
557 net_buf_simple_reset(buf);
558
559 net_buf_put_call_states_by_inst(inst, buf);
560
561 /* For GTBS we add all the calls the GTBS bearer has itself, as well as all the other
562 * bearers
563 */
564 if (inst_is_gtbs(inst)) {
565 for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) {
566 net_buf_put_call_states_by_inst(&svc_insts[i], buf);
567 }
568 }
569 }
570
net_buf_put_current_calls_by_inst(const struct tbs_inst * inst,struct net_buf_simple * buf)571 static void net_buf_put_current_calls_by_inst(const struct tbs_inst *inst,
572 struct net_buf_simple *buf)
573 {
574 const struct bt_tbs_call *call;
575 const struct bt_tbs_call *calls;
576 size_t call_count;
577 size_t uri_length;
578 size_t item_len;
579
580 calls = inst->calls;
581 call_count = ARRAY_SIZE(inst->calls);
582
583 for (size_t i = 0; i < call_count; i++) {
584 call = &calls[i];
585 if (call->index == BT_TBS_FREE_CALL_INDEX) {
586 continue;
587 }
588
589 uri_length = strlen(call->remote_uri);
590 item_len = sizeof(call->index) + sizeof(call->state) + sizeof(call->flags) +
591 uri_length;
592
593 __ASSERT_NO_MSG(item_len <= UINT8_MAX);
594
595 if (buf->len + sizeof(uint8_t) + item_len > buf->size) {
596 LOG_WRN("Not able to store all calls in buffer");
597 return;
598 }
599
600 net_buf_simple_add_u8(buf, (uint8_t)item_len);
601 net_buf_simple_add_u8(buf, call->index);
602 net_buf_simple_add_u8(buf, call->state);
603 net_buf_simple_add_u8(buf, call->flags);
604 net_buf_simple_add_mem(buf, call->remote_uri, uri_length);
605 }
606 }
607
net_buf_put_current_calls(const struct tbs_inst * inst,struct net_buf_simple * buf)608 static void net_buf_put_current_calls(const struct tbs_inst *inst, struct net_buf_simple *buf)
609 {
610 net_buf_simple_reset(buf);
611
612 net_buf_put_current_calls_by_inst(inst, buf);
613
614 /* For GTBS we add all the calls the GTBS bearer has itself, as well as all the other
615 * bearers
616 */
617 if (inst_is_gtbs(inst)) {
618 for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) {
619 net_buf_put_current_calls_by_inst(&svc_insts[i], buf);
620 }
621 }
622 }
623
set_call_state_changed_cb(struct tbs_flags * flags)624 static void set_call_state_changed_cb(struct tbs_flags *flags)
625 {
626 if (flags->call_state_changed) {
627 LOG_DBG("pending notification replaced");
628 }
629
630 flags->call_state_changed = true;
631 }
632
set_list_current_calls_changed_cb(struct tbs_flags * flags)633 static void set_list_current_calls_changed_cb(struct tbs_flags *flags)
634 {
635 if (flags->bearer_list_current_calls_changed) {
636 LOG_DBG("pending notification replaced");
637 }
638
639 flags->bearer_list_current_calls_changed = true;
640 }
641
inst_notify_calls(struct tbs_inst * inst)642 static int inst_notify_calls(struct tbs_inst *inst)
643 {
644 set_value_changed(inst, set_call_state_changed_cb, BT_UUID_TBS_CALL_STATE);
645 set_value_changed(inst, set_list_current_calls_changed_cb, BT_UUID_TBS_LIST_CURRENT_CALLS);
646
647 return 0;
648 }
649
notify_calls(struct tbs_inst * inst)650 static int notify_calls(struct tbs_inst *inst)
651 {
652 int err;
653
654 if (inst == NULL) {
655 return -EINVAL;
656 }
657
658 /* Notify TBS */
659 err = inst_notify_calls(inst);
660 if (err != 0) {
661 return err;
662 }
663
664 if (!inst_is_gtbs(inst)) {
665 /* If the instance is different than the GTBS notify on the GTBS instance as well */
666 err = inst_notify_calls(>bs_inst);
667 if (err != 0) {
668 return err;
669 }
670 }
671
672 return 0;
673 }
674
675 /**
676 * @brief Attempt to move a call in an instance from dialing to alerting
677 *
678 * This function will look through the state of an instance to see if there are any calls in the
679 * instance that are in the dialing state, and move them to the dialing state if we do not have any
680 * pending call state notification. The reason for this is that we do not have an API for the
681 * application to change from dialing to alterting state at this point, but the qualification tests
682 * require us to do this state change.
683 * Since we only notify the latest value, we need to notify dialing first for both current calls and
684 * call states, and then switch to the alerting state for the call and then notify again.
685 *
686 * @param inst The instance to attempt the state change on
687 * @retval true There was a state change
688 * @retval false There was not a state change
689 */
try_change_dialing_call_to_alerting(struct tbs_inst * inst)690 static bool try_change_dialing_call_to_alerting(struct tbs_inst *inst)
691 {
692 bool state_changed = false;
693
694 /* If we still have pending state change notifications, we cannot change the state
695 * autonomously
696 */
697 for (size_t i = 0U; i < ARRAY_SIZE(inst->flags); i++) {
698 const struct tbs_flags *flags = &inst->flags[i];
699
700 if (flags->bearer_list_current_calls_changed || flags->call_state_changed) {
701 return false;
702 }
703 }
704
705 if (!inst_is_gtbs(inst)) {
706 /* If inst is not the GTBS then we also need to ensure that GTBS is done notifying
707 * before changing state
708 */
709 for (size_t i = 0U; i < ARRAY_SIZE(gtbs_inst.flags); i++) {
710 const struct tbs_flags *flags = >bs_inst.flags[i];
711
712 if (flags->bearer_list_current_calls_changed || flags->call_state_changed) {
713 return false;
714 }
715 }
716 }
717
718 /* Check if we have any calls in the dialing state */
719 for (size_t i = 0U; i < ARRAY_SIZE(inst->calls); i++) {
720 if (inst->calls[i].state == BT_TBS_CALL_STATE_DIALING) {
721 inst->calls[i].state = BT_TBS_CALL_STATE_ALERTING;
722 state_changed = true;
723 break;
724 }
725 }
726
727 if (state_changed) {
728 notify_calls(inst);
729 }
730
731 return state_changed;
732 }
733
notify_handler_cb(struct bt_conn * conn,void * data)734 static void notify_handler_cb(struct bt_conn *conn, void *data)
735 {
736 struct tbs_inst *inst = data;
737 struct tbs_flags *flags = &inst->flags[bt_conn_index(conn)];
738 struct bt_conn_info info;
739 int err;
740
741 err = bt_conn_get_info(conn, &info);
742 __ASSERT(err == 0, "Failed to get conn info: %d", err);
743
744 if (info.state != BT_CONN_STATE_CONNECTED) {
745 /* Not connected */
746 return;
747 }
748
749 if (!inst_is_gtbs(inst)) {
750 notify_handler_cb(conn, >bs_inst);
751 }
752
753 err = k_mutex_lock(&inst->mutex, K_NO_WAIT);
754 if (err != 0) {
755 LOG_DBG("Failed to take mutex: %d", err);
756 goto reschedule;
757 }
758
759 if (flags->bearer_provider_name_changed) {
760 LOG_DBG("Notifying Bearer Provider Name: %s", inst->provider_name);
761
762 err = notify(conn, BT_UUID_TBS_PROVIDER_NAME, inst->attrs, inst->provider_name,
763 strlen(inst->provider_name));
764 if (err == 0) {
765 flags->bearer_provider_name_changed = false;
766 } else {
767 goto fail;
768 }
769 }
770
771 if (flags->bearer_technology_changed) {
772 LOG_DBG("Notifying Bearer Technology: %s (0x%02x)",
773 bt_tbs_technology_str(inst->technology), inst->technology);
774
775 err = notify(conn, BT_UUID_TBS_TECHNOLOGY, inst->attrs, &inst->technology,
776 sizeof(inst->technology));
777 if (err == 0) {
778 flags->bearer_technology_changed = false;
779 } else {
780 goto fail;
781 }
782 }
783
784 if (flags->bearer_uri_schemes_supported_list_changed) {
785 LOG_DBG("Notifying Bearer URI schemes supported list: %s", inst->uri_scheme_list);
786
787 err = notify(conn, BT_UUID_TBS_URI_LIST, inst->attrs, &inst->uri_scheme_list,
788 strlen(inst->uri_scheme_list));
789 if (err == 0) {
790 flags->bearer_uri_schemes_supported_list_changed = false;
791 } else {
792 goto fail;
793 }
794 }
795
796 if (flags->bearer_signal_strength_changed) {
797 LOG_DBG("Notifying Bearer Signal Strength: 0x%02x", inst->signal_strength);
798
799 err = notify(conn, BT_UUID_TBS_SIGNAL_STRENGTH, inst->attrs, &inst->signal_strength,
800 sizeof(inst->signal_strength));
801 if (err == 0) {
802 flags->bearer_signal_strength_changed = false;
803 } else {
804 goto fail;
805 }
806 }
807
808 if (flags->bearer_list_current_calls_changed) {
809 LOG_DBG("Notifying Bearer List Current Calls");
810
811 net_buf_put_current_calls(inst, &read_buf);
812 err = notify(conn, BT_UUID_TBS_LIST_CURRENT_CALLS, inst->attrs, read_buf.data,
813 read_buf.len);
814 if (err == 0) {
815 flags->bearer_list_current_calls_changed = false;
816 } else {
817 goto fail;
818 }
819
820 if (try_change_dialing_call_to_alerting(inst)) {
821 goto reschedule;
822 }
823 }
824
825 if (flags->status_flags_changed) {
826 LOG_DBG("Notifying Status Flags: 0x%02x", inst->status_flags);
827
828 err = notify(conn, BT_UUID_TBS_STATUS_FLAGS, inst->attrs, &inst->status_flags,
829 sizeof(inst->status_flags));
830 if (err == 0) {
831 flags->status_flags_changed = false;
832 } else {
833 goto fail;
834 }
835 }
836
837 if (flags->incoming_call_target_bearer_uri_changed) {
838 LOG_DBG("Notifying Incoming Call Target Bearer URI: call index 0x%02x, URI %s",
839 inst->incoming_uri.call_index, inst->incoming_uri.uri);
840
841 err = notify(conn, BT_UUID_TBS_INCOMING_URI, inst->attrs, &inst->incoming_uri,
842 sizeof(inst->incoming_uri.call_index) +
843 strlen(inst->incoming_uri.uri));
844 if (err == 0) {
845 flags->incoming_call_target_bearer_uri_changed = false;
846 } else {
847 goto fail;
848 }
849 }
850
851 if (flags->call_state_changed) {
852 LOG_DBG("Notifying Call States");
853
854 net_buf_put_call_states(inst, &read_buf);
855 err = notify(conn, BT_UUID_TBS_CALL_STATE, inst->attrs, read_buf.data,
856 read_buf.len);
857 if (err == 0) {
858 flags->call_state_changed = false;
859 } else {
860 goto fail;
861 }
862
863 if (try_change_dialing_call_to_alerting(inst)) {
864 goto reschedule;
865 }
866 }
867
868 if (flags->termination_reason_changed) {
869 LOG_DBG("Notifying Bearer Provider Name: call_index 0x%02x reason 0x%02x",
870 inst->terminate_reason.call_index, inst->terminate_reason.reason);
871
872 err = notify(conn, BT_UUID_TBS_TERMINATE_REASON, inst->attrs,
873 &inst->terminate_reason, sizeof(inst->terminate_reason));
874 if (err == 0) {
875 flags->termination_reason_changed = false;
876 } else {
877 goto fail;
878 }
879 }
880
881 if (flags->incoming_call_changed) {
882 LOG_DBG("Notifying Incoming Call: call index 0x%02x, URI %s",
883 inst->in_call.call_index, inst->in_call.uri);
884
885 err = notify(conn, BT_UUID_TBS_INCOMING_CALL, inst->attrs, &inst->in_call,
886 sizeof(inst->in_call.call_index) + strlen(inst->in_call.uri));
887 if (err == 0) {
888 flags->incoming_call_changed = false;
889 } else {
890 goto fail;
891 }
892 }
893
894 if (flags->call_friendly_name_changed) {
895 LOG_DBG("Notifying Friendly Name: call index 0x%02x, URI %s",
896 inst->friendly_name.call_index, inst->friendly_name.uri);
897
898 err = notify(conn, BT_UUID_TBS_FRIENDLY_NAME, inst->attrs, &inst->friendly_name,
899 sizeof(inst->friendly_name.call_index) +
900 strlen(inst->friendly_name.uri));
901 if (err == 0) {
902 flags->call_friendly_name_changed = false;
903 } else {
904 goto fail;
905 }
906 }
907
908 /* The TBS spec is a bit unclear on this, but the TBS test spec states that the control
909 * operation notification shall be sent after the current calls and call state
910 * notifications, this shall be triggered after those.
911 */
912 if (inst->cp_ntf.pending && bt_conn_index(conn) == inst->cp_ntf.conn_index &&
913 !flags->bearer_list_current_calls_changed && !flags->call_state_changed) {
914 const struct bt_tbs_call_cp_notify *notification = &inst->cp_ntf.notification;
915
916 LOG_DBG("Notifying CCP: Call index %u, %s opcode and status %s",
917 notification->call_index, bt_tbs_opcode_str(notification->opcode),
918 bt_tbs_status_str(notification->status));
919
920 err = notify(conn, BT_UUID_TBS_CALL_CONTROL_POINT, inst->attrs, notification,
921 sizeof(*notification));
922 if (err == 0) {
923 inst->cp_ntf.pending = false;
924 } else {
925 goto fail;
926 }
927 }
928
929 fail:
930 if (err != 0) {
931 LOG_DBG("Notify failed (%d), retrying next connection interval", err);
932 reschedule:
933 err = k_work_reschedule(&inst->notify_work,
934 K_USEC(BT_CONN_INTERVAL_TO_US(info.le.interval)));
935 __ASSERT(err >= 0, "Failed to reschedule work: %d", err);
936 }
937
938 err = k_mutex_unlock(&inst->mutex);
939 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
940 }
941
notify_work_handler(struct k_work * work)942 static void notify_work_handler(struct k_work *work)
943 {
944 struct tbs_inst *inst =
945 CONTAINER_OF(k_work_delayable_from_work(work), struct tbs_inst, notify_work);
946
947 bt_conn_foreach(BT_CONN_TYPE_LE, notify_handler_cb, inst);
948 }
949
read_provider_name(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)950 static ssize_t read_provider_name(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
951 uint16_t len, uint16_t offset)
952 {
953 const struct tbs_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
954
955 LOG_DBG("Index %u, Provider name %s", inst_index(inst), inst->provider_name);
956
957 return bt_gatt_attr_read(conn, attr, buf, len, offset, inst->provider_name,
958 strlen(inst->provider_name));
959 }
960
provider_name_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)961 static void provider_name_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
962 {
963 const struct tbs_inst *inst = lookup_inst_by_attr(attr);
964
965 if (inst != NULL) {
966 LOG_DBG("Index %u: value 0x%04x", inst_index(inst), value);
967 }
968 }
969
read_uci(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)970 static ssize_t read_uci(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
971 uint16_t len, uint16_t offset)
972 {
973 const struct tbs_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
974
975 LOG_DBG("Index %u: UCI %s", inst_index(inst), inst->uci);
976
977 return bt_gatt_attr_read(conn, attr, buf, len, offset, inst->uci, strlen(inst->uci));
978 }
979
read_technology(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)980 static ssize_t read_technology(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
981 uint16_t len, uint16_t offset)
982 {
983 const struct tbs_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
984
985 LOG_DBG("Index %u: Technology 0x%02x", inst_index(inst), inst->technology);
986
987 return bt_gatt_attr_read(conn, attr, buf, len, offset, &inst->technology,
988 sizeof(inst->technology));
989 }
990
technology_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)991 static void technology_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
992 {
993 const struct tbs_inst *inst = lookup_inst_by_attr(attr);
994
995 if (inst != NULL) {
996 LOG_DBG("Index %u: value 0x%04x", inst_index(inst), value);
997 }
998 }
999
read_uri_scheme_list(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)1000 static ssize_t read_uri_scheme_list(struct bt_conn *conn, const struct bt_gatt_attr *attr,
1001 void *buf, uint16_t len, uint16_t offset)
1002 {
1003 const struct tbs_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
1004
1005 net_buf_simple_reset(&read_buf);
1006
1007 net_buf_simple_add_mem(&read_buf, inst->uri_scheme_list, strlen(inst->uri_scheme_list));
1008
1009 if (inst_is_gtbs(inst)) {
1010 /* TODO: Make uri schemes unique */
1011 for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) {
1012 size_t uri_len = strlen(svc_insts[i].uri_scheme_list);
1013
1014 if (read_buf.len + uri_len >= read_buf.size) {
1015 LOG_WRN("Cannot fit all TBS instances in GTBS "
1016 "URI scheme list");
1017 break;
1018 }
1019
1020 net_buf_simple_add_mem(&read_buf, svc_insts[i].uri_scheme_list, uri_len);
1021 }
1022
1023 LOG_DBG("GTBS: URI scheme %.*s", read_buf.len, read_buf.data);
1024 } else {
1025 LOG_DBG("Index %u: URI scheme %.*s", inst_index(inst), read_buf.len, read_buf.data);
1026 }
1027
1028 return bt_gatt_attr_read(conn, attr, buf, len, offset, read_buf.data, read_buf.len);
1029 }
1030
uri_scheme_list_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)1031 static void uri_scheme_list_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
1032 {
1033 const struct tbs_inst *inst = lookup_inst_by_attr(attr);
1034
1035 if (inst != NULL) {
1036 LOG_DBG("Index %u: value 0x%04x", inst_index(inst), value);
1037 }
1038 }
1039
read_signal_strength(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)1040 static ssize_t read_signal_strength(struct bt_conn *conn, const struct bt_gatt_attr *attr,
1041 void *buf, uint16_t len, uint16_t offset)
1042 {
1043 const struct tbs_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
1044
1045 LOG_DBG("Index %u: Signal strength 0x%02x", inst_index(inst), inst->signal_strength);
1046
1047 return bt_gatt_attr_read(conn, attr, buf, len, offset, &inst->signal_strength,
1048 sizeof(inst->signal_strength));
1049 }
1050
signal_strength_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)1051 static void signal_strength_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
1052 {
1053 const struct tbs_inst *inst = lookup_inst_by_attr(attr);
1054
1055 if (inst != NULL) {
1056 LOG_DBG("Index %u: value 0x%04x", inst_index(inst), value);
1057 }
1058 }
1059
read_signal_strength_interval(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)1060 static ssize_t read_signal_strength_interval(struct bt_conn *conn, const struct bt_gatt_attr *attr,
1061 void *buf, uint16_t len, uint16_t offset)
1062 {
1063 const struct tbs_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
1064
1065 LOG_DBG("Index %u: Signal strength interval 0x%02x",
1066 inst_index(inst), inst->signal_strength_interval);
1067
1068 return bt_gatt_attr_read(conn, attr, buf, len, offset, &inst->signal_strength_interval,
1069 sizeof(inst->signal_strength_interval));
1070 }
1071
write_signal_strength_interval(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)1072 static ssize_t write_signal_strength_interval(struct bt_conn *conn, const struct bt_gatt_attr *attr,
1073 const void *buf, uint16_t len, uint16_t offset,
1074 uint8_t flags)
1075 {
1076 struct tbs_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
1077 struct net_buf_simple net_buf;
1078 uint8_t signal_strength_interval;
1079
1080 if (!is_authorized(inst, conn)) {
1081 return BT_GATT_ERR(BT_ATT_ERR_AUTHORIZATION);
1082 }
1083
1084 if (offset != 0) {
1085 return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
1086 }
1087
1088 if (len != sizeof(signal_strength_interval)) {
1089 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
1090 }
1091
1092 net_buf_simple_init_with_data(&net_buf, (void *)buf, len);
1093 signal_strength_interval = net_buf_simple_pull_u8(&net_buf);
1094
1095 inst->signal_strength_interval = signal_strength_interval;
1096 LOG_DBG("Index %u: 0x%02x", inst_index(inst), signal_strength_interval);
1097
1098 return len;
1099 }
1100
current_calls_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)1101 static void current_calls_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
1102 {
1103 struct tbs_inst *inst = lookup_inst_by_attr(attr);
1104
1105 if (inst != NULL) {
1106 LOG_DBG("Index %u: value 0x%04x", inst_index(inst), value);
1107 }
1108 }
1109
read_current_calls(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)1110 static ssize_t read_current_calls(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
1111 uint16_t len, uint16_t offset)
1112 {
1113 const struct tbs_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
1114
1115 LOG_DBG("Index %u", inst_index(inst));
1116
1117 net_buf_put_current_calls(inst, &read_buf);
1118
1119 if (offset == 0) {
1120 LOG_HEXDUMP_DBG(read_buf.data, read_buf.len, "Current calls");
1121 }
1122
1123 return bt_gatt_attr_read(conn, attr, buf, len, offset, read_buf.data, read_buf.len);
1124 }
1125
read_ccid(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)1126 static ssize_t read_ccid(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
1127 uint16_t len, uint16_t offset)
1128 {
1129 const struct tbs_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
1130
1131 LOG_DBG("Index %u: CCID 0x%02x", inst_index(inst), inst->ccid);
1132
1133 return bt_gatt_attr_read(conn, attr, buf, len, offset, &inst->ccid, sizeof(inst->ccid));
1134 }
1135
read_status_flags(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)1136 static ssize_t read_status_flags(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
1137 uint16_t len, uint16_t offset)
1138 {
1139 const struct tbs_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
1140 const uint16_t status_flags_le = sys_cpu_to_le16(inst->optional_opcodes);
1141
1142 LOG_DBG("Index %u: status_flags 0x%04x", inst_index(inst), inst->status_flags);
1143
1144 return bt_gatt_attr_read(conn, attr, buf, len, offset, &status_flags_le,
1145 sizeof(status_flags_le));
1146 }
1147
status_flags_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)1148 static void status_flags_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
1149 {
1150 const struct tbs_inst *inst = lookup_inst_by_attr(attr);
1151
1152 if (inst != NULL) {
1153 LOG_DBG("Index %u: value 0x%04x", inst_index(inst), value);
1154 }
1155 }
1156
read_incoming_uri(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)1157 static ssize_t read_incoming_uri(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
1158 uint16_t len, uint16_t offset)
1159 {
1160 const struct tbs_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
1161 const struct bt_tbs_in_uri *inc_call_target;
1162 size_t val_len;
1163
1164 inc_call_target = &inst->incoming_uri;
1165
1166 LOG_DBG("Index %u: call index 0x%02x, URI %s", inst_index(inst),
1167 inc_call_target->call_index, inc_call_target->uri);
1168
1169 if (!inc_call_target->call_index) {
1170 LOG_DBG("URI not set");
1171
1172 return bt_gatt_attr_read(conn, attr, buf, len, offset, NULL, 0);
1173 }
1174
1175 val_len = sizeof(inc_call_target->call_index) + strlen(inc_call_target->uri);
1176
1177 return bt_gatt_attr_read(conn, attr, buf, len, offset, inc_call_target, val_len);
1178 }
1179
incoming_uri_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)1180 static void incoming_uri_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
1181 {
1182 const struct tbs_inst *inst = lookup_inst_by_attr(attr);
1183
1184 if (inst != NULL) {
1185 LOG_DBG("Index %u: value 0x%04x", inst_index(inst), value);
1186 }
1187 }
1188
read_call_state(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)1189 static ssize_t read_call_state(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
1190 uint16_t len, uint16_t offset)
1191 {
1192 const struct tbs_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
1193
1194 LOG_DBG("Index %u", inst_index(inst));
1195
1196 net_buf_put_call_states(inst, &read_buf);
1197
1198 if (offset == 0) {
1199 LOG_HEXDUMP_DBG(read_buf.data, read_buf.len, "Call state");
1200 }
1201
1202 return bt_gatt_attr_read(conn, attr, buf, len, offset, read_buf.data, read_buf.len);
1203 }
1204
call_state_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)1205 static void call_state_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
1206 {
1207 struct tbs_inst *inst = lookup_inst_by_attr(attr);
1208
1209 if (inst != NULL) {
1210 LOG_DBG("Index %u: value 0x%04x", inst_index(inst), value);
1211 }
1212 }
1213
hold_other_calls(struct tbs_inst * inst,uint8_t call_index_cnt,const uint8_t * call_indexes)1214 static void hold_other_calls(struct tbs_inst *inst, uint8_t call_index_cnt,
1215 const uint8_t *call_indexes)
1216 {
1217 held_calls_cnt = 0;
1218
1219 for (int i = 0; i < ARRAY_SIZE(inst->calls); i++) {
1220 bool hold_call = true;
1221 uint8_t call_state;
1222
1223 for (int j = 0; j < call_index_cnt; j++) {
1224 if (inst->calls[i].index == call_indexes[j]) {
1225 hold_call = false;
1226 break;
1227 }
1228 }
1229
1230 if (!hold_call) {
1231 continue;
1232 }
1233
1234 call_state = inst->calls[i].state;
1235 if (call_state == BT_TBS_CALL_STATE_ACTIVE) {
1236 inst->calls[i].state = BT_TBS_CALL_STATE_LOCALLY_HELD;
1237 held_calls[held_calls_cnt++] = &inst->calls[i];
1238 } else if (call_state == BT_TBS_CALL_STATE_REMOTELY_HELD) {
1239 inst->calls[i].state = BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD;
1240 held_calls[held_calls_cnt++] = &inst->calls[i];
1241 }
1242 }
1243 }
1244
accept_call(struct tbs_inst * inst,const struct bt_tbs_call_cp_acc * ccp)1245 static uint8_t accept_call(struct tbs_inst *inst, const struct bt_tbs_call_cp_acc *ccp)
1246 {
1247 struct bt_tbs_call *call = lookup_call_in_inst(inst, ccp->call_index);
1248
1249 if (call == NULL) {
1250 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1251 }
1252
1253 if (call->state == BT_TBS_CALL_STATE_INCOMING) {
1254 call->state = BT_TBS_CALL_STATE_ACTIVE;
1255
1256 hold_other_calls(inst, 1, &ccp->call_index);
1257
1258 return BT_TBS_RESULT_CODE_SUCCESS;
1259 } else {
1260 return BT_TBS_RESULT_CODE_STATE_MISMATCH;
1261 }
1262 }
1263
terminate_call(struct tbs_inst * inst,const struct bt_tbs_call_cp_term * ccp,uint8_t reason)1264 static uint8_t terminate_call(struct tbs_inst *inst, const struct bt_tbs_call_cp_term *ccp,
1265 uint8_t reason)
1266 {
1267 struct bt_tbs_call *call = lookup_call_in_inst(inst, ccp->call_index);
1268
1269 if (call == NULL) {
1270 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1271 }
1272
1273 call_free(call);
1274 tbs_set_terminate_reason(inst, ccp->call_index, reason);
1275
1276 if (!inst_is_gtbs(inst)) {
1277 /* If the instance is different than the GTBS we set the termination reason and
1278 * notify on the GTBS instance as well
1279 */
1280 tbs_set_terminate_reason(>bs_inst, ccp->call_index, reason);
1281 }
1282
1283 return BT_TBS_RESULT_CODE_SUCCESS;
1284 }
1285
tbs_hold_call(struct tbs_inst * inst,const struct bt_tbs_call_cp_hold * ccp)1286 static uint8_t tbs_hold_call(struct tbs_inst *inst, const struct bt_tbs_call_cp_hold *ccp)
1287 {
1288 struct bt_tbs_call *call = lookup_call_in_inst(inst, ccp->call_index);
1289
1290 if ((inst->optional_opcodes & BT_TBS_FEATURE_HOLD) == 0) {
1291 return BT_TBS_RESULT_CODE_OPCODE_NOT_SUPPORTED;
1292 }
1293
1294 if (call == NULL) {
1295 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1296 }
1297
1298 if (call->state == BT_TBS_CALL_STATE_ACTIVE) {
1299 call->state = BT_TBS_CALL_STATE_LOCALLY_HELD;
1300 } else if (call->state == BT_TBS_CALL_STATE_REMOTELY_HELD) {
1301 call->state = BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD;
1302 } else if (call->state == BT_TBS_CALL_STATE_INCOMING) {
1303 call->state = BT_TBS_CALL_STATE_LOCALLY_HELD;
1304 } else {
1305 return BT_TBS_RESULT_CODE_STATE_MISMATCH;
1306 }
1307
1308 return BT_TBS_RESULT_CODE_SUCCESS;
1309 }
1310
retrieve_call(struct tbs_inst * inst,const struct bt_tbs_call_cp_retrieve * ccp)1311 static uint8_t retrieve_call(struct tbs_inst *inst, const struct bt_tbs_call_cp_retrieve *ccp)
1312 {
1313 struct bt_tbs_call *call = lookup_call_in_inst(inst, ccp->call_index);
1314
1315 if ((inst->optional_opcodes & BT_TBS_FEATURE_HOLD) == 0) {
1316 return BT_TBS_RESULT_CODE_OPCODE_NOT_SUPPORTED;
1317 }
1318
1319 if (call == NULL) {
1320 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1321 }
1322
1323 if (call->state == BT_TBS_CALL_STATE_LOCALLY_HELD) {
1324 call->state = BT_TBS_CALL_STATE_ACTIVE;
1325 } else if (call->state == BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD) {
1326 call->state = BT_TBS_CALL_STATE_REMOTELY_HELD;
1327 } else {
1328 return BT_TBS_RESULT_CODE_STATE_MISMATCH;
1329 }
1330
1331 hold_other_calls(inst, 1, &ccp->call_index);
1332
1333 return BT_TBS_RESULT_CODE_SUCCESS;
1334 }
1335
originate_call(struct tbs_inst * inst,const struct bt_tbs_call_cp_originate * ccp,uint16_t uri_len,uint8_t * call_index)1336 static int originate_call(struct tbs_inst *inst, const struct bt_tbs_call_cp_originate *ccp,
1337 uint16_t uri_len, uint8_t *call_index)
1338 {
1339 struct bt_tbs_call *call;
1340
1341 /* Only allow one active outgoing call */
1342 for (int i = 0; i < CONFIG_BT_TBS_MAX_CALLS; i++) {
1343 if (inst->calls[i].state == BT_TBS_CALL_STATE_ALERTING) {
1344 return BT_TBS_RESULT_CODE_OPERATION_NOT_POSSIBLE;
1345 }
1346 }
1347
1348 if (!bt_tbs_valid_uri(ccp->uri, uri_len)) {
1349 return BT_TBS_RESULT_CODE_INVALID_URI;
1350 }
1351
1352 call = call_alloc(inst, BT_TBS_CALL_STATE_DIALING, ccp->uri, uri_len);
1353 if (call == NULL) {
1354 return BT_TBS_RESULT_CODE_OUT_OF_RESOURCES;
1355 }
1356
1357 BT_TBS_CALL_FLAG_SET_OUTGOING(call->flags);
1358
1359 hold_other_calls(inst, 1, &call->index);
1360
1361 LOG_DBG("New call with call index %u", call->index);
1362
1363 *call_index = call->index;
1364 return BT_TBS_RESULT_CODE_SUCCESS;
1365 }
1366
join_calls(struct tbs_inst * inst,const struct bt_tbs_call_cp_join * ccp,uint16_t call_index_cnt)1367 static uint8_t join_calls(struct tbs_inst *inst, const struct bt_tbs_call_cp_join *ccp,
1368 uint16_t call_index_cnt)
1369 {
1370 struct bt_tbs_call *joined_calls[CONFIG_BT_TBS_MAX_CALLS];
1371 uint8_t call_state;
1372
1373 if ((inst->optional_opcodes & BT_TBS_FEATURE_JOIN) == 0) {
1374 return BT_TBS_RESULT_CODE_OPCODE_NOT_SUPPORTED;
1375 }
1376
1377 /* Check length */
1378 if (call_index_cnt < 2 || call_index_cnt > CONFIG_BT_TBS_MAX_CALLS) {
1379 return BT_TBS_RESULT_CODE_OPERATION_NOT_POSSIBLE;
1380 }
1381
1382 /* Check for duplicates */
1383 for (int i = 0; i < call_index_cnt; i++) {
1384 for (int j = 0; j < i; j++) {
1385 if (ccp->call_indexes[i] == ccp->call_indexes[j]) {
1386 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1387 }
1388 }
1389 }
1390
1391 /* Validate that all calls are in a joinable state */
1392 for (int i = 0; i < call_index_cnt; i++) {
1393 joined_calls[i] = lookup_call_in_inst(inst, ccp->call_indexes[i]);
1394 if (joined_calls[i] == NULL) {
1395 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1396 }
1397
1398 call_state = joined_calls[i]->state;
1399
1400 if (call_state == BT_TBS_CALL_STATE_INCOMING) {
1401 return BT_TBS_RESULT_CODE_OPERATION_NOT_POSSIBLE;
1402 }
1403
1404 if (call_state != BT_TBS_CALL_STATE_LOCALLY_HELD &&
1405 call_state != BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD &&
1406 call_state != BT_TBS_CALL_STATE_ACTIVE) {
1407 return BT_TBS_RESULT_CODE_STATE_MISMATCH;
1408 }
1409 }
1410
1411 /* Join all calls */
1412 for (int i = 0; i < call_index_cnt; i++) {
1413 call_state = joined_calls[i]->state;
1414
1415 if (call_state == BT_TBS_CALL_STATE_LOCALLY_HELD) {
1416 joined_calls[i]->state = BT_TBS_CALL_STATE_ACTIVE;
1417 } else if (call_state == BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD) {
1418 joined_calls[i]->state = BT_TBS_CALL_STATE_REMOTELY_HELD;
1419 } else if (call_state == BT_TBS_CALL_STATE_INCOMING) {
1420 joined_calls[i]->state = BT_TBS_CALL_STATE_ACTIVE;
1421 }
1422 /* else active => Do nothing */
1423 }
1424
1425 hold_other_calls(inst, call_index_cnt, ccp->call_indexes);
1426
1427 return BT_TBS_RESULT_CODE_SUCCESS;
1428 }
1429
notify_app(struct bt_conn * conn,struct tbs_inst * inst,uint16_t len,const union bt_tbs_call_cp_t * ccp,uint8_t status,uint8_t call_index)1430 static void notify_app(struct bt_conn *conn, struct tbs_inst *inst, uint16_t len,
1431 const union bt_tbs_call_cp_t *ccp, uint8_t status, uint8_t call_index)
1432 {
1433 if (tbs_cbs == NULL) {
1434 return;
1435 }
1436
1437 switch (ccp->opcode) {
1438 case BT_TBS_CALL_OPCODE_ACCEPT:
1439 if (tbs_cbs->accept_call != NULL) {
1440 tbs_cbs->accept_call(conn, call_index);
1441 }
1442 break;
1443 case BT_TBS_CALL_OPCODE_TERMINATE:
1444 if (tbs_cbs->terminate_call != NULL) {
1445 tbs_cbs->terminate_call(conn, call_index, inst->terminate_reason.reason);
1446 }
1447 break;
1448 case BT_TBS_CALL_OPCODE_HOLD:
1449 if (tbs_cbs->hold_call != NULL) {
1450 tbs_cbs->hold_call(conn, call_index);
1451 }
1452 break;
1453 case BT_TBS_CALL_OPCODE_RETRIEVE:
1454 if (tbs_cbs->retrieve_call != NULL) {
1455 tbs_cbs->retrieve_call(conn, call_index);
1456 }
1457 break;
1458 case BT_TBS_CALL_OPCODE_ORIGINATE: {
1459 char uri[CONFIG_BT_TBS_MAX_URI_LENGTH + 1];
1460 const uint16_t uri_len = len - sizeof(ccp->originate);
1461 bool remote_party_alerted = false;
1462 struct bt_tbs_call *call;
1463
1464 call = lookup_call_in_inst(inst, call_index);
1465
1466 if (call == NULL) {
1467 LOG_DBG("Could not find call by call index 0x%02x", call_index);
1468 break;
1469 }
1470
1471 (void)memcpy(uri, ccp->originate.uri, uri_len);
1472 uri[uri_len] = '\0';
1473 if (tbs_cbs->originate_call != NULL) {
1474 remote_party_alerted = tbs_cbs->originate_call(conn, call_index, uri);
1475 }
1476
1477 if (!remote_party_alerted) {
1478 const struct bt_tbs_call_cp_term term = {
1479 .call_index = call_index, .opcode = BT_TBS_CALL_OPCODE_TERMINATE};
1480
1481 /* Terminate and remove call */
1482 terminate_call(inst, &term, BT_TBS_REASON_CALL_FAILED);
1483 }
1484
1485 break;
1486 }
1487 case BT_TBS_CALL_OPCODE_JOIN: {
1488 const uint16_t call_index_cnt = len - sizeof(ccp->join);
1489
1490 /* Let the app know about joined calls */
1491 if (tbs_cbs->join_calls != NULL) {
1492 tbs_cbs->join_calls(conn, call_index_cnt, ccp->join.call_indexes);
1493 }
1494 break;
1495 }
1496 default:
1497 break;
1498 }
1499
1500 /* Let the app know about held calls */
1501 if (held_calls_cnt != 0 && tbs_cbs->hold_call != NULL) {
1502 for (int i = 0; i < held_calls_cnt; i++) {
1503 tbs_cbs->hold_call(conn, held_calls[i]->index);
1504 }
1505 }
1506 }
1507
is_valid_cp_len(uint16_t len,const union bt_tbs_call_cp_t * ccp)1508 static bool is_valid_cp_len(uint16_t len, const union bt_tbs_call_cp_t *ccp)
1509 {
1510 if (len < sizeof(ccp->opcode)) {
1511 return false;
1512 }
1513
1514 switch (ccp->opcode) {
1515 case BT_TBS_CALL_OPCODE_ACCEPT:
1516 return len == sizeof(ccp->accept);
1517 case BT_TBS_CALL_OPCODE_TERMINATE:
1518 return len == sizeof(ccp->terminate);
1519 case BT_TBS_CALL_OPCODE_HOLD:
1520 return len == sizeof(ccp->hold);
1521 case BT_TBS_CALL_OPCODE_RETRIEVE:
1522 return len == sizeof(ccp->retrieve);
1523 case BT_TBS_CALL_OPCODE_ORIGINATE:
1524 return len >= sizeof(ccp->originate) + BT_TBS_MIN_URI_LEN;
1525 case BT_TBS_CALL_OPCODE_JOIN:
1526 return len >= sizeof(ccp->join) + 1; /* at least 1 call index */
1527 default:
1528 return true; /* defer to future checks */
1529 }
1530 }
1531
write_call_cp(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)1532 static ssize_t write_call_cp(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf,
1533 uint16_t len, uint16_t offset, uint8_t flags)
1534 {
1535 struct tbs_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
1536 const union bt_tbs_call_cp_t *ccp = (union bt_tbs_call_cp_t *)buf;
1537 struct tbs_inst *tbs = NULL;
1538 uint8_t status;
1539 uint8_t call_index = 0;
1540 const bool is_gtbs = inst_is_gtbs(inst);
1541 bool calls_changed = false;
1542 int err;
1543
1544 if (!is_authorized(inst, conn)) {
1545 return BT_GATT_ERR(BT_ATT_ERR_AUTHORIZATION);
1546 }
1547
1548 if (offset != 0) {
1549 return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
1550 }
1551
1552 if (!is_valid_cp_len(len, ccp)) {
1553 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
1554 }
1555
1556 LOG_DBG("Index %u: Processing the %s opcode", inst_index(inst),
1557 bt_tbs_opcode_str(ccp->opcode));
1558
1559 err = k_mutex_lock(&inst->mutex, MUTEX_TIMEOUT);
1560 if (err != 0) {
1561 LOG_DBG("Failed to lock mutex");
1562 return -EBUSY;
1563 }
1564
1565 if (inst->cp_ntf.pending) {
1566 err = k_mutex_unlock(&inst->mutex);
1567 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
1568
1569 return BT_GATT_ERR(BT_TBS_RESULT_CODE_OPERATION_NOT_POSSIBLE);
1570 }
1571
1572 switch (ccp->opcode) {
1573 case BT_TBS_CALL_OPCODE_ACCEPT:
1574 call_index = ccp->accept.call_index;
1575
1576 if (is_gtbs) {
1577 tbs = lookup_inst_by_call_index(call_index);
1578 if (tbs == NULL) {
1579 status = BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1580 break;
1581 }
1582 } else {
1583 tbs = inst;
1584 }
1585
1586 status = accept_call(tbs, &ccp->accept);
1587 break;
1588 case BT_TBS_CALL_OPCODE_TERMINATE:
1589 call_index = ccp->terminate.call_index;
1590
1591 if (is_gtbs) {
1592 tbs = lookup_inst_by_call_index(call_index);
1593 if (tbs == NULL) {
1594 status = BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1595 break;
1596 }
1597 } else {
1598 tbs = inst;
1599 }
1600
1601 status = terminate_call(tbs, &ccp->terminate, BT_TBS_REASON_CLIENT_TERMINATED);
1602 break;
1603 case BT_TBS_CALL_OPCODE_HOLD:
1604 call_index = ccp->hold.call_index;
1605
1606 if (is_gtbs) {
1607 tbs = lookup_inst_by_call_index(call_index);
1608 if (tbs == NULL) {
1609 status = BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1610 break;
1611 }
1612 } else {
1613 tbs = inst;
1614 }
1615
1616 status = tbs_hold_call(tbs, &ccp->hold);
1617 break;
1618 case BT_TBS_CALL_OPCODE_RETRIEVE:
1619 call_index = ccp->retrieve.call_index;
1620
1621 if (is_gtbs) {
1622 tbs = lookup_inst_by_call_index(call_index);
1623 if (tbs == NULL) {
1624 status = BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1625 break;
1626 }
1627 } else {
1628 tbs = inst;
1629 }
1630
1631 status = retrieve_call(tbs, &ccp->retrieve);
1632 break;
1633 case BT_TBS_CALL_OPCODE_ORIGINATE: {
1634 const uint16_t uri_len = len - sizeof(ccp->originate);
1635
1636 if (is_gtbs) {
1637 tbs = lookup_inst_by_uri_scheme(ccp->originate.uri, uri_len);
1638 if (tbs == NULL) {
1639 status = BT_TBS_RESULT_CODE_INVALID_URI;
1640 break;
1641 }
1642 } else {
1643 tbs = inst;
1644 }
1645
1646 status = originate_call(tbs, &ccp->originate, uri_len, &call_index);
1647 break;
1648 }
1649 case BT_TBS_CALL_OPCODE_JOIN: {
1650 const uint16_t call_index_cnt = len - sizeof(ccp->join);
1651 call_index = ccp->join.call_indexes[0];
1652
1653 if (is_gtbs) {
1654 tbs = lookup_inst_by_call_index(call_index);
1655 if (tbs == NULL) {
1656 status = BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1657 break;
1658 }
1659 } else {
1660 tbs = inst;
1661 }
1662
1663 status = join_calls(tbs, &ccp->join, call_index_cnt);
1664 break;
1665 }
1666 default:
1667 status = BT_TBS_RESULT_CODE_OPCODE_NOT_SUPPORTED;
1668 call_index = 0;
1669 break;
1670 }
1671
1672 if (tbs != NULL) {
1673 LOG_DBG("Index %u: Processed the %s opcode with status %s for call index %u",
1674 inst_index(inst), bt_tbs_opcode_str(ccp->opcode), bt_tbs_status_str(status),
1675 call_index);
1676
1677 if (status == BT_TBS_RESULT_CODE_SUCCESS) {
1678 const struct bt_tbs_call *call = lookup_call(call_index);
1679
1680 if (call != NULL) {
1681 LOG_DBG("Call is now in the %s state",
1682 bt_tbs_state_str(call->state));
1683 } else {
1684 LOG_DBG("Call is now terminated");
1685 }
1686 }
1687 }
1688
1689 if (status != BT_TBS_RESULT_CODE_SUCCESS) {
1690 call_index = 0;
1691 }
1692
1693 if (tbs != NULL && status == BT_TBS_RESULT_CODE_SUCCESS) {
1694 notify_calls(tbs);
1695 calls_changed = true;
1696 }
1697
1698 if (conn != NULL && bt_gatt_is_subscribed(conn, attr, BT_GATT_CCC_NOTIFY)) {
1699 struct bt_tbs_call_cp_notify *notification = &inst->cp_ntf.notification;
1700
1701 notification->call_index = call_index;
1702 notification->opcode = ccp->opcode;
1703 notification->status = status;
1704 inst->cp_ntf.pending = true;
1705 inst->cp_ntf.conn_index = bt_conn_index(conn);
1706
1707 /* We may schedule the same work multiple times, but that is OK as scheduling the
1708 * same work multiple times is a no-op
1709 */
1710 err = k_work_schedule(&inst->notify_work, K_NO_WAIT);
1711 __ASSERT(err >= 0, "Failed to schedule work: %d", err);
1712 } /* else local operation; don't notify */
1713
1714 err = k_mutex_unlock(&inst->mutex);
1715 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
1716
1717 if (calls_changed) {
1718 notify_app(conn, tbs, len, ccp, status, call_index);
1719 }
1720
1721 return len;
1722 }
1723
call_cp_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)1724 static void call_cp_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
1725 {
1726 const struct tbs_inst *inst = lookup_inst_by_attr(attr);
1727
1728 if (inst != NULL) {
1729 LOG_DBG("Index %u: value 0x%04x", inst_index(inst), value);
1730 }
1731 }
1732
read_optional_opcodes(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)1733 static ssize_t read_optional_opcodes(struct bt_conn *conn, const struct bt_gatt_attr *attr,
1734 void *buf, uint16_t len, uint16_t offset)
1735 {
1736 const struct tbs_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
1737 const uint16_t optional_opcodes_le = sys_cpu_to_le16(inst->optional_opcodes);
1738
1739 LOG_DBG("Index %u: Supported opcodes 0x%02x", inst_index(inst), inst->optional_opcodes);
1740
1741 return bt_gatt_attr_read(conn, attr, buf, len, offset, &optional_opcodes_le,
1742 sizeof(optional_opcodes_le));
1743 }
1744
terminate_reason_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)1745 static void terminate_reason_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
1746 {
1747 const struct tbs_inst *inst = lookup_inst_by_attr(attr);
1748
1749 if (inst != NULL) {
1750 LOG_DBG("Index %u: value 0x%04x", inst_index(inst), value);
1751 }
1752 }
1753
read_friendly_name(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)1754 static ssize_t read_friendly_name(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
1755 uint16_t len, uint16_t offset)
1756 {
1757 const struct tbs_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
1758 const struct bt_tbs_in_uri *friendly_name = &inst->friendly_name;
1759 size_t val_len;
1760
1761 LOG_DBG("Index: 0x%02x call index 0x%02x, URI %s", inst_index(inst),
1762 friendly_name->call_index, friendly_name->uri);
1763
1764 if (friendly_name->call_index == BT_TBS_FREE_CALL_INDEX) {
1765 LOG_DBG("URI not set");
1766 return bt_gatt_attr_read(conn, attr, buf, len, offset, NULL, 0);
1767 }
1768
1769 val_len = sizeof(friendly_name->call_index) + strlen(friendly_name->uri);
1770
1771 return bt_gatt_attr_read(conn, attr, buf, len, offset, friendly_name, val_len);
1772 }
1773
friendly_name_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)1774 static void friendly_name_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
1775 {
1776 const struct tbs_inst *inst = lookup_inst_by_attr(attr);
1777
1778 if (inst != NULL) {
1779 LOG_DBG("Index %u: value 0x%04x", inst_index(inst), value);
1780 }
1781 }
1782
read_incoming_call(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)1783 static ssize_t read_incoming_call(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
1784 uint16_t len, uint16_t offset)
1785 {
1786 const struct tbs_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
1787 const struct bt_tbs_in_uri *remote_uri = &inst->in_call;
1788 size_t val_len;
1789
1790 LOG_DBG("Index: 0x%02x call index 0x%02x, URI %s", inst_index(inst), remote_uri->call_index,
1791 remote_uri->uri);
1792
1793 if (remote_uri->call_index == BT_TBS_FREE_CALL_INDEX) {
1794 LOG_DBG("URI not set");
1795
1796 return bt_gatt_attr_read(conn, attr, buf, len, offset, NULL, 0);
1797 }
1798
1799 val_len = sizeof(remote_uri->call_index) + strlen(remote_uri->uri);
1800
1801 return bt_gatt_attr_read(conn, attr, buf, len, offset, remote_uri, val_len);
1802 }
1803
in_call_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)1804 static void in_call_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
1805 {
1806 const struct tbs_inst *inst = lookup_inst_by_attr(attr);
1807
1808 if (inst != NULL) {
1809 LOG_DBG("Index %u: value 0x%04x", inst_index(inst), value);
1810 }
1811 }
1812
1813 #define BT_TBS_CHR_PROVIDER_NAME(inst) \
1814 BT_AUDIO_CHRC(BT_UUID_TBS_PROVIDER_NAME, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
1815 BT_GATT_PERM_READ_ENCRYPT, read_provider_name, NULL, inst), \
1816 BT_AUDIO_CCC(provider_name_cfg_changed)
1817
1818 #define BT_TBS_CHR_UCI(inst) \
1819 BT_AUDIO_CHRC(BT_UUID_TBS_UCI, BT_GATT_CHRC_READ, BT_GATT_PERM_READ_ENCRYPT, read_uci, \
1820 NULL, inst)
1821
1822 #define BT_TBS_CHR_TECHNOLOGY(inst) \
1823 BT_AUDIO_CHRC(BT_UUID_TBS_TECHNOLOGY, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
1824 BT_GATT_PERM_READ_ENCRYPT, read_technology, NULL, inst), \
1825 BT_AUDIO_CCC(technology_cfg_changed)
1826
1827 #define BT_TBS_CHR_URI_LIST(inst) \
1828 BT_AUDIO_CHRC(BT_UUID_TBS_URI_LIST, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
1829 BT_GATT_PERM_READ_ENCRYPT, read_uri_scheme_list, NULL, inst), \
1830 BT_AUDIO_CCC(uri_scheme_list_cfg_changed)
1831
1832 #define BT_TBS_CHR_SIGNAL_STRENGTH(inst) \
1833 BT_AUDIO_CHRC(BT_UUID_TBS_SIGNAL_STRENGTH, /* Optional */ \
1834 BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ_ENCRYPT, \
1835 read_signal_strength, NULL, inst), \
1836 BT_AUDIO_CCC(signal_strength_cfg_changed)
1837
1838 #define BT_TBS_CHR_SIGNAL_INTERVAL(inst) \
1839 BT_AUDIO_CHRC(BT_UUID_TBS_SIGNAL_INTERVAL, /* Conditional */ \
1840 BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP, \
1841 BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, \
1842 read_signal_strength_interval, write_signal_strength_interval, inst)
1843
1844 #define BT_TBS_CHR_CURRENT_CALLS(inst) \
1845 BT_AUDIO_CHRC(BT_UUID_TBS_LIST_CURRENT_CALLS, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
1846 BT_GATT_PERM_READ_ENCRYPT, read_current_calls, NULL, inst), \
1847 BT_AUDIO_CCC(current_calls_cfg_changed)
1848
1849 #define BT_TBS_CHR_CCID(inst) \
1850 BT_AUDIO_CHRC(BT_UUID_CCID, BT_GATT_CHRC_READ, BT_GATT_PERM_READ_ENCRYPT, read_ccid, NULL, \
1851 inst)
1852
1853 #define BT_TBS_CHR_STATUS_FLAGS(inst) \
1854 BT_AUDIO_CHRC(BT_UUID_TBS_STATUS_FLAGS, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
1855 BT_GATT_PERM_READ_ENCRYPT, read_status_flags, NULL, inst), \
1856 BT_AUDIO_CCC(status_flags_cfg_changed)
1857
1858 #define BT_TBS_CHR_INCOMING_URI(inst) \
1859 BT_AUDIO_CHRC(BT_UUID_TBS_INCOMING_URI, /* Optional */ \
1860 BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ_ENCRYPT, \
1861 read_incoming_uri, NULL, inst), \
1862 BT_AUDIO_CCC(incoming_uri_cfg_changed)
1863
1864 #define BT_TBS_CHR_CALL_STATE(inst) \
1865 BT_AUDIO_CHRC(BT_UUID_TBS_CALL_STATE, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
1866 BT_GATT_PERM_READ_ENCRYPT, read_call_state, NULL, inst), \
1867 BT_AUDIO_CCC(call_state_cfg_changed)
1868
1869 #define BT_TBS_CHR_CONTROL_POINT(inst) \
1870 BT_AUDIO_CHRC(BT_UUID_TBS_CALL_CONTROL_POINT, \
1871 BT_GATT_CHRC_WRITE | BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_WRITE_WITHOUT_RESP, \
1872 BT_GATT_PERM_WRITE_ENCRYPT, NULL, write_call_cp, inst), \
1873 BT_AUDIO_CCC(call_cp_cfg_changed)
1874
1875 #define BT_TBS_CHR_OPTIONAL_OPCODES(inst) \
1876 BT_AUDIO_CHRC(BT_UUID_TBS_OPTIONAL_OPCODES, BT_GATT_CHRC_READ, BT_GATT_PERM_READ_ENCRYPT, \
1877 read_optional_opcodes, NULL, inst)
1878
1879 #define BT_TBS_CHR_TERMINATE_REASON(inst) \
1880 BT_AUDIO_CHRC(BT_UUID_TBS_TERMINATE_REASON, BT_GATT_CHRC_NOTIFY, \
1881 BT_GATT_PERM_READ_ENCRYPT, NULL, NULL, inst), \
1882 BT_AUDIO_CCC(terminate_reason_cfg_changed)
1883
1884 #define BT_TBS_CHR_INCOMING_CALL(inst) \
1885 BT_AUDIO_CHRC(BT_UUID_TBS_INCOMING_CALL, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
1886 BT_GATT_PERM_READ_ENCRYPT, read_incoming_call, NULL, inst), \
1887 BT_AUDIO_CCC(in_call_cfg_changed)
1888
1889 #define BT_TBS_CHR_FRIENDLY_NAME(inst) \
1890 BT_AUDIO_CHRC(BT_UUID_TBS_FRIENDLY_NAME, /* Optional */ \
1891 BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ_ENCRYPT, \
1892 read_friendly_name, NULL, inst), \
1893 BT_AUDIO_CCC(friendly_name_cfg_changed)
1894
1895 #define BT_TBS_SERVICE_DEFINE(_uuid, _inst) \
1896 BT_GATT_PRIMARY_SERVICE(_uuid), BT_TBS_CHR_PROVIDER_NAME(_inst), BT_TBS_CHR_UCI(_inst), \
1897 BT_TBS_CHR_TECHNOLOGY(_inst), BT_TBS_CHR_URI_LIST(_inst), \
1898 BT_TBS_CHR_SIGNAL_STRENGTH(_inst), BT_TBS_CHR_SIGNAL_INTERVAL(_inst), \
1899 BT_TBS_CHR_CURRENT_CALLS(_inst), BT_TBS_CHR_CCID(_inst), \
1900 BT_TBS_CHR_STATUS_FLAGS(_inst), BT_TBS_CHR_INCOMING_URI(_inst), \
1901 BT_TBS_CHR_CALL_STATE(_inst), BT_TBS_CHR_CONTROL_POINT(_inst), \
1902 BT_TBS_CHR_OPTIONAL_OPCODES(_inst), BT_TBS_CHR_TERMINATE_REASON(_inst), \
1903 BT_TBS_CHR_INCOMING_CALL(_inst), BT_TBS_CHR_FRIENDLY_NAME(_inst)
1904
1905 #define BT_TBS_SERVICE_DEFINITION(_inst) \
1906 { \
1907 BT_TBS_SERVICE_DEFINE(BT_UUID_TBS, &(_inst)) \
1908 }
1909
1910 static struct bt_gatt_service gtbs_svc =
1911 BT_GATT_SERVICE(((struct bt_gatt_attr[]){BT_TBS_SERVICE_DEFINE(BT_UUID_GTBS, >bs_inst)}));
1912
1913 BT_GATT_SERVICE_INSTANCE_DEFINE(tbs_service_list, svc_insts, CONFIG_BT_TBS_BEARER_COUNT,
1914 BT_TBS_SERVICE_DEFINITION);
1915
signal_interval_timeout(struct k_work * work)1916 static void signal_interval_timeout(struct k_work *work)
1917 {
1918 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
1919 struct tbs_inst *inst = CONTAINER_OF(dwork, struct tbs_inst, reporting_interval_work);
1920
1921 if (!inst->pending_signal_strength_notification) {
1922 return;
1923 }
1924
1925 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_SIGNAL_STRENGTH, inst->attrs, &inst->signal_strength,
1926 sizeof(inst->signal_strength));
1927
1928 if (inst->signal_strength_interval) {
1929 k_work_reschedule(&inst->reporting_interval_work,
1930 K_SECONDS(inst->signal_strength_interval));
1931 }
1932
1933 inst->pending_signal_strength_notification = false;
1934 }
1935
tbs_inst_init_and_register(struct tbs_inst * inst,struct bt_gatt_service * svc,const struct bt_tbs_register_param * param)1936 static int tbs_inst_init_and_register(struct tbs_inst *inst, struct bt_gatt_service *svc,
1937 const struct bt_tbs_register_param *param)
1938 {
1939 int ret;
1940
1941 LOG_DBG("inst %p index 0x%02x", inst, inst_index(inst));
1942
1943 ret = bt_ccid_alloc_value();
1944 if (ret < 0) {
1945 LOG_DBG("Could not allocate CCID: %d", ret);
1946 return ret;
1947 }
1948
1949 inst->ccid = (uint8_t)ret;
1950 (void)utf8_lcpy(inst->provider_name, param->provider_name, sizeof(inst->provider_name));
1951 (void)utf8_lcpy(inst->uci, param->uci, sizeof(inst->uci));
1952 (void)utf8_lcpy(inst->uri_scheme_list, param->uri_schemes_supported,
1953 sizeof(inst->uri_scheme_list));
1954 inst->optional_opcodes = param->supported_features;
1955 inst->technology = param->technology;
1956 inst->attrs = svc->attrs;
1957 inst->attr_count = svc->attr_count;
1958 inst->authorization_required = param->authorization_required;
1959
1960 k_work_init_delayable(&inst->reporting_interval_work, signal_interval_timeout);
1961 k_work_init_delayable(&inst->notify_work, notify_work_handler);
1962
1963 ret = k_mutex_init(&inst->mutex);
1964 __ASSERT(ret == 0, "Failed to initialize mutex");
1965
1966 ret = bt_gatt_service_register(svc);
1967 if (ret != 0) {
1968 LOG_DBG("Could not register %sTBS: %d", param->gtbs ? "G" : "", ret);
1969 memset(inst, 0, sizeof(*inst));
1970
1971 return ret;
1972 }
1973
1974 return inst_index(inst);
1975 }
1976
gtbs_service_inst_register(const struct bt_tbs_register_param * param)1977 static int gtbs_service_inst_register(const struct bt_tbs_register_param *param)
1978 {
1979 return tbs_inst_init_and_register(>bs_inst, >bs_svc, param);
1980 }
1981
tbs_service_inst_register(const struct bt_tbs_register_param * param)1982 static int tbs_service_inst_register(const struct bt_tbs_register_param *param)
1983 {
1984 for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) {
1985 struct tbs_inst *inst = &svc_insts[i];
1986
1987 if (!(inst_is_registered(inst))) {
1988 return tbs_inst_init_and_register(inst, &tbs_service_list[i], param);
1989 }
1990 }
1991
1992 return -ENOMEM;
1993 }
1994
valid_register_param(const struct bt_tbs_register_param * param)1995 static bool valid_register_param(const struct bt_tbs_register_param *param)
1996 {
1997 size_t str_len;
1998
1999 if (param == NULL) {
2000 LOG_DBG("param is NULL");
2001
2002 return false;
2003 }
2004
2005 if (param->provider_name == NULL) {
2006 LOG_DBG("provider_name is NULL");
2007
2008 return false;
2009 }
2010
2011 str_len = strlen(param->provider_name);
2012 if (str_len > CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH) {
2013 LOG_DBG("Provider name length (%zu) larger than "
2014 "CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH %d",
2015 str_len, CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH);
2016
2017 return false;
2018 }
2019
2020 if (param->uci == NULL) {
2021 LOG_DBG("uci is NULL");
2022
2023 return false;
2024 }
2025
2026 if (param->uri_schemes_supported == NULL) {
2027 LOG_DBG("uri_schemes_supported is NULL");
2028
2029 return false;
2030 }
2031
2032 if (!IN_RANGE(param->technology, BT_TBS_TECHNOLOGY_3G, BT_TBS_TECHNOLOGY_WCDMA)) {
2033 LOG_DBG("Invalid technology: %u", param->technology);
2034
2035 return false;
2036 }
2037
2038 if (param->supported_features > BT_TBS_FEATURE_ALL) {
2039 LOG_DBG("Invalid supported_features: %u", param->supported_features);
2040
2041 return false;
2042 }
2043
2044 if (CONFIG_BT_TBS_BEARER_COUNT == 0 && !param->gtbs) {
2045 LOG_DBG("Cannot register TBS when CONFIG_BT_TBS_BEARER_COUNT=0");
2046
2047 return false;
2048 }
2049
2050 return true;
2051 }
2052
bt_tbs_register_bearer(const struct bt_tbs_register_param * param)2053 int bt_tbs_register_bearer(const struct bt_tbs_register_param *param)
2054 {
2055 int ret = -ENOEXEC;
2056
2057 CHECKIF(!valid_register_param(param)) {
2058 LOG_DBG("Invalid parameters");
2059
2060 return -EINVAL;
2061 }
2062
2063 if (param->gtbs && inst_is_registered(>bs_inst)) {
2064 LOG_DBG("GTBS already registered");
2065
2066 return -EALREADY;
2067 }
2068
2069 if (!param->gtbs && !inst_is_registered(>bs_inst)) {
2070 LOG_DBG("GTBS not yet registered");
2071
2072 return -EAGAIN;
2073 }
2074
2075 if (param->gtbs) {
2076 ret = gtbs_service_inst_register(param);
2077 if (ret < 0) {
2078 LOG_DBG("Failed to register GTBS: %d", ret);
2079
2080 return -ENOEXEC;
2081 }
2082 } else if (CONFIG_BT_TBS_BEARER_COUNT > 0) {
2083 ret = tbs_service_inst_register(param);
2084 if (ret < 0) {
2085 LOG_DBG("Failed to register GTBS: %d", ret);
2086
2087 if (ret == -ENOMEM) {
2088 return -ENOMEM;
2089 }
2090
2091 return -ENOEXEC;
2092 }
2093 }
2094
2095 /* ret will contain the index of the registered service */
2096 return ret;
2097 }
2098
bt_tbs_unregister_bearer(uint8_t bearer_index)2099 int bt_tbs_unregister_bearer(uint8_t bearer_index)
2100 {
2101 struct tbs_inst *inst = inst_lookup_index(bearer_index);
2102 struct bt_gatt_service *svc;
2103 struct k_work_sync sync;
2104 bool restart_reporting_interval;
2105 int err;
2106
2107 if (inst == NULL) {
2108 LOG_DBG("Could not find inst by index %u", bearer_index);
2109
2110 return -EINVAL;
2111 }
2112
2113 if (!inst_is_registered(inst)) {
2114 LOG_DBG("Instance from index %u is not registered", bearer_index);
2115
2116 return -EALREADY;
2117 }
2118
2119 if (inst_is_gtbs(inst)) {
2120 for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) {
2121 struct tbs_inst *tbs = &svc_insts[i];
2122
2123 if (inst_is_registered(tbs)) {
2124 LOG_DBG("TBS[%u] is registered, please unregister all TBS first",
2125 bearer_index);
2126 return -EAGAIN;
2127 }
2128 }
2129 svc = >bs_svc;
2130 } else {
2131 svc = &tbs_service_list[bearer_index];
2132 }
2133
2134 restart_reporting_interval =
2135 k_work_cancel_delayable_sync(&inst->reporting_interval_work, &sync);
2136
2137 err = bt_gatt_service_unregister(svc);
2138 if (err != 0) {
2139 LOG_DBG("Failed to unregister service %p: %d", svc, err);
2140
2141 if (restart_reporting_interval && inst->signal_strength_interval != 0U) {
2142 /* In this unlikely scenario we may report interval later than expected if
2143 * the k_work was cancelled right before it was set to trigger. It is not a
2144 * big deal and not worth trying to reschedule in a way that it would
2145 * trigger at the same time again, as specific timing over GATT is a wishful
2146 * dream anyways
2147 */
2148 k_work_schedule(&inst->reporting_interval_work,
2149 K_SECONDS(inst->signal_strength_interval));
2150 }
2151
2152 return -ENOEXEC;
2153 }
2154
2155 memset(inst, 0, sizeof(*inst));
2156
2157 return 0;
2158 }
2159
bt_tbs_accept(uint8_t call_index)2160 int bt_tbs_accept(uint8_t call_index)
2161 {
2162 struct tbs_inst *inst = lookup_inst_by_call_index(call_index);
2163 int status = -EINVAL;
2164 const struct bt_tbs_call_cp_acc ccp = {.call_index = call_index,
2165 .opcode = BT_TBS_CALL_OPCODE_ACCEPT};
2166 int err;
2167
2168 err = k_mutex_lock(&inst->mutex, K_NO_WAIT);
2169 if (err != 0) {
2170 LOG_DBG("Failed to lock mutex");
2171 return -EBUSY;
2172 }
2173
2174 if (inst != NULL) {
2175 status = accept_call(inst, &ccp);
2176 }
2177
2178 if (status == BT_TBS_RESULT_CODE_SUCCESS) {
2179 notify_calls(inst);
2180 }
2181
2182 err = k_mutex_unlock(&inst->mutex);
2183 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
2184
2185 return status;
2186 }
2187
bt_tbs_hold(uint8_t call_index)2188 int bt_tbs_hold(uint8_t call_index)
2189 {
2190 struct tbs_inst *inst = lookup_inst_by_call_index(call_index);
2191 int status = -EINVAL;
2192 const struct bt_tbs_call_cp_hold ccp = {.call_index = call_index,
2193 .opcode = BT_TBS_CALL_OPCODE_HOLD};
2194
2195 if (inst != NULL) {
2196 int err;
2197
2198 err = k_mutex_lock(&inst->mutex, K_NO_WAIT);
2199 if (err != 0) {
2200 LOG_DBG("Failed to lock mutex");
2201 return -EBUSY;
2202 }
2203
2204 status = tbs_hold_call(inst, &ccp);
2205
2206 if (status == BT_TBS_RESULT_CODE_SUCCESS) {
2207 notify_calls(inst);
2208 }
2209
2210 err = k_mutex_unlock(&inst->mutex);
2211 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
2212 }
2213
2214 return status;
2215 }
2216
bt_tbs_retrieve(uint8_t call_index)2217 int bt_tbs_retrieve(uint8_t call_index)
2218 {
2219 struct tbs_inst *inst = lookup_inst_by_call_index(call_index);
2220 int status = -EINVAL;
2221 const struct bt_tbs_call_cp_retrieve ccp = {.call_index = call_index,
2222 .opcode = BT_TBS_CALL_OPCODE_RETRIEVE};
2223
2224 if (inst != NULL) {
2225 int err;
2226
2227 err = k_mutex_lock(&inst->mutex, K_NO_WAIT);
2228 if (err != 0) {
2229 LOG_DBG("Failed to lock mutex");
2230 return -EBUSY;
2231 }
2232
2233 status = retrieve_call(inst, &ccp);
2234
2235 if (status == BT_TBS_RESULT_CODE_SUCCESS) {
2236 notify_calls(inst);
2237 }
2238
2239 err = k_mutex_unlock(&inst->mutex);
2240 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
2241 }
2242
2243 return status;
2244 }
2245
bt_tbs_terminate(uint8_t call_index)2246 int bt_tbs_terminate(uint8_t call_index)
2247 {
2248 struct tbs_inst *inst = lookup_inst_by_call_index(call_index);
2249 int status = -EINVAL;
2250 const struct bt_tbs_call_cp_term ccp = {.call_index = call_index,
2251 .opcode = BT_TBS_CALL_OPCODE_TERMINATE};
2252
2253 if (inst != NULL) {
2254 int err;
2255
2256 err = k_mutex_lock(&inst->mutex, K_NO_WAIT);
2257 if (err != 0) {
2258 LOG_DBG("Failed to lock mutex");
2259 return -EBUSY;
2260 }
2261
2262 status = terminate_call(inst, &ccp, BT_TBS_REASON_SERVER_ENDED_CALL);
2263
2264 if (status == BT_TBS_RESULT_CODE_SUCCESS) {
2265 notify_calls(inst);
2266 }
2267
2268 err = k_mutex_unlock(&inst->mutex);
2269 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
2270 }
2271
2272 return status;
2273 }
2274
bt_tbs_originate(uint8_t bearer_index,char * remote_uri,uint8_t * call_index)2275 int bt_tbs_originate(uint8_t bearer_index, char *remote_uri, uint8_t *call_index)
2276 {
2277 struct tbs_inst *inst = inst_lookup_index(bearer_index);
2278 uint8_t buf[CONFIG_BT_TBS_MAX_URI_LENGTH + sizeof(struct bt_tbs_call_cp_originate)];
2279 struct bt_tbs_call_cp_originate *ccp = (struct bt_tbs_call_cp_originate *)buf;
2280 size_t uri_len;
2281 int err;
2282 int ret;
2283
2284 if (inst == NULL) {
2285 LOG_DBG("Could not find TBS instance from index %u", bearer_index);
2286 return -EINVAL;
2287 } else if (!bt_tbs_valid_uri((uint8_t *)remote_uri, strlen(remote_uri))) {
2288 LOG_DBG("Invalid URI %s", remote_uri);
2289 return -EINVAL;
2290 }
2291
2292 err = k_mutex_lock(&inst->mutex, K_NO_WAIT);
2293 if (err != 0) {
2294 LOG_DBG("Failed to lock mutex");
2295 return -EBUSY;
2296 }
2297
2298 uri_len = strlen(remote_uri);
2299
2300 ccp->opcode = BT_TBS_CALL_OPCODE_ORIGINATE;
2301 (void)memcpy(ccp->uri, remote_uri, uri_len);
2302
2303 ret = originate_call(inst, ccp, uri_len, call_index);
2304
2305 /* In the case that we are not connected to any TBS clients, we won't notify and we can
2306 * attempt to change state from dialing to alerting immediately
2307 */
2308 (void)try_change_dialing_call_to_alerting(inst);
2309
2310 err = k_mutex_unlock(&inst->mutex);
2311 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
2312
2313 return ret;
2314 }
2315
bt_tbs_join(uint8_t call_index_cnt,uint8_t * call_indexes)2316 int bt_tbs_join(uint8_t call_index_cnt, uint8_t *call_indexes)
2317 {
2318 struct tbs_inst *inst;
2319 uint8_t buf[CONFIG_BT_TBS_MAX_CALLS + sizeof(struct bt_tbs_call_cp_join)];
2320 struct bt_tbs_call_cp_join *ccp = (struct bt_tbs_call_cp_join *)buf;
2321 int status = -EINVAL;
2322
2323 if (call_index_cnt != 0 && call_indexes != 0) {
2324 inst = lookup_inst_by_call_index(call_indexes[0]);
2325 } else {
2326 return status;
2327 }
2328
2329 if (inst != NULL) {
2330 int err;
2331
2332 err = k_mutex_lock(&inst->mutex, K_NO_WAIT);
2333 if (err != 0) {
2334 LOG_DBG("Failed to lock mutex");
2335 return -EBUSY;
2336 }
2337
2338 ccp->opcode = BT_TBS_CALL_OPCODE_JOIN;
2339 (void)memcpy(ccp->call_indexes, call_indexes,
2340 MIN(call_index_cnt, CONFIG_BT_TBS_MAX_CALLS));
2341
2342 status = join_calls(inst, ccp, call_index_cnt);
2343
2344 if (status == BT_TBS_RESULT_CODE_SUCCESS) {
2345 notify_calls(inst);
2346 }
2347
2348 err = k_mutex_unlock(&inst->mutex);
2349 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
2350 }
2351
2352 return status;
2353 }
2354
bt_tbs_remote_answer(uint8_t call_index)2355 int bt_tbs_remote_answer(uint8_t call_index)
2356 {
2357 struct tbs_inst *inst = lookup_inst_by_call_index(call_index);
2358 struct bt_tbs_call *call;
2359 int err;
2360 int ret;
2361
2362 if (inst == NULL) {
2363 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
2364 }
2365
2366 call = lookup_call_in_inst(inst, call_index);
2367
2368 if (call == NULL) {
2369 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
2370 }
2371
2372 err = k_mutex_lock(&inst->mutex, K_NO_WAIT);
2373 if (err != 0) {
2374 LOG_DBG("Failed to lock mutex");
2375 return -EBUSY;
2376 }
2377
2378 if (call->state == BT_TBS_CALL_STATE_ALERTING) {
2379 call->state = BT_TBS_CALL_STATE_ACTIVE;
2380 notify_calls(inst);
2381 ret = BT_TBS_RESULT_CODE_SUCCESS;
2382 } else {
2383 LOG_DBG("Call with index %u Invalid state %s", call_index,
2384 bt_tbs_state_str(call->state));
2385 ret = BT_TBS_RESULT_CODE_STATE_MISMATCH;
2386 }
2387
2388 err = k_mutex_unlock(&inst->mutex);
2389 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
2390
2391 return ret;
2392 }
2393
bt_tbs_remote_hold(uint8_t call_index)2394 int bt_tbs_remote_hold(uint8_t call_index)
2395 {
2396 struct tbs_inst *inst = lookup_inst_by_call_index(call_index);
2397 struct bt_tbs_call *call;
2398 uint8_t status;
2399 int err;
2400
2401 if (inst == NULL) {
2402 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
2403 }
2404
2405 call = lookup_call_in_inst(inst, call_index);
2406
2407 if (call == NULL) {
2408 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
2409 }
2410
2411 err = k_mutex_lock(&inst->mutex, K_NO_WAIT);
2412 if (err != 0) {
2413 LOG_DBG("Failed to lock mutex");
2414 return -EBUSY;
2415 }
2416
2417 if (call->state == BT_TBS_CALL_STATE_ACTIVE) {
2418 call->state = BT_TBS_CALL_STATE_REMOTELY_HELD;
2419 status = BT_TBS_RESULT_CODE_SUCCESS;
2420 } else if (call->state == BT_TBS_CALL_STATE_LOCALLY_HELD) {
2421 call->state = BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD;
2422 status = BT_TBS_RESULT_CODE_SUCCESS;
2423 } else {
2424 status = BT_TBS_RESULT_CODE_STATE_MISMATCH;
2425 }
2426
2427 if (status == BT_TBS_RESULT_CODE_SUCCESS) {
2428 notify_calls(inst);
2429 }
2430
2431 err = k_mutex_unlock(&inst->mutex);
2432 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
2433
2434 return status;
2435 }
2436
bt_tbs_remote_retrieve(uint8_t call_index)2437 int bt_tbs_remote_retrieve(uint8_t call_index)
2438 {
2439 struct tbs_inst *inst = lookup_inst_by_call_index(call_index);
2440 struct bt_tbs_call *call;
2441 int status;
2442 int err;
2443
2444 if (inst == NULL) {
2445 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
2446 }
2447
2448 call = lookup_call_in_inst(inst, call_index);
2449
2450 if (call == NULL) {
2451 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
2452 }
2453
2454 err = k_mutex_lock(&inst->mutex, K_NO_WAIT);
2455 if (err != 0) {
2456 LOG_DBG("Failed to lock mutex");
2457 return -EBUSY;
2458 }
2459 if (call->state == BT_TBS_CALL_STATE_REMOTELY_HELD) {
2460 call->state = BT_TBS_CALL_STATE_ACTIVE;
2461 status = BT_TBS_RESULT_CODE_SUCCESS;
2462 } else if (call->state == BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD) {
2463 call->state = BT_TBS_CALL_STATE_LOCALLY_HELD;
2464 status = BT_TBS_RESULT_CODE_SUCCESS;
2465 } else {
2466 status = BT_TBS_RESULT_CODE_STATE_MISMATCH;
2467 }
2468
2469 if (status == BT_TBS_RESULT_CODE_SUCCESS) {
2470 notify_calls(inst);
2471 }
2472
2473 err = k_mutex_unlock(&inst->mutex);
2474 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
2475
2476 return status;
2477 }
2478
bt_tbs_remote_terminate(uint8_t call_index)2479 int bt_tbs_remote_terminate(uint8_t call_index)
2480 {
2481 struct tbs_inst *inst = lookup_inst_by_call_index(call_index);
2482 int status = -EINVAL;
2483 const struct bt_tbs_call_cp_term ccp = {.call_index = call_index,
2484 .opcode = BT_TBS_CALL_OPCODE_TERMINATE};
2485
2486 if (inst != NULL) {
2487 int err;
2488
2489 err = k_mutex_lock(&inst->mutex, K_NO_WAIT);
2490 if (err != 0) {
2491 LOG_DBG("Failed to lock mutex");
2492 return -EBUSY;
2493 }
2494 status = terminate_call(inst, &ccp, BT_TBS_REASON_REMOTE_ENDED_CALL);
2495
2496 if (status == BT_TBS_RESULT_CODE_SUCCESS) {
2497 notify_calls(inst);
2498 }
2499
2500 err = k_mutex_unlock(&inst->mutex);
2501 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
2502 }
2503
2504 return status;
2505 }
2506
set_incoming_call_target_bearer_uri_changed_cb(struct tbs_flags * flags)2507 static void set_incoming_call_target_bearer_uri_changed_cb(struct tbs_flags *flags)
2508 {
2509 if (flags->incoming_call_target_bearer_uri_changed) {
2510 LOG_DBG("pending notification replaced");
2511 }
2512
2513 flags->incoming_call_target_bearer_uri_changed = true;
2514 }
2515
set_incoming_call_changed_cb(struct tbs_flags * flags)2516 static void set_incoming_call_changed_cb(struct tbs_flags *flags)
2517 {
2518 if (flags->incoming_call_changed) {
2519 LOG_DBG("pending notification replaced");
2520 }
2521
2522 flags->incoming_call_changed = true;
2523 }
2524
set_call_friendly_name_changed_cb(struct tbs_flags * flags)2525 static void set_call_friendly_name_changed_cb(struct tbs_flags *flags)
2526 {
2527 if (flags->call_friendly_name_changed) {
2528 LOG_DBG("pending notification replaced");
2529 }
2530
2531 flags->call_friendly_name_changed = true;
2532 }
2533
tbs_inst_remote_incoming(struct tbs_inst * inst,const char * to,const char * from,const char * friendly_name,const struct bt_tbs_call * call)2534 static void tbs_inst_remote_incoming(struct tbs_inst *inst, const char *to, const char *from,
2535 const char *friendly_name, const struct bt_tbs_call *call)
2536 {
2537 __ASSERT_NO_MSG(to != NULL);
2538 __ASSERT_NO_MSG(from != NULL);
2539
2540 inst->in_call.call_index = call->index;
2541 (void)utf8_lcpy(inst->in_call.uri, from, sizeof(inst->in_call.uri));
2542 set_value_changed(inst, set_incoming_call_target_bearer_uri_changed_cb,
2543 BT_UUID_TBS_INCOMING_URI);
2544
2545 inst->incoming_uri.call_index = call->index;
2546 (void)utf8_lcpy(inst->incoming_uri.uri, to, sizeof(inst->incoming_uri.uri));
2547 set_value_changed(inst, set_incoming_call_changed_cb, BT_UUID_TBS_INCOMING_CALL);
2548
2549 if (friendly_name) {
2550 inst->friendly_name.call_index = call->index;
2551 utf8_lcpy(inst->friendly_name.uri, friendly_name, sizeof(inst->friendly_name.uri));
2552 } else {
2553 inst->friendly_name.call_index = BT_TBS_FREE_CALL_INDEX;
2554 }
2555
2556 set_value_changed(inst, set_call_friendly_name_changed_cb, BT_UUID_TBS_FRIENDLY_NAME);
2557 }
2558
bt_tbs_remote_incoming(uint8_t bearer_index,const char * to,const char * from,const char * friendly_name)2559 int bt_tbs_remote_incoming(uint8_t bearer_index, const char *to, const char *from,
2560 const char *friendly_name)
2561 {
2562 struct tbs_inst *inst = inst_lookup_index(bearer_index);
2563 struct bt_tbs_call *call = NULL;
2564 int err;
2565
2566 if (inst == NULL) {
2567 LOG_DBG("Could not find TBS instance from index %u", bearer_index);
2568 return -EINVAL;
2569 } else if (!bt_tbs_valid_uri((uint8_t *)to, strlen(to))) {
2570 LOG_DBG("Invalid \"to\" URI: %s", to);
2571 return -EINVAL;
2572 } else if (!bt_tbs_valid_uri((uint8_t *)from, strlen(from))) {
2573 LOG_DBG("Invalid \"from\" URI: %s", from);
2574 return -EINVAL;
2575 }
2576
2577 call = call_alloc(inst, BT_TBS_CALL_STATE_INCOMING, (uint8_t *)from, strlen(from));
2578 if (call == NULL) {
2579 return -ENOMEM;
2580 }
2581
2582 err = k_mutex_lock(&inst->mutex, K_NO_WAIT);
2583 if (err != 0) {
2584 LOG_DBG("Failed to lock mutex");
2585 return -EBUSY;
2586 }
2587 BT_TBS_CALL_FLAG_SET_INCOMING(call->flags);
2588
2589 /* Notify TBS*/
2590 tbs_inst_remote_incoming(inst, to, from, friendly_name, call);
2591
2592 if (!inst_is_gtbs(inst)) {
2593 /* If the instance is different than the GTBS we set the remote incoming and
2594 * notify on the GTBS instance as well
2595 */
2596 tbs_inst_remote_incoming(>bs_inst, to, from, friendly_name, call);
2597 }
2598
2599 notify_calls(inst);
2600
2601 err = k_mutex_unlock(&inst->mutex);
2602 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
2603
2604 LOG_DBG("New call with call index %u", call->index);
2605
2606 return call->index;
2607 }
2608
set_bearer_provider_name_changed_cb(struct tbs_flags * flags)2609 static void set_bearer_provider_name_changed_cb(struct tbs_flags *flags)
2610 {
2611 flags->bearer_provider_name_changed = true;
2612 }
2613
bt_tbs_set_bearer_provider_name(uint8_t bearer_index,const char * name)2614 int bt_tbs_set_bearer_provider_name(uint8_t bearer_index, const char *name)
2615 {
2616 struct tbs_inst *inst = inst_lookup_index(bearer_index);
2617 const size_t len = strlen(name);
2618 int err;
2619
2620 if (len >= CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH || len == 0) {
2621 return -EINVAL;
2622 } else if (inst == NULL) {
2623 return -EINVAL;
2624 }
2625
2626 if (strcmp(inst->provider_name, name) == 0) {
2627 return 0;
2628 }
2629
2630 err = k_mutex_lock(&inst->mutex, K_NO_WAIT);
2631 if (err != 0) {
2632 LOG_DBG("Failed to lock mutex");
2633 return -EBUSY;
2634 }
2635
2636 (void)utf8_lcpy(inst->provider_name, name, sizeof(inst->provider_name));
2637
2638 set_value_changed(inst, set_bearer_provider_name_changed_cb, BT_UUID_TBS_PROVIDER_NAME);
2639
2640 err = k_mutex_unlock(&inst->mutex);
2641 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
2642
2643 return 0;
2644 }
2645
set_bearer_technology_changed_cb(struct tbs_flags * flags)2646 static void set_bearer_technology_changed_cb(struct tbs_flags *flags)
2647 {
2648 flags->bearer_technology_changed = true;
2649 }
2650
bt_tbs_set_bearer_technology(uint8_t bearer_index,uint8_t new_technology)2651 int bt_tbs_set_bearer_technology(uint8_t bearer_index, uint8_t new_technology)
2652 {
2653 struct tbs_inst *inst = inst_lookup_index(bearer_index);
2654 int err;
2655
2656 if (new_technology < BT_TBS_TECHNOLOGY_3G || new_technology > BT_TBS_TECHNOLOGY_WCDMA) {
2657 return -EINVAL;
2658 } else if (inst == NULL) {
2659 return -EINVAL;
2660 }
2661
2662 if (inst->technology == new_technology) {
2663 return 0;
2664 }
2665
2666 err = k_mutex_lock(&inst->mutex, K_NO_WAIT);
2667 if (err != 0) {
2668 LOG_DBG("Failed to lock mutex");
2669 return -EBUSY;
2670 }
2671
2672 inst->technology = new_technology;
2673
2674 set_value_changed(inst, set_bearer_technology_changed_cb, BT_UUID_TBS_TECHNOLOGY);
2675
2676 err = k_mutex_unlock(&inst->mutex);
2677 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
2678
2679 return 0;
2680 }
2681
bt_tbs_set_signal_strength(uint8_t bearer_index,uint8_t new_signal_strength)2682 int bt_tbs_set_signal_strength(uint8_t bearer_index, uint8_t new_signal_strength)
2683 {
2684 struct tbs_inst *inst = inst_lookup_index(bearer_index);
2685 uint32_t timer_status;
2686
2687 if (new_signal_strength > BT_TBS_SIGNAL_STRENGTH_MAX &&
2688 new_signal_strength != BT_TBS_SIGNAL_STRENGTH_UNKNOWN) {
2689 return -EINVAL;
2690 } else if (inst == NULL) {
2691 return -EINVAL;
2692 }
2693
2694 if (inst->signal_strength == new_signal_strength) {
2695 return 0;
2696 }
2697
2698 inst->signal_strength = new_signal_strength;
2699 inst->pending_signal_strength_notification = true;
2700
2701 timer_status = k_work_delayable_remaining_get(&inst->reporting_interval_work);
2702 if (timer_status == 0) {
2703 k_work_reschedule(&inst->reporting_interval_work, K_NO_WAIT);
2704 }
2705
2706 LOG_DBG("Index %u: Reporting signal strength in %d ms", bearer_index, timer_status);
2707
2708 return 0;
2709 }
2710
set_status_flags_changed_cb(struct tbs_flags * flags)2711 static void set_status_flags_changed_cb(struct tbs_flags *flags)
2712 {
2713 flags->status_flags_changed = true;
2714 }
2715
bt_tbs_set_status_flags(uint8_t bearer_index,uint16_t status_flags)2716 int bt_tbs_set_status_flags(uint8_t bearer_index, uint16_t status_flags)
2717 {
2718 struct tbs_inst *inst = inst_lookup_index(bearer_index);
2719 int err;
2720
2721 if (!BT_TBS_VALID_STATUS_FLAGS(status_flags)) {
2722 return -EINVAL;
2723 } else if (inst == NULL) {
2724 return -EINVAL;
2725 }
2726
2727 if (inst->status_flags == status_flags) {
2728 return 0;
2729 }
2730
2731 err = k_mutex_lock(&inst->mutex, K_NO_WAIT);
2732 if (err != 0) {
2733 LOG_DBG("Failed to lock mutex");
2734 return -EBUSY;
2735 }
2736
2737 inst->status_flags = status_flags;
2738
2739 set_value_changed(inst, set_status_flags_changed_cb, BT_UUID_TBS_STATUS_FLAGS);
2740
2741 err = k_mutex_unlock(&inst->mutex);
2742 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
2743
2744 return 0;
2745 }
2746
set_bearer_uri_schemes_supported_list_changed_cb(struct tbs_flags * flags)2747 static void set_bearer_uri_schemes_supported_list_changed_cb(struct tbs_flags *flags)
2748 {
2749 flags->bearer_uri_schemes_supported_list_changed = true;
2750 }
2751
bt_tbs_set_uri_scheme_list(uint8_t bearer_index,const char ** uri_list,uint8_t uri_count)2752 int bt_tbs_set_uri_scheme_list(uint8_t bearer_index, const char **uri_list, uint8_t uri_count)
2753 {
2754 char uri_scheme_list[CONFIG_BT_TBS_MAX_SCHEME_LIST_LENGTH];
2755 size_t len = 0;
2756 struct tbs_inst *inst;
2757 int err;
2758
2759 NET_BUF_SIMPLE_DEFINE(uri_scheme_buf, READ_BUF_SIZE);
2760
2761 if (bearer_index >= ARRAY_SIZE(svc_insts)) {
2762 return -EINVAL;
2763 }
2764
2765 inst = &svc_insts[bearer_index];
2766 (void)memset(uri_scheme_list, 0, sizeof(uri_scheme_list));
2767
2768 for (int i = 0; i < uri_count; i++) {
2769 if (len) {
2770 len++;
2771 if (len > sizeof(uri_scheme_list) - 1) {
2772 return -ENOMEM;
2773 }
2774
2775 strcat(uri_scheme_list, ",");
2776 }
2777
2778 len += strlen(uri_list[i]);
2779 if (len > sizeof(uri_scheme_list) - 1) {
2780 return -ENOMEM;
2781 }
2782
2783 /* Store list in temp list in case something goes wrong */
2784 strcat(uri_scheme_list, uri_list[i]);
2785 }
2786
2787 if (strcmp(inst->uri_scheme_list, uri_scheme_list) == 0) {
2788 /* identical; don't update or notify */
2789 return 0;
2790 }
2791
2792 err = k_mutex_lock(&inst->mutex, K_NO_WAIT);
2793 if (err != 0) {
2794 LOG_DBG("Failed to lock mutex");
2795 return -EBUSY;
2796 }
2797
2798 /* Store final result */
2799 (void)utf8_lcpy(inst->uri_scheme_list, uri_scheme_list, sizeof(inst->uri_scheme_list));
2800
2801 LOG_DBG("TBS instance %u uri prefix list is now %s", bearer_index, inst->uri_scheme_list);
2802
2803 set_value_changed(inst, set_bearer_uri_schemes_supported_list_changed_cb,
2804 BT_UUID_TBS_URI_LIST);
2805
2806 if (!inst_is_gtbs(inst)) {
2807 /* If the instance is different than the GTBS notify on the GTBS instance as well */
2808 net_buf_simple_add_mem(&uri_scheme_buf, gtbs_inst.uri_scheme_list,
2809 strlen(gtbs_inst.uri_scheme_list));
2810
2811 /* TODO: Make uri schemes unique */
2812 for (size_t i = 0U; i < ARRAY_SIZE(svc_insts); i++) {
2813 const size_t uri_len = strlen(svc_insts[i].uri_scheme_list);
2814
2815 if (uri_scheme_buf.len + uri_len >= uri_scheme_buf.size) {
2816 LOG_WRN("Cannot fit all TBS instances in GTBS "
2817 "URI scheme list");
2818 break;
2819 }
2820
2821 net_buf_simple_add_mem(&uri_scheme_buf, svc_insts[i].uri_scheme_list,
2822 uri_len);
2823 }
2824
2825 LOG_DBG("GTBS: URI scheme %.*s", uri_scheme_buf.len, uri_scheme_buf.data);
2826
2827 set_value_changed(>bs_inst, set_bearer_uri_schemes_supported_list_changed_cb,
2828 BT_UUID_TBS_URI_LIST);
2829 }
2830
2831 err = k_mutex_unlock(&inst->mutex);
2832 __ASSERT(err == 0, "Failed to unlock mutex: %d", err);
2833
2834 return 0;
2835 }
2836
bt_tbs_register_cb(struct bt_tbs_cb * cbs)2837 void bt_tbs_register_cb(struct bt_tbs_cb *cbs)
2838 {
2839 tbs_cbs = cbs;
2840 }
2841
2842 #if defined(CONFIG_BT_TBS_LOG_LEVEL_DBG)
bt_tbs_dbg_print_calls(void)2843 void bt_tbs_dbg_print_calls(void)
2844 {
2845 for (size_t i = 0U; i < ARRAY_SIZE(svc_insts); i++) {
2846 LOG_DBG("Bearer #%u", i);
2847 for (int j = 0; j < ARRAY_SIZE(svc_insts[i].calls); j++) {
2848 struct bt_tbs_call *call = &svc_insts[i].calls[j];
2849
2850 if (call->index == BT_TBS_FREE_CALL_INDEX) {
2851 continue;
2852 }
2853
2854 LOG_DBG(" Call #%u", call->index);
2855 LOG_DBG(" State: %s", bt_tbs_state_str(call->state));
2856 LOG_DBG(" Flags: 0x%02X", call->flags);
2857 LOG_DBG(" URI : %s", call->remote_uri);
2858 }
2859 }
2860 }
2861 #endif /* defined(CONFIG_BT_TBS_LOG_LEVEL_DBG) */
2862