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>
160 lines
3.9 KiB
C
160 lines
3.9 KiB
C
/** @file
|
|
* @brief Bluetooth Call Control Profile (CCP) Call Controller role.
|
|
*
|
|
* Copyright (c) 2020 Nordic Semiconductor ASA
|
|
* Copyright (c) 2022 Codecoup
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/kernel.h>
|
|
#include <zephyr/sys/printk.h>
|
|
#include <zephyr/sys/util.h>
|
|
|
|
#include <zephyr/bluetooth/conn.h>
|
|
#include <zephyr/bluetooth/hci.h>
|
|
#include <zephyr/bluetooth/audio/tbs.h>
|
|
|
|
enum {
|
|
CCP_FLAG_PROFILE_CONNECTED,
|
|
CCP_FLAG_GTBS_DISCOVER,
|
|
CCP_FLAG_CCID_READ,
|
|
CCP_FLAG_STATUS_FLAGS_READ,
|
|
CCP_FLAG_CALL_STATE_READ,
|
|
|
|
CCP_FLAG_NUM,
|
|
};
|
|
|
|
static ATOMIC_DEFINE(flags, CCP_FLAG_NUM)[CONFIG_BT_MAX_CONN];
|
|
|
|
static int process_profile_connection(struct bt_conn *conn)
|
|
{
|
|
atomic_t *flags_for_conn = flags[bt_conn_index(conn)];
|
|
int err = 0;
|
|
|
|
if (!atomic_test_and_set_bit(flags_for_conn, CCP_FLAG_GTBS_DISCOVER)) {
|
|
err = bt_tbs_client_discover(conn);
|
|
if (err != 0) {
|
|
printk("bt_tbs_client_discover (err %d)\n", err);
|
|
}
|
|
} else if (!atomic_test_and_set_bit(flags_for_conn, CCP_FLAG_CCID_READ)) {
|
|
err = bt_tbs_client_read_ccid(conn, BT_TBS_GTBS_INDEX);
|
|
if (err != 0) {
|
|
printk("bt_tbs_client_read_ccid (err %d)\n", err);
|
|
}
|
|
} else if (!atomic_test_and_set_bit(flags_for_conn, CCP_FLAG_STATUS_FLAGS_READ)) {
|
|
err = bt_tbs_client_read_status_flags(conn, BT_TBS_GTBS_INDEX);
|
|
if (err != 0) {
|
|
printk("bt_tbs_client_read_status_flags (err %d)\n", err);
|
|
}
|
|
} else if (!atomic_test_and_set_bit(flags_for_conn, CCP_FLAG_CALL_STATE_READ)) {
|
|
err = bt_tbs_client_read_call_state(conn, BT_TBS_GTBS_INDEX);
|
|
if (err != 0) {
|
|
printk("bt_tbs_client_read_call_state (err %d)\n", err);
|
|
}
|
|
} else if (!atomic_test_and_set_bit(flags_for_conn, CCP_FLAG_PROFILE_CONNECTED)) {
|
|
printk("CCP Profile connected\n");
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static void connected(struct bt_conn *conn, uint8_t err)
|
|
{
|
|
if (err) {
|
|
printk("Connection failed, err %d %s\n", err, bt_hci_err_to_str(err));
|
|
return;
|
|
}
|
|
|
|
atomic_set(flags[bt_conn_index(conn)], 0);
|
|
|
|
if (process_profile_connection(conn) != 0) {
|
|
printk("Profile connection failed");
|
|
}
|
|
}
|
|
|
|
BT_CONN_CB_DEFINE(conn_callbacks) = {
|
|
.connected = connected,
|
|
};
|
|
|
|
static void discover_cb(struct bt_conn *conn, int err, uint8_t tbs_count, bool gtbs_found)
|
|
{
|
|
if (!gtbs_found) {
|
|
printk("Failed to discover GTBS\n");
|
|
return;
|
|
}
|
|
|
|
if (err) {
|
|
printk("%s (err %d)\n", __func__, err);
|
|
return;
|
|
}
|
|
|
|
if (!atomic_test_bit(flags[bt_conn_index(conn)], CCP_FLAG_PROFILE_CONNECTED)) {
|
|
process_profile_connection(conn);
|
|
}
|
|
}
|
|
|
|
static void ccid_cb(struct bt_conn *conn, int err, uint8_t inst_index, uint32_t value)
|
|
{
|
|
if (inst_index != BT_TBS_GTBS_INDEX) {
|
|
printk("Unexpected %s for instance %u\n", __func__, inst_index);
|
|
return;
|
|
}
|
|
|
|
if (err) {
|
|
printk("%s (err %d)\n", __func__, err);
|
|
return;
|
|
}
|
|
|
|
if (!atomic_test_bit(flags[bt_conn_index(conn)], CCP_FLAG_PROFILE_CONNECTED)) {
|
|
process_profile_connection(conn);
|
|
}
|
|
}
|
|
|
|
static void status_flags_cb(struct bt_conn *conn, int err, uint8_t inst_index, uint32_t value)
|
|
{
|
|
if (inst_index != BT_TBS_GTBS_INDEX) {
|
|
printk("Unexpected %s for instance %u\n", __func__, inst_index);
|
|
return;
|
|
}
|
|
|
|
if (err) {
|
|
printk("%s (err %d)\n", __func__, err);
|
|
return;
|
|
}
|
|
|
|
if (!atomic_test_bit(flags[bt_conn_index(conn)], CCP_FLAG_PROFILE_CONNECTED)) {
|
|
process_profile_connection(conn);
|
|
}
|
|
}
|
|
|
|
static void call_state_cb(struct bt_conn *conn, int err, uint8_t inst_index, uint8_t call_count,
|
|
const struct bt_tbs_client_call_state *call_states)
|
|
{
|
|
if (inst_index != BT_TBS_GTBS_INDEX) {
|
|
printk("Unexpected %s for instance %u\n", __func__, inst_index);
|
|
return;
|
|
}
|
|
|
|
if (err) {
|
|
printk("%s (err %d)\n", __func__, err);
|
|
return;
|
|
}
|
|
|
|
if (!atomic_test_bit(flags[bt_conn_index(conn)], CCP_FLAG_PROFILE_CONNECTED)) {
|
|
process_profile_connection(conn);
|
|
}
|
|
}
|
|
|
|
struct bt_tbs_client_cb tbs_client_cb = {
|
|
.discover = discover_cb,
|
|
.ccid = ccid_cb,
|
|
.status_flags = status_flags_cb,
|
|
.call_state = call_state_cb,
|
|
};
|
|
|
|
int ccp_call_ctrl_init(void)
|
|
{
|
|
return bt_tbs_client_register_cb(&tbs_client_cb);
|
|
}
|