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