Bluetooth: TBS: Allow multiple callbacks for client
The TBS client callbacks are just informative so we provide the information to multiple listeners. To support this for the long strings, the function handle_string_long_read was refactored. This also allows for multiple users of the TBS client. Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
parent
94e548120b
commit
57b35e1047
8 changed files with 420 additions and 249 deletions
|
@ -78,6 +78,8 @@ Bluetooth
|
|||
|
||||
* Audio
|
||||
|
||||
* :c:func:`bt_tbs_client_register_cb` now supports multiple listeners and may now return an error.
|
||||
|
||||
* Host
|
||||
|
||||
* Added API :c:func:`bt_gatt_get_uatt_mtu` to get current Unenhanced ATT MTU of a given
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#include <zephyr/bluetooth/conn.h>
|
||||
#include <zephyr/sys/slist.h>
|
||||
#include <zephyr/sys/util_macro.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -680,6 +681,9 @@ struct bt_tbs_client_cb {
|
|||
/** Bearer friendly name has been read */
|
||||
bt_tbs_client_read_string_cb friendly_name;
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME) */
|
||||
|
||||
/** @internal Internally used field for list handling */
|
||||
sys_snode_t _node;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -998,8 +1002,12 @@ int bt_tbs_client_read_optional_opcodes(struct bt_conn *conn,
|
|||
* @brief Register the callbacks for CCP.
|
||||
*
|
||||
* @param cbs Pointer to the callback structure.
|
||||
*
|
||||
* @retval 0 Success
|
||||
* @retval -EINVAL @p cbs is NULL
|
||||
* @retval -EEXIST @p cbs is already registered
|
||||
*/
|
||||
void bt_tbs_client_register_cb(const struct bt_tbs_client_cb *cbs);
|
||||
int bt_tbs_client_register_cb(struct bt_tbs_client_cb *cbs);
|
||||
|
||||
/**
|
||||
* @brief Look up Telephone Bearer Service instance by CCID
|
||||
|
|
|
@ -155,7 +155,5 @@ struct bt_tbs_client_cb tbs_client_cb = {
|
|||
|
||||
int ccp_call_ctrl_init(void)
|
||||
{
|
||||
bt_tbs_client_register_cb(&tbs_client_cb);
|
||||
|
||||
return 0;
|
||||
return bt_tbs_client_register_cb(&tbs_client_cb);
|
||||
}
|
||||
|
|
|
@ -124,7 +124,11 @@ int ccp_call_ctrl_init(struct bt_conn *conn)
|
|||
int err;
|
||||
|
||||
default_conn = bt_conn_ref(conn);
|
||||
bt_tbs_client_register_cb(&tbs_client_cb);
|
||||
err = bt_tbs_client_register_cb(&tbs_client_cb);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_discover(conn);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Bluetooth TBS - Telephone Bearer Service - Client
|
||||
*
|
||||
* Copyright (c) 2020 Bose Corporation
|
||||
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2021-2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -26,6 +26,7 @@
|
|||
#include <zephyr/net/buf.h>
|
||||
#include <zephyr/sys/__assert.h>
|
||||
#include <zephyr/sys/atomic.h>
|
||||
#include <zephyr/sys/slist.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/sys/util_macro.h>
|
||||
#include <zephyr/toolchain.h>
|
||||
|
@ -68,7 +69,7 @@ struct bt_tbs_server_inst {
|
|||
struct bt_tbs_instance *current_inst;
|
||||
};
|
||||
|
||||
static const struct bt_tbs_client_cb *tbs_client_cbs;
|
||||
static sys_slist_t tbs_client_cbs = SYS_SLIST_STATIC_INIT(&tbs_client_cbs);
|
||||
|
||||
static struct bt_tbs_server_inst srv_insts[CONFIG_BT_MAX_CONN];
|
||||
|
||||
|
@ -245,6 +246,18 @@ static uint8_t net_buf_pull_call(struct net_buf_simple *buf,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void current_calls_changed(struct bt_conn *conn, int err, uint8_t inst_index,
|
||||
uint8_t call_count, const struct bt_tbs_client_call *calls)
|
||||
{
|
||||
struct bt_tbs_client_cb *listener, *next;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
|
||||
if (listener->current_calls != NULL) {
|
||||
listener->current_calls(conn, err, inst_index, call_count, calls);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void bearer_list_current_calls(struct bt_conn *conn, const struct bt_tbs_instance *inst,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
|
@ -276,9 +289,7 @@ static void bearer_list_current_calls(struct bt_conn *conn, const struct bt_tbs_
|
|||
cnt++;
|
||||
}
|
||||
|
||||
if (tbs_client_cbs != NULL && tbs_client_cbs->current_calls != NULL) {
|
||||
tbs_client_cbs->current_calls(conn, 0, tbs_index(conn, inst), cnt, calls);
|
||||
}
|
||||
current_calls_changed(conn, 0, tbs_index(conn, inst), cnt, calls);
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) */
|
||||
|
||||
|
@ -287,52 +298,58 @@ static void call_cp_callback_handler(struct bt_conn *conn, int err,
|
|||
uint8_t index, uint8_t opcode,
|
||||
uint8_t call_index)
|
||||
{
|
||||
bt_tbs_client_cp_cb cp_cb = NULL;
|
||||
struct bt_tbs_client_cb *listener, *next;
|
||||
|
||||
LOG_DBG("Status: %s for the %s opcode for call 0x%02x", bt_tbs_status_str(err),
|
||||
bt_tbs_opcode_str(opcode), call_index);
|
||||
|
||||
if (tbs_client_cbs == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (opcode) {
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
|
||||
switch (opcode) {
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_ACCEPT_CALL)
|
||||
case BT_TBS_CALL_OPCODE_ACCEPT:
|
||||
cp_cb = tbs_client_cbs->accept_call;
|
||||
break;
|
||||
case BT_TBS_CALL_OPCODE_ACCEPT:
|
||||
if (listener->accept_call != NULL) {
|
||||
listener->accept_call(conn, err, index, call_index);
|
||||
}
|
||||
break;
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_ACCEPT_CALL) */
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_TERMINATE_CALL)
|
||||
case BT_TBS_CALL_OPCODE_TERMINATE:
|
||||
cp_cb = tbs_client_cbs->terminate_call;
|
||||
break;
|
||||
case BT_TBS_CALL_OPCODE_TERMINATE:
|
||||
if (listener->terminate_call != NULL) {
|
||||
listener->terminate_call(conn, err, index, call_index);
|
||||
}
|
||||
break;
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_TERMINATE_CALL) */
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_HOLD_CALL)
|
||||
case BT_TBS_CALL_OPCODE_HOLD:
|
||||
cp_cb = tbs_client_cbs->hold_call;
|
||||
break;
|
||||
case BT_TBS_CALL_OPCODE_HOLD:
|
||||
if (listener->hold_call != NULL) {
|
||||
listener->hold_call(conn, err, index, call_index);
|
||||
}
|
||||
break;
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_HOLD_CALL) */
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_RETRIEVE_CALL)
|
||||
case BT_TBS_CALL_OPCODE_RETRIEVE:
|
||||
cp_cb = tbs_client_cbs->retrieve_call;
|
||||
break;
|
||||
case BT_TBS_CALL_OPCODE_RETRIEVE:
|
||||
if (listener->retrieve_call != NULL) {
|
||||
listener->retrieve_call(conn, err, index, call_index);
|
||||
}
|
||||
break;
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_RETRIEVE_CALL) */
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_ORIGINATE_CALL)
|
||||
case BT_TBS_CALL_OPCODE_ORIGINATE:
|
||||
cp_cb = tbs_client_cbs->originate_call;
|
||||
break;
|
||||
case BT_TBS_CALL_OPCODE_ORIGINATE:
|
||||
if (listener->originate_call != NULL) {
|
||||
listener->originate_call(conn, err, index, call_index);
|
||||
}
|
||||
break;
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_ORIGINATE_CALL) */
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_JOIN_CALLS)
|
||||
case BT_TBS_CALL_OPCODE_JOIN:
|
||||
cp_cb = tbs_client_cbs->join_calls;
|
||||
break;
|
||||
case BT_TBS_CALL_OPCODE_JOIN:
|
||||
if (listener->join_calls != NULL) {
|
||||
listener->join_calls(conn, err, index, call_index);
|
||||
}
|
||||
break;
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_JOIN_CALLS) */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (cp_cb != 0) {
|
||||
cp_cb(conn, err, index, call_index);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES) */
|
||||
|
@ -353,6 +370,18 @@ const char *parse_string_value(const void *data, uint16_t length,
|
|||
}
|
||||
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)
|
||||
static void provider_name_changed(struct bt_conn *conn, int err, uint8_t inst_index,
|
||||
const char *name)
|
||||
{
|
||||
struct bt_tbs_client_cb *listener, *next;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
|
||||
if (listener->bearer_provider_name != NULL) {
|
||||
listener->bearer_provider_name(conn, err, inst_index, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void provider_name_notify_handler(struct bt_conn *conn,
|
||||
const struct bt_tbs_instance *tbs_inst,
|
||||
const void *data, uint16_t length)
|
||||
|
@ -362,13 +391,23 @@ static void provider_name_notify_handler(struct bt_conn *conn,
|
|||
|
||||
LOG_DBG("%s", name);
|
||||
|
||||
if (tbs_client_cbs != NULL && tbs_client_cbs->bearer_provider_name != NULL) {
|
||||
tbs_client_cbs->bearer_provider_name(conn, 0, tbs_index(conn, tbs_inst), name);
|
||||
}
|
||||
provider_name_changed(conn, 0, tbs_index(conn, tbs_inst), name);
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME) */
|
||||
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY)
|
||||
static void technology_changed(struct bt_conn *conn, int err, uint8_t inst_index,
|
||||
uint8_t technology)
|
||||
{
|
||||
struct bt_tbs_client_cb *listener, *next;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
|
||||
if (listener->technology != NULL) {
|
||||
listener->technology(conn, err, inst_index, technology);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void technology_notify_handler(struct bt_conn *conn,
|
||||
const struct bt_tbs_instance *tbs_inst,
|
||||
const void *data, uint16_t length)
|
||||
|
@ -381,14 +420,24 @@ static void technology_notify_handler(struct bt_conn *conn,
|
|||
(void)memcpy(&technology, data, length);
|
||||
LOG_DBG("%s (0x%02x)", bt_tbs_technology_str(technology), technology);
|
||||
|
||||
if (tbs_client_cbs != NULL && tbs_client_cbs->technology != NULL) {
|
||||
tbs_client_cbs->technology(conn, 0, tbs_index(conn, tbs_inst), technology);
|
||||
}
|
||||
technology_changed(conn, 0, tbs_index(conn, tbs_inst), technology);
|
||||
}
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY) */
|
||||
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH)
|
||||
static void signal_strength_changed(struct bt_conn *conn, int err, uint8_t inst_index,
|
||||
uint8_t signal_strength)
|
||||
{
|
||||
struct bt_tbs_client_cb *listener, *next;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
|
||||
if (listener->signal_strength != NULL) {
|
||||
listener->signal_strength(conn, err, inst_index, signal_strength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void signal_strength_notify_handler(struct bt_conn *conn,
|
||||
const struct bt_tbs_instance *tbs_inst,
|
||||
const void *data, uint16_t length)
|
||||
|
@ -401,10 +450,7 @@ static void signal_strength_notify_handler(struct bt_conn *conn,
|
|||
(void)memcpy(&signal_strength, data, length);
|
||||
LOG_DBG("0x%02x", signal_strength);
|
||||
|
||||
if (tbs_client_cbs != NULL && tbs_client_cbs->signal_strength != NULL) {
|
||||
tbs_client_cbs->signal_strength(conn, 0, tbs_index(conn, tbs_inst),
|
||||
signal_strength);
|
||||
}
|
||||
signal_strength_changed(conn, 0, tbs_index(conn, tbs_inst), signal_strength);
|
||||
}
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH) */
|
||||
|
@ -427,6 +473,18 @@ static void current_calls_notify_handler(struct bt_conn *conn,
|
|||
#endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) */
|
||||
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS)
|
||||
static void status_flags_changed(struct bt_conn *conn, int err, uint8_t inst_index,
|
||||
uint16_t status_flags)
|
||||
{
|
||||
struct bt_tbs_client_cb *listener, *next;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
|
||||
if (listener->status_flags != NULL) {
|
||||
listener->status_flags(conn, err, inst_index, status_flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void status_flags_notify_handler(struct bt_conn *conn,
|
||||
const struct bt_tbs_instance *tbs_inst,
|
||||
const void *data, uint16_t length)
|
||||
|
@ -438,15 +496,25 @@ static void status_flags_notify_handler(struct bt_conn *conn,
|
|||
if (length == sizeof(status_flags)) {
|
||||
(void)memcpy(&status_flags, data, length);
|
||||
LOG_DBG("0x%04x", status_flags);
|
||||
if (tbs_client_cbs != NULL && tbs_client_cbs->status_flags != NULL) {
|
||||
tbs_client_cbs->status_flags(conn, 0, tbs_index(conn, tbs_inst),
|
||||
status_flags);
|
||||
}
|
||||
|
||||
status_flags_changed(conn, 0, tbs_index(conn, tbs_inst), status_flags);
|
||||
}
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS) */
|
||||
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI)
|
||||
static void call_uri_changed(struct bt_conn *conn, int err, uint8_t inst_index,
|
||||
const char *call_uri)
|
||||
{
|
||||
struct bt_tbs_client_cb *listener, *next;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
|
||||
if (listener->call_uri != NULL) {
|
||||
listener->call_uri(conn, err, inst_index, call_uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void incoming_uri_notify_handler(struct bt_conn *conn,
|
||||
const struct bt_tbs_instance *tbs_inst,
|
||||
const void *data, uint16_t length)
|
||||
|
@ -456,12 +524,23 @@ static void incoming_uri_notify_handler(struct bt_conn *conn,
|
|||
|
||||
LOG_DBG("%s", uri);
|
||||
|
||||
if (tbs_client_cbs != NULL && tbs_client_cbs->call_uri != NULL) {
|
||||
tbs_client_cbs->call_uri(conn, 0, tbs_index(conn, tbs_inst), uri);
|
||||
}
|
||||
call_uri_changed(conn, 0, tbs_index(conn, tbs_inst), uri);
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI) */
|
||||
|
||||
static void call_state_changed(struct bt_conn *conn, int err, uint8_t inst_index,
|
||||
uint8_t call_count,
|
||||
const struct bt_tbs_client_call_state *call_states)
|
||||
{
|
||||
struct bt_tbs_client_cb *listener, *next;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
|
||||
if (listener->call_state != NULL) {
|
||||
listener->call_state(conn, err, inst_index, call_count, call_states);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void call_state_notify_handler(struct bt_conn *conn,
|
||||
const struct bt_tbs_instance *tbs_inst,
|
||||
const void *data, uint16_t length)
|
||||
|
@ -496,9 +575,7 @@ static void call_state_notify_handler(struct bt_conn *conn,
|
|||
cnt++;
|
||||
}
|
||||
|
||||
if (tbs_client_cbs != NULL && tbs_client_cbs->call_state != NULL) {
|
||||
tbs_client_cbs->call_state(conn, 0, tbs_index(conn, tbs_inst), cnt, call_states);
|
||||
}
|
||||
call_state_changed(conn, 0, tbs_index(conn, tbs_inst), cnt, call_states);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_CP_PROCEDURES)
|
||||
|
@ -522,6 +599,19 @@ static void call_cp_notify_handler(struct bt_conn *conn,
|
|||
}
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_CP_PROCEDURES) */
|
||||
|
||||
static void terminate_reason_changed(struct bt_conn *conn, int err, uint8_t inst_index,
|
||||
struct bt_tbs_terminate_reason reason)
|
||||
{
|
||||
struct bt_tbs_client_cb *listener, *next;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
|
||||
if (listener->termination_reason != NULL) {
|
||||
listener->termination_reason(conn, err, inst_index, reason.call_index,
|
||||
reason.reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void termination_reason_notify_handler(struct bt_conn *conn,
|
||||
const struct bt_tbs_instance *tbs_inst,
|
||||
const void *data, uint16_t length)
|
||||
|
@ -535,14 +625,23 @@ static void termination_reason_notify_handler(struct bt_conn *conn,
|
|||
LOG_DBG("ID 0x%02X, reason %s", reason.call_index,
|
||||
bt_tbs_term_reason_str(reason.reason));
|
||||
|
||||
if (tbs_client_cbs != NULL && tbs_client_cbs->termination_reason != NULL) {
|
||||
tbs_client_cbs->termination_reason(conn, 0, tbs_index(conn, tbs_inst),
|
||||
reason.call_index, reason.reason);
|
||||
}
|
||||
terminate_reason_changed(conn, 0, tbs_index(conn, tbs_inst), reason);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL)
|
||||
static void remote_uri_changed(struct bt_conn *conn, int err, uint8_t inst_index,
|
||||
const char *remote_uri)
|
||||
{
|
||||
struct bt_tbs_client_cb *listener, *next;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
|
||||
if (listener->remote_uri != NULL) {
|
||||
listener->remote_uri(conn, err, inst_index, remote_uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void in_call_notify_handler(struct bt_conn *conn,
|
||||
const struct bt_tbs_instance *tbs_inst,
|
||||
const void *data, uint16_t length)
|
||||
|
@ -552,13 +651,23 @@ static void in_call_notify_handler(struct bt_conn *conn,
|
|||
|
||||
LOG_DBG("%s", uri);
|
||||
|
||||
if (tbs_client_cbs != NULL && tbs_client_cbs->remote_uri != NULL) {
|
||||
tbs_client_cbs->remote_uri(conn, 0, tbs_index(conn, tbs_inst), uri);
|
||||
}
|
||||
remote_uri_changed(conn, 0, tbs_index(conn, tbs_inst), uri);
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL) */
|
||||
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME)
|
||||
static void friendly_name_changed(struct bt_conn *conn, int err, uint8_t inst_index,
|
||||
const char *friendly_name)
|
||||
{
|
||||
struct bt_tbs_client_cb *listener, *next;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
|
||||
if (listener->friendly_name != NULL) {
|
||||
listener->friendly_name(conn, err, inst_index, friendly_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void friendly_name_notify_handler(struct bt_conn *conn,
|
||||
const struct bt_tbs_instance *tbs_inst,
|
||||
const void *data, uint16_t length)
|
||||
|
@ -568,9 +677,7 @@ static void friendly_name_notify_handler(struct bt_conn *conn,
|
|||
|
||||
LOG_DBG("%s", name);
|
||||
|
||||
if (tbs_client_cbs != NULL && tbs_client_cbs->friendly_name != NULL) {
|
||||
tbs_client_cbs->friendly_name(conn, 0, tbs_index(conn, tbs_inst), name);
|
||||
}
|
||||
friendly_name_changed(conn, 0, tbs_index(conn, tbs_inst), name);
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME) */
|
||||
|
||||
|
@ -713,14 +820,17 @@ static uint8_t inst_cnt(struct bt_tbs_server_inst *srv_inst)
|
|||
static void tbs_client_discover_complete(struct bt_conn *conn, int err)
|
||||
{
|
||||
struct bt_tbs_server_inst *srv_inst = &srv_insts[bt_conn_index(conn)];
|
||||
struct bt_tbs_client_cb *listener, *next;
|
||||
|
||||
LOG_DBG("conn %p err %d", (void *)conn, err);
|
||||
|
||||
/* Clear the current instance in discovery */
|
||||
srv_inst->current_inst = NULL;
|
||||
|
||||
if (tbs_client_cbs != NULL && tbs_client_cbs->discover != NULL) {
|
||||
tbs_client_cbs->discover(conn, err, inst_cnt(srv_inst), gtbs_found(srv_inst));
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
|
||||
if (listener->discover != NULL) {
|
||||
listener->discover(conn, err, inst_cnt(srv_inst), gtbs_found(srv_inst));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -730,105 +840,48 @@ static void tbs_client_discover_complete(struct bt_conn *conn, int err)
|
|||
defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI) || \
|
||||
defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL) || \
|
||||
defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME)
|
||||
/* Common function to read tbs_client strings which may require long reads */
|
||||
static uint8_t 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)
|
||||
|
||||
static bool can_add_string_to_net_buf(const struct net_buf_simple *buf, size_t len)
|
||||
{
|
||||
struct bt_tbs_instance *inst = CONTAINER_OF(params,
|
||||
struct bt_tbs_instance,
|
||||
read_params);
|
||||
uint16_t offset = params->single.offset;
|
||||
uint8_t inst_index = tbs_index(conn, inst);
|
||||
const char *received_string;
|
||||
int tbs_err = err;
|
||||
return buf->len + len + sizeof('\0') <= buf->size;
|
||||
}
|
||||
|
||||
if ((tbs_err == 0) && (data != NULL) &&
|
||||
(net_buf_simple_tailroom(&inst->net_buf) < length)) {
|
||||
LOG_DBG("Read length %u: String buffer full", length);
|
||||
if (truncatable) {
|
||||
/* Use the remaining buffer and continue reading */
|
||||
LOG_DBG("Truncating string");
|
||||
length = net_buf_simple_tailroom(&inst->net_buf);
|
||||
} else {
|
||||
tbs_err = BT_ATT_ERR_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
}
|
||||
/* Common function to read tbs_client strings which may require long reads */
|
||||
static uint8_t handle_string_long_read(struct bt_tbs_instance *inst, uint8_t err, const void *data,
|
||||
uint16_t offset, uint16_t length, bool truncatable)
|
||||
{
|
||||
if (err != 0) {
|
||||
LOG_DBG("err: %u", err);
|
||||
|
||||
if (tbs_err != 0) {
|
||||
LOG_DBG("err: %d", tbs_err);
|
||||
|
||||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
if (cb != NULL) {
|
||||
cb(conn, tbs_err, inst_index, NULL);
|
||||
}
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
return BT_GATT_ERR(err);
|
||||
}
|
||||
|
||||
if (data != NULL) {
|
||||
/* Get data and try to read more using read long procedure */
|
||||
LOG_DBG("Read (offset %u): %s", offset, bt_hex(data, length));
|
||||
|
||||
net_buf_simple_add_mem(&inst->net_buf, data, length);
|
||||
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
if (inst->net_buf.len == 0) {
|
||||
received_string = NULL;
|
||||
} else {
|
||||
uint16_t str_length = inst->net_buf.len;
|
||||
|
||||
/* Ensure there is space for string termination */
|
||||
if (net_buf_simple_tailroom(&inst->net_buf) < 1) {
|
||||
LOG_DBG("Truncating string");
|
||||
if (!can_add_string_to_net_buf(&inst->net_buf, length)) {
|
||||
LOG_DBG("Read length %u: String buffer full", length);
|
||||
if (truncatable) {
|
||||
/* Truncate */
|
||||
str_length--;
|
||||
} else {
|
||||
tbs_err = BT_ATT_ERR_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
}
|
||||
|
||||
if (tbs_err == 0) {
|
||||
char *str_data;
|
||||
|
||||
/* Get a reference to the string buffer */
|
||||
str_data = net_buf_simple_pull_mem(&inst->net_buf,
|
||||
inst->net_buf.len);
|
||||
|
||||
/* All strings are UTF-8, truncate properly if needed */
|
||||
str_data[str_length] = '\0';
|
||||
received_string = utf8_trunc(str_data);
|
||||
|
||||
/* The string might have been truncated */
|
||||
if (strlen(received_string) < str_length) {
|
||||
/* Use the remaining buffer and stop reading and leave room for NULL
|
||||
* terminator
|
||||
*/
|
||||
LOG_DBG("Truncating string");
|
||||
if (!truncatable) {
|
||||
tbs_err =
|
||||
BT_ATT_ERR_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
length = net_buf_simple_tailroom(&inst->net_buf) - sizeof('\0');
|
||||
net_buf_simple_add_mem(&inst->net_buf, data, length);
|
||||
|
||||
/* Ensure that the data is correctly truncated */
|
||||
utf8_trunc(inst->net_buf.data);
|
||||
} else {
|
||||
return BT_GATT_ERR(BT_ATT_ERR_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
} else {
|
||||
net_buf_simple_add_mem(&inst->net_buf, data, length);
|
||||
|
||||
LOG_DBG("%s", received_string);
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (tbs_err) {
|
||||
received_string = NULL;
|
||||
}
|
||||
|
||||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
if (cb != NULL) {
|
||||
cb(conn, tbs_err, inst_index, received_string);
|
||||
}
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME || \
|
||||
|
@ -871,38 +924,67 @@ static uint8_t read_bearer_provider_name_cb(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 = NULL;
|
||||
struct bt_tbs_instance *inst = CONTAINER_OF(params, struct bt_tbs_instance, read_params);
|
||||
const uint8_t inst_index = tbs_index(conn, inst);
|
||||
int ret;
|
||||
|
||||
LOG_DBG("Read bearer provider name");
|
||||
LOG_DBG("");
|
||||
|
||||
if (tbs_client_cbs != NULL &&
|
||||
tbs_client_cbs->bearer_provider_name != NULL) {
|
||||
cb = tbs_client_cbs->bearer_provider_name;
|
||||
ret = handle_string_long_read(inst, err, data, params->single.offset, length, true);
|
||||
if (ret != BT_GATT_ITER_CONTINUE) {
|
||||
if (ret == BT_GATT_ITER_STOP) {
|
||||
/* At this point the inst->net_buf.data contains a NULL terminator string */
|
||||
provider_name_changed(conn, 0, inst_index, (char *)inst->net_buf.data);
|
||||
} else {
|
||||
provider_name_changed(conn, ret, inst_index, NULL);
|
||||
}
|
||||
|
||||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
return handle_string_long_read(conn, err, params, data,
|
||||
length, cb, true);
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME) */
|
||||
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI)
|
||||
static void bearer_uci_changed(struct bt_conn *conn, int err, uint8_t inst_index, const char *uci)
|
||||
{
|
||||
struct bt_tbs_client_cb *listener, *next;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
|
||||
if (listener->bearer_uci != NULL) {
|
||||
listener->bearer_uci(conn, err, inst_index, uci);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t read_bearer_uci_cb(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 = NULL;
|
||||
struct bt_tbs_instance *inst = CONTAINER_OF(params, struct bt_tbs_instance, read_params);
|
||||
const uint8_t inst_index = tbs_index(conn, inst);
|
||||
int ret;
|
||||
|
||||
LOG_DBG("Read bearer UCI");
|
||||
LOG_DBG("");
|
||||
|
||||
if (tbs_client_cbs != NULL && tbs_client_cbs->bearer_uci != NULL) {
|
||||
cb = tbs_client_cbs->bearer_uci;
|
||||
ret = handle_string_long_read(inst, err, data, params->single.offset, length, true);
|
||||
if (ret != BT_GATT_ITER_CONTINUE) {
|
||||
if (ret == BT_GATT_ITER_STOP) {
|
||||
/* At this point the inst->net_buf.data contains a NULL terminator string */
|
||||
bearer_uci_changed(conn, 0, inst_index, (char *)inst->net_buf.data);
|
||||
} else {
|
||||
bearer_uci_changed(conn, ret, inst_index, NULL);
|
||||
}
|
||||
|
||||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
/* The specification does not indicate truncation as an option, so
|
||||
* fail if insufficient buffer space.
|
||||
*/
|
||||
return handle_string_long_read(conn, err, params, data,
|
||||
length, cb, false);
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI) */
|
||||
|
||||
|
@ -935,29 +1017,50 @@ static uint8_t read_technology_cb(struct bt_conn *conn, uint8_t err,
|
|||
|
||||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
if (tbs_client_cbs != NULL && tbs_client_cbs->technology != NULL) {
|
||||
tbs_client_cbs->technology(conn, cb_err, inst_index, technology);
|
||||
}
|
||||
technology_changed(conn, cb_err, inst_index, technology);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY) */
|
||||
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST)
|
||||
static void uri_list_changed(struct bt_conn *conn, int err, uint8_t inst_index,
|
||||
const char *uri_list)
|
||||
{
|
||||
struct bt_tbs_client_cb *listener, *next;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
|
||||
if (listener->uri_list != NULL) {
|
||||
listener->uri_list(conn, err, inst_index, uri_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t read_uri_list_cb(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 = NULL;
|
||||
struct bt_tbs_instance *inst = CONTAINER_OF(params, struct bt_tbs_instance, read_params);
|
||||
const uint8_t inst_index = tbs_index(conn, inst);
|
||||
int ret;
|
||||
|
||||
LOG_DBG("Read bearer UCI");
|
||||
LOG_DBG("");
|
||||
|
||||
if (tbs_client_cbs != NULL && tbs_client_cbs->uri_list != NULL) {
|
||||
cb = tbs_client_cbs->uri_list;
|
||||
ret = handle_string_long_read(inst, err, data, params->single.offset, length, true);
|
||||
if (ret != BT_GATT_ITER_CONTINUE) {
|
||||
if (ret == BT_GATT_ITER_STOP) {
|
||||
/* At this point the inst->net_buf.data contains a NULL terminator string */
|
||||
uri_list_changed(conn, 0, inst_index, (char *)inst->net_buf.data);
|
||||
} else {
|
||||
uri_list_changed(conn, ret, inst_index, NULL);
|
||||
}
|
||||
|
||||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
return handle_string_long_read(conn, err, params, data,
|
||||
length, cb, false);
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST) */
|
||||
|
||||
|
@ -990,16 +1093,25 @@ static uint8_t read_signal_strength_cb(struct bt_conn *conn, uint8_t err,
|
|||
|
||||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
if (tbs_client_cbs != NULL && tbs_client_cbs->signal_strength != NULL) {
|
||||
tbs_client_cbs->signal_strength(conn, cb_err, inst_index,
|
||||
signal_strength);
|
||||
}
|
||||
signal_strength_changed(conn, cb_err, inst_index, signal_strength);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH) */
|
||||
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL)
|
||||
static void signal_interval_changed(struct bt_conn *conn, int err, uint8_t inst_index,
|
||||
uint8_t signal_interval)
|
||||
{
|
||||
struct bt_tbs_client_cb *listener, *next;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
|
||||
if (listener->signal_interval != NULL) {
|
||||
listener->signal_interval(conn, err, inst_index, signal_interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t read_signal_interval_cb(struct bt_conn *conn, uint8_t err,
|
||||
struct bt_gatt_read_params *params,
|
||||
const void *data, uint16_t length)
|
||||
|
@ -1028,10 +1140,7 @@ static uint8_t read_signal_interval_cb(struct bt_conn *conn, uint8_t err,
|
|||
|
||||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
if (tbs_client_cbs && tbs_client_cbs->signal_interval) {
|
||||
tbs_client_cbs->signal_interval(conn, cb_err, inst_index,
|
||||
signal_interval);
|
||||
}
|
||||
signal_interval_changed(conn, cb_err, inst_index, signal_interval);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
@ -1060,11 +1169,7 @@ static uint8_t read_current_calls_cb(struct bt_conn *conn, uint8_t err,
|
|||
|
||||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
if (tbs_client_cbs != NULL &&
|
||||
tbs_client_cbs->current_calls != NULL) {
|
||||
tbs_client_cbs->current_calls(conn, tbs_err,
|
||||
inst_index, 0, NULL);
|
||||
}
|
||||
current_calls_changed(conn, tbs_err, inst_index, 0, NULL);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
@ -1085,11 +1190,7 @@ static uint8_t read_current_calls_cb(struct bt_conn *conn, uint8_t err,
|
|||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
if (inst->net_buf.len == 0) {
|
||||
if (tbs_client_cbs != NULL &&
|
||||
tbs_client_cbs->current_calls != NULL) {
|
||||
tbs_client_cbs->current_calls(conn, 0,
|
||||
inst_index, 0, NULL);
|
||||
}
|
||||
current_calls_changed(conn, 0, inst_index, 0, NULL);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
@ -1101,6 +1202,17 @@ static uint8_t read_current_calls_cb(struct bt_conn *conn, uint8_t err,
|
|||
#endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) */
|
||||
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_CCID)
|
||||
static void ccid_changed(struct bt_conn *conn, int err, uint8_t inst_index, uint8_t ccid)
|
||||
{
|
||||
struct bt_tbs_client_cb *listener, *next;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
|
||||
if (listener->ccid != NULL) {
|
||||
listener->ccid(conn, err, inst_index, ccid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t read_ccid_cb(struct bt_conn *conn, uint8_t err,
|
||||
struct bt_gatt_read_params *params,
|
||||
const void *data, uint16_t length)
|
||||
|
@ -1129,9 +1241,7 @@ static uint8_t read_ccid_cb(struct bt_conn *conn, uint8_t err,
|
|||
|
||||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
if (tbs_client_cbs != NULL && tbs_client_cbs->ccid != NULL) {
|
||||
tbs_client_cbs->ccid(conn, cb_err, inst_index, ccid);
|
||||
}
|
||||
ccid_changed(conn, cb_err, inst_index, ccid);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
@ -1166,11 +1276,7 @@ static uint8_t read_status_flags_cb(struct bt_conn *conn, uint8_t err,
|
|||
|
||||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
if (tbs_client_cbs != NULL &&
|
||||
tbs_client_cbs->status_flags != NULL) {
|
||||
tbs_client_cbs->status_flags(conn, cb_err, inst_index,
|
||||
status_flags);
|
||||
}
|
||||
status_flags_changed(conn, cb_err, inst_index, status_flags);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
@ -1181,16 +1287,27 @@ static uint8_t read_call_uri_cb(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 = NULL;
|
||||
struct bt_tbs_instance *inst = CONTAINER_OF(params, struct bt_tbs_instance, read_params);
|
||||
const uint8_t inst_index = tbs_index(conn, inst);
|
||||
int ret;
|
||||
|
||||
LOG_DBG("Read incoming call target bearer URI");
|
||||
LOG_DBG("");
|
||||
|
||||
if (tbs_client_cbs != NULL && tbs_client_cbs->call_uri != NULL) {
|
||||
cb = tbs_client_cbs->call_uri;
|
||||
ret = handle_string_long_read(inst, err, data, params->single.offset, length, true);
|
||||
if (ret != BT_GATT_ITER_CONTINUE) {
|
||||
if (ret == BT_GATT_ITER_STOP) {
|
||||
/* At this point the inst->net_buf.data contains a NULL terminator string */
|
||||
call_uri_changed(conn, 0, inst_index, (char *)inst->net_buf.data);
|
||||
} else {
|
||||
call_uri_changed(conn, ret, inst_index, NULL);
|
||||
}
|
||||
|
||||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
return handle_string_long_read(conn, err, params, data,
|
||||
length, cb, false);
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI) */
|
||||
|
||||
|
@ -1218,11 +1335,7 @@ static uint8_t read_call_state_cb(struct bt_conn *conn, uint8_t err,
|
|||
|
||||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
if (tbs_client_cbs != NULL &&
|
||||
tbs_client_cbs->call_state != NULL) {
|
||||
tbs_client_cbs->call_state(conn, tbs_err,
|
||||
inst_index, 0, NULL);
|
||||
}
|
||||
call_state_changed(conn, tbs_err, inst_index, 0, NULL);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
@ -1240,10 +1353,7 @@ static uint8_t read_call_state_cb(struct bt_conn *conn, uint8_t err,
|
|||
if (inst->net_buf.len == 0) {
|
||||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
if (tbs_client_cbs != NULL &&
|
||||
tbs_client_cbs->call_state != NULL) {
|
||||
tbs_client_cbs->call_state(conn, 0, inst_index, 0, NULL);
|
||||
}
|
||||
call_state_changed(conn, 0, inst_index, 0, NULL);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
@ -1270,14 +1380,24 @@ static uint8_t read_call_state_cb(struct bt_conn *conn, uint8_t err,
|
|||
|
||||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
if (tbs_client_cbs != NULL && tbs_client_cbs->call_state != NULL) {
|
||||
tbs_client_cbs->call_state(conn, tbs_err, inst_index, cnt, call_states);
|
||||
}
|
||||
call_state_changed(conn, tbs_err, inst_index, cnt, call_states);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES)
|
||||
static void optional_opcodes_changed(struct bt_conn *conn, int err, uint8_t inst_index,
|
||||
uint16_t optional_opcodes)
|
||||
{
|
||||
struct bt_tbs_client_cb *listener, *next;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tbs_client_cbs, listener, next, _node) {
|
||||
if (listener->optional_opcodes != NULL) {
|
||||
listener->optional_opcodes(conn, err, inst_index, optional_opcodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t read_optional_opcodes_cb(struct bt_conn *conn, uint8_t err,
|
||||
struct bt_gatt_read_params *params,
|
||||
const void *data, uint16_t length)
|
||||
|
@ -1304,10 +1424,7 @@ static uint8_t read_optional_opcodes_cb(struct bt_conn *conn, uint8_t err,
|
|||
|
||||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
if (tbs_client_cbs != NULL &&
|
||||
tbs_client_cbs->optional_opcodes != NULL) {
|
||||
tbs_client_cbs->optional_opcodes(conn, cb_err, inst_index, optional_opcodes);
|
||||
}
|
||||
optional_opcodes_changed(conn, cb_err, inst_index, optional_opcodes);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
@ -1318,17 +1435,27 @@ static uint8_t read_remote_uri_cb(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 = NULL;
|
||||
struct bt_tbs_instance *inst = CONTAINER_OF(params, struct bt_tbs_instance, read_params);
|
||||
const uint8_t inst_index = tbs_index(conn, inst);
|
||||
int ret;
|
||||
|
||||
LOG_DBG("Read incoming call URI");
|
||||
LOG_DBG("");
|
||||
|
||||
if (tbs_client_cbs != NULL &&
|
||||
tbs_client_cbs->remote_uri != NULL) {
|
||||
cb = tbs_client_cbs->remote_uri;
|
||||
ret = handle_string_long_read(inst, err, data, params->single.offset, length, true);
|
||||
if (ret != BT_GATT_ITER_CONTINUE) {
|
||||
if (ret == BT_GATT_ITER_STOP) {
|
||||
/* At this point the inst->net_buf.data contains a NULL terminator string */
|
||||
remote_uri_changed(conn, 0, inst_index, (char *)inst->net_buf.data);
|
||||
} else {
|
||||
remote_uri_changed(conn, ret, inst_index, NULL);
|
||||
}
|
||||
|
||||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
return handle_string_long_read(conn, err, params, data,
|
||||
length, cb, false);
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL) */
|
||||
|
||||
|
@ -1337,17 +1464,27 @@ static uint8_t read_friendly_name_cb(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 = NULL;
|
||||
struct bt_tbs_instance *inst = CONTAINER_OF(params, struct bt_tbs_instance, read_params);
|
||||
const uint8_t inst_index = tbs_index(conn, inst);
|
||||
int ret;
|
||||
|
||||
LOG_DBG("Read incoming call target bearer URI");
|
||||
LOG_DBG("");
|
||||
|
||||
if (tbs_client_cbs != NULL &&
|
||||
tbs_client_cbs->friendly_name != NULL) {
|
||||
cb = tbs_client_cbs->friendly_name;
|
||||
ret = handle_string_long_read(inst, err, data, params->single.offset, length, true);
|
||||
if (ret != BT_GATT_ITER_CONTINUE) {
|
||||
if (ret == BT_GATT_ITER_STOP) {
|
||||
/* At this point the inst->net_buf.data contains a NULL terminator string */
|
||||
friendly_name_changed(conn, 0, inst_index, (char *)inst->net_buf.data);
|
||||
} else {
|
||||
friendly_name_changed(conn, ret, inst_index, NULL);
|
||||
}
|
||||
|
||||
tbs_client_gatt_read_complete(inst);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
return handle_string_long_read(conn, err, params, data,
|
||||
length, cb, true);
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME) */
|
||||
|
||||
|
@ -2272,9 +2409,21 @@ int bt_tbs_client_discover(struct bt_conn *conn)
|
|||
#endif /* CONFIG_BT_TBS_CLIENT_GTBS */
|
||||
}
|
||||
|
||||
void bt_tbs_client_register_cb(const struct bt_tbs_client_cb *cbs)
|
||||
int bt_tbs_client_register_cb(struct bt_tbs_client_cb *cb)
|
||||
{
|
||||
tbs_client_cbs = cbs;
|
||||
CHECKIF(cb == NULL) {
|
||||
LOG_DBG("cb is NULL");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sys_slist_find(&tbs_client_cbs, &cb->_node, NULL)) {
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
sys_slist_append(&tbs_client_cbs, &cb->_node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_TBS_CLIENT_CCID)
|
||||
|
|
|
@ -301,7 +301,7 @@ struct bt_tbs_in_uri {
|
|||
defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL) || \
|
||||
defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME) || \
|
||||
defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS)
|
||||
#define BT_TBS_CLIENT_INST_READ_BUF_SIZE (BT_ATT_MAX_ATTRIBUTE_LEN)
|
||||
#define BT_TBS_CLIENT_INST_READ_BUF_SIZE (BT_ATT_MAX_ATTRIBUTE_LEN + 1 /* NULL terminator*/)
|
||||
#else
|
||||
/* Need only be the size of call state reads which is the largest of the
|
||||
* remaining characteristic values
|
||||
|
|
|
@ -277,7 +277,7 @@ static void tbs_client_cp_cb(struct bt_conn *conn, int err, uint8_t inst_index,
|
|||
tbs_client_cp_ev(conn, err);
|
||||
}
|
||||
|
||||
static const struct bt_tbs_client_cb tbs_client_callbacks = {
|
||||
static struct bt_tbs_client_cb tbs_client_callbacks = {
|
||||
.discover = tbs_client_discover_cb,
|
||||
.originate_call = tbs_client_cp_cb,
|
||||
.terminate_call = tbs_client_cp_cb,
|
||||
|
@ -860,10 +860,15 @@ static const struct btp_handler ccp_handlers[] = {
|
|||
|
||||
uint8_t tester_init_ccp(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
tester_register_command_handlers(BTP_SERVICE_ID_CCP, ccp_handlers,
|
||||
ARRAY_SIZE(ccp_handlers));
|
||||
|
||||
bt_tbs_client_register_cb(&tbs_client_callbacks);
|
||||
err = bt_tbs_client_register_cb(&tbs_client_callbacks);
|
||||
if (err != 0) {
|
||||
return BTP_STATUS_FAILED;
|
||||
}
|
||||
|
||||
return BTP_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -303,7 +303,7 @@ static void tbs_client_term_reason_cb(struct bt_conn *conn,
|
|||
SET_FLAG(term_reason);
|
||||
}
|
||||
|
||||
static const struct bt_tbs_client_cb tbs_client_cbs = {
|
||||
static struct bt_tbs_client_cb tbs_client_cbs = {
|
||||
.discover = tbs_client_discover_cb,
|
||||
.originate_call = tbs_client_originate_call_cb,
|
||||
.terminate_call = tbs_client_terminate_call_cb,
|
||||
|
@ -492,7 +492,12 @@ static void test_main(void)
|
|||
}
|
||||
|
||||
bt_conn_cb_register(&conn_callbacks);
|
||||
bt_tbs_client_register_cb(&tbs_client_cbs);
|
||||
|
||||
err = bt_tbs_client_register_cb(&tbs_client_cbs);
|
||||
if (err != 0) {
|
||||
FAIL("Failed to register TBS client cbs (err %d)\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
WAIT_FOR_COND(bt_init);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue