1 /* Bluetooth TBS - Telephone Bearer Service
2 *
3 * Copyright (c) 2020 Bose Corporation
4 * Copyright (c) 2021 Nordic Semiconductor ASA
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <zephyr/kernel.h>
10 #include <zephyr/types.h>
11
12 #include <zephyr/init.h>
13 #include <stdlib.h>
14
15 #include <zephyr/bluetooth/bluetooth.h>
16 #include <zephyr/bluetooth/conn.h>
17 #include <zephyr/bluetooth/gatt.h>
18
19 #include "audio_internal.h"
20 #include "tbs_internal.h"
21 #include "ccid_internal.h"
22
23 #include <zephyr/logging/log.h>
24
25 LOG_MODULE_REGISTER(bt_tbs, CONFIG_BT_TBS_LOG_LEVEL);
26
27 #define BT_TBS_VALID_STATUS_FLAGS(val) ((val) <= (BIT(0) | BIT(1)))
28 #define IS_GTBS_CHRC(_attr) \
29 IS_ENABLED(CONFIG_BT_GTBS) && BT_AUDIO_CHRC_USER_DATA(_attr) == >bs_inst
30
31 /* TODO: Have tbs_service_inst include gtbs_service_inst and use CONTAINER_OF
32 * to get a specific TBS instance from a GTBS pointer.
33 */
34 struct tbs_service_inst {
35 /* Attribute values */
36 char provider_name[CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH];
37 char uci[BT_TBS_MAX_UCI_SIZE];
38 char uri_scheme_list[CONFIG_BT_TBS_MAX_SCHEME_LIST_LENGTH];
39 uint8_t technology;
40 uint8_t signal_strength;
41 uint8_t signal_strength_interval;
42 uint8_t ccid;
43 uint16_t optional_opcodes;
44 uint16_t status_flags;
45 struct bt_tbs_in_uri incoming_uri;
46 struct bt_tbs_terminate_reason terminate_reason;
47 struct bt_tbs_in_uri friendly_name;
48 struct bt_tbs_in_uri in_call;
49
50 /* Instance values */
51 uint8_t index;
52 struct bt_tbs_call calls[CONFIG_BT_TBS_MAX_CALLS];
53 bool notify_current_calls;
54 bool notify_call_states;
55 bool pending_signal_strength_notification;
56 struct k_work_delayable reporting_interval_work;
57
58 /* TODO: The TBS (service) and the Telephone Bearers should be separated
59 * into two different instances. This is due to the addition of GTBS,
60 * where we now are in a state where this isn't a 1-to-1 correlation
61 * between TBS and the Telephone Bearers
62 */
63 struct bt_gatt_service *service_p;
64 };
65
66 struct gtbs_service_inst {
67 /* Attribute values */
68 char provider_name[CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH];
69 char uci[BT_TBS_MAX_UCI_SIZE];
70 uint8_t technology;
71 uint8_t signal_strength;
72 uint8_t signal_strength_interval;
73 uint8_t ccid;
74 uint16_t optional_opcodes;
75 uint16_t status_flags;
76 struct bt_tbs_in_uri incoming_uri;
77 struct bt_tbs_in_uri friendly_name;
78 struct bt_tbs_in_uri in_call;
79
80 /* Instance values */
81 bool notify_current_calls;
82 bool notify_call_states;
83 bool pending_signal_strength_notification;
84 struct k_work_delayable reporting_interval_work;
85
86 /* TODO: The TBS (service) and the Telephone Bearers should be separated
87 * into two different instances. This is due to the addition of GTBS,
88 * where we now are in a state where this isn't a 1-to-1 correlation
89 * between TBS and the Telephone Bearers
90 */
91 const struct bt_gatt_service_static *service_p;
92 };
93
94 #if defined(CONFIG_BT_GTBS)
95 #define READ_BUF_SIZE (CONFIG_BT_TBS_MAX_CALLS * \
96 sizeof(struct bt_tbs_current_call_item) * \
97 CONFIG_BT_TBS_BEARER_COUNT)
98 #else
99 #define READ_BUF_SIZE (CONFIG_BT_TBS_MAX_CALLS * \
100 sizeof(struct bt_tbs_current_call_item))
101 #endif /* IS_ENABLED(CONFIG_BT_GTBS) */
102 NET_BUF_SIMPLE_DEFINE_STATIC(read_buf, READ_BUF_SIZE);
103
104 static struct tbs_service_inst svc_insts[CONFIG_BT_TBS_BEARER_COUNT];
105 static struct gtbs_service_inst gtbs_inst;
106
107 /* Used to notify app with held calls in case of join */
108 static struct bt_tbs_call *held_calls[CONFIG_BT_TBS_MAX_CALLS];
109 static uint8_t held_calls_cnt;
110
111 static struct bt_tbs_cb *tbs_cbs;
112
lookup_call_in_inst(struct tbs_service_inst * inst,uint8_t call_index)113 static struct bt_tbs_call *lookup_call_in_inst(struct tbs_service_inst *inst,
114 uint8_t call_index)
115 {
116 if (call_index == BT_TBS_FREE_CALL_INDEX) {
117 return NULL;
118 }
119
120 for (int i = 0; i < ARRAY_SIZE(svc_insts[i].calls); i++) {
121 if (inst->calls[i].index == call_index) {
122 return &inst->calls[i];
123 }
124 }
125
126 return NULL;
127 }
128
129 /**
130 * @brief Finds and returns a call
131 *
132 * @param call_index The ID of the call
133 * @return struct bt_tbs_call* Pointer to the call. NULL if not found
134 */
lookup_call(uint8_t call_index)135 static struct bt_tbs_call *lookup_call(uint8_t call_index)
136 {
137
138 if (call_index == BT_TBS_FREE_CALL_INDEX) {
139 return NULL;
140 }
141
142 for (int i = 0; i < ARRAY_SIZE(svc_insts); i++) {
143 struct bt_tbs_call *call = lookup_call_in_inst(&svc_insts[i],
144 call_index);
145
146 if (call != NULL) {
147 return call;
148 }
149 }
150
151 return NULL;
152 }
153
lookup_inst_by_ccc(const struct bt_gatt_attr * ccc)154 static struct tbs_service_inst *lookup_inst_by_ccc(const struct bt_gatt_attr *ccc)
155 {
156 if (ccc == NULL) {
157 return NULL;
158 }
159
160 for (int i = 0; i < ARRAY_SIZE(svc_insts); i++) {
161 struct tbs_service_inst *inst = &svc_insts[i];
162
163 if (inst->service_p == NULL) {
164 continue;
165 }
166
167 for (size_t j = 0; j < inst->service_p->attr_count; j++) {
168 if (inst->service_p->attrs[j].user_data == ccc->user_data) {
169 return inst;
170 }
171 }
172 }
173
174 return NULL;
175 }
176
lookup_inst_by_call_index(uint8_t call_index)177 static struct tbs_service_inst *lookup_inst_by_call_index(uint8_t call_index)
178 {
179 if (call_index == BT_TBS_FREE_CALL_INDEX) {
180 return NULL;
181 }
182
183 for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) {
184 if (lookup_call_in_inst(&svc_insts[i], call_index) != NULL) {
185 return &svc_insts[i];
186 }
187 }
188
189 return NULL;
190 }
191
is_authorized(struct bt_conn * conn)192 static bool is_authorized(struct bt_conn *conn)
193 {
194 if (IS_ENABLED(CONFIG_BT_TBS_AUTHORIZATION)) {
195 if (tbs_cbs != NULL && tbs_cbs->authorize != NULL) {
196 return tbs_cbs->authorize(conn);
197 } else {
198 return false;
199 }
200 }
201
202 return true;
203 }
204
uri_scheme_in_list(const char * uri_scheme,const char * uri_scheme_list)205 static bool uri_scheme_in_list(const char *uri_scheme,
206 const char *uri_scheme_list)
207 {
208 const size_t scheme_len = strlen(uri_scheme);
209 const size_t scheme_list_len = strlen(uri_scheme_list);
210 const char *uri_scheme_cand = uri_scheme_list;
211 size_t uri_scheme_cand_len;
212 size_t start_idx = 0;
213
214 for (size_t i = 0; i < scheme_list_len; i++) {
215 if (uri_scheme_list[i] == ',') {
216 uri_scheme_cand_len = i - start_idx;
217 if (uri_scheme_cand_len != scheme_len) {
218 continue;
219 }
220
221 if (memcmp(uri_scheme, uri_scheme_cand, scheme_len) == 0) {
222 return true;
223 }
224
225 if (i + 1 < scheme_list_len) {
226 uri_scheme_cand = &uri_scheme_list[i + 1];
227 }
228 }
229 }
230
231 return false;
232 }
233
lookup_inst_by_uri_scheme(const char * uri,uint8_t uri_len)234 static struct tbs_service_inst *lookup_inst_by_uri_scheme(const char *uri,
235 uint8_t uri_len)
236 {
237 char uri_scheme[CONFIG_BT_TBS_MAX_URI_LENGTH] = { 0 };
238
239 /* Look for ':' between the first and last char */
240 for (int i = 1; i < uri_len - 1; i++) {
241 if (uri[i] == ':') {
242 (void)memcpy(uri_scheme, uri, i);
243 }
244 }
245
246 if (strlen(uri_scheme) == 0) {
247 /* No URI scheme found */
248 return NULL;
249 }
250
251 for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) {
252 for (size_t j = 0; j < ARRAY_SIZE(svc_insts[i].calls); j++) {
253 if (uri_scheme_in_list(uri_scheme,
254 svc_insts[i].uri_scheme_list)) {
255 return &svc_insts[i];
256 }
257 }
258 }
259
260 return NULL;
261 }
262
lookup_inst_by_work(const struct k_work * work)263 static struct tbs_service_inst *lookup_inst_by_work(const struct k_work *work)
264 {
265 if (work == NULL) {
266 return NULL;
267 }
268
269 for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) {
270 if (&svc_insts[i].reporting_interval_work.work == work) {
271 return &svc_insts[i];
272 }
273 }
274
275 return NULL;
276 }
277
tbs_set_terminate_reason(struct tbs_service_inst * inst,uint8_t call_index,uint8_t reason)278 static void tbs_set_terminate_reason(struct tbs_service_inst *inst,
279 uint8_t call_index, uint8_t reason)
280 {
281 inst->terminate_reason.call_index = call_index;
282 inst->terminate_reason.reason = reason;
283 LOG_DBG("Index %u: call index 0x%02x, reason %s", inst->index, call_index,
284 bt_tbs_term_reason_str(reason));
285
286 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_TERMINATE_REASON,
287 inst->service_p->attrs,
288 (void *)&inst->terminate_reason,
289 sizeof(inst->terminate_reason));
290
291 if (IS_ENABLED(CONFIG_BT_GTBS)) {
292 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_TERMINATE_REASON,
293 gtbs_inst.service_p->attrs,
294 (void *)&inst->terminate_reason,
295 sizeof(inst->terminate_reason));
296 }
297 }
298
299 /**
300 * @brief Gets the next free call_index
301 *
302 * For each new call, the call index should be incremented and wrap at 255.
303 * However, the index = 0 is reserved for outgoing calls
304 *
305 * @return uint8_t The next free call index
306 */
next_free_call_index(void)307 static uint8_t next_free_call_index(void)
308 {
309 for (int i = 0; i < CONFIG_BT_TBS_MAX_CALLS; i++) {
310 static uint8_t next_call_index = 1;
311 const struct bt_tbs_call *call = lookup_call(next_call_index);
312
313 if (call == NULL) {
314 return next_call_index++;
315 }
316
317 next_call_index++;
318 if (next_call_index == UINT8_MAX) {
319 /* call_index = 0 reserved for outgoing calls */
320 next_call_index = 1;
321 }
322 }
323
324 LOG_DBG("No more free call spots");
325
326 return BT_TBS_FREE_CALL_INDEX;
327 }
328
net_buf_put_call_state(const void * inst_p)329 static void net_buf_put_call_state(const void *inst_p)
330 {
331 const struct bt_tbs_call *call;
332 const struct bt_tbs_call *calls;
333 size_t call_count;
334
335 if (inst_p == NULL) {
336 return;
337 }
338
339 net_buf_simple_reset(&read_buf);
340
341 if (IS_ENABLED(CONFIG_BT_GTBS) && inst_p == >bs_inst) {
342 for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) {
343 calls = svc_insts[i].calls;
344 call_count = ARRAY_SIZE(svc_insts[i].calls);
345
346 for (size_t j = 0; j < call_count; j++) {
347 call = &calls[j];
348 if (call->index == BT_TBS_FREE_CALL_INDEX) {
349 continue;
350 }
351
352 net_buf_simple_add_u8(&read_buf, call->index);
353 net_buf_simple_add_u8(&read_buf, call->state);
354 net_buf_simple_add_u8(&read_buf, call->flags);
355 }
356
357 }
358 } else {
359 const struct tbs_service_inst *inst = (struct tbs_service_inst *)inst_p;
360
361 calls = inst->calls;
362 call_count = ARRAY_SIZE(inst->calls);
363
364 for (int i = 0; i < call_count; i++) {
365 call = &calls[i];
366 if (call->index == BT_TBS_FREE_CALL_INDEX) {
367 continue;
368 }
369
370 net_buf_simple_add_u8(&read_buf, call->index);
371 net_buf_simple_add_u8(&read_buf, call->state);
372 net_buf_simple_add_u8(&read_buf, call->flags);
373 }
374 }
375 }
376
net_buf_put_current_calls(const void * inst_p)377 static void net_buf_put_current_calls(const void *inst_p)
378 {
379 const struct bt_tbs_call *call;
380 const struct bt_tbs_call *calls;
381 size_t call_count;
382 size_t uri_length;
383 size_t item_len;
384
385 if (inst_p == NULL) {
386 return;
387 }
388
389 net_buf_simple_reset(&read_buf);
390
391 if (IS_ENABLED(CONFIG_BT_GTBS) && inst_p == >bs_inst) {
392 for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) {
393 calls = svc_insts[i].calls;
394 call_count = ARRAY_SIZE(svc_insts[i].calls);
395
396 for (size_t j = 0; j < call_count; j++) {
397 call = &calls[j];
398 if (call->index == BT_TBS_FREE_CALL_INDEX) {
399 continue;
400 }
401 uri_length = strlen(call->remote_uri);
402 item_len = sizeof(call->index) + sizeof(call->state) +
403 sizeof(call->flags) + uri_length;
404
405 net_buf_simple_add_u8(&read_buf, item_len);
406 net_buf_simple_add_u8(&read_buf, call->index);
407 net_buf_simple_add_u8(&read_buf, call->state);
408 net_buf_simple_add_u8(&read_buf, call->flags);
409 net_buf_simple_add_mem(&read_buf,
410 call->remote_uri,
411 uri_length);
412 }
413
414 }
415 } else {
416 const struct tbs_service_inst *inst = (struct tbs_service_inst *)inst_p;
417
418 calls = inst->calls;
419 call_count = ARRAY_SIZE(inst->calls);
420
421 for (size_t i = 0; i < call_count; i++) {
422 call = &calls[i];
423 if (call->index == BT_TBS_FREE_CALL_INDEX) {
424 continue;
425 }
426
427 uri_length = strlen(call->remote_uri);
428 item_len = sizeof(call->index) + sizeof(call->state) +
429 sizeof(call->flags) + uri_length;
430 net_buf_simple_add_u8(&read_buf, item_len);
431 net_buf_simple_add_u8(&read_buf, call->index);
432 net_buf_simple_add_u8(&read_buf, call->state);
433 net_buf_simple_add_u8(&read_buf, call->flags);
434 net_buf_simple_add_mem(&read_buf, call->remote_uri,
435 uri_length);
436 }
437 }
438 }
439
notify_calls(const struct tbs_service_inst * inst)440 static int notify_calls(const struct tbs_service_inst *inst)
441 {
442 int err = 0;
443
444 if (inst == NULL) {
445 return -EINVAL;
446 }
447
448 if (IS_ENABLED(CONFIG_BT_GTBS)) {
449 if (gtbs_inst.notify_call_states) {
450 net_buf_put_call_state(>bs_inst);
451
452 err = bt_gatt_notify_uuid(NULL, BT_UUID_TBS_CALL_STATE,
453 gtbs_inst.service_p->attrs,
454 read_buf.data, read_buf.len);
455 if (err != 0) {
456 return err;
457 }
458 }
459
460 if (gtbs_inst.notify_current_calls) {
461 net_buf_put_current_calls(>bs_inst);
462
463 err = bt_gatt_notify_uuid(
464 NULL, BT_UUID_TBS_LIST_CURRENT_CALLS,
465 gtbs_inst.service_p->attrs,
466 read_buf.data, read_buf.len);
467 if (err != 0) {
468 return err;
469 }
470 }
471 }
472
473 if (inst->notify_call_states) {
474 net_buf_put_call_state(inst);
475
476 err = bt_gatt_notify_uuid(NULL, BT_UUID_TBS_CALL_STATE,
477 inst->service_p->attrs,
478 read_buf.data, read_buf.len);
479 if (err != 0) {
480 return err;
481 }
482 }
483 if (inst->notify_current_calls) {
484 net_buf_put_current_calls(inst);
485
486 err = bt_gatt_notify_uuid(NULL, BT_UUID_TBS_LIST_CURRENT_CALLS,
487 inst->service_p->attrs,
488 read_buf.data, read_buf.len);
489 if (err != 0) {
490 return err;
491 }
492 }
493
494 return err;
495 }
496
read_provider_name(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)497 static ssize_t read_provider_name(struct bt_conn *conn,
498 const struct bt_gatt_attr *attr,
499 void *buf, uint16_t len, uint16_t offset)
500 {
501 const char *provider_name;
502
503 if (IS_GTBS_CHRC(attr)) {
504 provider_name = gtbs_inst.provider_name;
505 LOG_DBG("GTBS: Provider name %s", provider_name);
506 } else {
507 const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
508
509 provider_name = inst->provider_name;
510 LOG_DBG("Index %u, Provider name %s", inst->index, provider_name);
511 }
512
513 return bt_gatt_attr_read(conn, attr, buf, len, offset,
514 provider_name,
515 strlen(provider_name));
516 }
517
provider_name_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)518 static void provider_name_cfg_changed(const struct bt_gatt_attr *attr,
519 uint16_t value)
520 {
521 const struct tbs_service_inst *inst = lookup_inst_by_ccc(attr);
522
523 if (inst != NULL) {
524 LOG_DBG("Index %u: value 0x%04x", inst->index, value);
525 } else if (IS_ENABLED(CONFIG_BT_GTBS)) {
526 LOG_DBG("GTBS: value 0x%04x", value);
527 }
528 }
529
read_uci(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)530 static ssize_t read_uci(struct bt_conn *conn, const struct bt_gatt_attr *attr,
531 void *buf, uint16_t len, uint16_t offset)
532 {
533 const char *uci;
534
535 if (IS_GTBS_CHRC(attr)) {
536 uci = gtbs_inst.uci;
537 LOG_DBG("GTBS: UCI %s", uci);
538 } else {
539 const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
540
541 uci = inst->uci;
542 LOG_DBG("Index %u: UCI %s", inst->index, uci);
543 }
544
545 return bt_gatt_attr_read(conn, attr, buf, len, offset,
546 uci, strlen(uci));
547 }
548
read_technology(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)549 static ssize_t read_technology(struct bt_conn *conn,
550 const struct bt_gatt_attr *attr,
551 void *buf, uint16_t len, uint16_t offset)
552 {
553 uint8_t technology;
554
555 if (IS_GTBS_CHRC(attr)) {
556 technology = gtbs_inst.technology;
557 LOG_DBG("GTBS: Technology 0x%02X", technology);
558 } else {
559 const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
560
561 technology = inst->technology;
562 LOG_DBG("Index %u: Technology 0x%02X", inst->index, technology);
563 }
564
565 return bt_gatt_attr_read(conn, attr, buf, len, offset,
566 &technology, sizeof(technology));
567 }
568
technology_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)569 static void technology_cfg_changed(const struct bt_gatt_attr *attr,
570 uint16_t value)
571 {
572 const struct tbs_service_inst *inst = lookup_inst_by_ccc(attr);
573
574 if (inst != NULL) {
575 LOG_DBG("Index %u: value 0x%04x", inst->index, value);
576 } else if (IS_ENABLED(CONFIG_BT_GTBS)) {
577 LOG_DBG("GTBS: value 0x%04x", value);
578 }
579 }
580
read_uri_scheme_list(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)581 static ssize_t read_uri_scheme_list(struct bt_conn *conn,
582 const struct bt_gatt_attr *attr,
583 void *buf, uint16_t len, uint16_t offset)
584 {
585 net_buf_simple_reset(&read_buf);
586
587 if (IS_GTBS_CHRC(attr)) {
588 /* TODO: Make uri schemes unique */
589 for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) {
590 size_t uri_len = strlen(svc_insts[i].uri_scheme_list);
591
592 if (read_buf.len + uri_len >= read_buf.size) {
593 LOG_WRN("Cannot fit all TBS instances in GTBS "
594 "URI scheme list");
595 break;
596 }
597
598 net_buf_simple_add_mem(&read_buf,
599 svc_insts[i].uri_scheme_list,
600 uri_len);
601 }
602
603 LOG_DBG("GTBS: URI scheme %.*s", read_buf.len, read_buf.data);
604 } else {
605 const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
606
607 net_buf_simple_add_mem(&read_buf, inst->uri_scheme_list,
608 strlen(inst->uri_scheme_list));
609
610 LOG_DBG("Index %u: URI scheme %.*s", inst->index, read_buf.len, read_buf.data);
611 }
612
613 return bt_gatt_attr_read(conn, attr, buf, len, offset,
614 read_buf.data, read_buf.len);
615 }
616
uri_scheme_list_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)617 static void uri_scheme_list_cfg_changed(const struct bt_gatt_attr *attr,
618 uint16_t value)
619 {
620 const struct tbs_service_inst *inst = lookup_inst_by_ccc(attr);
621
622 if (inst != NULL) {
623 LOG_DBG("Index %u: value 0x%04x", inst->index, value);
624 } else if (IS_ENABLED(CONFIG_BT_GTBS)) {
625 LOG_DBG("GTBS: value 0x%04x", value);
626 }
627 }
628
read_signal_strength(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)629 static ssize_t read_signal_strength(struct bt_conn *conn,
630 const struct bt_gatt_attr *attr,
631 void *buf, uint16_t len, uint16_t offset)
632 {
633 uint8_t signal_strength;
634
635 if (IS_GTBS_CHRC(attr)) {
636 signal_strength = gtbs_inst.signal_strength;
637 LOG_DBG("GTBS: Signal strength 0x%02x", signal_strength);
638 } else {
639 const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
640
641 signal_strength = inst->signal_strength;
642 LOG_DBG("Index %u: Signal strength 0x%02x", inst->index, signal_strength);
643 }
644
645 return bt_gatt_attr_read(conn, attr, buf, len, offset,
646 &signal_strength, sizeof(signal_strength));
647 }
648
signal_strength_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)649 static void signal_strength_cfg_changed(const struct bt_gatt_attr *attr,
650 uint16_t value)
651 {
652 const struct tbs_service_inst *inst = lookup_inst_by_ccc(attr);
653
654 if (inst != NULL) {
655 LOG_DBG("Index %u: value 0x%04x", inst->index, value);
656 } else if (IS_ENABLED(CONFIG_BT_GTBS)) {
657 LOG_DBG("GTBS: value 0x%04x", value);
658 }
659 }
660
read_signal_strength_interval(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)661 static ssize_t read_signal_strength_interval(struct bt_conn *conn,
662 const struct bt_gatt_attr *attr,
663 void *buf, uint16_t len,
664 uint16_t offset)
665 {
666 uint8_t signal_strength_interval;
667
668 if (!is_authorized(conn)) {
669 return BT_GATT_ERR(BT_ATT_ERR_AUTHORIZATION);
670 }
671
672 if (IS_GTBS_CHRC(attr)) {
673 signal_strength_interval = gtbs_inst.signal_strength_interval;
674 LOG_DBG("GTBS: Signal strength interval 0x%02x", signal_strength_interval);
675 } else {
676 const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
677
678 signal_strength_interval = inst->signal_strength_interval;
679 LOG_DBG("Index %u: Signal strength interval 0x%02x", inst->index,
680 signal_strength_interval);
681 }
682
683 return bt_gatt_attr_read(conn, attr, buf, len, offset,
684 &signal_strength_interval,
685 sizeof(signal_strength_interval));
686 }
687
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)688 static ssize_t write_signal_strength_interval(struct bt_conn *conn,
689 const struct bt_gatt_attr *attr,
690 const void *buf, uint16_t len,
691 uint16_t offset, uint8_t flags)
692 {
693 struct net_buf_simple net_buf;
694 uint8_t signal_strength_interval;
695
696 if (!is_authorized(conn)) {
697 return BT_GATT_ERR(BT_ATT_ERR_AUTHORIZATION);
698 }
699
700 if (offset != 0) {
701 return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
702 }
703
704 if (len != sizeof(signal_strength_interval)) {
705 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
706 }
707
708 net_buf_simple_init_with_data(&net_buf, (void *)buf, len);
709 signal_strength_interval = net_buf_simple_pull_u8(&net_buf);
710
711 if (IS_GTBS_CHRC(attr)) {
712 gtbs_inst.signal_strength_interval = signal_strength_interval;
713 LOG_DBG("GTBS: 0x%02x", signal_strength_interval);
714 } else {
715 struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
716
717 inst->signal_strength_interval = signal_strength_interval;
718 LOG_DBG("Index %u: 0x%02x", inst->index, signal_strength_interval);
719 }
720
721 return len;
722 }
723
current_calls_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)724 static void current_calls_cfg_changed(const struct bt_gatt_attr *attr,
725 uint16_t value)
726 {
727 struct tbs_service_inst *inst = lookup_inst_by_ccc(attr);
728
729 if (inst != NULL) {
730 LOG_DBG("Index %u: value 0x%04x", inst->index, value);
731 inst->notify_current_calls = (value == BT_GATT_CCC_NOTIFY);
732 } else if (IS_ENABLED(CONFIG_BT_GTBS)) {
733 LOG_DBG("GTBS: value 0x%04x", value);
734 gtbs_inst.notify_current_calls = (value == BT_GATT_CCC_NOTIFY);
735 }
736 }
737
read_current_calls(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)738 static ssize_t read_current_calls(struct bt_conn *conn,
739 const struct bt_gatt_attr *attr,
740 void *buf, uint16_t len, uint16_t offset)
741 {
742 net_buf_put_current_calls(BT_AUDIO_CHRC_USER_DATA(attr));
743
744 if (IS_GTBS_CHRC(attr)) {
745 LOG_DBG("GTBS");
746 } else {
747 const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
748
749 LOG_DBG("Index %u", inst->index);
750 }
751
752 if (offset == 0) {
753 LOG_HEXDUMP_DBG(read_buf.data, read_buf.len, "Current calls");
754 }
755
756 return bt_gatt_attr_read(conn, attr, buf, len, offset,
757 read_buf.data, read_buf.len);
758 }
759
read_ccid(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)760 static ssize_t read_ccid(struct bt_conn *conn,
761 const struct bt_gatt_attr *attr,
762 void *buf, uint16_t len, uint16_t offset)
763 {
764 uint8_t ccid;
765
766 if (IS_GTBS_CHRC(attr)) {
767 ccid = gtbs_inst.ccid;
768 LOG_DBG("GTBS: CCID 0x%02X", ccid);
769 } else {
770 const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
771
772 ccid = inst->ccid;
773 LOG_DBG("Index %u: CCID 0x%02X", inst->index, ccid);
774 }
775
776 return bt_gatt_attr_read(conn, attr, buf, len, offset,
777 &ccid, sizeof(ccid));
778 }
779
read_status_flags(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)780 static ssize_t read_status_flags(struct bt_conn *conn,
781 const struct bt_gatt_attr *attr,
782 void *buf, uint16_t len, uint16_t offset)
783 {
784 uint16_t status_flags;
785
786 if (IS_GTBS_CHRC(attr)) {
787 status_flags = gtbs_inst.status_flags;
788 LOG_DBG("GTBS: status_flags 0x%04X", status_flags);
789 } else {
790 const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
791
792 status_flags = inst->status_flags;
793 LOG_DBG("Index %u: status_flags 0x%04X", inst->index, status_flags);
794 }
795
796 return bt_gatt_attr_read(conn, attr, buf, len, offset,
797 &status_flags, sizeof(status_flags));
798 }
799
status_flags_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)800 static void status_flags_cfg_changed(const struct bt_gatt_attr *attr,
801 uint16_t value)
802 {
803 const struct tbs_service_inst *inst = lookup_inst_by_ccc(attr);
804
805 if (inst != NULL) {
806 LOG_DBG("Index %u: value 0x%04x", inst->index, value);
807 } else if (IS_ENABLED(CONFIG_BT_GTBS)) {
808 LOG_DBG("GTBS: value 0x%04x", value);
809 }
810 }
811
read_incoming_uri(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)812 static ssize_t read_incoming_uri(struct bt_conn *conn,
813 const struct bt_gatt_attr *attr,
814 void *buf, uint16_t len,
815 uint16_t offset)
816 {
817 const struct bt_tbs_in_uri *inc_call_target;
818 size_t val_len;
819
820 if (IS_GTBS_CHRC(attr)) {
821 inc_call_target = >bs_inst.incoming_uri;
822 LOG_DBG("GTBS: call index 0x%02X, URI %s", inc_call_target->call_index,
823 inc_call_target->uri);
824 } else {
825 const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
826
827 inc_call_target = &inst->incoming_uri;
828 LOG_DBG("Index %u: call index 0x%02X, URI %s", inst->index,
829 inc_call_target->call_index, inc_call_target->uri);
830 }
831
832 if (!inc_call_target->call_index) {
833 LOG_DBG("URI not set");
834
835 return bt_gatt_attr_read(conn, attr, buf, len, offset, NULL, 0);
836 }
837
838 val_len = sizeof(inc_call_target->call_index) +
839 strlen(inc_call_target->uri);
840
841 return bt_gatt_attr_read(conn, attr, buf, len, offset,
842 inc_call_target, val_len);
843 }
844
incoming_uri_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)845 static void incoming_uri_cfg_changed(const struct bt_gatt_attr *attr,
846 uint16_t value)
847 {
848 const struct tbs_service_inst *inst = lookup_inst_by_ccc(attr);
849
850 if (inst != NULL) {
851 LOG_DBG("Index %u: value 0x%04x", inst->index, value);
852 } else if (IS_ENABLED(CONFIG_BT_GTBS)) {
853 LOG_DBG("GTBS: value 0x%04x", value);
854 }
855 }
856
read_call_state(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)857 static ssize_t read_call_state(struct bt_conn *conn,
858 const struct bt_gatt_attr *attr,
859 void *buf, uint16_t len, uint16_t offset)
860 {
861 net_buf_put_call_state(BT_AUDIO_CHRC_USER_DATA(attr));
862
863 if (IS_GTBS_CHRC(attr)) {
864 LOG_DBG("GTBS");
865 } else {
866 const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
867
868 LOG_DBG("Index %u", inst->index);
869 }
870
871 if (offset == 0) {
872 LOG_HEXDUMP_DBG(read_buf.data, read_buf.len, "Call state");
873 }
874
875 return bt_gatt_attr_read(conn, attr, buf, len, offset,
876 read_buf.data, read_buf.len);
877 }
878
call_state_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)879 static void call_state_cfg_changed(const struct bt_gatt_attr *attr,
880 uint16_t value)
881 {
882 struct tbs_service_inst *inst = lookup_inst_by_ccc(attr);
883
884 if (inst != NULL) {
885 LOG_DBG("Index %u: value 0x%04x", inst->index, value);
886 inst->notify_call_states = (value == BT_GATT_CCC_NOTIFY);
887 } else if (IS_ENABLED(CONFIG_BT_GTBS)) {
888 LOG_DBG("GTBS: value 0x%04x", value);
889 gtbs_inst.notify_call_states = (value == BT_GATT_CCC_NOTIFY);
890 }
891 }
892
notify_ccp(struct bt_conn * conn,const struct bt_gatt_attr * attr,uint8_t call_index,uint8_t opcode,uint8_t status)893 static int notify_ccp(struct bt_conn *conn, const struct bt_gatt_attr *attr,
894 uint8_t call_index, uint8_t opcode, uint8_t status)
895 {
896 const struct bt_tbs_call_cp_notify ccp_not = {
897 .call_index = call_index,
898 .opcode = opcode,
899 .status = status
900 };
901
902 LOG_DBG("Notifying CCP: Call index %u, %s opcode and status %s", call_index,
903 bt_tbs_opcode_str(opcode), bt_tbs_status_str(status));
904
905 return bt_gatt_notify(conn, attr, &ccp_not, sizeof(ccp_not));
906 }
907
hold_other_calls(struct tbs_service_inst * inst,uint8_t call_index_cnt,const uint8_t * call_indexes)908 static void hold_other_calls(struct tbs_service_inst *inst,
909 uint8_t call_index_cnt,
910 const uint8_t *call_indexes)
911 {
912 held_calls_cnt = 0;
913
914 for (int i = 0; i < ARRAY_SIZE(inst->calls); i++) {
915 bool hold_call = true;
916 uint8_t call_state;
917
918 for (int j = 0; j < call_index_cnt; j++) {
919 if (inst->calls[i].index == call_indexes[j]) {
920 hold_call = false;
921 break;
922 }
923 }
924
925 if (!hold_call) {
926 continue;
927 }
928
929 call_state = inst->calls[i].state;
930 if (call_state == BT_TBS_CALL_STATE_ACTIVE) {
931 inst->calls[i].state = BT_TBS_CALL_STATE_LOCALLY_HELD;
932 held_calls[held_calls_cnt++] = &inst->calls[i];
933 } else if (call_state == BT_TBS_CALL_STATE_REMOTELY_HELD) {
934 inst->calls[i].state =
935 BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD;
936 held_calls[held_calls_cnt++] = &inst->calls[i];
937 }
938 }
939 }
940
accept_call(struct tbs_service_inst * inst,const struct bt_tbs_call_cp_acc * ccp)941 static uint8_t accept_call(struct tbs_service_inst *inst,
942 const struct bt_tbs_call_cp_acc *ccp)
943 {
944 struct bt_tbs_call *call = lookup_call_in_inst(inst, ccp->call_index);
945
946 if (call == NULL) {
947 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
948 }
949
950 if (call->state == BT_TBS_CALL_STATE_INCOMING) {
951 call->state = BT_TBS_CALL_STATE_ACTIVE;
952
953 hold_other_calls(inst, 1, &ccp->call_index);
954
955 return BT_TBS_RESULT_CODE_SUCCESS;
956 } else {
957 return BT_TBS_RESULT_CODE_STATE_MISMATCH;
958 }
959 }
960
terminate_call(struct tbs_service_inst * inst,const struct bt_tbs_call_cp_term * ccp,uint8_t reason)961 static uint8_t terminate_call(struct tbs_service_inst *inst,
962 const struct bt_tbs_call_cp_term *ccp,
963 uint8_t reason)
964 {
965 struct bt_tbs_call *call = lookup_call_in_inst(inst, ccp->call_index);
966
967 if (call == NULL) {
968 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
969 }
970
971 call->index = BT_TBS_FREE_CALL_INDEX;
972 tbs_set_terminate_reason(inst, ccp->call_index, reason);
973
974 return BT_TBS_RESULT_CODE_SUCCESS;
975 }
976
tbs_hold_call(struct tbs_service_inst * inst,const struct bt_tbs_call_cp_hold * ccp)977 static uint8_t tbs_hold_call(struct tbs_service_inst *inst,
978 const struct bt_tbs_call_cp_hold *ccp)
979 {
980 struct bt_tbs_call *call = lookup_call_in_inst(inst, ccp->call_index);
981
982 if ((inst->optional_opcodes & BT_TBS_FEATURE_HOLD) == 0) {
983 return BT_TBS_RESULT_CODE_OPCODE_NOT_SUPPORTED;
984 }
985
986 if (call == NULL) {
987 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
988 }
989
990 if (call->state == BT_TBS_CALL_STATE_ACTIVE) {
991 call->state = BT_TBS_CALL_STATE_LOCALLY_HELD;
992 } else if (call->state == BT_TBS_CALL_STATE_REMOTELY_HELD) {
993 call->state = BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD;
994 } else if (call->state == BT_TBS_CALL_STATE_INCOMING) {
995 call->state = BT_TBS_CALL_STATE_LOCALLY_HELD;
996 } else {
997 return BT_TBS_RESULT_CODE_STATE_MISMATCH;
998 }
999
1000 return BT_TBS_RESULT_CODE_SUCCESS;
1001 }
1002
retrieve_call(struct tbs_service_inst * inst,const struct bt_tbs_call_cp_retrieve * ccp)1003 static uint8_t retrieve_call(struct tbs_service_inst *inst,
1004 const struct bt_tbs_call_cp_retrieve *ccp)
1005 {
1006 struct bt_tbs_call *call = lookup_call_in_inst(inst, ccp->call_index);
1007
1008 if ((inst->optional_opcodes & BT_TBS_FEATURE_HOLD) == 0) {
1009 return BT_TBS_RESULT_CODE_OPCODE_NOT_SUPPORTED;
1010 }
1011
1012 if (call == NULL) {
1013 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1014 }
1015
1016 if (call->state == BT_TBS_CALL_STATE_LOCALLY_HELD) {
1017 call->state = BT_TBS_CALL_STATE_ACTIVE;
1018 } else if (call->state == BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD) {
1019 call->state = BT_TBS_CALL_STATE_REMOTELY_HELD;
1020 } else {
1021 return BT_TBS_RESULT_CODE_STATE_MISMATCH;
1022 }
1023
1024 hold_other_calls(inst, 1, &ccp->call_index);
1025
1026 return BT_TBS_RESULT_CODE_SUCCESS;
1027 }
1028
originate_call(struct tbs_service_inst * inst,const struct bt_tbs_call_cp_originate * ccp,uint16_t uri_len,uint8_t * call_index)1029 static int originate_call(struct tbs_service_inst *inst,
1030 const struct bt_tbs_call_cp_originate *ccp,
1031 uint16_t uri_len, uint8_t *call_index)
1032 {
1033 struct bt_tbs_call *call = NULL;
1034
1035 /* New call - Look for unused call item */
1036 for (int i = 0; i < CONFIG_BT_TBS_MAX_CALLS; i++) {
1037 if (inst->calls[i].index == BT_TBS_FREE_CALL_INDEX) {
1038 call = &inst->calls[i];
1039 break;
1040 }
1041 }
1042
1043 /* Only allow one active outgoing call */
1044 for (int i = 0; i < CONFIG_BT_TBS_MAX_CALLS; i++) {
1045 if (inst->calls[i].state == BT_TBS_CALL_STATE_ALERTING) {
1046 return BT_TBS_RESULT_CODE_OPERATION_NOT_POSSIBLE;
1047 }
1048 }
1049
1050 if (call == NULL) {
1051 return BT_TBS_RESULT_CODE_OUT_OF_RESOURCES;
1052 }
1053
1054 call->index = next_free_call_index();
1055
1056 if (call->index == BT_TBS_FREE_CALL_INDEX) {
1057 return BT_TBS_RESULT_CODE_OUT_OF_RESOURCES;
1058 }
1059
1060 if (uri_len == 0 || uri_len > CONFIG_BT_TBS_MAX_URI_LENGTH) {
1061 call->index = BT_TBS_FREE_CALL_INDEX;
1062 return BT_TBS_RESULT_CODE_INVALID_URI;
1063 }
1064
1065 (void)memcpy(call->remote_uri, ccp->uri, uri_len);
1066 call->remote_uri[uri_len] = '\0';
1067 if (!bt_tbs_valid_uri(call->remote_uri)) {
1068 LOG_DBG("Invalid URI: %s", call->remote_uri);
1069 call->index = BT_TBS_FREE_CALL_INDEX;
1070
1071 return BT_TBS_RESULT_CODE_INVALID_URI;
1072 }
1073
1074 /* We need to notify dialing state for test,
1075 * even though we don't have an internal dialing state.
1076 */
1077 call->state = BT_TBS_CALL_STATE_DIALING;
1078 if (call->index != BT_TBS_FREE_CALL_INDEX) {
1079 *call_index = call->index;
1080 }
1081 BT_TBS_CALL_FLAG_SET_OUTGOING(call->flags);
1082
1083 hold_other_calls(inst, 1, &call->index);
1084
1085 notify_calls(inst);
1086 call->state = BT_TBS_CALL_STATE_ALERTING;
1087 notify_calls(inst);
1088
1089 LOG_DBG("New call with call index %u", call->index);
1090
1091 return BT_TBS_RESULT_CODE_SUCCESS;
1092 }
1093
join_calls(struct tbs_service_inst * inst,const struct bt_tbs_call_cp_join * ccp,uint16_t call_index_cnt)1094 static uint8_t join_calls(struct tbs_service_inst *inst,
1095 const struct bt_tbs_call_cp_join *ccp,
1096 uint16_t call_index_cnt)
1097 {
1098 struct bt_tbs_call *joined_calls[CONFIG_BT_TBS_MAX_CALLS];
1099 uint8_t call_state;
1100
1101 if ((inst->optional_opcodes & BT_TBS_FEATURE_JOIN) == 0) {
1102 return BT_TBS_RESULT_CODE_OPCODE_NOT_SUPPORTED;
1103 }
1104
1105 /* Check length */
1106 if (call_index_cnt < 2 || call_index_cnt > CONFIG_BT_TBS_MAX_CALLS) {
1107 return BT_TBS_RESULT_CODE_OPERATION_NOT_POSSIBLE;
1108 }
1109
1110 /* Check for duplicates */
1111 for (int i = 0; i < call_index_cnt; i++) {
1112 for (int j = 0; j < i; j++) {
1113 if (ccp->call_indexes[i] == ccp->call_indexes[j]) {
1114 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1115 }
1116 }
1117 }
1118
1119 /* Validate that all calls are in a joinable state */
1120 for (int i = 0; i < call_index_cnt; i++) {
1121 joined_calls[i] = lookup_call_in_inst(inst,
1122 ccp->call_indexes[i]);
1123 if (joined_calls[i] == NULL) {
1124 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1125 }
1126
1127 call_state = joined_calls[i]->state;
1128
1129 if (call_state == BT_TBS_CALL_STATE_INCOMING) {
1130 return BT_TBS_RESULT_CODE_OPERATION_NOT_POSSIBLE;
1131 }
1132
1133 if (call_state != BT_TBS_CALL_STATE_LOCALLY_HELD &&
1134 call_state != BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD &&
1135 call_state != BT_TBS_CALL_STATE_ACTIVE) {
1136 return BT_TBS_RESULT_CODE_STATE_MISMATCH;
1137 }
1138 }
1139
1140 /* Join all calls */
1141 for (int i = 0; i < call_index_cnt; i++) {
1142 call_state = joined_calls[i]->state;
1143
1144 if (call_state == BT_TBS_CALL_STATE_LOCALLY_HELD) {
1145 joined_calls[i]->state = BT_TBS_CALL_STATE_ACTIVE;
1146 } else if (call_state ==
1147 BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD) {
1148 joined_calls[i]->state =
1149 BT_TBS_CALL_STATE_REMOTELY_HELD;
1150 } else if (call_state == BT_TBS_CALL_STATE_INCOMING) {
1151 joined_calls[i]->state = BT_TBS_CALL_STATE_ACTIVE;
1152 }
1153 /* else active => Do nothing */
1154 }
1155
1156 hold_other_calls(inst, call_index_cnt, ccp->call_indexes);
1157
1158 return BT_TBS_RESULT_CODE_SUCCESS;
1159 }
1160
notify_app(struct bt_conn * conn,struct tbs_service_inst * inst,uint16_t len,const union bt_tbs_call_cp_t * ccp,uint8_t status,uint8_t call_index)1161 static void notify_app(struct bt_conn *conn, struct tbs_service_inst *inst, uint16_t len,
1162 const union bt_tbs_call_cp_t *ccp, uint8_t status, uint8_t call_index)
1163 {
1164 if (tbs_cbs == NULL) {
1165 return;
1166 }
1167
1168 switch (ccp->opcode) {
1169 case BT_TBS_CALL_OPCODE_ACCEPT:
1170 if (tbs_cbs->accept_call != NULL) {
1171 tbs_cbs->accept_call(conn, call_index);
1172 }
1173 break;
1174 case BT_TBS_CALL_OPCODE_TERMINATE:
1175 if (tbs_cbs->terminate_call != NULL) {
1176 tbs_cbs->terminate_call(conn, call_index,
1177 inst->terminate_reason.reason);
1178 }
1179 break;
1180 case BT_TBS_CALL_OPCODE_HOLD:
1181 if (tbs_cbs->hold_call != NULL) {
1182 tbs_cbs->hold_call(conn, call_index);
1183 }
1184 break;
1185 case BT_TBS_CALL_OPCODE_RETRIEVE:
1186 if (tbs_cbs->retrieve_call != NULL) {
1187 tbs_cbs->retrieve_call(conn, call_index);
1188 }
1189 break;
1190 case BT_TBS_CALL_OPCODE_ORIGINATE:
1191 {
1192 char uri[CONFIG_BT_TBS_MAX_URI_LENGTH + 1];
1193 const uint16_t uri_len = len - sizeof(ccp->originate);
1194 bool remote_party_alerted = false;
1195 struct bt_tbs_call *call;
1196
1197 call = lookup_call_in_inst(inst, call_index);
1198
1199 if (call == NULL) {
1200 LOG_DBG("Could not find call by call index 0x%02X", call_index);
1201 break;
1202 }
1203
1204 (void)memcpy(uri, ccp->originate.uri, uri_len);
1205 uri[uri_len] = '\0';
1206 if (tbs_cbs->originate_call != NULL) {
1207 remote_party_alerted = tbs_cbs->originate_call(conn,
1208 call_index,
1209 uri);
1210 }
1211
1212 if (remote_party_alerted) {
1213 call->state = BT_TBS_CALL_STATE_ALERTING;
1214 } else {
1215 const struct bt_tbs_call_cp_term term = {
1216 .call_index = call_index,
1217 .opcode = BT_TBS_CALL_OPCODE_TERMINATE
1218 };
1219
1220 /* Terminate and remove call */
1221 terminate_call(inst, &term, BT_TBS_REASON_CALL_FAILED);
1222 }
1223
1224 notify_calls(inst);
1225
1226 break;
1227 }
1228 case BT_TBS_CALL_OPCODE_JOIN:
1229 {
1230 const uint16_t call_index_cnt = len - sizeof(ccp->join);
1231
1232 /* Let the app know about joined calls */
1233 if (tbs_cbs->join_calls != NULL) {
1234 tbs_cbs->join_calls(conn, call_index_cnt,
1235 ccp->join.call_indexes);
1236 }
1237 break;
1238 }
1239 default:
1240 break;
1241 }
1242
1243 /* Let the app know about held calls */
1244 if (held_calls_cnt != 0 && tbs_cbs->hold_call != NULL) {
1245 for (int i = 0; i < held_calls_cnt; i++) {
1246 tbs_cbs->hold_call(conn, held_calls[i]->index);
1247 }
1248 }
1249 }
1250
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)1251 static ssize_t write_call_cp(struct bt_conn *conn,
1252 const struct bt_gatt_attr *attr,
1253 const void *buf, uint16_t len,
1254 uint16_t offset, uint8_t flags)
1255 {
1256 struct tbs_service_inst *inst = NULL;
1257 const union bt_tbs_call_cp_t *ccp = (union bt_tbs_call_cp_t *)buf;
1258 uint8_t status;
1259 uint8_t call_index = 0;
1260 const bool is_gtbs = IS_GTBS_CHRC(attr);
1261
1262 if (!is_authorized(conn)) {
1263 return BT_GATT_ERR(BT_ATT_ERR_AUTHORIZATION);
1264 }
1265
1266 if (offset != 0) {
1267 return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
1268 }
1269
1270 if (len < sizeof(ccp->opcode)) {
1271 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
1272 }
1273
1274 if (is_gtbs) {
1275 LOG_DBG("GTBS: Processing the %s opcode", bt_tbs_opcode_str(ccp->opcode));
1276 } else {
1277 inst = BT_AUDIO_CHRC_USER_DATA(attr);
1278
1279 LOG_DBG("Index %u: Processing the %s opcode", inst->index,
1280 bt_tbs_opcode_str(ccp->opcode));
1281 }
1282
1283 switch (ccp->opcode) {
1284 case BT_TBS_CALL_OPCODE_ACCEPT:
1285 if (len != sizeof(ccp->accept)) {
1286 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
1287 }
1288
1289 call_index = ccp->accept.call_index;
1290
1291 if (is_gtbs) {
1292 inst = lookup_inst_by_call_index(call_index);
1293 if (inst == NULL) {
1294 status = BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1295 break;
1296 }
1297 }
1298
1299 status = accept_call(inst, &ccp->accept);
1300 break;
1301 case BT_TBS_CALL_OPCODE_TERMINATE:
1302 if (len != sizeof(ccp->terminate)) {
1303 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
1304 }
1305
1306 call_index = ccp->terminate.call_index;
1307
1308 if (is_gtbs) {
1309 inst = lookup_inst_by_call_index(call_index);
1310 if (inst == NULL) {
1311 status = BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1312 break;
1313 }
1314 }
1315
1316 status = terminate_call(inst, &ccp->terminate,
1317 BT_TBS_REASON_CLIENT_TERMINATED);
1318 break;
1319 case BT_TBS_CALL_OPCODE_HOLD:
1320 if (len != sizeof(ccp->hold)) {
1321 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
1322 }
1323
1324 call_index = ccp->hold.call_index;
1325
1326 if (is_gtbs) {
1327 inst = lookup_inst_by_call_index(call_index);
1328 if (inst == NULL) {
1329 status = BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1330 break;
1331 }
1332 }
1333
1334 status = tbs_hold_call(inst, &ccp->hold);
1335 break;
1336 case BT_TBS_CALL_OPCODE_RETRIEVE:
1337 if (len != sizeof(ccp->retrieve)) {
1338 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
1339 }
1340
1341 call_index = ccp->retrieve.call_index;
1342
1343 if (is_gtbs) {
1344 inst = lookup_inst_by_call_index(call_index);
1345 if (inst == NULL) {
1346 status = BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1347 break;
1348 }
1349 }
1350
1351 status = retrieve_call(inst, &ccp->retrieve);
1352 break;
1353 case BT_TBS_CALL_OPCODE_ORIGINATE:
1354 {
1355 const uint16_t uri_len = len - sizeof(ccp->originate);
1356
1357 if (len < sizeof(ccp->originate) + BT_TBS_MIN_URI_LEN) {
1358 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
1359 }
1360
1361 if (is_gtbs) {
1362 inst = lookup_inst_by_uri_scheme(ccp->originate.uri,
1363 uri_len);
1364 if (inst == NULL) {
1365 /* TODO: Couldn't find fitting TBS instance;
1366 * use the first. If we want to be
1367 * restrictive about URIs, return
1368 * Invalid Caller ID instead
1369 */
1370 inst = &svc_insts[0];
1371 }
1372 }
1373
1374 status = originate_call(inst, &ccp->originate, uri_len,
1375 &call_index);
1376 break;
1377 }
1378 case BT_TBS_CALL_OPCODE_JOIN:
1379 {
1380 const uint16_t call_index_cnt = len - sizeof(ccp->join);
1381
1382 if (len < sizeof(ccp->join) + 1) { /* at least 1 call index */
1383 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
1384 }
1385
1386 call_index = ccp->join.call_indexes[0];
1387
1388 if (is_gtbs) {
1389 inst = lookup_inst_by_call_index(call_index);
1390 if (inst == NULL) {
1391 status = BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1392 break;
1393 }
1394 }
1395
1396 status = join_calls(inst, &ccp->join, call_index_cnt);
1397 break;
1398 }
1399 default:
1400 status = BT_TBS_RESULT_CODE_OPCODE_NOT_SUPPORTED;
1401 call_index = 0;
1402 break;
1403 }
1404
1405 if (inst != NULL) {
1406 if (is_gtbs) {
1407 LOG_DBG("GTBS: Processed the %s opcode with status %s "
1408 "for call index %u",
1409 bt_tbs_opcode_str(ccp->opcode),
1410 bt_tbs_status_str(status),
1411 call_index);
1412 } else {
1413 LOG_DBG("Index %u: Processed the %s opcode with status "
1414 "%s for call index %u",
1415 inst->index,
1416 bt_tbs_opcode_str(ccp->opcode),
1417 bt_tbs_status_str(status),
1418 call_index);
1419 }
1420
1421 if (status == BT_TBS_RESULT_CODE_SUCCESS) {
1422 const struct bt_tbs_call *call = lookup_call(call_index);
1423
1424 if (call != NULL) {
1425 LOG_DBG("Call is now in the %s state",
1426 bt_tbs_state_str(call->state));
1427 } else {
1428 LOG_DBG("Call is now terminated");
1429 }
1430 }
1431 }
1432
1433 if (status != BT_TBS_RESULT_CODE_SUCCESS) {
1434 call_index = 0;
1435 }
1436
1437 if (conn != NULL) {
1438 notify_ccp(conn, attr, call_index, ccp->opcode, status);
1439 } /* else local operation; don't notify */
1440
1441 if (inst != NULL && status == BT_TBS_RESULT_CODE_SUCCESS) {
1442 notify_calls(inst);
1443 notify_app(conn, inst, len, ccp, status, call_index);
1444 }
1445
1446 return len;
1447 }
1448
call_cp_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)1449 static void call_cp_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
1450 {
1451 const struct tbs_service_inst *inst = lookup_inst_by_ccc(attr);
1452
1453 if (inst != NULL) {
1454 LOG_DBG("Index %u: value 0x%04x", inst->index, value);
1455 } else if (IS_ENABLED(CONFIG_BT_GTBS)) {
1456 LOG_DBG("GTBS: value 0x%04x", value);
1457 }
1458 }
1459
read_optional_opcodes(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)1460 static ssize_t read_optional_opcodes(struct bt_conn *conn,
1461 const struct bt_gatt_attr *attr,
1462 void *buf, uint16_t len, uint16_t offset)
1463 {
1464 uint16_t optional_opcodes;
1465
1466 if (IS_GTBS_CHRC(attr)) {
1467 optional_opcodes = gtbs_inst.optional_opcodes;
1468 LOG_DBG("GTBS: Supported opcodes 0x%02x", optional_opcodes);
1469 } else {
1470 const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
1471
1472 optional_opcodes = inst->optional_opcodes;
1473 LOG_DBG("Index %u: Supported opcodes 0x%02x", inst->index, optional_opcodes);
1474 }
1475
1476 return bt_gatt_attr_read(conn, attr, buf, len, offset,
1477 &optional_opcodes, sizeof(optional_opcodes));
1478 }
1479
terminate_reason_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)1480 static void terminate_reason_cfg_changed(const struct bt_gatt_attr *attr,
1481 uint16_t value)
1482 {
1483 const struct tbs_service_inst *inst = lookup_inst_by_ccc(attr);
1484
1485 if (inst != NULL) {
1486 LOG_DBG("Index %u: value 0x%04x", inst->index, value);
1487 } else if (IS_ENABLED(CONFIG_BT_GTBS)) {
1488 LOG_DBG("GTBS: value 0x%04x", value);
1489 }
1490 }
1491
read_friendly_name(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)1492 static ssize_t read_friendly_name(struct bt_conn *conn,
1493 const struct bt_gatt_attr *attr,
1494 void *buf, uint16_t len, uint16_t offset)
1495 {
1496 const struct bt_tbs_in_uri *friendly_name;
1497 size_t val_len;
1498
1499 if (IS_GTBS_CHRC(attr)) {
1500 friendly_name = >bs_inst.friendly_name;
1501 LOG_DBG("GTBS: call index 0x%02X, URI %s", friendly_name->call_index,
1502 friendly_name->uri);
1503 } else {
1504 const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
1505
1506 friendly_name = &inst->friendly_name;
1507 LOG_DBG("Index %u: call index 0x%02X, URI %s", inst->index,
1508 friendly_name->call_index, friendly_name->uri);
1509 }
1510
1511 if (friendly_name->call_index == BT_TBS_FREE_CALL_INDEX) {
1512 LOG_DBG("URI not set");
1513 return bt_gatt_attr_read(conn, attr, buf, len, offset, NULL, 0);
1514 }
1515
1516 val_len = sizeof(friendly_name->call_index) +
1517 strlen(friendly_name->uri);
1518
1519 return bt_gatt_attr_read(conn, attr, buf, len, offset,
1520 friendly_name, val_len);
1521 }
1522
friendly_name_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)1523 static void friendly_name_cfg_changed(const struct bt_gatt_attr *attr,
1524 uint16_t value)
1525 {
1526 const struct tbs_service_inst *inst = lookup_inst_by_ccc(attr);
1527
1528 if (inst != NULL) {
1529 LOG_DBG("Index %u: value 0x%04x", inst->index, value);
1530 } else if (IS_ENABLED(CONFIG_BT_GTBS)) {
1531 LOG_DBG("GTBS: value 0x%04x", value);
1532 }
1533 }
1534
read_incoming_call(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)1535 static ssize_t read_incoming_call(struct bt_conn *conn,
1536 const struct bt_gatt_attr *attr,
1537 void *buf, uint16_t len, uint16_t offset)
1538 {
1539 const struct bt_tbs_in_uri *remote_uri;
1540 size_t val_len;
1541
1542 if (IS_GTBS_CHRC(attr)) {
1543 remote_uri = >bs_inst.in_call;
1544 LOG_DBG("GTBS: call index 0x%02X, URI %s", remote_uri->call_index, remote_uri->uri);
1545 } else {
1546 const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr);
1547
1548 remote_uri = &inst->in_call;
1549 LOG_DBG("Index %u: call index 0x%02X, URI %s", inst->index, remote_uri->call_index,
1550 remote_uri->uri);
1551 }
1552
1553 if (remote_uri->call_index == BT_TBS_FREE_CALL_INDEX) {
1554 LOG_DBG("URI not set");
1555
1556 return bt_gatt_attr_read(conn, attr, buf, len, offset, NULL, 0);
1557 }
1558
1559 val_len = sizeof(remote_uri->call_index) + strlen(remote_uri->uri);
1560
1561 return bt_gatt_attr_read(conn, attr, buf, len, offset,
1562 remote_uri, val_len);
1563 }
1564
in_call_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)1565 static void in_call_cfg_changed(const struct bt_gatt_attr *attr,
1566 uint16_t value)
1567 {
1568 const struct tbs_service_inst *inst = lookup_inst_by_ccc(attr);
1569
1570 if (inst != NULL) {
1571 LOG_DBG("Index %u: value 0x%04x", inst->index, value);
1572 } else if (IS_ENABLED(CONFIG_BT_GTBS)) {
1573 LOG_DBG("GTBS: value 0x%04x", value);
1574 }
1575 }
1576
1577 #define BT_TBS_CHR_PROVIDER_NAME(inst) \
1578 BT_AUDIO_CHRC(BT_UUID_TBS_PROVIDER_NAME, \
1579 BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
1580 BT_GATT_PERM_READ_ENCRYPT, \
1581 read_provider_name, NULL, inst), \
1582 BT_AUDIO_CCC(provider_name_cfg_changed)
1583
1584 #define BT_TBS_CHR_UCI(inst) \
1585 BT_AUDIO_CHRC(BT_UUID_TBS_UCI, \
1586 BT_GATT_CHRC_READ, \
1587 BT_GATT_PERM_READ_ENCRYPT, \
1588 read_uci, NULL, inst)
1589
1590 #define BT_TBS_CHR_TECHNOLOGY(inst) \
1591 BT_AUDIO_CHRC(BT_UUID_TBS_TECHNOLOGY, \
1592 BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
1593 BT_GATT_PERM_READ_ENCRYPT, \
1594 read_technology, NULL, inst), \
1595 BT_AUDIO_CCC(technology_cfg_changed)
1596
1597 #define BT_TBS_CHR_URI_LIST(inst) \
1598 BT_AUDIO_CHRC(BT_UUID_TBS_URI_LIST, \
1599 BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
1600 BT_GATT_PERM_READ_ENCRYPT, \
1601 read_uri_scheme_list, NULL, inst), \
1602 BT_AUDIO_CCC(uri_scheme_list_cfg_changed)
1603
1604 #define BT_TBS_CHR_SIGNAL_STRENGTH(inst) \
1605 BT_AUDIO_CHRC(BT_UUID_TBS_SIGNAL_STRENGTH, /* Optional */ \
1606 BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
1607 BT_GATT_PERM_READ_ENCRYPT, \
1608 read_signal_strength, NULL, inst), \
1609 BT_AUDIO_CCC(signal_strength_cfg_changed)
1610
1611 #define BT_TBS_CHR_SIGNAL_INTERVAL(inst) \
1612 BT_AUDIO_CHRC(BT_UUID_TBS_SIGNAL_INTERVAL, /* Conditional */ \
1613 BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP, \
1614 BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, \
1615 read_signal_strength_interval, write_signal_strength_interval, inst)
1616
1617 #define BT_TBS_CHR_CURRENT_CALLS(inst) \
1618 BT_AUDIO_CHRC(BT_UUID_TBS_LIST_CURRENT_CALLS, \
1619 BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
1620 BT_GATT_PERM_READ_ENCRYPT, \
1621 read_current_calls, NULL, inst), \
1622 BT_AUDIO_CCC(current_calls_cfg_changed)
1623
1624 #define BT_TBS_CHR_CCID(inst) \
1625 BT_AUDIO_CHRC(BT_UUID_CCID, \
1626 BT_GATT_CHRC_READ, \
1627 BT_GATT_PERM_READ_ENCRYPT, \
1628 read_ccid, NULL, inst)
1629
1630 #define BT_TBS_CHR_STATUS_FLAGS(inst) \
1631 BT_AUDIO_CHRC(BT_UUID_TBS_STATUS_FLAGS, \
1632 BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
1633 BT_GATT_PERM_READ_ENCRYPT, \
1634 read_status_flags, NULL, inst), \
1635 BT_AUDIO_CCC(status_flags_cfg_changed)
1636
1637 #define BT_TBS_CHR_INCOMING_URI(inst) \
1638 BT_AUDIO_CHRC(BT_UUID_TBS_INCOMING_URI, /* Optional */ \
1639 BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
1640 BT_GATT_PERM_READ_ENCRYPT, \
1641 read_incoming_uri, NULL, inst), \
1642 BT_AUDIO_CCC(incoming_uri_cfg_changed)
1643
1644 #define BT_TBS_CHR_CALL_STATE(inst) \
1645 BT_AUDIO_CHRC(BT_UUID_TBS_CALL_STATE, \
1646 BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
1647 BT_GATT_PERM_READ_ENCRYPT, \
1648 read_call_state, NULL, inst), \
1649 BT_AUDIO_CCC(call_state_cfg_changed)
1650
1651 #define BT_TBS_CHR_CONTROL_POINT(inst) \
1652 BT_AUDIO_CHRC(BT_UUID_TBS_CALL_CONTROL_POINT, \
1653 BT_GATT_CHRC_WRITE | BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_WRITE_WITHOUT_RESP, \
1654 BT_GATT_PERM_WRITE_ENCRYPT, \
1655 NULL, write_call_cp, inst), \
1656 BT_AUDIO_CCC(call_cp_cfg_changed)
1657
1658 #define BT_TBS_CHR_OPTIONAL_OPCODES(inst) \
1659 BT_AUDIO_CHRC(BT_UUID_TBS_OPTIONAL_OPCODES, \
1660 BT_GATT_CHRC_READ, \
1661 BT_GATT_PERM_READ_ENCRYPT, \
1662 read_optional_opcodes, NULL, inst) \
1663
1664 #define BT_TBS_CHR_TERMINATE_REASON(inst) \
1665 BT_AUDIO_CHRC(BT_UUID_TBS_TERMINATE_REASON, \
1666 BT_GATT_CHRC_NOTIFY, \
1667 BT_GATT_PERM_READ_ENCRYPT, \
1668 NULL, NULL, inst), \
1669 BT_AUDIO_CCC(terminate_reason_cfg_changed)
1670
1671 #define BT_TBS_CHR_INCOMING_CALL(inst) \
1672 BT_AUDIO_CHRC(BT_UUID_TBS_INCOMING_CALL, \
1673 BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
1674 BT_GATT_PERM_READ_ENCRYPT, \
1675 read_incoming_call, NULL, inst), \
1676 BT_AUDIO_CCC(in_call_cfg_changed)
1677
1678 #define BT_TBS_CHR_FRIENDLY_NAME(inst) \
1679 BT_AUDIO_CHRC(BT_UUID_TBS_FRIENDLY_NAME, /* Optional */ \
1680 BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
1681 BT_GATT_PERM_READ_ENCRYPT, \
1682 read_friendly_name, NULL, inst), \
1683 BT_AUDIO_CCC(friendly_name_cfg_changed)
1684
1685 #define BT_TBS_SERVICE_DEFINE(_uuid, _inst) \
1686 BT_GATT_PRIMARY_SERVICE(_uuid), \
1687 BT_TBS_CHR_PROVIDER_NAME(_inst), \
1688 BT_TBS_CHR_UCI(_inst), \
1689 BT_TBS_CHR_TECHNOLOGY(_inst), \
1690 BT_TBS_CHR_URI_LIST(_inst), \
1691 BT_TBS_CHR_SIGNAL_STRENGTH(_inst), \
1692 BT_TBS_CHR_SIGNAL_INTERVAL(_inst), \
1693 BT_TBS_CHR_CURRENT_CALLS(_inst), \
1694 BT_TBS_CHR_CCID(_inst), \
1695 BT_TBS_CHR_STATUS_FLAGS(_inst), \
1696 BT_TBS_CHR_INCOMING_URI(_inst), \
1697 BT_TBS_CHR_CALL_STATE(_inst), \
1698 BT_TBS_CHR_CONTROL_POINT(_inst), \
1699 BT_TBS_CHR_OPTIONAL_OPCODES(_inst), \
1700 BT_TBS_CHR_TERMINATE_REASON(_inst), \
1701 BT_TBS_CHR_INCOMING_CALL(_inst), \
1702 BT_TBS_CHR_FRIENDLY_NAME(_inst)
1703
1704 #define BT_TBS_SERVICE_DEFINITION(_inst) { BT_TBS_SERVICE_DEFINE(BT_UUID_TBS, &(_inst)) }
1705
1706 /*
1707 * Defining this as extern make it possible to link code that otherwise would
1708 * give "unknown identifier" linking errors.
1709 */
1710 extern const struct bt_gatt_service_static gtbs_svc;
1711
1712 /* TODO: Can we make the multiple service instance more generic? */
1713 #if CONFIG_BT_GTBS
1714 BT_GATT_SERVICE_DEFINE(gtbs_svc, BT_TBS_SERVICE_DEFINE(BT_UUID_GTBS, >bs_inst));
1715 #endif /* CONFIG_BT_GTBS */
1716
1717 BT_GATT_SERVICE_INSTANCE_DEFINE(tbs_service_list, svc_insts, CONFIG_BT_TBS_BEARER_COUNT,
1718 BT_TBS_SERVICE_DEFINITION);
1719
signal_interval_timeout(struct k_work * work)1720 static void signal_interval_timeout(struct k_work *work)
1721 {
1722 struct tbs_service_inst *inst = lookup_inst_by_work(work);
1723
1724 if (inst && inst->pending_signal_strength_notification) {
1725 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_SIGNAL_STRENGTH,
1726 inst->service_p->attrs,
1727 &inst->signal_strength,
1728 sizeof(inst->signal_strength));
1729
1730 if (inst->signal_strength_interval) {
1731 k_work_reschedule(
1732 &inst->reporting_interval_work,
1733 K_SECONDS(inst->signal_strength_interval));
1734 }
1735
1736 inst->pending_signal_strength_notification = false;
1737 } else if (IS_ENABLED(CONFIG_BT_GTBS) &&
1738 gtbs_inst.pending_signal_strength_notification) {
1739
1740 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_SIGNAL_STRENGTH,
1741 gtbs_inst.service_p->attrs,
1742 >bs_inst.signal_strength,
1743 sizeof(gtbs_inst.signal_strength));
1744
1745 if (gtbs_inst.signal_strength_interval) {
1746 k_work_reschedule(
1747 >bs_inst.reporting_interval_work,
1748 K_SECONDS(gtbs_inst.signal_strength_interval));
1749 }
1750
1751 gtbs_inst.pending_signal_strength_notification = false;
1752 }
1753 }
1754
bt_tbs_init(void)1755 static int bt_tbs_init(void)
1756 {
1757 for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) {
1758 int err;
1759
1760 svc_insts[i].service_p = &tbs_service_list[i];
1761
1762 err = bt_gatt_service_register(svc_insts[i].service_p);
1763 if (err != 0) {
1764 LOG_ERR("Could not register TBS[%d]: %d", i, err);
1765 }
1766 }
1767
1768 if (IS_ENABLED(CONFIG_BT_GTBS)) {
1769 gtbs_inst.service_p = >bs_svc;
1770 (void)strcpy(gtbs_inst.provider_name, "Generic TBS");
1771 gtbs_inst.optional_opcodes = CONFIG_BT_TBS_SUPPORTED_FEATURES;
1772 gtbs_inst.ccid = bt_ccid_get_value();
1773 (void)strcpy(gtbs_inst.uci, "un000");
1774
1775 k_work_init_delayable(>bs_inst.reporting_interval_work,
1776 signal_interval_timeout);
1777 }
1778
1779 for (int i = 0; i < ARRAY_SIZE(svc_insts); i++) {
1780 /* Init default values */
1781 svc_insts[i].index = i;
1782 svc_insts[i].ccid = bt_ccid_get_value();
1783 (void)strcpy(svc_insts[i].provider_name,
1784 CONFIG_BT_TBS_PROVIDER_NAME);
1785 (void)strcpy(svc_insts[i].uci, CONFIG_BT_TBS_UCI);
1786 (void)strcpy(svc_insts[i].uri_scheme_list,
1787 CONFIG_BT_TBS_URI_SCHEMES_LIST);
1788 svc_insts[i].optional_opcodes = CONFIG_BT_TBS_SUPPORTED_FEATURES;
1789 svc_insts[i].technology = CONFIG_BT_TBS_TECHNOLOGY;
1790 svc_insts[i].signal_strength_interval = CONFIG_BT_TBS_SIGNAL_STRENGTH_INTERVAL;
1791 svc_insts[i].status_flags = CONFIG_BT_TBS_STATUS_FLAGS;
1792
1793 k_work_init_delayable(&svc_insts[i].reporting_interval_work,
1794 signal_interval_timeout);
1795 }
1796
1797 return 0;
1798 }
1799
1800 SYS_INIT(bt_tbs_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
1801
1802 /***************************** Profile API *****************************/
bt_tbs_accept(uint8_t call_index)1803 int bt_tbs_accept(uint8_t call_index)
1804 {
1805 struct tbs_service_inst *inst = lookup_inst_by_call_index(call_index);
1806 int status = -EINVAL;
1807 const struct bt_tbs_call_cp_acc ccp = {
1808 .call_index = call_index,
1809 .opcode = BT_TBS_CALL_OPCODE_ACCEPT
1810 };
1811
1812 if (inst != NULL) {
1813 status = accept_call(inst, &ccp);
1814 }
1815
1816 if (status == BT_TBS_RESULT_CODE_SUCCESS) {
1817 notify_calls(inst);
1818 }
1819
1820 return status;
1821 }
1822
bt_tbs_hold(uint8_t call_index)1823 int bt_tbs_hold(uint8_t call_index)
1824 {
1825 struct tbs_service_inst *inst = lookup_inst_by_call_index(call_index);
1826 int status = -EINVAL;
1827 const struct bt_tbs_call_cp_hold ccp = {
1828 .call_index = call_index,
1829 .opcode = BT_TBS_CALL_OPCODE_HOLD
1830 };
1831
1832 if (inst != NULL) {
1833 status = tbs_hold_call(inst, &ccp);
1834 }
1835
1836 return status;
1837 }
1838
bt_tbs_retrieve(uint8_t call_index)1839 int bt_tbs_retrieve(uint8_t call_index)
1840 {
1841 struct tbs_service_inst *inst = lookup_inst_by_call_index(call_index);
1842 int status = -EINVAL;
1843 const struct bt_tbs_call_cp_retrieve ccp = {
1844 .call_index = call_index,
1845 .opcode = BT_TBS_CALL_OPCODE_RETRIEVE
1846 };
1847
1848 if (inst != NULL) {
1849 status = retrieve_call(inst, &ccp);
1850 }
1851
1852 return status;
1853 }
1854
bt_tbs_terminate(uint8_t call_index)1855 int bt_tbs_terminate(uint8_t call_index)
1856 {
1857 struct tbs_service_inst *inst = lookup_inst_by_call_index(call_index);
1858 int status = -EINVAL;
1859 const struct bt_tbs_call_cp_term ccp = {
1860 .call_index = call_index,
1861 .opcode = BT_TBS_CALL_OPCODE_TERMINATE
1862 };
1863
1864 if (inst != NULL) {
1865 status = terminate_call(inst, &ccp,
1866 BT_TBS_REASON_SERVER_ENDED_CALL);
1867 }
1868
1869 return status;
1870 }
1871
bt_tbs_originate(uint8_t bearer_index,char * remote_uri,uint8_t * call_index)1872 int bt_tbs_originate(uint8_t bearer_index, char *remote_uri,
1873 uint8_t *call_index)
1874 {
1875 struct tbs_service_inst *inst;
1876 uint8_t buf[CONFIG_BT_TBS_MAX_URI_LENGTH +
1877 sizeof(struct bt_tbs_call_cp_originate)];
1878 struct bt_tbs_call_cp_originate *ccp =
1879 (struct bt_tbs_call_cp_originate *)buf;
1880 size_t uri_len;
1881
1882 if (bearer_index >= CONFIG_BT_TBS_BEARER_COUNT) {
1883 return -EINVAL;
1884 } else if (!bt_tbs_valid_uri(remote_uri)) {
1885 LOG_DBG("Invalid URI %s", remote_uri);
1886 return -EINVAL;
1887 }
1888
1889 uri_len = strlen(remote_uri);
1890
1891 inst = &svc_insts[bearer_index];
1892
1893 ccp->opcode = BT_TBS_CALL_OPCODE_ORIGINATE;
1894 (void)memcpy(ccp->uri, remote_uri, uri_len);
1895
1896 return originate_call(inst, ccp, uri_len, call_index);
1897 }
1898
bt_tbs_join(uint8_t call_index_cnt,uint8_t * call_indexes)1899 int bt_tbs_join(uint8_t call_index_cnt, uint8_t *call_indexes)
1900 {
1901 struct tbs_service_inst *inst;
1902 uint8_t buf[CONFIG_BT_TBS_MAX_CALLS +
1903 sizeof(struct bt_tbs_call_cp_join)];
1904 struct bt_tbs_call_cp_join *ccp = (struct bt_tbs_call_cp_join *)buf;
1905 int status = -EINVAL;
1906
1907 if (call_index_cnt != 0 && call_indexes != 0) {
1908 inst = lookup_inst_by_call_index(call_indexes[0]);
1909 } else {
1910 return status;
1911 }
1912
1913 if (inst != NULL) {
1914 ccp->opcode = BT_TBS_CALL_OPCODE_JOIN;
1915 (void)memcpy(ccp->call_indexes, call_indexes,
1916 MIN(call_index_cnt, CONFIG_BT_TBS_MAX_CALLS));
1917
1918 status = join_calls(inst, ccp, call_index_cnt);
1919 }
1920
1921 return status;
1922 }
1923
bt_tbs_remote_answer(uint8_t call_index)1924 int bt_tbs_remote_answer(uint8_t call_index)
1925 {
1926 struct tbs_service_inst *inst = lookup_inst_by_call_index(call_index);
1927 struct bt_tbs_call *call;
1928
1929 if (inst == NULL) {
1930 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1931 }
1932
1933 call = lookup_call_in_inst(inst, call_index);
1934
1935 if (call == NULL) {
1936 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1937 }
1938
1939 if (call->state == BT_TBS_CALL_STATE_ALERTING) {
1940 call->state = BT_TBS_CALL_STATE_ACTIVE;
1941 notify_calls(inst);
1942 return BT_TBS_RESULT_CODE_SUCCESS;
1943 } else {
1944 return BT_TBS_RESULT_CODE_STATE_MISMATCH;
1945 }
1946 }
1947
bt_tbs_remote_hold(uint8_t call_index)1948 int bt_tbs_remote_hold(uint8_t call_index)
1949 {
1950 struct tbs_service_inst *inst = lookup_inst_by_call_index(call_index);
1951 struct bt_tbs_call *call;
1952 uint8_t status;
1953
1954 if (inst == NULL) {
1955 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1956 }
1957
1958 call = lookup_call_in_inst(inst, call_index);
1959
1960 if (call == NULL) {
1961 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1962 }
1963
1964 if (call->state == BT_TBS_CALL_STATE_ACTIVE) {
1965 call->state = BT_TBS_CALL_STATE_REMOTELY_HELD;
1966 status = BT_TBS_RESULT_CODE_SUCCESS;
1967 } else if (call->state == BT_TBS_CALL_STATE_LOCALLY_HELD) {
1968 call->state = BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD;
1969 status = BT_TBS_RESULT_CODE_SUCCESS;
1970 } else {
1971 status = BT_TBS_RESULT_CODE_STATE_MISMATCH;
1972 }
1973
1974 if (status == BT_TBS_RESULT_CODE_SUCCESS) {
1975 notify_calls(inst);
1976 }
1977
1978 return status;
1979 }
1980
bt_tbs_remote_retrieve(uint8_t call_index)1981 int bt_tbs_remote_retrieve(uint8_t call_index)
1982 {
1983 struct tbs_service_inst *inst = lookup_inst_by_call_index(call_index);
1984 struct bt_tbs_call *call;
1985 int status;
1986
1987 if (inst == NULL) {
1988 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1989 }
1990
1991 call = lookup_call_in_inst(inst, call_index);
1992
1993 if (call == NULL) {
1994 return BT_TBS_RESULT_CODE_INVALID_CALL_INDEX;
1995 }
1996
1997 if (call->state == BT_TBS_CALL_STATE_REMOTELY_HELD) {
1998 call->state = BT_TBS_CALL_STATE_ACTIVE;
1999 status = BT_TBS_RESULT_CODE_SUCCESS;
2000 } else if (call->state == BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD) {
2001 call->state = BT_TBS_CALL_STATE_LOCALLY_HELD;
2002 status = BT_TBS_RESULT_CODE_SUCCESS;
2003 } else {
2004 status = BT_TBS_RESULT_CODE_STATE_MISMATCH;
2005 }
2006
2007 if (status == BT_TBS_RESULT_CODE_SUCCESS) {
2008 notify_calls(inst);
2009 }
2010
2011 return status;
2012 }
2013
bt_tbs_remote_terminate(uint8_t call_index)2014 int bt_tbs_remote_terminate(uint8_t call_index)
2015 {
2016 struct tbs_service_inst *inst = lookup_inst_by_call_index(call_index);
2017 int status = -EINVAL;
2018 const struct bt_tbs_call_cp_term ccp = {
2019 .call_index = call_index,
2020 .opcode = BT_TBS_CALL_OPCODE_TERMINATE
2021 };
2022
2023 if (inst != NULL) {
2024 status = terminate_call(inst, &ccp,
2025 BT_TBS_REASON_REMOTE_ENDED_CALL);
2026 }
2027
2028 return status;
2029 }
2030
bt_tbs_remote_incoming(uint8_t bearer_index,const char * to,const char * from,const char * friendly_name)2031 int bt_tbs_remote_incoming(uint8_t bearer_index, const char *to,
2032 const char *from, const char *friendly_name)
2033 {
2034 struct tbs_service_inst *inst;
2035 struct bt_tbs_call *call = NULL;
2036 size_t local_uri_ind_len;
2037 size_t remote_uri_ind_len;
2038 size_t friend_name_ind_len;
2039
2040 if (bearer_index >= CONFIG_BT_TBS_BEARER_COUNT) {
2041 return -EINVAL;
2042 } else if (!bt_tbs_valid_uri(to)) {
2043 LOG_DBG("Invalid \"to\" URI: %s", to);
2044 return -EINVAL;
2045 } else if (!bt_tbs_valid_uri(from)) {
2046 LOG_DBG("Invalid \"from\" URI: %s", from);
2047 return -EINVAL;
2048 }
2049
2050 local_uri_ind_len = strlen(to) + 1;
2051 remote_uri_ind_len = strlen(from) + 1;
2052
2053 inst = &svc_insts[bearer_index];
2054
2055 /* New call - Look for unused call item */
2056 for (int i = 0; i < CONFIG_BT_TBS_MAX_CALLS; i++) {
2057 if (inst->calls[i].index == BT_TBS_FREE_CALL_INDEX) {
2058 call = &inst->calls[i];
2059 break;
2060 }
2061 }
2062
2063 if (call == NULL) {
2064 return -BT_TBS_RESULT_CODE_OUT_OF_RESOURCES;
2065 }
2066
2067 call->index = next_free_call_index();
2068
2069 if (call->index == BT_TBS_FREE_CALL_INDEX) {
2070 return -BT_TBS_RESULT_CODE_OUT_OF_RESOURCES;
2071 }
2072
2073 BT_TBS_CALL_FLAG_SET_INCOMING(call->flags);
2074
2075 (void)strcpy(call->remote_uri, from);
2076 call->state = BT_TBS_CALL_STATE_INCOMING;
2077
2078 inst->in_call.call_index = call->index;
2079 (void)strcpy(inst->in_call.uri, from);
2080
2081 inst->incoming_uri.call_index = call->index;
2082 (void)strcpy(inst->incoming_uri.uri, to);
2083
2084 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_INCOMING_URI,
2085 inst->service_p->attrs,
2086 &inst->incoming_uri, local_uri_ind_len);
2087
2088 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_INCOMING_CALL,
2089 inst->service_p->attrs,
2090 &inst->in_call, remote_uri_ind_len);
2091
2092 if (friendly_name) {
2093 inst->friendly_name.call_index = call->index;
2094 utf8_lcpy(inst->friendly_name.uri, friendly_name, sizeof(inst->friendly_name.uri));
2095 friend_name_ind_len = strlen(from) + 1;
2096
2097 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_FRIENDLY_NAME,
2098 inst->service_p->attrs,
2099 &inst->friendly_name,
2100 friend_name_ind_len);
2101 } else {
2102 inst->friendly_name.call_index = BT_TBS_FREE_CALL_INDEX;
2103 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_FRIENDLY_NAME,
2104 inst->service_p->attrs, NULL, 0);
2105 }
2106
2107 if (IS_ENABLED(CONFIG_BT_GTBS)) {
2108 gtbs_inst.in_call.call_index = call->index;
2109 (void)strcpy(gtbs_inst.in_call.uri, from);
2110
2111 gtbs_inst.incoming_uri.call_index = call->index;
2112 (void)strcpy(gtbs_inst.incoming_uri.uri, to);
2113
2114 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_INCOMING_URI,
2115 gtbs_inst.service_p->attrs,
2116 >bs_inst.incoming_uri, local_uri_ind_len);
2117
2118 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_INCOMING_CALL,
2119 gtbs_inst.service_p->attrs,
2120 >bs_inst.in_call, remote_uri_ind_len);
2121
2122 if (friendly_name) {
2123 gtbs_inst.friendly_name.call_index = call->index;
2124 utf8_lcpy(inst->friendly_name.uri, friendly_name,
2125 sizeof(inst->friendly_name.uri));
2126 friend_name_ind_len = strlen(from) + 1;
2127
2128 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_FRIENDLY_NAME,
2129 gtbs_inst.service_p->attrs,
2130 >bs_inst.friendly_name,
2131 friend_name_ind_len);
2132 } else {
2133 gtbs_inst.friendly_name.call_index = 0;
2134 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_FRIENDLY_NAME,
2135 gtbs_inst.service_p->attrs,
2136 NULL, 0);
2137 }
2138 }
2139
2140 notify_calls(inst);
2141
2142 LOG_DBG("New call with call index %u", call->index);
2143
2144 return call->index;
2145 }
2146
bt_tbs_set_bearer_provider_name(uint8_t bearer_index,const char * name)2147 int bt_tbs_set_bearer_provider_name(uint8_t bearer_index, const char *name)
2148 {
2149 const size_t len = strlen(name);
2150 const struct bt_gatt_attr *attr;
2151
2152 if (len >= CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH || len == 0) {
2153 return -EINVAL;
2154 } else if (bearer_index >= CONFIG_BT_TBS_BEARER_COUNT) {
2155 if (!(IS_ENABLED(CONFIG_BT_GTBS) &&
2156 bearer_index == BT_TBS_GTBS_INDEX)) {
2157 return -EINVAL;
2158 }
2159 }
2160
2161 if (bearer_index == BT_TBS_GTBS_INDEX) {
2162 if (strcmp(gtbs_inst.provider_name, name) == 0) {
2163 return 0;
2164 }
2165
2166 (void)strcpy(gtbs_inst.provider_name, name);
2167 attr = gtbs_inst.service_p->attrs;
2168 } else {
2169 if (strcmp(svc_insts[bearer_index].provider_name, name) == 0) {
2170 return 0;
2171 }
2172
2173 (void)strcpy(svc_insts[bearer_index].provider_name, name);
2174 attr = svc_insts[bearer_index].service_p->attrs;
2175 }
2176
2177 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_PROVIDER_NAME,
2178 attr, name, strlen(name));
2179 return 0;
2180 }
2181
bt_tbs_set_bearer_technology(uint8_t bearer_index,uint8_t new_technology)2182 int bt_tbs_set_bearer_technology(uint8_t bearer_index, uint8_t new_technology)
2183 {
2184 const struct bt_gatt_attr *attr;
2185
2186 if (new_technology < BT_TBS_TECHNOLOGY_3G ||
2187 new_technology > BT_TBS_TECHNOLOGY_IP) {
2188 return -EINVAL;
2189 } else if (bearer_index >= CONFIG_BT_TBS_BEARER_COUNT) {
2190 if (!(IS_ENABLED(CONFIG_BT_GTBS) &&
2191 bearer_index == BT_TBS_GTBS_INDEX)) {
2192 return -EINVAL;
2193 }
2194 }
2195
2196 if (bearer_index == BT_TBS_GTBS_INDEX) {
2197 if (gtbs_inst.technology == new_technology) {
2198 return 0;
2199 }
2200
2201 gtbs_inst.technology = new_technology;
2202 attr = gtbs_inst.service_p->attrs;
2203 } else {
2204 if (svc_insts[bearer_index].technology == new_technology) {
2205 return 0;
2206 }
2207
2208 svc_insts[bearer_index].technology = new_technology;
2209 attr = svc_insts[bearer_index].service_p->attrs;
2210 }
2211
2212 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_TECHNOLOGY,
2213 attr, &new_technology, sizeof(new_technology));
2214
2215 return 0;
2216 }
2217
bt_tbs_set_signal_strength(uint8_t bearer_index,uint8_t new_signal_strength)2218 int bt_tbs_set_signal_strength(uint8_t bearer_index,
2219 uint8_t new_signal_strength)
2220 {
2221 const struct bt_gatt_attr *attr;
2222 uint32_t timer_status;
2223 uint8_t interval;
2224 struct k_work_delayable *reporting_interval_work;
2225 struct tbs_service_inst *inst;
2226
2227 if (new_signal_strength > BT_TBS_SIGNAL_STRENGTH_MAX &&
2228 new_signal_strength != BT_TBS_SIGNAL_STRENGTH_UNKNOWN) {
2229 return -EINVAL;
2230 } else if (bearer_index >= CONFIG_BT_TBS_BEARER_COUNT) {
2231 if (!(IS_ENABLED(CONFIG_BT_GTBS) &&
2232 bearer_index == BT_TBS_GTBS_INDEX)) {
2233 return -EINVAL;
2234 }
2235 }
2236
2237 if (bearer_index == BT_TBS_GTBS_INDEX) {
2238 if (gtbs_inst.signal_strength == new_signal_strength) {
2239 return 0;
2240 }
2241
2242 gtbs_inst.signal_strength = new_signal_strength;
2243 attr = gtbs_inst.service_p->attrs;
2244 timer_status = k_work_delayable_remaining_get(
2245 >bs_inst.reporting_interval_work);
2246 interval = gtbs_inst.signal_strength_interval;
2247 reporting_interval_work = >bs_inst.reporting_interval_work;
2248 } else {
2249 inst = &svc_insts[bearer_index];
2250 if (inst->signal_strength == new_signal_strength) {
2251 return 0;
2252 }
2253
2254 inst->signal_strength = new_signal_strength;
2255 attr = inst->service_p->attrs;
2256 timer_status = k_work_delayable_remaining_get(
2257 &inst->reporting_interval_work);
2258 interval = inst->signal_strength_interval;
2259 reporting_interval_work = &inst->reporting_interval_work;
2260 }
2261
2262 if (timer_status == 0) {
2263 const k_timeout_t delay = K_SECONDS(interval);
2264
2265 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_SIGNAL_STRENGTH,
2266 attr, &new_signal_strength,
2267 sizeof(new_signal_strength));
2268 if (interval) {
2269 k_work_reschedule(reporting_interval_work, delay);
2270 }
2271 } else {
2272 if (bearer_index == BT_TBS_GTBS_INDEX) {
2273 LOG_DBG("GTBS: Reporting signal strength in %d ms", timer_status);
2274 gtbs_inst.pending_signal_strength_notification = true;
2275
2276 } else {
2277 LOG_DBG("Index %u: Reporting signal strength in %d ms", bearer_index,
2278 timer_status);
2279 inst->pending_signal_strength_notification = true;
2280 }
2281 }
2282
2283 return 0;
2284 }
2285
bt_tbs_set_status_flags(uint8_t bearer_index,uint16_t status_flags)2286 int bt_tbs_set_status_flags(uint8_t bearer_index, uint16_t status_flags)
2287 {
2288 const struct bt_gatt_attr *attr;
2289
2290 if (!BT_TBS_VALID_STATUS_FLAGS(status_flags)) {
2291 return -EINVAL;
2292 } else if (bearer_index >= CONFIG_BT_TBS_BEARER_COUNT) {
2293 if (!(IS_ENABLED(CONFIG_BT_GTBS) &&
2294 bearer_index == BT_TBS_GTBS_INDEX)) {
2295 return -EINVAL;
2296 }
2297 }
2298
2299 if (bearer_index == BT_TBS_GTBS_INDEX) {
2300 if (gtbs_inst.status_flags == status_flags) {
2301 return 0;
2302 }
2303
2304 gtbs_inst.status_flags = status_flags;
2305 attr = gtbs_inst.service_p->attrs;
2306 } else {
2307 if (svc_insts[bearer_index].status_flags == status_flags) {
2308 return 0;
2309 }
2310
2311 svc_insts[bearer_index].status_flags = status_flags;
2312 attr = svc_insts[bearer_index].service_p->attrs;
2313 }
2314
2315 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_STATUS_FLAGS,
2316 attr, &status_flags, sizeof(status_flags));
2317 return 0;
2318 }
2319
bt_tbs_set_uri_scheme_list(uint8_t bearer_index,const char ** uri_list,uint8_t uri_count)2320 int bt_tbs_set_uri_scheme_list(uint8_t bearer_index, const char **uri_list,
2321 uint8_t uri_count)
2322 {
2323 char uri_scheme_list[CONFIG_BT_TBS_MAX_SCHEME_LIST_LENGTH];
2324 size_t len = 0;
2325 struct tbs_service_inst *inst;
2326
2327 if (bearer_index >= CONFIG_BT_TBS_BEARER_COUNT) {
2328 return -EINVAL;
2329 }
2330
2331 inst = &svc_insts[bearer_index];
2332 (void)memset(uri_scheme_list, 0, sizeof(uri_scheme_list));
2333
2334 for (int i = 0; i < uri_count; i++) {
2335 if (len) {
2336 len++;
2337 if (len > sizeof(uri_scheme_list) - 1) {
2338 return -ENOMEM;
2339 }
2340
2341 strcat(uri_scheme_list, ",");
2342 }
2343
2344 len += strlen(uri_list[i]);
2345 if (len > sizeof(uri_scheme_list) - 1) {
2346 return -ENOMEM;
2347 }
2348
2349 /* Store list in temp list in case something goes wrong */
2350 strcat(uri_scheme_list, uri_list[i]);
2351 }
2352
2353 if (strcmp(inst->uri_scheme_list, uri_scheme_list) == 0) {
2354 /* identical; don't update or notify */
2355 return 0;
2356 }
2357
2358 /* Store final result */
2359 (void)strcpy(inst->uri_scheme_list, uri_scheme_list);
2360
2361 LOG_DBG("TBS instance %u uri prefix list is now %s", bearer_index, inst->uri_scheme_list);
2362
2363 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_URI_LIST,
2364 inst->service_p->attrs, &inst->uri_scheme_list,
2365 strlen(inst->uri_scheme_list));
2366
2367 if (IS_ENABLED(CONFIG_BT_GTBS)) {
2368 NET_BUF_SIMPLE_DEFINE(uri_scheme_buf, READ_BUF_SIZE);
2369
2370 /* TODO: Make uri schemes unique */
2371 for (int i = 0; i < ARRAY_SIZE(svc_insts); i++) {
2372 const size_t uri_len = strlen(svc_insts[i].uri_scheme_list);
2373
2374 if (uri_scheme_buf.len + uri_len >= uri_scheme_buf.size) {
2375 LOG_WRN("Cannot fit all TBS instances in GTBS "
2376 "URI scheme list");
2377 break;
2378 }
2379
2380 net_buf_simple_add_mem(&uri_scheme_buf,
2381 svc_insts[i].uri_scheme_list,
2382 uri_len);
2383 }
2384
2385 LOG_DBG("GTBS: URI scheme %.*s", uri_scheme_buf.len, uri_scheme_buf.data);
2386
2387 bt_gatt_notify_uuid(NULL, BT_UUID_TBS_URI_LIST,
2388 gtbs_inst.service_p->attrs,
2389 uri_scheme_buf.data, uri_scheme_buf.len);
2390 }
2391
2392 return 0;
2393 }
2394
bt_tbs_register_cb(struct bt_tbs_cb * cbs)2395 void bt_tbs_register_cb(struct bt_tbs_cb *cbs)
2396 {
2397 tbs_cbs = cbs;
2398 }
2399
2400 #if defined(CONFIG_BT_TBS_LOG_LEVEL_DBG)
bt_tbs_dbg_print_calls(void)2401 void bt_tbs_dbg_print_calls(void)
2402 {
2403 for (int i = 0; i < CONFIG_BT_TBS_BEARER_COUNT; i++) {
2404 LOG_DBG("Bearer #%u", i);
2405 for (int j = 0; j < ARRAY_SIZE(svc_insts[i].calls); j++) {
2406 struct bt_tbs_call *call = &svc_insts[i].calls[j];
2407
2408 if (call->index == BT_TBS_FREE_CALL_INDEX) {
2409 continue;
2410 }
2411
2412 LOG_DBG(" Call #%u", call->index);
2413 LOG_DBG(" State: %s", bt_tbs_state_str(call->state));
2414 LOG_DBG(" Flags: 0x%02X", call->flags);
2415 LOG_DBG(" URI : %s", call->remote_uri);
2416 }
2417 }
2418 }
2419 #endif /* defined(CONFIG_BT_TBS_LOG_LEVEL_DBG) */
2420