1 /* Bluetooth CCP - Call Control Profile Call Control Server
2  *
3  * Copyright (c) 2024 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <errno.h>
9 #include <stddef.h>
10 #include <stdint.h>
11 
12 #include <zephyr/autoconf.h>
13 #include <zephyr/bluetooth/audio/tbs.h>
14 #include <zephyr/logging/log.h>
15 #include <zephyr/sys/check.h>
16 #include <zephyr/sys/util.h>
17 
18 LOG_MODULE_REGISTER(bt_ccp_call_control_server, CONFIG_BT_CCP_CALL_CONTROL_SERVER_LOG_LEVEL);
19 
20 /* A service instance can either be a GTBS or a TBS instance */
21 struct bt_ccp_call_control_server_bearer {
22 	uint8_t tbs_index;
23 	bool registered;
24 };
25 
26 static struct bt_ccp_call_control_server_bearer
27 	bearers[CONFIG_BT_CCP_CALL_CONTROL_SERVER_BEARER_COUNT];
28 
get_free_bearer(void)29 static struct bt_ccp_call_control_server_bearer *get_free_bearer(void)
30 {
31 
32 	for (size_t i = 0; i < ARRAY_SIZE(bearers); i++) {
33 		if (!bearers[i].registered) {
34 			return &bearers[i];
35 		}
36 	}
37 
38 	return NULL;
39 }
40 
bt_ccp_call_control_server_register_bearer(const struct bt_tbs_register_param * param,struct bt_ccp_call_control_server_bearer ** bearer)41 int bt_ccp_call_control_server_register_bearer(const struct bt_tbs_register_param *param,
42 					       struct bt_ccp_call_control_server_bearer **bearer)
43 {
44 	struct bt_ccp_call_control_server_bearer *free_bearer;
45 	int ret;
46 
47 	CHECKIF(bearer == NULL) {
48 		LOG_DBG("bearer is NULL");
49 
50 		return -EINVAL;
51 	}
52 
53 	free_bearer = get_free_bearer();
54 	if (free_bearer == NULL) {
55 		return -ENOMEM;
56 	}
57 
58 	ret = bt_tbs_register_bearer(param);
59 	if (ret < 0) {
60 		LOG_DBG("Failed to register TBS bearer: %d", ret);
61 
62 		/* Return known errors */
63 		if (ret == -EINVAL || ret == -EALREADY || ret == -EAGAIN || ret == -ENOMEM) {
64 			return ret;
65 		}
66 
67 		return -ENOEXEC;
68 	}
69 
70 	free_bearer->registered = true;
71 	free_bearer->tbs_index = (uint8_t)ret;
72 	*bearer = free_bearer;
73 
74 	return 0;
75 }
76 
bt_ccp_call_control_server_unregister_bearer(struct bt_ccp_call_control_server_bearer * bearer)77 int bt_ccp_call_control_server_unregister_bearer(struct bt_ccp_call_control_server_bearer *bearer)
78 {
79 	int err;
80 
81 	CHECKIF(bearer == NULL) {
82 		LOG_DBG("bearer is NULL");
83 
84 		return -EINVAL;
85 	}
86 
87 	if (!bearer->registered) {
88 		LOG_DBG("Bearer %p already unregistered", bearer);
89 
90 		return -EALREADY;
91 	}
92 
93 	err = bt_tbs_unregister_bearer(bearer->tbs_index);
94 	if (err != 0) {
95 		/* Return known errors */
96 		if (err == -EINVAL || err == -EALREADY) {
97 			return err;
98 		}
99 
100 		return -ENOEXEC;
101 	}
102 
103 	bearer->registered = false;
104 
105 	return 0;
106 }
107