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