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