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_ATT_TX_COUNT >= TBS_CLIENT_BUF_COUNT, "Too few ATT 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
1543 err = bt_gatt_subscribe(conn, sub_params);
1544 if (err != 0 && err != -EALREADY) {
1545 LOG_DBG("Could not subscribe to "
1546 "characterstic at handle 0x%04X"
1547 "(%d)",
1548 sub_params->value_handle, err);
1549 tbs_client_discover_complete(conn, err);
1550
1551 return BT_GATT_ITER_STOP;
1552 } else {
1553 LOG_DBG("Subscribed to characterstic at "
1554 "handle 0x%04X",
1555 sub_params->value_handle);
1556 }
1557 }
1558 }
1559 }
1560
1561 return BT_GATT_ITER_CONTINUE;
1562 }
1563
get_next_instance(struct bt_conn * conn,struct bt_tbs_server_inst * srv_inst)1564 static struct bt_tbs_instance *get_next_instance(struct bt_conn *conn,
1565 struct bt_tbs_server_inst *srv_inst)
1566 {
1567 uint8_t inst_index;
1568
1569 if (srv_inst->current_inst != NULL) {
1570 inst_index = tbs_index(conn, srv_inst->current_inst);
1571 if (inst_index == BT_TBS_GTBS_INDEX) {
1572 inst_index = 0;
1573 } else {
1574 inst_index++;
1575 }
1576
1577 return tbs_inst_by_index(conn, inst_index);
1578 }
1579
1580 inst_index = gtbs_found(srv_inst) ? BT_TBS_GTBS_INDEX : 0;
1581
1582 return tbs_inst_by_index(conn, inst_index);
1583 }
1584
discover_next_instance(struct bt_conn * conn)1585 static void discover_next_instance(struct bt_conn *conn)
1586 {
1587 int err;
1588 uint8_t conn_index = bt_conn_index(conn);
1589 struct bt_tbs_server_inst *srv_inst = &srv_insts[conn_index];
1590
1591 srv_inst->current_inst = get_next_instance(conn, srv_inst);
1592 if (srv_inst->current_inst == NULL) {
1593 tbs_client_discover_complete(conn, 0);
1594 return;
1595 }
1596
1597 LOG_DBG("inst_index %u", tbs_index(conn, srv_inst->current_inst));
1598
1599 (void)memset(&srv_inst->discover_params, 0, sizeof(srv_inst->discover_params));
1600 srv_inst->discover_params.uuid = NULL;
1601 srv_inst->discover_params.start_handle = srv_inst->current_inst->start_handle;
1602 srv_inst->discover_params.end_handle = srv_inst->current_inst->end_handle;
1603 srv_inst->discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
1604 srv_inst->discover_params.func = discover_func;
1605
1606 err = bt_gatt_discover(conn, &srv_inst->discover_params);
1607 if (err != 0) {
1608 tbs_client_discover_complete(conn, err);
1609 }
1610 }
1611
primary_discover_complete(struct bt_tbs_server_inst * server,struct bt_conn * conn)1612 static void primary_discover_complete(struct bt_tbs_server_inst *server, struct bt_conn *conn)
1613 {
1614 if (IS_ENABLED(CONFIG_BT_TBS_CLIENT_GTBS)) {
1615 LOG_DBG("Discover complete, found %u instances (GTBS%s found)",
1616 inst_cnt(server), gtbs_found(server) ? "" : " not");
1617 } else {
1618 LOG_DBG("Discover complete, found %u instances", inst_cnt(server));
1619 }
1620
1621 server->current_inst = NULL;
1622
1623 if (gtbs_found(server) || inst_cnt(server) > 0) {
1624 discover_next_instance(conn);
1625 } else {
1626 tbs_client_discover_complete(conn, 0);
1627 }
1628 }
1629
1630 /**
1631 * @brief This will discover all characteristics on the server, retrieving the
1632 * handles of the writeable characteristics and subscribing to all notify and
1633 * indicate characteristics.
1634 */
1635 #if defined(CONFIG_BT_TBS_CLIENT_TBS)
1636 static const struct bt_uuid *tbs_uuid = BT_UUID_TBS;
1637
primary_discover_tbs_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)1638 static uint8_t primary_discover_tbs_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr,
1639 struct bt_gatt_discover_params *params)
1640 {
1641 const uint8_t conn_index = bt_conn_index(conn);
1642 struct bt_tbs_server_inst *srv_inst = &srv_insts[conn_index];
1643
1644 LOG_DBG("conn %p attr %p", (void *)conn, attr);
1645
1646 if (attr != NULL) {
1647 const struct bt_gatt_service_val *prim_service;
1648
1649 LOG_DBG("[ATTRIBUTE] handle 0x%04X", attr->handle);
1650
1651 prim_service = (struct bt_gatt_service_val *)attr->user_data;
1652
1653 srv_inst->current_inst = &srv_inst->tbs_insts[srv_inst->inst_cnt++];
1654 srv_inst->current_inst->start_handle = attr->handle + 1;
1655 srv_inst->current_inst->end_handle = prim_service->end_handle;
1656
1657 if (srv_inst->inst_cnt < ARRAY_SIZE(srv_inst->tbs_insts)) {
1658 return BT_GATT_ITER_CONTINUE;
1659 }
1660 }
1661
1662 primary_discover_complete(srv_inst, conn);
1663
1664 return BT_GATT_ITER_STOP;
1665 }
1666
primary_discover_tbs(struct bt_conn * conn)1667 static int primary_discover_tbs(struct bt_conn *conn)
1668 {
1669 struct bt_tbs_server_inst *srv_inst = &srv_insts[bt_conn_index(conn)];
1670 struct bt_gatt_discover_params *params = &srv_inst->discover_params;
1671
1672 LOG_DBG("conn %p", (void *)conn);
1673
1674 (void)memset(params, 0, sizeof(*params));
1675 params->uuid = tbs_uuid;
1676 params->func = primary_discover_tbs_cb;
1677 params->type = BT_GATT_DISCOVER_PRIMARY;
1678 params->start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
1679 params->end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
1680
1681 return bt_gatt_discover(conn, params);
1682 }
1683 #endif /* CONFIG_BT_TBS_CLIENT_TBS */
1684
1685 #if defined(CONFIG_BT_TBS_CLIENT_GTBS)
1686 static const struct bt_uuid *gtbs_uuid = BT_UUID_GTBS;
1687
primary_discover_gtbs_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)1688 static uint8_t primary_discover_gtbs_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr,
1689 struct bt_gatt_discover_params *params)
1690 {
1691 const uint8_t conn_index = bt_conn_index(conn);
1692 struct bt_tbs_server_inst *srv_inst = &srv_insts[conn_index];
1693
1694 LOG_DBG("conn %p attr %p", (void *)conn, attr);
1695
1696 if (attr != NULL) {
1697 const struct bt_gatt_service_val *prim_service;
1698
1699 LOG_DBG("[ATTRIBUTE] handle 0x%04X", attr->handle);
1700
1701 prim_service = (struct bt_gatt_service_val *)attr->user_data;
1702
1703 srv_inst->current_inst = &srv_inst->gtbs_inst;
1704 srv_inst->current_inst->start_handle = attr->handle + 1;
1705 srv_inst->current_inst->end_handle = prim_service->end_handle;
1706 }
1707
1708 #if defined(CONFIG_BT_TBS_CLIENT_TBS)
1709 int err;
1710
1711 err = primary_discover_tbs(conn);
1712 if (err == 0) {
1713 return BT_GATT_ITER_STOP;
1714 }
1715
1716 LOG_DBG("Discover failed (err %d)", err);
1717 #endif /* CONFIG_BT_TBS_CLIENT_TBS */
1718
1719 primary_discover_complete(srv_inst, conn);
1720
1721 return BT_GATT_ITER_STOP;
1722 }
1723
primary_discover_gtbs(struct bt_conn * conn)1724 static int primary_discover_gtbs(struct bt_conn *conn)
1725 {
1726 struct bt_tbs_server_inst *srv_inst = &srv_insts[bt_conn_index(conn)];
1727 struct bt_gatt_discover_params *params = &srv_inst->discover_params;
1728
1729 LOG_DBG("conn %p", (void *)conn);
1730
1731 (void)memset(params, 0, sizeof(*params));
1732 params->uuid = gtbs_uuid;
1733 params->func = primary_discover_gtbs_cb;
1734 params->type = BT_GATT_DISCOVER_PRIMARY;
1735 params->start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
1736 params->end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
1737
1738 return bt_gatt_discover(conn, params);
1739 }
1740 #endif /* IS_ENABLED(CONFIG_BT_TBS_CLIENT_GTBS) */
1741
1742 /****************************** PUBLIC API ******************************/
1743
1744 #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)1745 int bt_tbs_client_hold_call(struct bt_conn *conn, uint8_t inst_index,
1746 uint8_t call_index)
1747 {
1748 return tbs_client_common_call_control(conn, inst_index, call_index,
1749 BT_TBS_CALL_OPCODE_HOLD);
1750 }
1751 #endif /* defined(CONFIG_BT_TBS_CLIENT_HOLD_CALL) */
1752
1753 #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)1754 int bt_tbs_client_accept_call(struct bt_conn *conn, uint8_t inst_index,
1755 uint8_t call_index)
1756 {
1757 return tbs_client_common_call_control(conn, inst_index, call_index,
1758 BT_TBS_CALL_OPCODE_ACCEPT);
1759 }
1760 #endif /* defined(CONFIG_BT_TBS_CLIENT_ACCEPT_CALL) */
1761
1762 #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)1763 int bt_tbs_client_retrieve_call(struct bt_conn *conn, uint8_t inst_index,
1764 uint8_t call_index)
1765 {
1766 return tbs_client_common_call_control(conn, inst_index, call_index,
1767 BT_TBS_CALL_OPCODE_RETRIEVE);
1768 }
1769 #endif /* defined(CONFIG_BT_TBS_CLIENT_RETRIEVE_CALL) */
1770
1771 #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)1772 int bt_tbs_client_terminate_call(struct bt_conn *conn, uint8_t inst_index,
1773 uint8_t call_index)
1774 {
1775 return tbs_client_common_call_control(conn, inst_index, call_index,
1776 BT_TBS_CALL_OPCODE_TERMINATE);
1777 }
1778 #endif /* defined(CONFIG_BT_TBS_CLIENT_TERMINATE_CALL) */
1779
1780 #if defined(CONFIG_BT_TBS_CLIENT_ORIGINATE_CALL)
bt_tbs_client_originate_call(struct bt_conn * conn,uint8_t inst_index,const char * uri)1781 int bt_tbs_client_originate_call(struct bt_conn *conn, uint8_t inst_index,
1782 const char *uri)
1783 {
1784 struct bt_tbs_instance *inst;
1785 uint8_t write_buf[CONFIG_BT_L2CAP_TX_MTU];
1786 struct bt_tbs_call_cp_originate *originate;
1787 size_t uri_len;
1788 const size_t max_uri_len = sizeof(write_buf) - sizeof(*originate);
1789
1790 if (conn == NULL) {
1791 return -ENOTCONN;
1792 } else if (!bt_tbs_valid_uri(uri, strlen(uri))) {
1793 LOG_DBG("Invalid URI: %s", uri);
1794 return -EINVAL;
1795 }
1796
1797 inst = tbs_inst_by_index(conn, inst_index);
1798 if (inst == NULL) {
1799 return -EINVAL;
1800 }
1801
1802 /* Check if there are free spots */
1803 if (!free_call_spot(inst)) {
1804 LOG_DBG("Cannot originate more calls");
1805 return -ENOMEM;
1806 }
1807
1808 uri_len = strlen(uri);
1809
1810 if (uri_len > max_uri_len) {
1811 LOG_DBG("URI len (%zu) longer than maximum writable %zu", uri_len, max_uri_len);
1812 return -ENOMEM;
1813 }
1814
1815 originate = (struct bt_tbs_call_cp_originate *)write_buf;
1816 originate->opcode = BT_TBS_CALL_OPCODE_ORIGINATE;
1817 (void)memcpy(originate->uri, uri, uri_len);
1818
1819 return bt_gatt_write_without_response(conn, inst->call_cp_sub_params.value_handle,
1820 originate,
1821 sizeof(*originate) + uri_len,
1822 false);
1823 }
1824 #endif /* defined(CONFIG_BT_TBS_CLIENT_ORIGINATE_CALL) */
1825
1826 #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)1827 int bt_tbs_client_join_calls(struct bt_conn *conn, uint8_t inst_index,
1828 const uint8_t *call_indexes, uint8_t count)
1829 {
1830 if (conn == NULL) {
1831 return -ENOTCONN;
1832 }
1833
1834 /* Write to call control point */
1835 if (call_indexes && count > 1 &&
1836 count <= CONFIG_BT_TBS_CLIENT_MAX_CALLS) {
1837 struct bt_tbs_instance *inst;
1838 struct bt_tbs_call_cp_join *join;
1839 uint8_t write_buf[CONFIG_BT_L2CAP_TX_MTU];
1840 const size_t max_call_cnt = sizeof(write_buf) - sizeof(join->opcode);
1841
1842 inst = tbs_inst_by_index(conn, inst_index);
1843 if (inst == NULL) {
1844 return -EINVAL;
1845 }
1846
1847 if (inst->call_cp_sub_params.value_handle == 0) {
1848 LOG_DBG("Handle not set");
1849 return -EINVAL;
1850 }
1851
1852 if (count > max_call_cnt) {
1853 LOG_DBG("Call count (%u) larger than maximum writable %zu", count,
1854 max_call_cnt);
1855 return -ENOMEM;
1856 }
1857
1858 join = (struct bt_tbs_call_cp_join *)write_buf;
1859
1860 join->opcode = BT_TBS_CALL_OPCODE_JOIN;
1861 (void)memcpy(join->call_indexes, call_indexes, count);
1862
1863 return bt_gatt_write_without_response(conn,
1864 inst->call_cp_sub_params.value_handle,
1865 join,
1866 sizeof(*join) + count,
1867 false);
1868 }
1869
1870 return -EINVAL;
1871 }
1872 #endif /* defined(CONFIG_BT_TBS_CLIENT_JOIN_CALLS) */
1873
1874 #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)1875 int bt_tbs_client_set_signal_strength_interval(struct bt_conn *conn,
1876 uint8_t inst_index,
1877 uint8_t interval)
1878 {
1879 struct bt_tbs_instance *inst;
1880
1881 if (conn == NULL) {
1882 return -ENOTCONN;
1883 }
1884
1885 inst = tbs_inst_by_index(conn, inst_index);
1886 if (inst == NULL) {
1887 return -EINVAL;
1888 }
1889
1890 /* Populate Outgoing Remote URI */
1891 if (inst->signal_interval_handle == 0) {
1892 LOG_DBG("Handle not set");
1893 return -EINVAL;
1894 }
1895
1896 return bt_gatt_write_without_response(conn,
1897 inst->signal_interval_handle,
1898 &interval, sizeof(interval),
1899 false);
1900 }
1901 #endif /* defined(CONFIG_BT_TBS_CLIENT_SET_BEARER_SIGNAL_INTERVAL) */
1902
1903 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)
bt_tbs_client_read_bearer_provider_name(struct bt_conn * conn,uint8_t inst_index)1904 int bt_tbs_client_read_bearer_provider_name(struct bt_conn *conn,
1905 uint8_t inst_index)
1906 {
1907 struct bt_tbs_instance *inst;
1908
1909 if (conn == NULL) {
1910 return -ENOTCONN;
1911 }
1912
1913 inst = tbs_inst_by_index(conn, inst_index);
1914 if (inst == NULL) {
1915 return -EINVAL;
1916 }
1917
1918 if (inst->name_sub_params.value_handle == 0) {
1919 LOG_DBG("Handle not set");
1920 return -EINVAL;
1921 }
1922
1923 return tbs_client_gatt_read(conn, inst, inst->name_sub_params.value_handle,
1924 read_bearer_provider_name_cb);
1925 }
1926 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME) */
1927
1928 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI)
bt_tbs_client_read_bearer_uci(struct bt_conn * conn,uint8_t inst_index)1929 int bt_tbs_client_read_bearer_uci(struct bt_conn *conn, uint8_t inst_index)
1930 {
1931 struct bt_tbs_instance *inst;
1932
1933 if (conn == NULL) {
1934 return -ENOTCONN;
1935 }
1936
1937 inst = tbs_inst_by_index(conn, inst_index);
1938 if (inst == NULL) {
1939 return -EINVAL;
1940 }
1941
1942 if (inst->bearer_uci_handle == 0) {
1943 LOG_DBG("Handle not set");
1944 return -EINVAL;
1945 }
1946
1947 return tbs_client_gatt_read(conn, inst, inst->bearer_uci_handle, read_bearer_uci_cb);
1948 }
1949 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI) */
1950
1951 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY)
bt_tbs_client_read_technology(struct bt_conn * conn,uint8_t inst_index)1952 int bt_tbs_client_read_technology(struct bt_conn *conn, uint8_t inst_index)
1953 {
1954 struct bt_tbs_instance *inst;
1955
1956 if (conn == NULL) {
1957 return -ENOTCONN;
1958 }
1959
1960 inst = tbs_inst_by_index(conn, inst_index);
1961 if (inst == NULL) {
1962 return -EINVAL;
1963 }
1964
1965 if (inst->technology_sub_params.value_handle == 0) {
1966 LOG_DBG("Handle not set");
1967 return -EINVAL;
1968 }
1969
1970 return tbs_client_gatt_read(conn, inst, inst->technology_sub_params.value_handle,
1971 read_technology_cb);
1972 }
1973 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY) */
1974
1975 #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)1976 int bt_tbs_client_read_uri_list(struct bt_conn *conn, uint8_t inst_index)
1977 {
1978 struct bt_tbs_instance *inst;
1979
1980 if (conn == NULL) {
1981 return -ENOTCONN;
1982 }
1983
1984 inst = tbs_inst_by_index(conn, inst_index);
1985 if (inst == NULL) {
1986 return -EINVAL;
1987 }
1988
1989 if (inst->uri_list_handle == 0) {
1990 LOG_DBG("Handle not set");
1991 return -EINVAL;
1992 }
1993
1994 return tbs_client_gatt_read(conn, inst, inst->uri_list_handle, read_uri_list_cb);
1995 }
1996 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST) */
1997
1998 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH)
bt_tbs_client_read_signal_strength(struct bt_conn * conn,uint8_t inst_index)1999 int bt_tbs_client_read_signal_strength(struct bt_conn *conn, uint8_t inst_index)
2000 {
2001 struct bt_tbs_instance *inst;
2002
2003 if (conn == NULL) {
2004 return -ENOTCONN;
2005 }
2006
2007 inst = tbs_inst_by_index(conn, inst_index);
2008 if (inst == NULL) {
2009 return -EINVAL;
2010 }
2011
2012 if (inst->signal_strength_sub_params.value_handle == 0) {
2013 LOG_DBG("Handle not set");
2014 return -EINVAL;
2015 }
2016
2017 return tbs_client_gatt_read(conn, inst, inst->signal_strength_sub_params.value_handle,
2018 read_signal_strength_cb);
2019 }
2020 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH) */
2021
2022 #if defined(CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL)
bt_tbs_client_read_signal_interval(struct bt_conn * conn,uint8_t inst_index)2023 int bt_tbs_client_read_signal_interval(struct bt_conn *conn, uint8_t inst_index)
2024 {
2025 struct bt_tbs_instance *inst;
2026
2027 if (conn == NULL) {
2028 return -ENOTCONN;
2029 }
2030
2031 inst = tbs_inst_by_index(conn, inst_index);
2032 if (inst == NULL) {
2033 return -EINVAL;
2034 }
2035
2036 if (inst->signal_interval_handle == 0) {
2037 LOG_DBG("Handle not set");
2038 return -EINVAL;
2039 }
2040
2041 return tbs_client_gatt_read(conn, inst, inst->signal_interval_handle,
2042 read_signal_interval_cb);
2043 }
2044 #endif /* defined(CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL) */
2045
2046 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS)
bt_tbs_client_read_current_calls(struct bt_conn * conn,uint8_t inst_index)2047 int bt_tbs_client_read_current_calls(struct bt_conn *conn, uint8_t inst_index)
2048 {
2049 struct bt_tbs_instance *inst;
2050
2051 if (conn == NULL) {
2052 return -ENOTCONN;
2053 }
2054
2055 inst = tbs_inst_by_index(conn, inst_index);
2056 if (inst == NULL) {
2057 return -EINVAL;
2058 }
2059
2060 if (inst->current_calls_sub_params.value_handle == 0) {
2061 LOG_DBG("Handle not set");
2062 return -EINVAL;
2063 }
2064
2065 return tbs_client_gatt_read(conn, inst, inst->current_calls_sub_params.value_handle,
2066 read_current_calls_cb);
2067 }
2068 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) */
2069
2070 #if defined(CONFIG_BT_TBS_CLIENT_CCID)
bt_tbs_client_read_ccid(struct bt_conn * conn,uint8_t inst_index)2071 int bt_tbs_client_read_ccid(struct bt_conn *conn, uint8_t inst_index)
2072 {
2073 struct bt_tbs_instance *inst;
2074
2075 if (conn == NULL) {
2076 return -ENOTCONN;
2077 }
2078
2079 inst = tbs_inst_by_index(conn, inst_index);
2080 if (inst == NULL) {
2081 return -EINVAL;
2082 }
2083
2084 if (inst->ccid_handle == 0) {
2085 LOG_DBG("Handle not set");
2086 return -EINVAL;
2087 }
2088
2089 return tbs_client_gatt_read(conn, inst, inst->ccid_handle, read_ccid_cb);
2090 }
2091 #endif /* defined(CONFIG_BT_TBS_CLIENT_CCID) */
2092
2093 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI)
bt_tbs_client_read_call_uri(struct bt_conn * conn,uint8_t inst_index)2094 int bt_tbs_client_read_call_uri(struct bt_conn *conn, uint8_t inst_index)
2095 {
2096 struct bt_tbs_instance *inst;
2097
2098 if (conn == NULL) {
2099 return -ENOTCONN;
2100 }
2101
2102 inst = tbs_inst_by_index(conn, inst_index);
2103 if (inst == NULL) {
2104 return -EINVAL;
2105 }
2106
2107 if (inst->in_target_uri_sub_params.value_handle == 0) {
2108 LOG_DBG("Handle not set");
2109 return -EINVAL;
2110 }
2111
2112 return tbs_client_gatt_read(conn, inst, inst->in_target_uri_sub_params.value_handle,
2113 read_call_uri_cb);
2114 }
2115 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI) */
2116
2117 #if defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS)
bt_tbs_client_read_status_flags(struct bt_conn * conn,uint8_t inst_index)2118 int bt_tbs_client_read_status_flags(struct bt_conn *conn, uint8_t inst_index)
2119 {
2120 struct bt_tbs_instance *inst;
2121
2122 if (conn == NULL) {
2123 return -ENOTCONN;
2124 }
2125
2126 inst = tbs_inst_by_index(conn, inst_index);
2127 if (inst == NULL) {
2128 return -EINVAL;
2129 }
2130
2131 if (inst->status_flags_sub_params.value_handle == 0) {
2132 LOG_DBG("Handle not set");
2133 return -EINVAL;
2134 }
2135
2136 return tbs_client_gatt_read(conn, inst, inst->status_flags_sub_params.value_handle,
2137 read_status_flags_cb);
2138 }
2139 #endif /* defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS) */
2140
bt_tbs_client_read_call_state(struct bt_conn * conn,uint8_t inst_index)2141 int bt_tbs_client_read_call_state(struct bt_conn *conn, uint8_t inst_index)
2142 {
2143 struct bt_tbs_instance *inst;
2144
2145 if (conn == NULL) {
2146 return -ENOTCONN;
2147 }
2148
2149 inst = tbs_inst_by_index(conn, inst_index);
2150 if (inst == NULL) {
2151 return -EINVAL;
2152 }
2153
2154 if (inst->call_state_sub_params.value_handle == 0) {
2155 LOG_DBG("Handle not set");
2156 return -EINVAL;
2157 }
2158
2159 return tbs_client_gatt_read(conn, inst, inst->call_state_sub_params.value_handle,
2160 read_call_state_cb);
2161 }
2162
2163 #if defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES)
bt_tbs_client_read_optional_opcodes(struct bt_conn * conn,uint8_t inst_index)2164 int bt_tbs_client_read_optional_opcodes(struct bt_conn *conn,
2165 uint8_t inst_index)
2166 {
2167 struct bt_tbs_instance *inst;
2168
2169 if (conn == NULL) {
2170 return -ENOTCONN;
2171 }
2172
2173 inst = tbs_inst_by_index(conn, inst_index);
2174 if (inst == NULL) {
2175 return -EINVAL;
2176 }
2177
2178 if (inst->optional_opcodes_handle == 0) {
2179 LOG_DBG("Handle not set");
2180 return -EINVAL;
2181 }
2182
2183 return tbs_client_gatt_read(conn, inst, inst->optional_opcodes_handle,
2184 read_optional_opcodes_cb);
2185 }
2186 #endif /* defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES) */
2187
2188 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL)
bt_tbs_client_read_remote_uri(struct bt_conn * conn,uint8_t inst_index)2189 int bt_tbs_client_read_remote_uri(struct bt_conn *conn, uint8_t inst_index)
2190 {
2191 struct bt_tbs_instance *inst;
2192
2193 if (conn == NULL) {
2194 return -ENOTCONN;
2195 }
2196
2197 inst = tbs_inst_by_index(conn, inst_index);
2198 if (inst == NULL) {
2199 return -EINVAL;
2200 }
2201
2202 if (inst->incoming_call_sub_params.value_handle == 0) {
2203 LOG_DBG("Handle not set");
2204 return -EINVAL;
2205 }
2206
2207 return tbs_client_gatt_read(conn, inst, inst->incoming_call_sub_params.value_handle,
2208 read_remote_uri_cb);
2209 }
2210 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL) */
2211
2212 #if defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME)
bt_tbs_client_read_friendly_name(struct bt_conn * conn,uint8_t inst_index)2213 int bt_tbs_client_read_friendly_name(struct bt_conn *conn, uint8_t inst_index)
2214 {
2215 struct bt_tbs_instance *inst;
2216
2217 if (conn == NULL) {
2218 return -ENOTCONN;
2219 }
2220
2221 inst = tbs_inst_by_index(conn, inst_index);
2222 if (inst == NULL) {
2223 return -EINVAL;
2224 }
2225
2226 if (inst->friendly_name_sub_params.value_handle == 0) {
2227 LOG_DBG("Handle not set");
2228 return -EINVAL;
2229 }
2230
2231 return tbs_client_gatt_read(conn, inst, inst->friendly_name_sub_params.value_handle,
2232 read_friendly_name_cb);
2233 }
2234 #endif /* defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME) */
2235
bt_tbs_client_discover(struct bt_conn * conn)2236 int bt_tbs_client_discover(struct bt_conn *conn)
2237 {
2238 uint8_t conn_index;
2239 struct bt_tbs_server_inst *srv_inst;
2240
2241 if (conn == NULL) {
2242 return -ENOTCONN;
2243 }
2244
2245 conn_index = bt_conn_index(conn);
2246 srv_inst = &srv_insts[conn_index];
2247
2248 if (srv_inst->current_inst) {
2249 return -EBUSY;
2250 }
2251
2252 #if defined(CONFIG_BT_TBS_CLIENT_TBS)
2253 (void)memset(srv_inst->tbs_insts, 0, sizeof(srv_inst->tbs_insts)); /* reset data */
2254 srv_inst->inst_cnt = 0;
2255 #endif /* CONFIG_BT_TBS_CLIENT_TBS */
2256 #if defined(CONFIG_BT_TBS_CLIENT_GTBS)
2257 (void)memset(&srv_inst->gtbs_inst, 0, sizeof(srv_inst->gtbs_inst)); /* reset data */
2258 return primary_discover_gtbs(conn);
2259 #else
2260 return primary_discover_tbs(conn);
2261 #endif /* CONFIG_BT_TBS_CLIENT_GTBS */
2262 }
2263
bt_tbs_client_register_cb(const struct bt_tbs_client_cb * cbs)2264 void bt_tbs_client_register_cb(const struct bt_tbs_client_cb *cbs)
2265 {
2266 tbs_client_cbs = cbs;
2267 }
2268
2269 #if defined(CONFIG_BT_TBS_CLIENT_CCID)
tbs_instance_ccid_is_eq(struct bt_tbs_instance * inst,void * user_data)2270 static bool tbs_instance_ccid_is_eq(struct bt_tbs_instance *inst, void *user_data)
2271 {
2272 uint8_t ccid = POINTER_TO_UINT(user_data);
2273
2274 return inst->ccid == ccid;
2275 }
2276
bt_tbs_client_get_by_ccid(const struct bt_conn * conn,uint8_t ccid)2277 struct bt_tbs_instance *bt_tbs_client_get_by_ccid(const struct bt_conn *conn,
2278 uint8_t ccid)
2279 {
2280 struct bt_tbs_server_inst *server;
2281
2282 CHECKIF(conn == NULL) {
2283 LOG_DBG("conn was NULL");
2284 return NULL;
2285 }
2286
2287 server = &srv_insts[bt_conn_index(conn)];
2288
2289 return tbs_instance_find(server, tbs_instance_ccid_is_eq, UINT_TO_POINTER(ccid));
2290 }
2291 #endif /* defined(CONFIG_BT_TBS_CLIENT_CCID) */
2292