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