zephyr/subsys/bluetooth/audio/ccp_call_control_server.c
Emil Gydesen e45830893f Bluetooth: CCP: Introduce new CCP API
The CCP API for the Call Control Profile works on top of the
TBS API, and will eventually replace parts of the TBS API.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
2025-01-08 07:50:32 +01:00

107 lines
2.2 KiB
C

/* Bluetooth CCP - Call Control Profile Call Control Server
*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <zephyr/autoconf.h>
#include <zephyr/bluetooth/audio/tbs.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/check.h>
#include <zephyr/sys/util.h>
LOG_MODULE_REGISTER(bt_ccp_call_control_server, CONFIG_BT_CCP_CALL_CONTROL_SERVER_LOG_LEVEL);
/* A service instance can either be a GTBS or a TBS instance */
struct bt_ccp_call_control_server_bearer {
uint8_t tbs_index;
bool registered;
};
static struct bt_ccp_call_control_server_bearer
bearers[CONFIG_BT_CCP_CALL_CONTROL_SERVER_BEARER_COUNT];
static struct bt_ccp_call_control_server_bearer *get_free_bearer(void)
{
for (size_t i = 0; i < ARRAY_SIZE(bearers); i++) {
if (!bearers[i].registered) {
return &bearers[i];
}
}
return NULL;
}
int bt_ccp_call_control_server_register_bearer(const struct bt_tbs_register_param *param,
struct bt_ccp_call_control_server_bearer **bearer)
{
struct bt_ccp_call_control_server_bearer *free_bearer;
int ret;
CHECKIF(bearer == NULL) {
LOG_DBG("bearer is NULL");
return -EINVAL;
}
free_bearer = get_free_bearer();
if (free_bearer == NULL) {
return -ENOMEM;
}
ret = bt_tbs_register_bearer(param);
if (ret < 0) {
LOG_DBG("Failed to register TBS bearer: %d", ret);
/* Return known errors */
if (ret == -EINVAL || ret == -EALREADY || ret == -EAGAIN || ret == -ENOMEM) {
return ret;
}
return -ENOEXEC;
}
free_bearer->registered = true;
free_bearer->tbs_index = (uint8_t)ret;
*bearer = free_bearer;
return 0;
}
int bt_ccp_call_control_server_unregister_bearer(struct bt_ccp_call_control_server_bearer *bearer)
{
int err;
CHECKIF(bearer == NULL) {
LOG_DBG("bearer is NULL");
return -EINVAL;
}
if (!bearer->registered) {
LOG_DBG("Bearer %p already unregistered", bearer);
return -EALREADY;
}
err = bt_tbs_unregister_bearer(bearer->tbs_index);
if (err != 0) {
/* Return known errors */
if (err == -EINVAL || err == -EALREADY) {
return err;
}
return -ENOEXEC;
}
bearer->registered = false;
return 0;
}