1 /* Bluetooth TBS - Telephone Bearer Service - Client
2 *
3 * Copyright (c) 2020 Bose Corporation
4 * Copyright (c) 2021-2024 Nordic Semiconductor ASA
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8 #include <errno.h>
9 #include <stdbool.h>
10 #include <stddef.h>
11 #include <stdint.h>
12 #include <string.h>
13
14 #include <zephyr/autoconf.h>
15 #include <zephyr/bluetooth/att.h>
16 #include <zephyr/bluetooth/audio/tbs.h>
17 #include <zephyr/bluetooth/bluetooth.h>
18 #include <zephyr/bluetooth/buf.h>
19 #include <zephyr/bluetooth/conn.h>
20 #include <zephyr/bluetooth/gatt.h>
21 #include <zephyr/bluetooth/uuid.h>
22 #include <zephyr/device.h>
23 #include <zephyr/init.h>
24 #include <zephyr/kernel.h>
25 #include <zephyr/logging/log.h>
26 #include <zephyr/net_buf.h>
27 #include <zephyr/sys/__assert.h>
28 #include <zephyr/sys/atomic.h>
29 #include <zephyr/sys/slist.h>
30 #include <zephyr/sys/util.h>
31 #include <zephyr/sys/util_macro.h>
32 #include <zephyr/toolchain.h>
33 #include <zephyr/types.h>
34 #include <zephyr/sys/check.h>
35
36 #include "tbs_internal.h"
37
38 LOG_MODULE_REGISTER(bt_tbs_client, CONFIG_BT_TBS_CLIENT_LOG_LEVEL);
39 /* TODO TBS client attempts to subscribe to all characteristics at once if the MTU is large enough.
40 * This requires a significant amount of buffers, and should be optimized.
41 */
42
43 /* Calculate the required buffers for TBS Client discovery */
44 #define TBS_CLIENT_BUF_COUNT \
45 (1 /* Discover buffer */ + 1 /* terminate reason */ + \
46 IS_ENABLED(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME) + \
47 IS_ENABLED(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY) + \
48 IS_ENABLED(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH) + \
49 IS_ENABLED(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) + \
50 IS_ENABLED(CONFIG_BT_TBS_CLIENT_INCOMING_URI) + \
51 IS_ENABLED(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS) + \
52 IS_ENABLED(CONFIG_BT_TBS_CLIENT_CP_PROCEDURES) + \
53 IS_ENABLED(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME) + \
54 IS_ENABLED(CONFIG_BT_TBS_CLIENT_INCOMING_CALL))
55
56 BUILD_ASSERT(CONFIG_BT_ATT_TX_COUNT >= TBS_CLIENT_BUF_COUNT, "Too few ATT buffers");
57
58 #include "common/bt_str.h"
59
60 struct bt_tbs_server_inst {
61 #if defined(CONFIG_BT_TBS_CLIENT_TBS)
62 struct bt_tbs_instance tbs_insts[CONFIG_BT_TBS_CLIENT_MAX_TBS_INSTANCES];
63 uint8_t inst_cnt;
64 #endif /* CONFIG_BT_TBS_CLIENT_TBS */
65 #if defined(CONFIG_BT_TBS_CLIENT_GTBS)
66 struct bt_tbs_instance gtbs_inst;
67 #endif /* defined(CONFIG_BT_TBS_CLIENT_GTBS) */
68 struct bt_gatt_discover_params discover_params;
69 struct bt_tbs_instance *current_inst;
70 };
71
72 static sys_slist_t tbs_client_cbs = SYS_SLIST_STATIC_INIT(&tbs_client_cbs);
73
74 static struct bt_tbs_server_inst srv_insts[CONFIG_BT_MAX_CONN];
75
76 static void discover_next_instance(struct bt_conn *conn);
77
78 typedef bool (*tbs_instance_find_func_t)(struct bt_tbs_instance *inst, void *user_data);
79
tbs_instance_find(struct bt_tbs_server_inst * server,tbs_instance_find_func_t func,void * user_data)80 static struct bt_tbs_instance *tbs_instance_find(struct bt_tbs_server_inst *server,
81 tbs_instance_find_func_t func, void *user_data)
82 {
83 #if defined(CONFIG_BT_TBS_CLIENT_GTBS)
84 if (func(&server->gtbs_inst, user_data)) {
85 return &server->gtbs_inst;
86 }
87 #endif /* CONFIG_BT_TBS_CLIENT_GTBS */
88 #if defined(CONFIG_BT_TBS_CLIENT_TBS)
89 for (size_t i = 0; i < server->inst_cnt; i++) {
90 if (func(&server->tbs_insts[i], user_data)) {
91 return &server->tbs_insts[i];
92 }
93 }
94 #endif /* CONFIG_BT_TBS_CLIENT_TBS */
95
96 return NULL;
97 }
98
tbs_inst_by_index(struct bt_conn * conn,uint8_t index)99 static struct bt_tbs_instance *tbs_inst_by_index(struct bt_conn *conn, uint8_t index)
100 {
101 struct bt_tbs_server_inst *server;
102
103 __ASSERT(conn, "NULL conn");
104
105 server = &srv_insts[bt_conn_index(conn)];
106
107 #if defined(CONFIG_BT_TBS_CLIENT_GTBS)
108 if (index == BT_TBS_GTBS_INDEX) {
109 return &server->gtbs_inst;
110 }
111 #endif /* CONFIG_BT_TBS_CLIENT_GTBS */
112 #if defined(CONFIG_BT_TBS_CLIENT_TBS)
113 if (index < server->inst_cnt) {
114 return &server->tbs_insts[index];
115 }
116 #endif /* CONFIG_BT_TBS_CLIENT_TBS */
117
118 return NULL;
119 }
120
tbs_index(struct bt_conn * conn,const struct bt_tbs_instance * inst)121 static uint8_t tbs_index(struct bt_conn *conn, const struct bt_tbs_instance *inst)
122 {
123 struct bt_tbs_server_inst *server;
124 ptrdiff_t index = 0;
125
126 __ASSERT_NO_MSG(conn);
127 __ASSERT_NO_MSG(inst);
128
129 server = &srv_insts[bt_conn_index(conn)];
130
131 #if defined(CONFIG_BT_TBS_CLIENT_GTBS)
132 if (inst == &server->gtbs_inst) {
133 return BT_TBS_GTBS_INDEX;
134 }
135 #endif /* CONFIG_BT_TBS_CLIENT_GTBS */
136 #if defined(CONFIG_BT_TBS_CLIENT_TBS)
137 index = inst - server->tbs_insts;
138 __ASSERT(index >= 0 && index < ARRAY_SIZE(server->tbs_insts),
139 "Invalid bt_tbs_instance pointer");
140
141 #else
142 __ASSERT_PRINT("Invalid bt_tbs_instance pointer");
143 #endif /* CONFIG_BT_TBS_CLIENT_TBS */
144
145 return (uint8_t)index;
146 }
147
148 #if defined(CONFIG_BT_TBS_CLIENT_ORIGINATE_CALL)
free_call_spot(struct bt_tbs_instance * inst)149 static bool free_call_spot(struct bt_tbs_instance *inst)
150 {
151 for (int i = 0; i < CONFIG_BT_TBS_CLIENT_MAX_CALLS; i++) {
152 if (inst->calls[i].index == BT_TBS_FREE_CALL_INDEX) {
153 return true;
154 }
155 }
156
157 return false;
158 }
159 #endif /* defined(CONFIG_BT_TBS_CLIENT_ORIGINATE_CALL) */
160
is_instance_handle(struct bt_tbs_instance * inst,void * user_data)161 static bool is_instance_handle(struct bt_tbs_instance *inst, void *user_data)
162 {
163 uint16_t handle = POINTER_TO_UINT(user_data);
164
165 return inst->start_handle <= handle && inst->end_handle >= handle;
166 }
167
lookup_inst_by_handle(struct bt_conn * conn,uint16_t handle)168 static struct bt_tbs_instance *lookup_inst_by_handle(struct bt_conn *conn,
169 uint16_t handle)
170 {
171 uint8_t conn_index;
172 struct bt_tbs_server_inst *srv_inst;
173 struct bt_tbs_instance *inst;
174
175 __ASSERT(conn, "NULL conn");
176
177 conn_index = bt_conn_index(conn);
178 srv_inst = &srv_insts[conn_index];
179
180 inst = tbs_instance_find(srv_inst, is_instance_handle, UINT_TO_POINTER(handle));
181 if (inst != NULL) {
182 return inst;
183 }
184
185 LOG_DBG("Could not find instance with handle 0x%04x", handle);
186
187 return NULL;
188 }
189
net_buf_pull_call_state(struct net_buf_simple * buf,struct bt_tbs_client_call_state * call_state)190 static uint8_t net_buf_pull_call_state(struct net_buf_simple *buf,
191 struct bt_tbs_client_call_state *call_state)
192 {
193 if (buf->len < sizeof(*call_state)) {
194 LOG_DBG("Invalid buffer length %u", buf->len);
195 return BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
196 }
197
198 call_state->index = net_buf_simple_pull_u8(buf);
199 call_state->state = net_buf_simple_pull_u8(buf);
200 call_state->flags = net_buf_simple_pull_u8(buf);
201
202 return 0;
203 }
204
205 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS)
net_buf_pull_call(struct net_buf_simple * buf,struct bt_tbs_client_call * call)206 static uint8_t net_buf_pull_call(struct net_buf_simple *buf,
207 struct bt_tbs_client_call *call)
208 {
209 const size_t min_item_len = sizeof(call->call_info) + BT_TBS_MIN_URI_LEN;
210 uint8_t item_len;
211 uint8_t uri_len;
212 uint8_t err;
213 uint8_t *uri;
214
215 __ASSERT(buf, "NULL buf");
216 __ASSERT(call, "NULL call");
217
218 if (buf->len < sizeof(item_len) + min_item_len) {
219 LOG_DBG("Invalid buffer length %u", buf->len);
220 return BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
221 }
222
223 item_len = net_buf_simple_pull_u8(buf);
224 uri_len = item_len - sizeof(call->call_info);
225
226 if (item_len > buf->len || item_len < min_item_len) {
227 LOG_DBG("Invalid current call item length %u", item_len);
228 return BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
229 }
230
231 err = net_buf_pull_call_state(buf, &call->call_info);
232 if (err != 0) {
233 return err;
234 }
235
236 uri = net_buf_simple_pull_mem(buf, uri_len);
237 if (uri_len > CONFIG_BT_TBS_MAX_URI_LENGTH) {
238 LOG_WRN("Current call (index %u) uri length larger than supported %u/%zu",
239 call->call_info.index, uri_len, CONFIG_BT_TBS_MAX_URI_LENGTH);
240 return BT_ATT_ERR_INSUFFICIENT_RESOURCES;
241 }
242
243 (void)memcpy(call->remote_uri, uri, uri_len);
244 call->remote_uri[uri_len] = '\0';
245
246 return 0;
247 }
248
current_calls_changed(struct bt_conn * conn,int err,uint8_t inst_index,uint8_t call_count,const struct bt_tbs_client_call * calls)249 static void current_calls_changed(struct bt_conn *conn, int err, uint8_t inst_index,
250 uint8_t call_count, const struct bt_tbs_client_call *calls)
251 {
252 struct bt_tbs_client_cb *listener, *next;
253
254 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
255 if (listener->current_calls != NULL) {
256 listener->current_calls(conn, err, inst_index, call_count, calls);
257 }
258 }
259 }
260
bearer_list_current_calls(struct bt_conn * conn,const struct bt_tbs_instance * inst,struct net_buf_simple * buf)261 static void bearer_list_current_calls(struct bt_conn *conn, const struct bt_tbs_instance *inst,
262 struct net_buf_simple *buf)
263 {
264 struct bt_tbs_client_call calls[CONFIG_BT_TBS_CLIENT_MAX_CALLS];
265 char remote_uris[CONFIG_BT_TBS_CLIENT_MAX_CALLS][CONFIG_BT_TBS_MAX_URI_LENGTH + 1];
266 uint8_t cnt = 0;
267 int err;
268
269 while (buf->len) {
270 struct bt_tbs_client_call *call;
271
272 if (cnt == CONFIG_BT_TBS_CLIENT_MAX_CALLS) {
273 LOG_WRN("Could not parse all calls due to memory restrictions");
274 break;
275 }
276
277 call = &calls[cnt];
278 call->remote_uri = remote_uris[cnt];
279
280 err = net_buf_pull_call(buf, call);
281 if (err == BT_ATT_ERR_INSUFFICIENT_RESOURCES) {
282 LOG_WRN("Call with skipped due to too long URI");
283 continue;
284 } else if (err != 0) {
285 LOG_DBG("Invalid current call notification: %d", err);
286 return;
287 }
288
289 cnt++;
290 }
291
292 current_calls_changed(conn, 0, tbs_index(conn, inst), cnt, calls);
293 }
294 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) */
295
296 #if defined(CONFIG_BT_TBS_CLIENT_CP_PROCEDURES)
call_cp_callback_handler(struct bt_conn * conn,int err,uint8_t index,uint8_t opcode,uint8_t call_index)297 static void call_cp_callback_handler(struct bt_conn *conn, int err,
298 uint8_t index, uint8_t opcode,
299 uint8_t call_index)
300 {
301 struct bt_tbs_client_cb *listener, *next;
302
303 LOG_DBG("Status: %s for the %s opcode for call 0x%02x", bt_tbs_status_str(err),
304 bt_tbs_opcode_str(opcode), call_index);
305
306 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
307 switch (opcode) {
308 #if defined(CONFIG_BT_TBS_CLIENT_ACCEPT_CALL)
309 case BT_TBS_CALL_OPCODE_ACCEPT:
310 if (listener->accept_call != NULL) {
311 listener->accept_call(conn, err, index, call_index);
312 }
313 break;
314 #endif /* defined(CONFIG_BT_TBS_CLIENT_ACCEPT_CALL) */
315 #if defined(CONFIG_BT_TBS_CLIENT_TERMINATE_CALL)
316 case BT_TBS_CALL_OPCODE_TERMINATE:
317 if (listener->terminate_call != NULL) {
318 listener->terminate_call(conn, err, index, call_index);
319 }
320 break;
321 #endif /* defined(CONFIG_BT_TBS_CLIENT_TERMINATE_CALL) */
322 #if defined(CONFIG_BT_TBS_CLIENT_HOLD_CALL)
323 case BT_TBS_CALL_OPCODE_HOLD:
324 if (listener->hold_call != NULL) {
325 listener->hold_call(conn, err, index, call_index);
326 }
327 break;
328 #endif /* defined(CONFIG_BT_TBS_CLIENT_HOLD_CALL) */
329 #if defined(CONFIG_BT_TBS_CLIENT_RETRIEVE_CALL)
330 case BT_TBS_CALL_OPCODE_RETRIEVE:
331 if (listener->retrieve_call != NULL) {
332 listener->retrieve_call(conn, err, index, call_index);
333 }
334 break;
335 #endif /* defined(CONFIG_BT_TBS_CLIENT_RETRIEVE_CALL) */
336 #if defined(CONFIG_BT_TBS_CLIENT_ORIGINATE_CALL)
337 case BT_TBS_CALL_OPCODE_ORIGINATE:
338 if (listener->originate_call != NULL) {
339 listener->originate_call(conn, err, index, call_index);
340 }
341 break;
342 #endif /* defined(CONFIG_BT_TBS_CLIENT_ORIGINATE_CALL) */
343 #if defined(CONFIG_BT_TBS_CLIENT_JOIN_CALLS)
344 case BT_TBS_CALL_OPCODE_JOIN:
345 if (listener->join_calls != NULL) {
346 listener->join_calls(conn, err, index, call_index);
347 }
348 break;
349 #endif /* defined(CONFIG_BT_TBS_CLIENT_JOIN_CALLS) */
350 default:
351 break;
352 }
353 }
354 }
355 #endif /* defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES) */
356
parse_string_value(const void * data,uint16_t length,uint16_t max_len)357 const char *parse_string_value(const void *data, uint16_t length,
358 uint16_t max_len)
359 {
360 static char string_val[CONFIG_BT_TBS_MAX_URI_LENGTH + 1];
361 const size_t len = MIN(length, max_len);
362
363 if (len != 0) {
364 (void)memcpy(string_val, data, len);
365 }
366
367 string_val[len] = '\0';
368
369 return string_val;
370 }
371
372 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)
provider_name_changed(struct bt_conn * conn,int err,uint8_t inst_index,const char * name)373 static void provider_name_changed(struct bt_conn *conn, int err, uint8_t inst_index,
374 const char *name)
375 {
376 struct bt_tbs_client_cb *listener, *next;
377
378 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
379 if (listener->bearer_provider_name != NULL) {
380 listener->bearer_provider_name(conn, err, inst_index, name);
381 }
382 }
383 }
384
provider_name_notify_handler(struct bt_conn * conn,const struct bt_tbs_instance * tbs_inst,const void * data,uint16_t length)385 static void provider_name_notify_handler(struct bt_conn *conn,
386 const struct bt_tbs_instance *tbs_inst,
387 const void *data, uint16_t length)
388 {
389 const char *name = parse_string_value(data, length,
390 CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH);
391
392 LOG_DBG("%s", name);
393
394 provider_name_changed(conn, 0, tbs_index(conn, tbs_inst), name);
395 }
396 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME) */
397
398 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY)
technology_changed(struct bt_conn * conn,int err,uint8_t inst_index,uint8_t technology)399 static void technology_changed(struct bt_conn *conn, int err, uint8_t inst_index,
400 uint8_t technology)
401 {
402 struct bt_tbs_client_cb *listener, *next;
403
404 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
405 if (listener->technology != NULL) {
406 listener->technology(conn, err, inst_index, technology);
407 }
408 }
409 }
410
technology_notify_handler(struct bt_conn * conn,const struct bt_tbs_instance * tbs_inst,const void * data,uint16_t length)411 static void technology_notify_handler(struct bt_conn *conn,
412 const struct bt_tbs_instance *tbs_inst,
413 const void *data, uint16_t length)
414 {
415 uint8_t technology;
416
417 LOG_DBG("");
418
419 if (length == sizeof(technology)) {
420 (void)memcpy(&technology, data, length);
421 LOG_DBG("%s (0x%02x)", bt_tbs_technology_str(technology), technology);
422
423 technology_changed(conn, 0, tbs_index(conn, tbs_inst), technology);
424 }
425 }
426 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY) */
427
428 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH)
signal_strength_changed(struct bt_conn * conn,int err,uint8_t inst_index,uint8_t signal_strength)429 static void signal_strength_changed(struct bt_conn *conn, int err, uint8_t inst_index,
430 uint8_t signal_strength)
431 {
432 struct bt_tbs_client_cb *listener, *next;
433
434 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
435 if (listener->signal_strength != NULL) {
436 listener->signal_strength(conn, err, inst_index, signal_strength);
437 }
438 }
439 }
440
signal_strength_notify_handler(struct bt_conn * conn,const struct bt_tbs_instance * tbs_inst,const void * data,uint16_t length)441 static void signal_strength_notify_handler(struct bt_conn *conn,
442 const struct bt_tbs_instance *tbs_inst,
443 const void *data, uint16_t length)
444 {
445 uint8_t signal_strength;
446
447 LOG_DBG("");
448
449 if (length == sizeof(signal_strength)) {
450 (void)memcpy(&signal_strength, data, length);
451 LOG_DBG("0x%02x", signal_strength);
452
453 signal_strength_changed(conn, 0, tbs_index(conn, tbs_inst), signal_strength);
454 }
455 }
456 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH) */
457
458 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS)
current_calls_notify_handler(struct bt_conn * conn,const struct bt_tbs_instance * tbs_inst,const void * data,uint16_t length)459 static void current_calls_notify_handler(struct bt_conn *conn,
460 const struct bt_tbs_instance *tbs_inst,
461 const void *data, uint16_t length)
462 {
463 struct net_buf_simple buf;
464
465 LOG_DBG("");
466
467 net_buf_simple_init_with_data(&buf, (void *)data, length);
468
469 /* TODO: If length == MTU, do long read for all calls */
470
471 bearer_list_current_calls(conn, tbs_inst, &buf);
472 }
473 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) */
474
475 #if defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS)
status_flags_changed(struct bt_conn * conn,int err,uint8_t inst_index,uint16_t status_flags)476 static void status_flags_changed(struct bt_conn *conn, int err, uint8_t inst_index,
477 uint16_t status_flags)
478 {
479 struct bt_tbs_client_cb *listener, *next;
480
481 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
482 if (listener->status_flags != NULL) {
483 listener->status_flags(conn, err, inst_index, status_flags);
484 }
485 }
486 }
487
status_flags_notify_handler(struct bt_conn * conn,const struct bt_tbs_instance * tbs_inst,const void * data,uint16_t length)488 static void status_flags_notify_handler(struct bt_conn *conn,
489 const struct bt_tbs_instance *tbs_inst,
490 const void *data, uint16_t length)
491 {
492 uint16_t status_flags;
493
494 LOG_DBG("");
495
496 if (length == sizeof(status_flags)) {
497 (void)memcpy(&status_flags, data, length);
498 LOG_DBG("0x%04x", status_flags);
499
500 status_flags_changed(conn, 0, tbs_index(conn, tbs_inst), status_flags);
501 }
502 }
503 #endif /* defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS) */
504
505 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI)
call_uri_changed(struct bt_conn * conn,int err,uint8_t inst_index,const char * call_uri)506 static void call_uri_changed(struct bt_conn *conn, int err, uint8_t inst_index,
507 const char *call_uri)
508 {
509 struct bt_tbs_client_cb *listener, *next;
510
511 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
512 if (listener->call_uri != NULL) {
513 listener->call_uri(conn, err, inst_index, call_uri);
514 }
515 }
516 }
517
incoming_uri_notify_handler(struct bt_conn * conn,const struct bt_tbs_instance * tbs_inst,const void * data,uint16_t length)518 static void incoming_uri_notify_handler(struct bt_conn *conn,
519 const struct bt_tbs_instance *tbs_inst,
520 const void *data, uint16_t length)
521 {
522 const char *uri = parse_string_value(data, length,
523 CONFIG_BT_TBS_MAX_URI_LENGTH);
524
525 LOG_DBG("%s", uri);
526
527 call_uri_changed(conn, 0, tbs_index(conn, tbs_inst), uri);
528 }
529 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI) */
530
call_state_changed(struct bt_conn * conn,int err,uint8_t inst_index,uint8_t call_count,const struct bt_tbs_client_call_state * call_states)531 static void call_state_changed(struct bt_conn *conn, int err, uint8_t inst_index,
532 uint8_t call_count,
533 const struct bt_tbs_client_call_state *call_states)
534 {
535 struct bt_tbs_client_cb *listener, *next;
536
537 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
538 if (listener->call_state != NULL) {
539 listener->call_state(conn, err, inst_index, call_count, call_states);
540 }
541 }
542 }
543
call_state_notify_handler(struct bt_conn * conn,const struct bt_tbs_instance * tbs_inst,const void * data,uint16_t length)544 static void call_state_notify_handler(struct bt_conn *conn,
545 const struct bt_tbs_instance *tbs_inst,
546 const void *data, uint16_t length)
547 {
548 struct bt_tbs_client_call_state call_states[CONFIG_BT_TBS_CLIENT_MAX_CALLS];
549 uint8_t cnt = 0;
550 struct net_buf_simple buf;
551
552 LOG_DBG("");
553
554 net_buf_simple_init_with_data(&buf, (void *)data, length);
555
556 /* TODO: If length == MTU, do long read for all call states */
557
558 while (buf.len) {
559 struct bt_tbs_client_call_state *call_state;
560 int err;
561
562 if (cnt == CONFIG_BT_TBS_CLIENT_MAX_CALLS) {
563 LOG_WRN("Could not parse all calls due to memory restrictions");
564 break;
565 }
566
567 call_state = &call_states[cnt];
568
569 err = net_buf_pull_call_state(&buf, call_state);
570 if (err != 0) {
571 LOG_DBG("Invalid current call notification: %d", err);
572 return;
573 }
574
575 cnt++;
576 }
577
578 call_state_changed(conn, 0, tbs_index(conn, tbs_inst), cnt, call_states);
579 }
580
581 #if defined(CONFIG_BT_TBS_CLIENT_CP_PROCEDURES)
call_cp_notify_handler(struct bt_conn * conn,const struct bt_tbs_instance * tbs_inst,const void * data,uint16_t length)582 static void call_cp_notify_handler(struct bt_conn *conn,
583 const struct bt_tbs_instance *tbs_inst,
584 const void *data, uint16_t length)
585 {
586 struct bt_tbs_call_cp_notify *ind_val;
587
588 LOG_DBG("");
589
590 if (length == sizeof(*ind_val)) {
591 ind_val = (struct bt_tbs_call_cp_notify *)data;
592 LOG_DBG("Status: %s for the %s opcode for call 0x%02X",
593 bt_tbs_status_str(ind_val->status), bt_tbs_opcode_str(ind_val->opcode),
594 ind_val->call_index);
595
596 call_cp_callback_handler(conn, ind_val->status, tbs_index(conn, tbs_inst),
597 ind_val->opcode, ind_val->call_index);
598 }
599 }
600 #endif /* defined(CONFIG_BT_TBS_CLIENT_CP_PROCEDURES) */
601
terminate_reason_changed(struct bt_conn * conn,int err,uint8_t inst_index,struct bt_tbs_terminate_reason reason)602 static void terminate_reason_changed(struct bt_conn *conn, int err, uint8_t inst_index,
603 struct bt_tbs_terminate_reason reason)
604 {
605 struct bt_tbs_client_cb *listener, *next;
606
607 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
608 if (listener->termination_reason != NULL) {
609 listener->termination_reason(conn, err, inst_index, reason.call_index,
610 reason.reason);
611 }
612 }
613 }
614
termination_reason_notify_handler(struct bt_conn * conn,const struct bt_tbs_instance * tbs_inst,const void * data,uint16_t length)615 static void termination_reason_notify_handler(struct bt_conn *conn,
616 const struct bt_tbs_instance *tbs_inst,
617 const void *data, uint16_t length)
618 {
619 struct bt_tbs_terminate_reason reason;
620
621 LOG_DBG("");
622
623 if (length == sizeof(reason)) {
624 (void)memcpy(&reason, data, length);
625 LOG_DBG("ID 0x%02X, reason %s", reason.call_index,
626 bt_tbs_term_reason_str(reason.reason));
627
628 terminate_reason_changed(conn, 0, tbs_index(conn, tbs_inst), reason);
629 }
630 }
631
632 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL)
remote_uri_changed(struct bt_conn * conn,int err,uint8_t inst_index,const char * remote_uri)633 static void remote_uri_changed(struct bt_conn *conn, int err, uint8_t inst_index,
634 const char *remote_uri)
635 {
636 struct bt_tbs_client_cb *listener, *next;
637
638 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
639 if (listener->remote_uri != NULL) {
640 listener->remote_uri(conn, err, inst_index, remote_uri);
641 }
642 }
643 }
644
in_call_notify_handler(struct bt_conn * conn,const struct bt_tbs_instance * tbs_inst,const void * data,uint16_t length)645 static void in_call_notify_handler(struct bt_conn *conn,
646 const struct bt_tbs_instance *tbs_inst,
647 const void *data, uint16_t length)
648 {
649 const char *uri = parse_string_value(data, length,
650 CONFIG_BT_TBS_MAX_URI_LENGTH);
651
652 LOG_DBG("%s", uri);
653
654 remote_uri_changed(conn, 0, tbs_index(conn, tbs_inst), uri);
655 }
656 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL) */
657
658 #if defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME)
friendly_name_changed(struct bt_conn * conn,int err,uint8_t inst_index,const char * friendly_name)659 static void friendly_name_changed(struct bt_conn *conn, int err, uint8_t inst_index,
660 const char *friendly_name)
661 {
662 struct bt_tbs_client_cb *listener, *next;
663
664 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
665 if (listener->friendly_name != NULL) {
666 listener->friendly_name(conn, err, inst_index, friendly_name);
667 }
668 }
669 }
670
friendly_name_notify_handler(struct bt_conn * conn,const struct bt_tbs_instance * tbs_inst,const void * data,uint16_t length)671 static void friendly_name_notify_handler(struct bt_conn *conn,
672 const struct bt_tbs_instance *tbs_inst,
673 const void *data, uint16_t length)
674 {
675 const char *name = parse_string_value(data, length,
676 CONFIG_BT_TBS_MAX_URI_LENGTH);
677
678 LOG_DBG("%s", name);
679
680 friendly_name_changed(conn, 0, tbs_index(conn, tbs_inst), name);
681 }
682 #endif /* defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME) */
683
684 /** @brief Handles notifications and indications from the server */
notify_handler(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)685 static uint8_t notify_handler(struct bt_conn *conn,
686 struct bt_gatt_subscribe_params *params,
687 const void *data, uint16_t length)
688 {
689 uint16_t handle = params->value_handle;
690 struct bt_tbs_instance *tbs_inst;
691
692 if (data == NULL || conn == NULL) {
693 LOG_DBG("[UNSUBSCRIBED] 0x%04X", params->value_handle);
694 params->value_handle = 0U;
695
696 return BT_GATT_ITER_STOP;
697 }
698
699 tbs_inst = lookup_inst_by_handle(conn, handle);
700 if (tbs_inst != NULL) {
701 uint8_t inst_index = tbs_index(conn, tbs_inst);
702
703 LOG_DBG("Index %u", inst_index);
704
705 LOG_HEXDUMP_DBG(data, length, "notify handler value");
706
707 if (handle == tbs_inst->call_state_sub_params.value_handle) {
708 call_state_notify_handler(conn, tbs_inst, data, length);
709 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)
710 } else if (handle == tbs_inst->name_sub_params.value_handle) {
711 provider_name_notify_handler(conn, tbs_inst, data,
712 length);
713 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME) */
714 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY)
715 } else if (handle == tbs_inst->technology_sub_params.value_handle) {
716 technology_notify_handler(conn, tbs_inst, data, length);
717 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY) */
718 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH)
719 } else if (handle == tbs_inst->signal_strength_sub_params.value_handle) {
720 signal_strength_notify_handler(conn, tbs_inst, data,
721 length);
722 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH) */
723 #if defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS)
724 } else if (handle == tbs_inst->status_flags_sub_params.value_handle) {
725 status_flags_notify_handler(conn, tbs_inst, data,
726 length);
727 #endif /* defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS) */
728 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS)
729 } else if (handle == tbs_inst->current_calls_sub_params.value_handle) {
730 current_calls_notify_handler(conn, tbs_inst, data,
731 length);
732 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) */
733 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI)
734 } else if (handle == tbs_inst->in_target_uri_sub_params.value_handle) {
735 incoming_uri_notify_handler(conn, tbs_inst, data,
736 length);
737 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI) */
738 #if defined(CONFIG_BT_TBS_CLIENT_CP_PROCEDURES)
739 } else if (handle == tbs_inst->call_cp_sub_params.value_handle) {
740 call_cp_notify_handler(conn, tbs_inst, data, length);
741 #endif /* defined(CONFIG_BT_TBS_CLIENT_CP_PROCEDURES) */
742 } else if (handle == tbs_inst->termination_reason_handle) {
743 termination_reason_notify_handler(conn, tbs_inst, data,
744 length);
745 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL)
746 } else if (handle == tbs_inst->incoming_call_sub_params.value_handle) {
747 in_call_notify_handler(conn, tbs_inst, data, length);
748 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL) */
749 #if defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME)
750 } else if (handle == tbs_inst->friendly_name_sub_params.value_handle) {
751 friendly_name_notify_handler(conn, tbs_inst, data,
752 length);
753 #endif /* defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME) */
754 }
755 } else {
756 LOG_DBG("Notification/Indication on unknown TBS inst");
757 }
758
759 return BT_GATT_ITER_CONTINUE;
760 }
761
initialize_net_buf_read_buffer(struct bt_tbs_instance * inst)762 static void initialize_net_buf_read_buffer(struct bt_tbs_instance *inst)
763 {
764 net_buf_simple_init_with_data(&inst->net_buf, &inst->read_buf,
765 sizeof(inst->read_buf));
766 net_buf_simple_reset(&inst->net_buf);
767 }
768
tbs_client_gatt_read_complete(struct bt_tbs_instance * inst)769 static void tbs_client_gatt_read_complete(struct bt_tbs_instance *inst)
770 {
771 (void)memset(&inst->read_params, 0, sizeof(inst->read_params));
772 atomic_clear_bit(inst->flags, BT_TBS_CLIENT_FLAG_BUSY);
773 }
774
tbs_client_gatt_read(struct bt_conn * conn,struct bt_tbs_instance * inst,uint16_t handle,bt_gatt_read_func_t func)775 static int tbs_client_gatt_read(struct bt_conn *conn, struct bt_tbs_instance *inst, uint16_t handle,
776 bt_gatt_read_func_t func)
777 {
778 int err;
779
780 if (atomic_test_and_set_bit(inst->flags, BT_TBS_CLIENT_FLAG_BUSY)) {
781 LOG_DBG("Instance is busy");
782
783 return -EBUSY;
784 }
785
786 /* Use read_buf; length may be larger than minimum BT_ATT_MTU */
787 initialize_net_buf_read_buffer(inst);
788 inst->read_params.func = func;
789 inst->read_params.handle_count = 1U;
790 inst->read_params.single.handle = handle;
791 inst->read_params.single.offset = 0U;
792
793 err = bt_gatt_read(conn, &inst->read_params);
794 if (err != 0) {
795 tbs_client_gatt_read_complete(inst);
796
797 return err;
798 }
799
800 return 0;
801 }
802
gtbs_found(struct bt_tbs_server_inst * srv_inst)803 static bool gtbs_found(struct bt_tbs_server_inst *srv_inst)
804 {
805 #if defined(CONFIG_BT_TBS_CLIENT_GTBS)
806 return srv_inst->gtbs_inst.start_handle != 0;
807 #else
808 return false;
809 #endif /* CONFIG_BT_TBS_CLIENT_GTBS */
810 }
811
inst_cnt(struct bt_tbs_server_inst * srv_inst)812 static uint8_t inst_cnt(struct bt_tbs_server_inst *srv_inst)
813 {
814 #if defined(CONFIG_BT_TBS_CLIENT_TBS)
815 return srv_inst->inst_cnt;
816 #else
817 return 0;
818 #endif /* CONFIG_BT_TBS_CLIENT_TBS */
819 }
820
tbs_client_discover_complete(struct bt_conn * conn,int err)821 static void tbs_client_discover_complete(struct bt_conn *conn, int err)
822 {
823 struct bt_tbs_server_inst *srv_inst = &srv_insts[bt_conn_index(conn)];
824 struct bt_tbs_client_cb *listener, *next;
825
826 LOG_DBG("conn %p err %d", (void *)conn, err);
827
828 /* Clear the current instance in discovery */
829 srv_inst->current_inst = NULL;
830
831 #if defined(CONFIG_BT_TBS_CLIENT_GTBS)
832 atomic_clear_bit(srv_inst->gtbs_inst.flags, BT_TBS_CLIENT_FLAG_BUSY);
833 #endif /* CONFIG_BT_TBS_CLIENT_GTBS */
834 #if defined(CONFIG_BT_TBS_CLIENT_TBS)
835 for (size_t i = 0U; i < ARRAY_SIZE(srv_inst->tbs_insts); i++) {
836 atomic_clear_bit(srv_inst->tbs_insts[i].flags, BT_TBS_CLIENT_FLAG_BUSY);
837 }
838 #endif /* CONFIG_BT_TBS_CLIENT_TBS */
839
840 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
841 if (listener->discover != NULL) {
842 listener->discover(conn, err, inst_cnt(srv_inst), gtbs_found(srv_inst));
843 }
844 }
845 }
846
847 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME) || \
848 defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI) || \
849 defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST) || \
850 defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI) || \
851 defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL) || \
852 defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME)
853
can_add_string_to_net_buf(const struct net_buf_simple * buf,size_t len)854 static bool can_add_string_to_net_buf(const struct net_buf_simple *buf, size_t len)
855 {
856 return buf->len + len + sizeof('\0') <= buf->size;
857 }
858
859 /* Common function to read tbs_client strings which may require long reads */
handle_string_long_read(struct bt_tbs_instance * inst,uint8_t err,const void * data,uint16_t offset,uint16_t length,bool truncatable)860 static uint8_t handle_string_long_read(struct bt_tbs_instance *inst, uint8_t err, const void *data,
861 uint16_t offset, uint16_t length, bool truncatable)
862 {
863 if (err != 0) {
864 LOG_DBG("err: %u", err);
865
866 return BT_GATT_ERR(err);
867 }
868
869 if (data != NULL) {
870 /* Get data and try to read more using read long procedure */
871 LOG_DBG("Read (offset %u): %s", offset, bt_hex(data, length));
872
873 if (!can_add_string_to_net_buf(&inst->net_buf, length)) {
874 LOG_DBG("Read length %u: String buffer full", length);
875 if (truncatable) {
876 /* Use the remaining buffer and stop reading and leave room for NULL
877 * terminator
878 */
879 LOG_DBG("Truncating string");
880 length = net_buf_simple_tailroom(&inst->net_buf) - sizeof('\0');
881 net_buf_simple_add_mem(&inst->net_buf, data, length);
882
883 /* Ensure that the data is correctly truncated */
884 utf8_trunc(inst->net_buf.data);
885 } else {
886 return BT_GATT_ERR(BT_ATT_ERR_INSUFFICIENT_RESOURCES);
887 }
888 } else {
889 net_buf_simple_add_mem(&inst->net_buf, data, length);
890
891 return BT_GATT_ITER_CONTINUE;
892 }
893 }
894
895 return BT_GATT_ITER_STOP;
896 }
897 #endif /* CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME || \
898 * CONFIG_BT_TBS_CLIENT_BEARER_UCI || \
899 * CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST || \
900 * CONFIG_BT_TBS_CLIENT_INCOMING_URI || \
901 * CONFIG_BT_TBS_CLIENT_INCOMING_CALL || \
902 * CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME \
903 */
904
905 #if defined(CONFIG_BT_TBS_CLIENT_CP_PROCEDURES)
tbs_client_common_call_control(struct bt_conn * conn,uint8_t inst_index,uint8_t call_index,uint8_t opcode)906 static int tbs_client_common_call_control(struct bt_conn *conn,
907 uint8_t inst_index,
908 uint8_t call_index,
909 uint8_t opcode)
910 {
911 struct bt_tbs_instance *inst;
912 struct bt_tbs_call_cp_acc common;
913
914 inst = tbs_inst_by_index(conn, inst_index);
915 if (inst == NULL) {
916 return -EINVAL;
917 }
918
919 if (inst->call_cp_sub_params.value_handle == 0) {
920 LOG_DBG("Handle not set");
921 return -EINVAL;
922 }
923
924 common.opcode = opcode;
925 common.call_index = call_index;
926
927 return bt_gatt_write_without_response(conn, inst->call_cp_sub_params.value_handle,
928 &common, sizeof(common), false);
929 }
930 #endif /* CONFIG_BT_TBS_CLIENT_CP_PROCEDURES */
931
932 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)
read_bearer_provider_name_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)933 static uint8_t read_bearer_provider_name_cb(struct bt_conn *conn, uint8_t err,
934 struct bt_gatt_read_params *params,
935 const void *data, uint16_t length)
936 {
937 struct bt_tbs_instance *inst = CONTAINER_OF(params, struct bt_tbs_instance, read_params);
938 const uint8_t inst_index = tbs_index(conn, inst);
939 int ret;
940
941 LOG_DBG("");
942
943 ret = handle_string_long_read(inst, err, data, params->single.offset, length, true);
944 if (ret != BT_GATT_ITER_CONTINUE) {
945 if (ret == BT_GATT_ITER_STOP) {
946 /* At this point the inst->net_buf.data contains a NULL terminator string */
947 provider_name_changed(conn, 0, inst_index, (char *)inst->net_buf.data);
948 } else {
949 provider_name_changed(conn, ret, inst_index, NULL);
950 }
951
952 tbs_client_gatt_read_complete(inst);
953
954 return BT_GATT_ITER_STOP;
955 }
956
957 return BT_GATT_ITER_CONTINUE;
958 }
959 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME) */
960
961 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI)
bearer_uci_changed(struct bt_conn * conn,int err,uint8_t inst_index,const char * uci)962 static void bearer_uci_changed(struct bt_conn *conn, int err, uint8_t inst_index, const char *uci)
963 {
964 struct bt_tbs_client_cb *listener, *next;
965
966 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
967 if (listener->bearer_uci != NULL) {
968 listener->bearer_uci(conn, err, inst_index, uci);
969 }
970 }
971 }
972
read_bearer_uci_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)973 static uint8_t read_bearer_uci_cb(struct bt_conn *conn, uint8_t err,
974 struct bt_gatt_read_params *params,
975 const void *data, uint16_t length)
976 {
977 struct bt_tbs_instance *inst = CONTAINER_OF(params, struct bt_tbs_instance, read_params);
978 const uint8_t inst_index = tbs_index(conn, inst);
979 int ret;
980
981 LOG_DBG("");
982
983 ret = handle_string_long_read(inst, err, data, params->single.offset, length, true);
984 if (ret != BT_GATT_ITER_CONTINUE) {
985 if (ret == BT_GATT_ITER_STOP) {
986 /* At this point the inst->net_buf.data contains a NULL terminator string */
987 bearer_uci_changed(conn, 0, inst_index, (char *)inst->net_buf.data);
988 } else {
989 bearer_uci_changed(conn, ret, inst_index, NULL);
990 }
991
992 tbs_client_gatt_read_complete(inst);
993
994 return BT_GATT_ITER_STOP;
995 }
996
997 return BT_GATT_ITER_CONTINUE;
998 }
999 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI) */
1000
1001 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY)
read_technology_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)1002 static uint8_t read_technology_cb(struct bt_conn *conn, uint8_t err,
1003 struct bt_gatt_read_params *params,
1004 const void *data, uint16_t length)
1005 {
1006 struct bt_tbs_instance *inst = CONTAINER_OF(params,
1007 struct bt_tbs_instance,
1008 read_params);
1009 uint8_t inst_index = tbs_index(conn, inst);
1010 uint8_t cb_err = err;
1011 uint8_t technology = 0;
1012
1013 LOG_DBG("Index %u", inst_index);
1014
1015 if (err != 0) {
1016 LOG_DBG("err: 0x%02X", err);
1017 } else if (data != NULL) {
1018 LOG_HEXDUMP_DBG(data, length, "Data read");
1019 if (length == sizeof(technology)) {
1020 (void)memcpy(&technology, data, length);
1021 LOG_DBG("%s (0x%02x)", bt_tbs_technology_str(technology), technology);
1022 } else {
1023 LOG_DBG("Invalid length");
1024 cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
1025 }
1026 }
1027
1028 tbs_client_gatt_read_complete(inst);
1029
1030 technology_changed(conn, cb_err, inst_index, technology);
1031
1032 return BT_GATT_ITER_STOP;
1033 }
1034 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY) */
1035
1036 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST)
uri_list_changed(struct bt_conn * conn,int err,uint8_t inst_index,const char * uri_list)1037 static void uri_list_changed(struct bt_conn *conn, int err, uint8_t inst_index,
1038 const char *uri_list)
1039 {
1040 struct bt_tbs_client_cb *listener, *next;
1041
1042 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
1043 if (listener->uri_list != NULL) {
1044 listener->uri_list(conn, err, inst_index, uri_list);
1045 }
1046 }
1047 }
1048
read_uri_list_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)1049 static uint8_t read_uri_list_cb(struct bt_conn *conn, uint8_t err,
1050 struct bt_gatt_read_params *params,
1051 const void *data, uint16_t length)
1052 {
1053 struct bt_tbs_instance *inst = CONTAINER_OF(params, struct bt_tbs_instance, read_params);
1054 const uint8_t inst_index = tbs_index(conn, inst);
1055 int ret;
1056
1057 LOG_DBG("");
1058
1059 ret = handle_string_long_read(inst, err, data, params->single.offset, length, true);
1060 if (ret != BT_GATT_ITER_CONTINUE) {
1061 if (ret == BT_GATT_ITER_STOP) {
1062 /* At this point the inst->net_buf.data contains a NULL terminator string */
1063 uri_list_changed(conn, 0, inst_index, (char *)inst->net_buf.data);
1064 } else {
1065 uri_list_changed(conn, ret, inst_index, NULL);
1066 }
1067
1068 tbs_client_gatt_read_complete(inst);
1069
1070 return BT_GATT_ITER_STOP;
1071 }
1072
1073 return BT_GATT_ITER_CONTINUE;
1074 }
1075 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST) */
1076
1077 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH)
read_signal_strength_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)1078 static uint8_t read_signal_strength_cb(struct bt_conn *conn, uint8_t err,
1079 struct bt_gatt_read_params *params,
1080 const void *data, uint16_t length)
1081 {
1082 struct bt_tbs_instance *inst = CONTAINER_OF(params,
1083 struct bt_tbs_instance,
1084 read_params);
1085 uint8_t inst_index = tbs_index(conn, inst);
1086 uint8_t cb_err = err;
1087 uint8_t signal_strength = 0;
1088
1089 LOG_DBG("Index %u", inst_index);
1090
1091 if (err != 0) {
1092 LOG_DBG("err: 0x%02X", err);
1093 } else if (data != NULL) {
1094 LOG_HEXDUMP_DBG(data, length, "Data read");
1095 if (length == sizeof(signal_strength)) {
1096 (void)memcpy(&signal_strength, data, length);
1097 LOG_DBG("0x%02x", signal_strength);
1098 } else {
1099 LOG_DBG("Invalid length");
1100 cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
1101 }
1102 }
1103
1104 tbs_client_gatt_read_complete(inst);
1105
1106 signal_strength_changed(conn, cb_err, inst_index, signal_strength);
1107
1108 return BT_GATT_ITER_STOP;
1109 }
1110 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH) */
1111
1112 #if defined(CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL)
signal_interval_changed(struct bt_conn * conn,int err,uint8_t inst_index,uint8_t signal_interval)1113 static void signal_interval_changed(struct bt_conn *conn, int err, uint8_t inst_index,
1114 uint8_t signal_interval)
1115 {
1116 struct bt_tbs_client_cb *listener, *next;
1117
1118 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
1119 if (listener->signal_interval != NULL) {
1120 listener->signal_interval(conn, err, inst_index, signal_interval);
1121 }
1122 }
1123 }
1124
read_signal_interval_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)1125 static uint8_t read_signal_interval_cb(struct bt_conn *conn, uint8_t err,
1126 struct bt_gatt_read_params *params,
1127 const void *data, uint16_t length)
1128 {
1129 struct bt_tbs_instance *inst = CONTAINER_OF(params,
1130 struct bt_tbs_instance,
1131 read_params);
1132 uint8_t inst_index = tbs_index(conn, inst);
1133 uint8_t cb_err = err;
1134 uint8_t signal_interval = 0;
1135
1136 LOG_DBG("Index %u", inst_index);
1137
1138 if (err != 0) {
1139 LOG_DBG("err: 0x%02X", err);
1140 } else if (data != NULL) {
1141 LOG_HEXDUMP_DBG(data, length, "Data read");
1142 if (length == sizeof(signal_interval)) {
1143 (void)memcpy(&signal_interval, data, length);
1144 LOG_DBG("0x%02x", signal_interval);
1145 } else {
1146 LOG_DBG("Invalid length");
1147 cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
1148 }
1149 }
1150
1151 tbs_client_gatt_read_complete(inst);
1152
1153 signal_interval_changed(conn, cb_err, inst_index, signal_interval);
1154
1155 return BT_GATT_ITER_STOP;
1156 }
1157 #endif /* defined(CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL) */
1158
1159 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS)
read_current_calls_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)1160 static uint8_t read_current_calls_cb(struct bt_conn *conn, uint8_t err,
1161 struct bt_gatt_read_params *params,
1162 const void *data, uint16_t length)
1163 {
1164 struct bt_tbs_instance *inst = CONTAINER_OF(params,
1165 struct bt_tbs_instance,
1166 read_params);
1167 uint8_t inst_index = tbs_index(conn, inst);
1168 int tbs_err = err;
1169
1170 LOG_DBG("Read bearer list current calls, index %u", inst_index);
1171
1172 if ((tbs_err == 0) && (data != NULL) &&
1173 (net_buf_simple_tailroom(&inst->net_buf) < length)) {
1174 tbs_err = BT_ATT_ERR_INSUFFICIENT_RESOURCES;
1175 }
1176
1177 if (tbs_err != 0) {
1178 LOG_DBG("err: %d", tbs_err);
1179
1180 tbs_client_gatt_read_complete(inst);
1181
1182 current_calls_changed(conn, tbs_err, inst_index, 0, NULL);
1183
1184 return BT_GATT_ITER_STOP;
1185 }
1186
1187 if (data != NULL) {
1188 LOG_DBG("Current calls read (offset %u): %s",
1189 params->single.offset,
1190 bt_hex(data, length));
1191
1192 net_buf_simple_add_mem(&inst->net_buf, data, length);
1193
1194 /* Returning continue will try to read more using read
1195 * long procedure
1196 */
1197 return BT_GATT_ITER_CONTINUE;
1198 }
1199
1200 tbs_client_gatt_read_complete(inst);
1201
1202 if (inst->net_buf.len == 0) {
1203 current_calls_changed(conn, 0, inst_index, 0, NULL);
1204
1205 return BT_GATT_ITER_STOP;
1206 }
1207
1208 bearer_list_current_calls(conn, inst, &inst->net_buf);
1209
1210 return BT_GATT_ITER_STOP;
1211 }
1212 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) */
1213
1214 #if defined(CONFIG_BT_TBS_CLIENT_CCID)
ccid_changed(struct bt_conn * conn,int err,uint8_t inst_index,uint8_t ccid)1215 static void ccid_changed(struct bt_conn *conn, int err, uint8_t inst_index, uint8_t ccid)
1216 {
1217 struct bt_tbs_client_cb *listener, *next;
1218
1219 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
1220 if (listener->ccid != NULL) {
1221 listener->ccid(conn, err, inst_index, ccid);
1222 }
1223 }
1224 }
1225
read_ccid_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)1226 static uint8_t read_ccid_cb(struct bt_conn *conn, uint8_t err,
1227 struct bt_gatt_read_params *params,
1228 const void *data, uint16_t length)
1229 {
1230 struct bt_tbs_instance *inst = CONTAINER_OF(params,
1231 struct bt_tbs_instance,
1232 read_params);
1233 uint8_t inst_index = tbs_index(conn, inst);
1234 uint8_t cb_err = err;
1235 uint8_t ccid = 0;
1236
1237 LOG_DBG("Index %u", inst_index);
1238
1239 if (err != 0) {
1240 LOG_DBG("err: 0x%02X", err);
1241 } else if (data != NULL) {
1242 LOG_HEXDUMP_DBG(data, length, "Data read");
1243 if (length == sizeof(ccid)) {
1244 (void)memcpy(&ccid, data, length);
1245 LOG_DBG("0x%02x", ccid);
1246 } else {
1247 LOG_DBG("Invalid length");
1248 cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
1249 }
1250 }
1251
1252 tbs_client_gatt_read_complete(inst);
1253
1254 ccid_changed(conn, cb_err, inst_index, ccid);
1255
1256 return BT_GATT_ITER_STOP;
1257 }
1258 #endif /* defined(CONFIG_BT_TBS_CLIENT_CCID) */
1259
1260 #if defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS)
read_status_flags_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)1261 static uint8_t read_status_flags_cb(struct bt_conn *conn, uint8_t err,
1262 struct bt_gatt_read_params *params,
1263 const void *data, uint16_t length)
1264 {
1265 struct bt_tbs_instance *inst = CONTAINER_OF(params,
1266 struct bt_tbs_instance,
1267 read_params);
1268 uint8_t inst_index = tbs_index(conn, inst);
1269 uint8_t cb_err = err;
1270 uint16_t status_flags = 0;
1271
1272 LOG_DBG("Index %u", inst_index);
1273
1274 if (err != 0) {
1275 LOG_DBG("err: 0x%02X", err);
1276 } else if (data != NULL) {
1277 LOG_HEXDUMP_DBG(data, length, "Data read");
1278 if (length == sizeof(status_flags)) {
1279 (void)memcpy(&status_flags, data, length);
1280 LOG_DBG("0x%04x", status_flags);
1281 } else {
1282 LOG_DBG("Invalid length");
1283 cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
1284 }
1285 }
1286
1287 tbs_client_gatt_read_complete(inst);
1288
1289 status_flags_changed(conn, cb_err, inst_index, status_flags);
1290
1291 return BT_GATT_ITER_STOP;
1292 }
1293 #endif /* defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS) */
1294
1295 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI)
read_call_uri_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)1296 static uint8_t read_call_uri_cb(struct bt_conn *conn, uint8_t err,
1297 struct bt_gatt_read_params *params,
1298 const void *data, uint16_t length)
1299 {
1300 struct bt_tbs_instance *inst = CONTAINER_OF(params, struct bt_tbs_instance, read_params);
1301 const uint8_t inst_index = tbs_index(conn, inst);
1302 int ret;
1303
1304 LOG_DBG("");
1305
1306 ret = handle_string_long_read(inst, err, data, params->single.offset, length, true);
1307 if (ret != BT_GATT_ITER_CONTINUE) {
1308 if (ret == BT_GATT_ITER_STOP) {
1309 /* At this point the inst->net_buf.data contains a NULL terminator string */
1310 call_uri_changed(conn, 0, inst_index, (char *)inst->net_buf.data);
1311 } else {
1312 call_uri_changed(conn, ret, inst_index, NULL);
1313 }
1314
1315 tbs_client_gatt_read_complete(inst);
1316
1317 return BT_GATT_ITER_STOP;
1318 }
1319
1320 return BT_GATT_ITER_CONTINUE;
1321 }
1322 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI) */
1323
read_call_state_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)1324 static uint8_t read_call_state_cb(struct bt_conn *conn, uint8_t err,
1325 struct bt_gatt_read_params *params,
1326 const void *data, uint16_t length)
1327 {
1328 struct bt_tbs_instance *inst = CONTAINER_OF(params,
1329 struct bt_tbs_instance,
1330 read_params);
1331 uint8_t inst_index = tbs_index(conn, inst);
1332 uint8_t cnt = 0;
1333 struct bt_tbs_client_call_state call_states[CONFIG_BT_TBS_CLIENT_MAX_CALLS];
1334 int tbs_err = err;
1335
1336 LOG_DBG("Index %u", inst_index);
1337
1338 if ((tbs_err == 0) && (data != NULL) &&
1339 (net_buf_simple_tailroom(&inst->net_buf) < length)) {
1340 tbs_err = BT_ATT_ERR_INSUFFICIENT_RESOURCES;
1341 }
1342
1343 if (tbs_err != 0) {
1344 LOG_DBG("err: %d", tbs_err);
1345
1346 tbs_client_gatt_read_complete(inst);
1347
1348 call_state_changed(conn, tbs_err, inst_index, 0, NULL);
1349
1350 return BT_GATT_ITER_STOP;
1351 }
1352
1353 if (data != NULL) {
1354 LOG_DBG("Call states read (offset %u): %s", params->single.offset,
1355 bt_hex(data, length));
1356
1357 net_buf_simple_add_mem(&inst->net_buf, data, length);
1358
1359 /* Returning continue will try to read more using read long procedure */
1360 return BT_GATT_ITER_CONTINUE;
1361 }
1362
1363 if (inst->net_buf.len == 0) {
1364 tbs_client_gatt_read_complete(inst);
1365
1366 call_state_changed(conn, 0, inst_index, 0, NULL);
1367
1368 return BT_GATT_ITER_STOP;
1369 }
1370
1371 /* Finished reading, start parsing */
1372 while (inst->net_buf.len != 0) {
1373 struct bt_tbs_client_call_state *call_state;
1374
1375 if (cnt == CONFIG_BT_TBS_CLIENT_MAX_CALLS) {
1376 LOG_WRN("Could not parse all calls due to memory restrictions");
1377 break;
1378 }
1379
1380 call_state = &call_states[cnt];
1381
1382 tbs_err = net_buf_pull_call_state(&inst->net_buf, call_state);
1383 if (tbs_err != 0) {
1384 LOG_DBG("Invalid current call notification: %d", err);
1385 break;
1386 }
1387
1388 cnt++;
1389 }
1390
1391 tbs_client_gatt_read_complete(inst);
1392
1393 call_state_changed(conn, tbs_err, inst_index, cnt, call_states);
1394
1395 return BT_GATT_ITER_STOP;
1396 }
1397
1398 #if defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES)
optional_opcodes_changed(struct bt_conn * conn,int err,uint8_t inst_index,uint16_t optional_opcodes)1399 static void optional_opcodes_changed(struct bt_conn *conn, int err, uint8_t inst_index,
1400 uint16_t optional_opcodes)
1401 {
1402 struct bt_tbs_client_cb *listener, *next;
1403
1404 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
1405 if (listener->optional_opcodes != NULL) {
1406 listener->optional_opcodes(conn, err, inst_index, optional_opcodes);
1407 }
1408 }
1409 }
1410
read_optional_opcodes_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)1411 static uint8_t read_optional_opcodes_cb(struct bt_conn *conn, uint8_t err,
1412 struct bt_gatt_read_params *params,
1413 const void *data, uint16_t length)
1414 {
1415 struct bt_tbs_instance *inst = CONTAINER_OF(params, struct bt_tbs_instance, read_params);
1416 uint8_t inst_index = tbs_index(conn, inst);
1417 uint8_t cb_err = err;
1418 uint16_t optional_opcodes = 0;
1419
1420 LOG_DBG("Index %u", inst_index);
1421
1422 if (err != 0) {
1423 LOG_DBG("err: 0x%02X", err);
1424 } else if (data != NULL) {
1425 LOG_HEXDUMP_DBG(data, length, "Data read");
1426 if (length == sizeof(optional_opcodes)) {
1427 (void)memcpy(&optional_opcodes, data, length);
1428 LOG_DBG("0x%04x", optional_opcodes);
1429 } else {
1430 LOG_DBG("Invalid length");
1431 cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
1432 }
1433 }
1434
1435 tbs_client_gatt_read_complete(inst);
1436
1437 optional_opcodes_changed(conn, cb_err, inst_index, optional_opcodes);
1438
1439 return BT_GATT_ITER_STOP;
1440 }
1441 #endif /* defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES) */
1442
1443 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL)
read_remote_uri_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)1444 static uint8_t read_remote_uri_cb(struct bt_conn *conn, uint8_t err,
1445 struct bt_gatt_read_params *params,
1446 const void *data, uint16_t length)
1447 {
1448 struct bt_tbs_instance *inst = CONTAINER_OF(params, struct bt_tbs_instance, read_params);
1449 const uint8_t inst_index = tbs_index(conn, inst);
1450 int ret;
1451
1452 LOG_DBG("");
1453
1454 ret = handle_string_long_read(inst, err, data, params->single.offset, length, true);
1455 if (ret != BT_GATT_ITER_CONTINUE) {
1456 if (ret == BT_GATT_ITER_STOP) {
1457 /* At this point the inst->net_buf.data contains a NULL terminator string */
1458 remote_uri_changed(conn, 0, inst_index, (char *)inst->net_buf.data);
1459 } else {
1460 remote_uri_changed(conn, ret, inst_index, NULL);
1461 }
1462
1463 tbs_client_gatt_read_complete(inst);
1464
1465 return BT_GATT_ITER_STOP;
1466 }
1467
1468 return BT_GATT_ITER_CONTINUE;
1469 }
1470 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL) */
1471
1472 #if defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME)
read_friendly_name_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)1473 static uint8_t read_friendly_name_cb(struct bt_conn *conn, uint8_t err,
1474 struct bt_gatt_read_params *params,
1475 const void *data, uint16_t length)
1476 {
1477 struct bt_tbs_instance *inst = CONTAINER_OF(params, struct bt_tbs_instance, read_params);
1478 const uint8_t inst_index = tbs_index(conn, inst);
1479 int ret;
1480
1481 LOG_DBG("");
1482
1483 ret = handle_string_long_read(inst, err, data, params->single.offset, length, true);
1484 if (ret != BT_GATT_ITER_CONTINUE) {
1485 if (ret == BT_GATT_ITER_STOP) {
1486 /* At this point the inst->net_buf.data contains a NULL terminator string */
1487 friendly_name_changed(conn, 0, inst_index, (char *)inst->net_buf.data);
1488 } else {
1489 friendly_name_changed(conn, ret, inst_index, NULL);
1490 }
1491
1492 tbs_client_gatt_read_complete(inst);
1493
1494 return BT_GATT_ITER_STOP;
1495 }
1496
1497 return BT_GATT_ITER_CONTINUE;
1498 }
1499 #endif /* defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME) */
1500
1501 #if defined(CONFIG_BT_TBS_CLIENT_CCID)
disc_read_ccid_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)1502 static uint8_t disc_read_ccid_cb(struct bt_conn *conn, uint8_t err,
1503 struct bt_gatt_read_params *params,
1504 const void *data, uint16_t length)
1505 {
1506 struct bt_tbs_instance *inst = CONTAINER_OF(params, struct bt_tbs_instance, read_params);
1507 uint8_t inst_index = tbs_index(conn, inst);
1508 int cb_err = err;
1509
1510 LOG_DBG("Index %u", inst_index);
1511
1512 if (cb_err != 0) {
1513 LOG_DBG("err: 0x%02X", cb_err);
1514 } else if (data != NULL) {
1515 if (length == sizeof(inst->ccid)) {
1516 inst->ccid = ((uint8_t *)data)[0];
1517 LOG_DBG("0x%02x", inst->ccid);
1518 } else {
1519 LOG_DBG("Invalid length");
1520 cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
1521 }
1522 }
1523
1524 tbs_client_gatt_read_complete(inst);
1525
1526 if (cb_err != 0) {
1527 tbs_client_discover_complete(conn, cb_err);
1528 } else {
1529 discover_next_instance(conn);
1530 }
1531
1532 return BT_GATT_ITER_STOP;
1533 }
1534
tbs_client_disc_read_ccid(struct bt_conn * conn)1535 static void tbs_client_disc_read_ccid(struct bt_conn *conn)
1536 {
1537 const uint8_t conn_index = bt_conn_index(conn);
1538 struct bt_tbs_server_inst *srv_inst = &srv_insts[conn_index];
1539 struct bt_tbs_instance *inst = srv_inst->current_inst;
1540 int err;
1541
1542 err = tbs_client_gatt_read(conn, inst, inst->ccid_handle, disc_read_ccid_cb);
1543 if (err != 0) {
1544 tbs_client_discover_complete(conn, err);
1545 }
1546 }
1547 #endif /* defined(CONFIG_BT_TBS_CLIENT_CCID) */
1548
1549 /**
1550 * @brief This will discover all characteristics on the server, retrieving the
1551 * handles of the writeable characteristics and subscribing to all notify and
1552 * indicate characteristics.
1553 */
discover_func(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)1554 static uint8_t discover_func(struct bt_conn *conn,
1555 const struct bt_gatt_attr *attr,
1556 struct bt_gatt_discover_params *params)
1557 {
1558 const uint8_t conn_index = bt_conn_index(conn);
1559 struct bt_tbs_server_inst *srv_inst = &srv_insts[conn_index];
1560 struct bt_tbs_instance *current_inst = srv_inst->current_inst;
1561
1562 if (attr == NULL) {
1563 #if defined(CONFIG_BT_TBS_CLIENT_CCID)
1564 /* Read the CCID as the last part of discovering a TBS instance */
1565 tbs_client_disc_read_ccid(conn);
1566 #else
1567 discover_next_instance(conn);
1568 #endif /* defined(CONFIG_BT_TBS_CLIENT_CCID) */
1569
1570 return BT_GATT_ITER_STOP;
1571 }
1572
1573 LOG_DBG("[ATTRIBUTE] handle 0x%04X", attr->handle);
1574
1575 if (params->type == BT_GATT_DISCOVER_CHARACTERISTIC) {
1576 const struct bt_gatt_chrc *chrc;
1577 struct bt_gatt_subscribe_params *sub_params = NULL;
1578
1579 chrc = (struct bt_gatt_chrc *)attr->user_data;
1580
1581 if (bt_uuid_cmp(chrc->uuid, BT_UUID_TBS_CALL_STATE) == 0) {
1582 LOG_DBG("Call state");
1583 sub_params = ¤t_inst->call_state_sub_params;
1584 sub_params->value_handle = chrc->value_handle;
1585 sub_params->disc_params = ¤t_inst->call_state_sub_disc_params;
1586 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)
1587 } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_TBS_PROVIDER_NAME) == 0) {
1588 LOG_DBG("Provider name");
1589 sub_params = ¤t_inst->name_sub_params;
1590 sub_params->value_handle = chrc->value_handle;
1591 sub_params->disc_params = ¤t_inst->name_sub_disc_params;
1592 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME) */
1593 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI)
1594 } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_TBS_UCI) == 0) {
1595 LOG_DBG("Bearer UCI");
1596 current_inst->bearer_uci_handle = chrc->value_handle;
1597 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI) */
1598 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY)
1599 } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_TBS_TECHNOLOGY) == 0) {
1600 LOG_DBG("Technology");
1601 sub_params = ¤t_inst->technology_sub_params;
1602 sub_params->value_handle = chrc->value_handle;
1603 sub_params->disc_params = ¤t_inst->technology_sub_disc_params;
1604 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY) */
1605 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST)
1606 } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_TBS_URI_LIST) == 0) {
1607 LOG_DBG("URI Scheme List");
1608 current_inst->uri_list_handle = chrc->value_handle;
1609 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST) */
1610 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH)
1611 } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_TBS_SIGNAL_STRENGTH) == 0) {
1612 LOG_DBG("Signal strength");
1613 sub_params = ¤t_inst->signal_strength_sub_params;
1614 sub_params->value_handle = chrc->value_handle;
1615 sub_params->disc_params = ¤t_inst->signal_strength_sub_disc_params;
1616 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH) */
1617 #if defined(CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL) \
1618 || defined(CONFIG_BT_TBS_CLIENT_SET_BEARER_SIGNAL_INTERVAL)
1619 } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_TBS_SIGNAL_INTERVAL) == 0) {
1620 LOG_DBG("Signal strength reporting interval");
1621 current_inst->signal_interval_handle = chrc->value_handle;
1622 #endif /* defined(CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL) */
1623 /* || defined(CONFIG_BT_TBS_CLIENT_SET_BEARER_SIGNAL_INTERVAL) */
1624 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS)
1625 } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_TBS_LIST_CURRENT_CALLS) == 0) {
1626 LOG_DBG("Current calls");
1627 sub_params = ¤t_inst->current_calls_sub_params;
1628 sub_params->value_handle = chrc->value_handle;
1629 sub_params->disc_params = ¤t_inst->current_calls_sub_disc_params;
1630 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) */
1631 #if defined(CONFIG_BT_TBS_CLIENT_CCID)
1632 } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_CCID) == 0) {
1633 LOG_DBG("CCID");
1634 current_inst->ccid_handle = chrc->value_handle;
1635 #endif /* defined(CONFIG_BT_TBS_CLIENT_CCID) */
1636 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI)
1637 } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_TBS_INCOMING_URI) == 0) {
1638 LOG_DBG("Incoming target URI");
1639 sub_params = ¤t_inst->in_target_uri_sub_params;
1640 sub_params->value_handle = chrc->value_handle;
1641 sub_params->disc_params = ¤t_inst->in_target_uri_sub_disc_params;
1642 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI) */
1643 #if defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS)
1644 } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_TBS_STATUS_FLAGS) == 0) {
1645 LOG_DBG("Status flags");
1646 sub_params = ¤t_inst->status_flags_sub_params;
1647 sub_params->value_handle = chrc->value_handle;
1648 sub_params->disc_params = ¤t_inst->status_sub_disc_params;
1649 #endif /* defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS) */
1650 #if defined(CONFIG_BT_TBS_CLIENT_CP_PROCEDURES)
1651 } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_TBS_CALL_CONTROL_POINT) == 0) {
1652 LOG_DBG("Call control point");
1653 sub_params = ¤t_inst->call_cp_sub_params;
1654 sub_params->value_handle = chrc->value_handle;
1655 sub_params->disc_params = ¤t_inst->call_cp_sub_disc_params;
1656 #endif /* defined(CONFIG_BT_TBS_CLIENT_CP_PROCEDURES) */
1657 #if defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES)
1658 } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_TBS_OPTIONAL_OPCODES) == 0) {
1659 LOG_DBG("Supported opcodes");
1660 current_inst->optional_opcodes_handle = chrc->value_handle;
1661 #endif /* defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES) */
1662 } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_TBS_TERMINATE_REASON) == 0) {
1663 LOG_DBG("Termination reason");
1664 current_inst->termination_reason_handle = chrc->value_handle;
1665 sub_params = ¤t_inst->termination_sub_params;
1666 sub_params->value_handle = chrc->value_handle;
1667 sub_params->disc_params = ¤t_inst->termination_sub_disc_params;
1668 #if defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME)
1669 } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_TBS_FRIENDLY_NAME) == 0) {
1670 LOG_DBG("Incoming friendly name");
1671 sub_params = ¤t_inst->friendly_name_sub_params;
1672 sub_params->value_handle = chrc->value_handle;
1673 sub_params->disc_params = ¤t_inst->friendly_name_sub_disc_params;
1674 #endif /* defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME) */
1675 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL)
1676 } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_TBS_INCOMING_CALL) == 0) {
1677 LOG_DBG("Incoming call");
1678 sub_params = ¤t_inst->incoming_call_sub_params;
1679 sub_params->value_handle = chrc->value_handle;
1680 sub_params->disc_params = ¤t_inst->incoming_call_sub_disc_params;
1681 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL) */
1682 }
1683
1684 if (sub_params != NULL) {
1685 sub_params->value = 0;
1686 if (chrc->properties & BT_GATT_CHRC_NOTIFY) {
1687 sub_params->value = BT_GATT_CCC_NOTIFY;
1688 } else if (chrc->properties & BT_GATT_CHRC_INDICATE) {
1689 sub_params->value = BT_GATT_CCC_INDICATE;
1690 }
1691
1692 if (sub_params->value != 0) {
1693 int err;
1694
1695 sub_params->ccc_handle = BT_GATT_AUTO_DISCOVER_CCC_HANDLE;
1696 sub_params->end_handle = current_inst->end_handle;
1697 sub_params->notify = notify_handler;
1698 atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
1699
1700 err = bt_gatt_subscribe(conn, sub_params);
1701 if (err != 0 && err != -EALREADY) {
1702 LOG_DBG("Could not subscribe to "
1703 "characteristic at handle 0x%04X"
1704 "(%d)",
1705 sub_params->value_handle, err);
1706 tbs_client_discover_complete(conn, err);
1707
1708 return BT_GATT_ITER_STOP;
1709 } else {
1710 LOG_DBG("Subscribed to characteristic at "
1711 "handle 0x%04X",
1712 sub_params->value_handle);
1713 }
1714 }
1715 }
1716 }
1717
1718 return BT_GATT_ITER_CONTINUE;
1719 }
1720
get_next_instance(struct bt_conn * conn,struct bt_tbs_server_inst * srv_inst)1721 static struct bt_tbs_instance *get_next_instance(struct bt_conn *conn,
1722 struct bt_tbs_server_inst *srv_inst)
1723 {
1724 uint8_t inst_index;
1725
1726 if (srv_inst->current_inst != NULL) {
1727 inst_index = tbs_index(conn, srv_inst->current_inst);
1728 if (inst_index == BT_TBS_GTBS_INDEX) {
1729 inst_index = 0;
1730 } else {
1731 inst_index++;
1732 }
1733
1734 return tbs_inst_by_index(conn, inst_index);
1735 }
1736
1737 inst_index = gtbs_found(srv_inst) ? BT_TBS_GTBS_INDEX : 0;
1738
1739 return tbs_inst_by_index(conn, inst_index);
1740 }
1741
discover_next_instance(struct bt_conn * conn)1742 static void discover_next_instance(struct bt_conn *conn)
1743 {
1744 int err;
1745 uint8_t conn_index = bt_conn_index(conn);
1746 struct bt_tbs_server_inst *srv_inst = &srv_insts[conn_index];
1747
1748 srv_inst->current_inst = get_next_instance(conn, srv_inst);
1749 if (srv_inst->current_inst == NULL) {
1750 tbs_client_discover_complete(conn, 0);
1751 return;
1752 }
1753
1754 LOG_DBG("inst_index %u", tbs_index(conn, srv_inst->current_inst));
1755
1756 (void)memset(&srv_inst->discover_params, 0, sizeof(srv_inst->discover_params));
1757 srv_inst->discover_params.uuid = NULL;
1758 srv_inst->discover_params.start_handle = srv_inst->current_inst->start_handle;
1759 srv_inst->discover_params.end_handle = srv_inst->current_inst->end_handle;
1760 srv_inst->discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
1761 srv_inst->discover_params.func = discover_func;
1762
1763 err = bt_gatt_discover(conn, &srv_inst->discover_params);
1764 if (err != 0) {
1765 tbs_client_discover_complete(conn, err);
1766 }
1767 }
1768
primary_discover_complete(struct bt_tbs_server_inst * server,struct bt_conn * conn)1769 static void primary_discover_complete(struct bt_tbs_server_inst *server, struct bt_conn *conn)
1770 {
1771 if (IS_ENABLED(CONFIG_BT_TBS_CLIENT_GTBS)) {
1772 LOG_DBG("Discover complete, found %u instances (GTBS%s found)",
1773 inst_cnt(server), gtbs_found(server) ? "" : " not");
1774 } else {
1775 LOG_DBG("Discover complete, found %u instances", inst_cnt(server));
1776 }
1777
1778 server->current_inst = NULL;
1779
1780 if (gtbs_found(server) || inst_cnt(server) > 0) {
1781 discover_next_instance(conn);
1782 } else {
1783 tbs_client_discover_complete(conn, 0);
1784 }
1785 }
1786
1787 /**
1788 * @brief This will discover all characteristics on the server, retrieving the
1789 * handles of the writeable characteristics and subscribing to all notify and
1790 * indicate characteristics.
1791 */
1792 #if defined(CONFIG_BT_TBS_CLIENT_TBS)
1793 static const struct bt_uuid *tbs_uuid = BT_UUID_TBS;
1794
primary_discover_tbs_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)1795 static uint8_t primary_discover_tbs_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr,
1796 struct bt_gatt_discover_params *params)
1797 {
1798 const uint8_t conn_index = bt_conn_index(conn);
1799 struct bt_tbs_server_inst *srv_inst = &srv_insts[conn_index];
1800
1801 LOG_DBG("conn %p attr %p", (void *)conn, attr);
1802
1803 if (attr != NULL) {
1804 const struct bt_gatt_service_val *prim_service;
1805
1806 LOG_DBG("[ATTRIBUTE] handle 0x%04X", attr->handle);
1807
1808 prim_service = (struct bt_gatt_service_val *)attr->user_data;
1809
1810 srv_inst->current_inst = &srv_inst->tbs_insts[srv_inst->inst_cnt++];
1811 srv_inst->current_inst->start_handle = attr->handle + 1;
1812 srv_inst->current_inst->end_handle = prim_service->end_handle;
1813
1814 if (srv_inst->inst_cnt < ARRAY_SIZE(srv_inst->tbs_insts)) {
1815 return BT_GATT_ITER_CONTINUE;
1816 }
1817 }
1818
1819 primary_discover_complete(srv_inst, conn);
1820
1821 return BT_GATT_ITER_STOP;
1822 }
1823
primary_discover_tbs(struct bt_conn * conn)1824 static int primary_discover_tbs(struct bt_conn *conn)
1825 {
1826 struct bt_tbs_server_inst *srv_inst = &srv_insts[bt_conn_index(conn)];
1827 struct bt_gatt_discover_params *params = &srv_inst->discover_params;
1828
1829 LOG_DBG("conn %p", (void *)conn);
1830
1831 (void)memset(params, 0, sizeof(*params));
1832 params->uuid = tbs_uuid;
1833 params->func = primary_discover_tbs_cb;
1834 params->type = BT_GATT_DISCOVER_PRIMARY;
1835 params->start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
1836 params->end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
1837
1838 return bt_gatt_discover(conn, params);
1839 }
1840 #endif /* CONFIG_BT_TBS_CLIENT_TBS */
1841
1842 #if defined(CONFIG_BT_TBS_CLIENT_GTBS)
1843 static const struct bt_uuid *gtbs_uuid = BT_UUID_GTBS;
1844
primary_discover_gtbs_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)1845 static uint8_t primary_discover_gtbs_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr,
1846 struct bt_gatt_discover_params *params)
1847 {
1848 const uint8_t conn_index = bt_conn_index(conn);
1849 struct bt_tbs_server_inst *srv_inst = &srv_insts[conn_index];
1850
1851 LOG_DBG("conn %p attr %p", (void *)conn, attr);
1852
1853 if (attr != NULL) {
1854 const struct bt_gatt_service_val *prim_service;
1855
1856 LOG_DBG("[ATTRIBUTE] handle 0x%04X", attr->handle);
1857
1858 prim_service = (struct bt_gatt_service_val *)attr->user_data;
1859
1860 srv_inst->current_inst = &srv_inst->gtbs_inst;
1861 srv_inst->current_inst->start_handle = attr->handle + 1;
1862 srv_inst->current_inst->end_handle = prim_service->end_handle;
1863 }
1864
1865 #if defined(CONFIG_BT_TBS_CLIENT_TBS)
1866 int err;
1867
1868 err = primary_discover_tbs(conn);
1869 if (err == 0) {
1870 return BT_GATT_ITER_STOP;
1871 }
1872
1873 LOG_DBG("Discover failed (err %d)", err);
1874 #endif /* CONFIG_BT_TBS_CLIENT_TBS */
1875
1876 primary_discover_complete(srv_inst, conn);
1877
1878 return BT_GATT_ITER_STOP;
1879 }
1880
primary_discover_gtbs(struct bt_conn * conn)1881 static int primary_discover_gtbs(struct bt_conn *conn)
1882 {
1883 struct bt_tbs_server_inst *srv_inst = &srv_insts[bt_conn_index(conn)];
1884 struct bt_gatt_discover_params *params = &srv_inst->discover_params;
1885
1886 LOG_DBG("conn %p", (void *)conn);
1887
1888 (void)memset(params, 0, sizeof(*params));
1889 params->uuid = gtbs_uuid;
1890 params->func = primary_discover_gtbs_cb;
1891 params->type = BT_GATT_DISCOVER_PRIMARY;
1892 params->start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
1893 params->end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
1894
1895 return bt_gatt_discover(conn, params);
1896 }
1897 #endif /* defined(CONFIG_BT_TBS_CLIENT_GTBS) */
1898
1899 /****************************** PUBLIC API ******************************/
1900
1901 #if defined(CONFIG_BT_TBS_CLIENT_HOLD_CALL)
bt_tbs_client_hold_call(struct bt_conn * conn,uint8_t inst_index,uint8_t call_index)1902 int bt_tbs_client_hold_call(struct bt_conn *conn, uint8_t inst_index,
1903 uint8_t call_index)
1904 {
1905 return tbs_client_common_call_control(conn, inst_index, call_index,
1906 BT_TBS_CALL_OPCODE_HOLD);
1907 }
1908 #endif /* defined(CONFIG_BT_TBS_CLIENT_HOLD_CALL) */
1909
1910 #if defined(CONFIG_BT_TBS_CLIENT_ACCEPT_CALL)
bt_tbs_client_accept_call(struct bt_conn * conn,uint8_t inst_index,uint8_t call_index)1911 int bt_tbs_client_accept_call(struct bt_conn *conn, uint8_t inst_index,
1912 uint8_t call_index)
1913 {
1914 return tbs_client_common_call_control(conn, inst_index, call_index,
1915 BT_TBS_CALL_OPCODE_ACCEPT);
1916 }
1917 #endif /* defined(CONFIG_BT_TBS_CLIENT_ACCEPT_CALL) */
1918
1919 #if defined(CONFIG_BT_TBS_CLIENT_RETRIEVE_CALL)
bt_tbs_client_retrieve_call(struct bt_conn * conn,uint8_t inst_index,uint8_t call_index)1920 int bt_tbs_client_retrieve_call(struct bt_conn *conn, uint8_t inst_index,
1921 uint8_t call_index)
1922 {
1923 return tbs_client_common_call_control(conn, inst_index, call_index,
1924 BT_TBS_CALL_OPCODE_RETRIEVE);
1925 }
1926 #endif /* defined(CONFIG_BT_TBS_CLIENT_RETRIEVE_CALL) */
1927
1928 #if defined(CONFIG_BT_TBS_CLIENT_TERMINATE_CALL)
bt_tbs_client_terminate_call(struct bt_conn * conn,uint8_t inst_index,uint8_t call_index)1929 int bt_tbs_client_terminate_call(struct bt_conn *conn, uint8_t inst_index,
1930 uint8_t call_index)
1931 {
1932 return tbs_client_common_call_control(conn, inst_index, call_index,
1933 BT_TBS_CALL_OPCODE_TERMINATE);
1934 }
1935 #endif /* defined(CONFIG_BT_TBS_CLIENT_TERMINATE_CALL) */
1936
1937 #if defined(CONFIG_BT_TBS_CLIENT_ORIGINATE_CALL)
bt_tbs_client_originate_call(struct bt_conn * conn,uint8_t inst_index,const char * uri)1938 int bt_tbs_client_originate_call(struct bt_conn *conn, uint8_t inst_index,
1939 const char *uri)
1940 {
1941 struct bt_tbs_instance *inst;
1942 uint8_t write_buf[CONFIG_BT_L2CAP_TX_MTU];
1943 struct bt_tbs_call_cp_originate *originate;
1944 size_t uri_len;
1945 const size_t max_uri_len = sizeof(write_buf) - sizeof(*originate);
1946
1947 if (conn == NULL) {
1948 return -ENOTCONN;
1949 } else if (!bt_tbs_valid_uri(uri, strlen(uri))) {
1950 LOG_DBG("Invalid URI: %s", uri);
1951 return -EINVAL;
1952 }
1953
1954 inst = tbs_inst_by_index(conn, inst_index);
1955 if (inst == NULL) {
1956 return -EINVAL;
1957 }
1958
1959 /* Check if there are free spots */
1960 if (!free_call_spot(inst)) {
1961 LOG_DBG("Cannot originate more calls");
1962 return -ENOMEM;
1963 }
1964
1965 uri_len = strlen(uri);
1966
1967 if (uri_len > max_uri_len) {
1968 LOG_DBG("URI len (%zu) longer than maximum writable %zu", uri_len, max_uri_len);
1969 return -ENOMEM;
1970 }
1971
1972 originate = (struct bt_tbs_call_cp_originate *)write_buf;
1973 originate->opcode = BT_TBS_CALL_OPCODE_ORIGINATE;
1974 (void)memcpy(originate->uri, uri, uri_len);
1975
1976 return bt_gatt_write_without_response(conn, inst->call_cp_sub_params.value_handle,
1977 originate,
1978 sizeof(*originate) + uri_len,
1979 false);
1980 }
1981 #endif /* defined(CONFIG_BT_TBS_CLIENT_ORIGINATE_CALL) */
1982
1983 #if defined(CONFIG_BT_TBS_CLIENT_JOIN_CALLS)
bt_tbs_client_join_calls(struct bt_conn * conn,uint8_t inst_index,const uint8_t * call_indexes,uint8_t count)1984 int bt_tbs_client_join_calls(struct bt_conn *conn, uint8_t inst_index,
1985 const uint8_t *call_indexes, uint8_t count)
1986 {
1987 if (conn == NULL) {
1988 return -ENOTCONN;
1989 }
1990
1991 /* Write to call control point */
1992 if (call_indexes && count > 1 &&
1993 count <= CONFIG_BT_TBS_CLIENT_MAX_CALLS) {
1994 struct bt_tbs_instance *inst;
1995 struct bt_tbs_call_cp_join *join;
1996 uint8_t write_buf[CONFIG_BT_L2CAP_TX_MTU];
1997 const size_t max_call_cnt = sizeof(write_buf) - sizeof(join->opcode);
1998
1999 inst = tbs_inst_by_index(conn, inst_index);
2000 if (inst == NULL) {
2001 return -EINVAL;
2002 }
2003
2004 if (inst->call_cp_sub_params.value_handle == 0) {
2005 LOG_DBG("Handle not set");
2006 return -EINVAL;
2007 }
2008
2009 if (count > max_call_cnt) {
2010 LOG_DBG("Call count (%u) larger than maximum writable %zu", count,
2011 max_call_cnt);
2012 return -ENOMEM;
2013 }
2014
2015 join = (struct bt_tbs_call_cp_join *)write_buf;
2016
2017 join->opcode = BT_TBS_CALL_OPCODE_JOIN;
2018 (void)memcpy(join->call_indexes, call_indexes, count);
2019
2020 return bt_gatt_write_without_response(conn,
2021 inst->call_cp_sub_params.value_handle,
2022 join,
2023 sizeof(*join) + count,
2024 false);
2025 }
2026
2027 return -EINVAL;
2028 }
2029 #endif /* defined(CONFIG_BT_TBS_CLIENT_JOIN_CALLS) */
2030
2031 #if defined(CONFIG_BT_TBS_CLIENT_SET_BEARER_SIGNAL_INTERVAL)
bt_tbs_client_set_signal_strength_interval(struct bt_conn * conn,uint8_t inst_index,uint8_t interval)2032 int bt_tbs_client_set_signal_strength_interval(struct bt_conn *conn,
2033 uint8_t inst_index,
2034 uint8_t interval)
2035 {
2036 struct bt_tbs_instance *inst;
2037
2038 if (conn == NULL) {
2039 return -ENOTCONN;
2040 }
2041
2042 inst = tbs_inst_by_index(conn, inst_index);
2043 if (inst == NULL) {
2044 return -EINVAL;
2045 }
2046
2047 /* Populate Outgoing Remote URI */
2048 if (inst->signal_interval_handle == 0) {
2049 LOG_DBG("Handle not set");
2050 return -EINVAL;
2051 }
2052
2053 return bt_gatt_write_without_response(conn,
2054 inst->signal_interval_handle,
2055 &interval, sizeof(interval),
2056 false);
2057 }
2058 #endif /* defined(CONFIG_BT_TBS_CLIENT_SET_BEARER_SIGNAL_INTERVAL) */
2059
2060 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)
bt_tbs_client_read_bearer_provider_name(struct bt_conn * conn,uint8_t inst_index)2061 int bt_tbs_client_read_bearer_provider_name(struct bt_conn *conn,
2062 uint8_t inst_index)
2063 {
2064 struct bt_tbs_instance *inst;
2065
2066 if (conn == NULL) {
2067 return -ENOTCONN;
2068 }
2069
2070 inst = tbs_inst_by_index(conn, inst_index);
2071 if (inst == NULL) {
2072 return -EINVAL;
2073 }
2074
2075 if (inst->name_sub_params.value_handle == 0) {
2076 LOG_DBG("Handle not set");
2077 return -EINVAL;
2078 }
2079
2080 return tbs_client_gatt_read(conn, inst, inst->name_sub_params.value_handle,
2081 read_bearer_provider_name_cb);
2082 }
2083 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME) */
2084
2085 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI)
bt_tbs_client_read_bearer_uci(struct bt_conn * conn,uint8_t inst_index)2086 int bt_tbs_client_read_bearer_uci(struct bt_conn *conn, uint8_t inst_index)
2087 {
2088 struct bt_tbs_instance *inst;
2089
2090 if (conn == NULL) {
2091 return -ENOTCONN;
2092 }
2093
2094 inst = tbs_inst_by_index(conn, inst_index);
2095 if (inst == NULL) {
2096 return -EINVAL;
2097 }
2098
2099 if (inst->bearer_uci_handle == 0) {
2100 LOG_DBG("Handle not set");
2101 return -EINVAL;
2102 }
2103
2104 return tbs_client_gatt_read(conn, inst, inst->bearer_uci_handle, read_bearer_uci_cb);
2105 }
2106 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI) */
2107
2108 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY)
bt_tbs_client_read_technology(struct bt_conn * conn,uint8_t inst_index)2109 int bt_tbs_client_read_technology(struct bt_conn *conn, uint8_t inst_index)
2110 {
2111 struct bt_tbs_instance *inst;
2112
2113 if (conn == NULL) {
2114 return -ENOTCONN;
2115 }
2116
2117 inst = tbs_inst_by_index(conn, inst_index);
2118 if (inst == NULL) {
2119 return -EINVAL;
2120 }
2121
2122 if (inst->technology_sub_params.value_handle == 0) {
2123 LOG_DBG("Handle not set");
2124 return -EINVAL;
2125 }
2126
2127 return tbs_client_gatt_read(conn, inst, inst->technology_sub_params.value_handle,
2128 read_technology_cb);
2129 }
2130 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY) */
2131
2132 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST)
bt_tbs_client_read_uri_list(struct bt_conn * conn,uint8_t inst_index)2133 int bt_tbs_client_read_uri_list(struct bt_conn *conn, uint8_t inst_index)
2134 {
2135 struct bt_tbs_instance *inst;
2136
2137 if (conn == NULL) {
2138 return -ENOTCONN;
2139 }
2140
2141 inst = tbs_inst_by_index(conn, inst_index);
2142 if (inst == NULL) {
2143 return -EINVAL;
2144 }
2145
2146 if (inst->uri_list_handle == 0) {
2147 LOG_DBG("Handle not set");
2148 return -EINVAL;
2149 }
2150
2151 return tbs_client_gatt_read(conn, inst, inst->uri_list_handle, read_uri_list_cb);
2152 }
2153 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST) */
2154
2155 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH)
bt_tbs_client_read_signal_strength(struct bt_conn * conn,uint8_t inst_index)2156 int bt_tbs_client_read_signal_strength(struct bt_conn *conn, uint8_t inst_index)
2157 {
2158 struct bt_tbs_instance *inst;
2159
2160 if (conn == NULL) {
2161 return -ENOTCONN;
2162 }
2163
2164 inst = tbs_inst_by_index(conn, inst_index);
2165 if (inst == NULL) {
2166 return -EINVAL;
2167 }
2168
2169 if (inst->signal_strength_sub_params.value_handle == 0) {
2170 LOG_DBG("Handle not set");
2171 return -EINVAL;
2172 }
2173
2174 return tbs_client_gatt_read(conn, inst, inst->signal_strength_sub_params.value_handle,
2175 read_signal_strength_cb);
2176 }
2177 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH) */
2178
2179 #if defined(CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL)
bt_tbs_client_read_signal_interval(struct bt_conn * conn,uint8_t inst_index)2180 int bt_tbs_client_read_signal_interval(struct bt_conn *conn, uint8_t inst_index)
2181 {
2182 struct bt_tbs_instance *inst;
2183
2184 if (conn == NULL) {
2185 return -ENOTCONN;
2186 }
2187
2188 inst = tbs_inst_by_index(conn, inst_index);
2189 if (inst == NULL) {
2190 return -EINVAL;
2191 }
2192
2193 if (inst->signal_interval_handle == 0) {
2194 LOG_DBG("Handle not set");
2195 return -EINVAL;
2196 }
2197
2198 return tbs_client_gatt_read(conn, inst, inst->signal_interval_handle,
2199 read_signal_interval_cb);
2200 }
2201 #endif /* defined(CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL) */
2202
2203 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS)
bt_tbs_client_read_current_calls(struct bt_conn * conn,uint8_t inst_index)2204 int bt_tbs_client_read_current_calls(struct bt_conn *conn, uint8_t inst_index)
2205 {
2206 struct bt_tbs_instance *inst;
2207
2208 if (conn == NULL) {
2209 return -ENOTCONN;
2210 }
2211
2212 inst = tbs_inst_by_index(conn, inst_index);
2213 if (inst == NULL) {
2214 return -EINVAL;
2215 }
2216
2217 if (inst->current_calls_sub_params.value_handle == 0) {
2218 LOG_DBG("Handle not set");
2219 return -EINVAL;
2220 }
2221
2222 return tbs_client_gatt_read(conn, inst, inst->current_calls_sub_params.value_handle,
2223 read_current_calls_cb);
2224 }
2225 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) */
2226
2227 #if defined(CONFIG_BT_TBS_CLIENT_CCID)
bt_tbs_client_read_ccid(struct bt_conn * conn,uint8_t inst_index)2228 int bt_tbs_client_read_ccid(struct bt_conn *conn, uint8_t inst_index)
2229 {
2230 struct bt_tbs_instance *inst;
2231
2232 if (conn == NULL) {
2233 return -ENOTCONN;
2234 }
2235
2236 inst = tbs_inst_by_index(conn, inst_index);
2237 if (inst == NULL) {
2238 return -EINVAL;
2239 }
2240
2241 if (inst->ccid_handle == 0) {
2242 LOG_DBG("Handle not set");
2243 return -EINVAL;
2244 }
2245
2246 return tbs_client_gatt_read(conn, inst, inst->ccid_handle, read_ccid_cb);
2247 }
2248 #endif /* defined(CONFIG_BT_TBS_CLIENT_CCID) */
2249
2250 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI)
bt_tbs_client_read_call_uri(struct bt_conn * conn,uint8_t inst_index)2251 int bt_tbs_client_read_call_uri(struct bt_conn *conn, uint8_t inst_index)
2252 {
2253 struct bt_tbs_instance *inst;
2254
2255 if (conn == NULL) {
2256 return -ENOTCONN;
2257 }
2258
2259 inst = tbs_inst_by_index(conn, inst_index);
2260 if (inst == NULL) {
2261 return -EINVAL;
2262 }
2263
2264 if (inst->in_target_uri_sub_params.value_handle == 0) {
2265 LOG_DBG("Handle not set");
2266 return -EINVAL;
2267 }
2268
2269 return tbs_client_gatt_read(conn, inst, inst->in_target_uri_sub_params.value_handle,
2270 read_call_uri_cb);
2271 }
2272 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI) */
2273
2274 #if defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS)
bt_tbs_client_read_status_flags(struct bt_conn * conn,uint8_t inst_index)2275 int bt_tbs_client_read_status_flags(struct bt_conn *conn, uint8_t inst_index)
2276 {
2277 struct bt_tbs_instance *inst;
2278
2279 if (conn == NULL) {
2280 return -ENOTCONN;
2281 }
2282
2283 inst = tbs_inst_by_index(conn, inst_index);
2284 if (inst == NULL) {
2285 return -EINVAL;
2286 }
2287
2288 if (inst->status_flags_sub_params.value_handle == 0) {
2289 LOG_DBG("Handle not set");
2290 return -EINVAL;
2291 }
2292
2293 return tbs_client_gatt_read(conn, inst, inst->status_flags_sub_params.value_handle,
2294 read_status_flags_cb);
2295 }
2296 #endif /* defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS) */
2297
bt_tbs_client_read_call_state(struct bt_conn * conn,uint8_t inst_index)2298 int bt_tbs_client_read_call_state(struct bt_conn *conn, uint8_t inst_index)
2299 {
2300 struct bt_tbs_instance *inst;
2301
2302 if (conn == NULL) {
2303 return -ENOTCONN;
2304 }
2305
2306 inst = tbs_inst_by_index(conn, inst_index);
2307 if (inst == NULL) {
2308 return -EINVAL;
2309 }
2310
2311 if (inst->call_state_sub_params.value_handle == 0) {
2312 LOG_DBG("Handle not set");
2313 return -EINVAL;
2314 }
2315
2316 return tbs_client_gatt_read(conn, inst, inst->call_state_sub_params.value_handle,
2317 read_call_state_cb);
2318 }
2319
2320 #if defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES)
bt_tbs_client_read_optional_opcodes(struct bt_conn * conn,uint8_t inst_index)2321 int bt_tbs_client_read_optional_opcodes(struct bt_conn *conn,
2322 uint8_t inst_index)
2323 {
2324 struct bt_tbs_instance *inst;
2325
2326 if (conn == NULL) {
2327 return -ENOTCONN;
2328 }
2329
2330 inst = tbs_inst_by_index(conn, inst_index);
2331 if (inst == NULL) {
2332 return -EINVAL;
2333 }
2334
2335 if (inst->optional_opcodes_handle == 0) {
2336 LOG_DBG("Handle not set");
2337 return -EINVAL;
2338 }
2339
2340 return tbs_client_gatt_read(conn, inst, inst->optional_opcodes_handle,
2341 read_optional_opcodes_cb);
2342 }
2343 #endif /* defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES) */
2344
2345 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL)
bt_tbs_client_read_remote_uri(struct bt_conn * conn,uint8_t inst_index)2346 int bt_tbs_client_read_remote_uri(struct bt_conn *conn, uint8_t inst_index)
2347 {
2348 struct bt_tbs_instance *inst;
2349
2350 if (conn == NULL) {
2351 return -ENOTCONN;
2352 }
2353
2354 inst = tbs_inst_by_index(conn, inst_index);
2355 if (inst == NULL) {
2356 return -EINVAL;
2357 }
2358
2359 if (inst->incoming_call_sub_params.value_handle == 0) {
2360 LOG_DBG("Handle not set");
2361 return -EINVAL;
2362 }
2363
2364 return tbs_client_gatt_read(conn, inst, inst->incoming_call_sub_params.value_handle,
2365 read_remote_uri_cb);
2366 }
2367 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL) */
2368
2369 #if defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME)
bt_tbs_client_read_friendly_name(struct bt_conn * conn,uint8_t inst_index)2370 int bt_tbs_client_read_friendly_name(struct bt_conn *conn, uint8_t inst_index)
2371 {
2372 struct bt_tbs_instance *inst;
2373
2374 if (conn == NULL) {
2375 return -ENOTCONN;
2376 }
2377
2378 inst = tbs_inst_by_index(conn, inst_index);
2379 if (inst == NULL) {
2380 return -EINVAL;
2381 }
2382
2383 if (inst->friendly_name_sub_params.value_handle == 0) {
2384 LOG_DBG("Handle not set");
2385 return -EINVAL;
2386 }
2387
2388 return tbs_client_gatt_read(conn, inst, inst->friendly_name_sub_params.value_handle,
2389 read_friendly_name_cb);
2390 }
2391 #endif /* defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME) */
2392
check_and_set_all_busy(struct bt_tbs_server_inst * srv_inst)2393 static bool check_and_set_all_busy(struct bt_tbs_server_inst *srv_inst)
2394 {
2395 bool all_idle = true;
2396
2397 #if defined(CONFIG_BT_TBS_CLIENT_GTBS)
2398 if (atomic_test_and_set_bit(srv_inst->gtbs_inst.flags, BT_TBS_CLIENT_FLAG_BUSY)) {
2399 LOG_DBG("GTBS is busy");
2400
2401 return false;
2402 }
2403 #endif /* CONFIG_BT_TBS_CLIENT_GTBS */
2404
2405 #if defined(CONFIG_BT_TBS_CLIENT_TBS)
2406 size_t num_free;
2407
2408 for (num_free = 0U; num_free < ARRAY_SIZE(srv_inst->tbs_insts); num_free++) {
2409 struct bt_tbs_instance *tbs_inst = &srv_inst->tbs_insts[num_free];
2410
2411 if (atomic_test_and_set_bit(tbs_inst->flags, BT_TBS_CLIENT_FLAG_BUSY)) {
2412 LOG_DBG("inst[%zu] (%p) is busy", num_free, tbs_inst);
2413 all_idle = false;
2414
2415 break;
2416 }
2417 }
2418 #endif /* CONFIG_BT_TBS_CLIENT_TBS */
2419
2420 /* If any is busy, revert any busy states we've set */
2421 if (!all_idle) {
2422 #if defined(CONFIG_BT_TBS_CLIENT_GTBS)
2423 atomic_clear_bit(srv_inst->gtbs_inst.flags, BT_TBS_CLIENT_FLAG_BUSY);
2424 #endif /* CONFIG_BT_TBS_CLIENT_GTBS */
2425 #if defined(CONFIG_BT_TBS_CLIENT_TBS)
2426 for (uint8_t i = 0U; i < num_free; i++) {
2427 atomic_clear_bit(srv_inst->tbs_insts[i].flags, BT_TBS_CLIENT_FLAG_BUSY);
2428 }
2429 #endif /* CONFIG_BT_TBS_CLIENT_TBS */
2430 }
2431
2432 return all_idle;
2433 }
2434
bt_tbs_client_discover(struct bt_conn * conn)2435 int bt_tbs_client_discover(struct bt_conn *conn)
2436 {
2437 uint8_t conn_index;
2438 struct bt_tbs_server_inst *srv_inst;
2439
2440 if (conn == NULL) {
2441 return -ENOTCONN;
2442 }
2443
2444 conn_index = bt_conn_index(conn);
2445 srv_inst = &srv_insts[conn_index];
2446
2447 /* Before we do discovery we ensure that all TBS instances are currently not busy as to not
2448 * interfere with any procedures in progress
2449 */
2450 if (!check_and_set_all_busy(srv_inst)) {
2451 return -EBUSY;
2452 }
2453
2454 #if defined(CONFIG_BT_TBS_CLIENT_TBS)
2455 (void)memset(srv_inst->tbs_insts, 0, sizeof(srv_inst->tbs_insts)); /* reset data */
2456 srv_inst->inst_cnt = 0;
2457 #endif /* CONFIG_BT_TBS_CLIENT_TBS */
2458 #if defined(CONFIG_BT_TBS_CLIENT_GTBS)
2459 (void)memset(&srv_inst->gtbs_inst, 0, sizeof(srv_inst->gtbs_inst)); /* reset data */
2460 return primary_discover_gtbs(conn);
2461 #else
2462 return primary_discover_tbs(conn);
2463 #endif /* CONFIG_BT_TBS_CLIENT_GTBS */
2464 }
2465
bt_tbs_client_register_cb(struct bt_tbs_client_cb * cb)2466 int bt_tbs_client_register_cb(struct bt_tbs_client_cb *cb)
2467 {
2468 CHECKIF(cb == NULL) {
2469 LOG_DBG("cb is NULL");
2470
2471 return -EINVAL;
2472 }
2473
2474 if (sys_slist_find(&tbs_client_cbs, &cb->_node, NULL)) {
2475 return -EEXIST;
2476 }
2477
2478 sys_slist_append(&tbs_client_cbs, &cb->_node);
2479
2480 return 0;
2481 }
2482
2483 #if defined(CONFIG_BT_TBS_CLIENT_CCID)
tbs_instance_ccid_is_eq(struct bt_tbs_instance * inst,void * user_data)2484 static bool tbs_instance_ccid_is_eq(struct bt_tbs_instance *inst, void *user_data)
2485 {
2486 uint8_t ccid = POINTER_TO_UINT(user_data);
2487
2488 return inst->ccid == ccid;
2489 }
2490
bt_tbs_client_get_by_ccid(const struct bt_conn * conn,uint8_t ccid)2491 struct bt_tbs_instance *bt_tbs_client_get_by_ccid(const struct bt_conn *conn,
2492 uint8_t ccid)
2493 {
2494 struct bt_tbs_server_inst *server;
2495
2496 CHECKIF(conn == NULL) {
2497 LOG_DBG("conn was NULL");
2498 return NULL;
2499 }
2500
2501 server = &srv_insts[bt_conn_index(conn)];
2502
2503 return tbs_instance_find(server, tbs_instance_ccid_is_eq, UINT_TO_POINTER(ccid));
2504 }
2505 #endif /* defined(CONFIG_BT_TBS_CLIENT_CCID) */
2506