zephyr/samples/bluetooth/hap_ha/src/ccp_call_ctrl.c
Gerard Marull-Paretas 79e6b0e0f6 includes: prefer <zephyr/kernel.h> over <zephyr/zephyr.h>
As of today <zephyr/zephyr.h> is 100% equivalent to <zephyr/kernel.h>.
This patch proposes to then include <zephyr/kernel.h> instead of
<zephyr/zephyr.h> since it is more clear that you are including the
Kernel APIs and (probably) nothing else. <zephyr/zephyr.h> sounds like a
catch-all header that may be confusing. Most applications need to
include a bunch of other things to compile, e.g. driver headers or
subsystem headers like BT, logging, etc.

The idea of a catch-all header in Zephyr is probably not feasible
anyway. Reason is that Zephyr is not a library, like it could be for
example `libpython`. Zephyr provides many utilities nowadays: a kernel,
drivers, subsystems, etc and things will likely grow. A catch-all header
would be massive, difficult to keep up-to-date. It is also likely that
an application will only build a small subset. Note that subsystem-level
headers may use a catch-all approach to make things easier, though.

NOTE: This patch is **NOT** removing the header, just removing its usage
in-tree. I'd advocate for its deprecation (add a #warning on it), but I
understand many people will have concerns.

Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
2022-09-05 16:31:47 +02:00

161 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/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, true);
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)\n", 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)
{
bt_tbs_client_register_cb(&tbs_client_cb);
return 0;
}