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