1 /*
2 * Copyright 2023 NXP
3 * Copyright (c) 2024 Nordic Semiconductor ASA
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <stddef.h>
9 #include <stdint.h>
10
11 #include <zephyr/bluetooth/addr.h>
12 #include <zephyr/bluetooth/bluetooth.h>
13 #include <zephyr/bluetooth/conn.h>
14 #include <zephyr/bluetooth/audio/audio.h>
15 #include <zephyr/bluetooth/audio/bap.h>
16 #include <zephyr/bluetooth/audio/bap_lc3_preset.h>
17 #include <zephyr/bluetooth/audio/tmap.h>
18 #include <zephyr/bluetooth/audio/cap.h>
19 #include <zephyr/bluetooth/gap.h>
20 #include <zephyr/bluetooth/gatt.h>
21 #include <zephyr/bluetooth/hci.h>
22 #include <zephyr/bluetooth/uuid.h>
23 #include <zephyr/kernel.h>
24 #include <zephyr/net_buf.h>
25 #include <zephyr/sys/byteorder.h>
26 #include <zephyr/sys/printk.h>
27 #include <zephyr/types.h>
28
29 #include "tmap_central.h"
30
31 static struct bt_conn *default_conn;
32
33 static K_SEM_DEFINE(sem_connected, 0, 1);
34 static K_SEM_DEFINE(sem_security_updated, 0, 1);
35 static K_SEM_DEFINE(sem_disconnected, 0, 1);
36 static K_SEM_DEFINE(sem_mtu_exchanged, 0, 1);
37 static K_SEM_DEFINE(sem_discovery_done, 0, 1);
38
att_mtu_updated(struct bt_conn * conn,uint16_t tx,uint16_t rx)39 static void att_mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
40 {
41 printk("MTU exchanged: %u/%u\n", tx, rx);
42 k_sem_give(&sem_mtu_exchanged);
43 }
44
45 static struct bt_gatt_cb gatt_callbacks = {
46 .att_mtu_updated = att_mtu_updated
47 };
48
tmap_discovery_complete(enum bt_tmap_role role,struct bt_conn * conn,int err)49 void tmap_discovery_complete(enum bt_tmap_role role, struct bt_conn *conn, int err)
50 {
51 if (conn != default_conn) {
52 return;
53 }
54
55 if (err) {
56 printk("TMAS discovery failed! (err %d)\n", err);
57 return;
58 }
59 printk("TMAS discovery done\n");
60 k_sem_give(&sem_discovery_done);
61 }
62
63 static struct bt_tmap_cb tmap_callbacks = {
64 .discovery_complete = tmap_discovery_complete
65 };
66
67 static void start_scan(void);
68
init(void)69 static int init(void)
70 {
71 int err;
72
73 err = bt_enable(NULL);
74 if (err != 0) {
75 printk("Bluetooth enable failed (err %d)\n", err);
76 return err;
77 }
78
79 printk("Bluetooth initialized\n");
80 bt_gatt_cb_register(&gatt_callbacks);
81
82 return 0;
83 }
84
connected(struct bt_conn * conn,uint8_t err)85 static void connected(struct bt_conn *conn, uint8_t err)
86 {
87 char addr[BT_ADDR_LE_STR_LEN];
88
89 (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
90
91 if (err != 0) {
92 printk("Failed to connect to %s %u %s\n", addr, err, bt_hci_err_to_str(err));
93
94 bt_conn_unref(default_conn);
95 default_conn = NULL;
96
97 start_scan();
98 return;
99 }
100
101 if (conn != default_conn) {
102 return;
103 }
104
105 printk("Connected: %s\n", addr);
106 k_sem_give(&sem_connected);
107 }
108
disconnected(struct bt_conn * conn,uint8_t reason)109 static void disconnected(struct bt_conn *conn, uint8_t reason)
110 {
111 char addr[BT_ADDR_LE_STR_LEN];
112
113 if (conn != default_conn) {
114 return;
115 }
116
117 (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
118
119 printk("Disconnected: %s, reason 0x%02x %s\n", addr, reason, bt_hci_err_to_str(reason));
120
121 bt_conn_unref(default_conn);
122 default_conn = NULL;
123
124 k_sem_give(&sem_disconnected);
125 }
126
security_changed(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)127 static void security_changed(struct bt_conn *conn, bt_security_t level,
128 enum bt_security_err err)
129 {
130 if (err == 0) {
131 printk("Security changed: %u\n", err);
132 k_sem_give(&sem_security_updated);
133 } else {
134 printk("Failed to set security level: %s(%u)\n", bt_security_err_to_str(err), err);
135 }
136 }
137
138 BT_CONN_CB_DEFINE(conn_callbacks) = {
139 .connected = connected,
140 .disconnected = disconnected,
141 .security_changed = security_changed
142 };
143
check_audio_support_and_connect(struct bt_data * data,void * user_data)144 static bool check_audio_support_and_connect(struct bt_data *data, void *user_data)
145 {
146 bt_addr_le_t *addr = user_data;
147 struct net_buf_simple tmas_svc_data;
148 const struct bt_uuid *uuid;
149 uint16_t uuid_val;
150 uint16_t peer_tmap_role = 0;
151 int err;
152
153 printk("[AD]: %u data_len %u\n", data->type, data->data_len);
154
155 if (data->type != BT_DATA_SVC_DATA16) {
156 return true; /* Continue parsing to next AD data type */
157 }
158
159 if (data->data_len < sizeof(uuid_val)) {
160 printk("AD invalid size %u\n", data->data_len);
161 return true; /* Continue parsing to next AD data type */
162 }
163
164 net_buf_simple_init_with_data(&tmas_svc_data, (void *)data->data, data->data_len);
165 uuid_val = net_buf_simple_pull_le16(&tmas_svc_data);
166 uuid = BT_UUID_DECLARE_16(sys_le16_to_cpu(uuid_val));
167 if (bt_uuid_cmp(uuid, BT_UUID_TMAS) != 0) {
168 /* We are looking for the TMAS service data */
169 return true; /* Continue parsing to next AD data type */
170 }
171
172 printk("Found TMAS in peer adv data!\n");
173 if (tmas_svc_data.len < sizeof(peer_tmap_role)) {
174 printk("AD invalid size %u\n", data->data_len);
175 return false; /* Stop parsing */
176 }
177
178 peer_tmap_role = net_buf_simple_pull_le16(&tmas_svc_data);
179 if (!(sys_le16_to_cpu(peer_tmap_role) & BT_TMAP_ROLE_UMR)) {
180 printk("No TMAS UMR support!\n");
181 return false; /* Stop parsing */
182 }
183
184 printk("Attempt to connect!\n");
185 err = bt_le_scan_stop();
186 if (err != 0) {
187 printk("Failed to stop scan: %d\n", err);
188 return false;
189 }
190
191 err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_BAP_CONN_PARAM_RELAXED,
192 &default_conn);
193 if (err != 0) {
194 printk("Create conn to failed (%u)\n", err);
195 start_scan();
196 }
197
198 return false; /* Stop parsing */
199 }
200
scan_recv(const struct bt_le_scan_recv_info * info,struct net_buf_simple * buf)201 static void scan_recv(const struct bt_le_scan_recv_info *info,
202 struct net_buf_simple *buf)
203 {
204 char le_addr[BT_ADDR_LE_STR_LEN];
205
206 if (default_conn != NULL) {
207 /* Already connected */
208 return;
209 }
210
211 /* Check for connectable, extended advertising */
212 if (((info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0) ||
213 ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE)) != 0) {
214 bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
215 printk("[DEVICE]: %s, ", le_addr);
216 /* Check for TMAS support in advertising data */
217 bt_data_parse(buf, check_audio_support_and_connect, (void *)info->addr);
218 }
219 }
220
221 static struct bt_le_scan_cb scan_callbacks = {
222 .recv = scan_recv,
223 };
224
start_scan(void)225 static void start_scan(void)
226 {
227 int err;
228
229 err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
230 if (err != 0) {
231 printk("Scanning failed to start (err %d)\n", err);
232 return;
233 }
234
235 printk("Scanning successfully started\n");
236 }
237
scan_and_connect(void)238 static int scan_and_connect(void)
239 {
240 int err;
241
242 start_scan();
243
244 err = k_sem_take(&sem_connected, K_FOREVER);
245 if (err != 0) {
246 printk("failed to take sem_connected (err %d)\n", err);
247 return err;
248 }
249
250 err = k_sem_take(&sem_mtu_exchanged, K_FOREVER);
251 if (err != 0) {
252 printk("failed to take sem_mtu_exchanged (err %d)\n", err);
253 return err;
254 }
255
256 err = bt_conn_set_security(default_conn, BT_SECURITY_L2);
257 if (err != 0) {
258 printk("failed to set security (err %d)\n", err);
259 return err;
260 }
261
262 err = k_sem_take(&sem_security_updated, K_FOREVER);
263 if (err != 0) {
264 printk("failed to take sem_security_updated (err %d)\n", err);
265 return err;
266 }
267
268 return 0;
269 }
270
main(void)271 int main(void)
272 {
273 int err;
274
275 err = init();
276 if (err != 0) {
277 return err;
278 }
279
280 printk("Initializing TMAP and setting role\n");
281 /* Initialize TMAP */
282 err = bt_tmap_register(BT_TMAP_ROLE_CG | BT_TMAP_ROLE_UMS);
283 if (err != 0) {
284 return err;
285 }
286
287 /* Initialize CAP Initiator */
288 err = cap_initiator_init();
289 if (err != 0) {
290 return err;
291 }
292 printk("CAP initialized\n");
293
294 /* Initialize VCP Volume Controller */
295 err = vcp_vol_ctlr_init();
296 if (err != 0) {
297 return err;
298 }
299 printk("VCP initialized\n");
300
301 /* Initialize MCP Server */
302 err = mcp_server_init();
303 if (err != 0) {
304 return err;
305 }
306 printk("MCP initialized\n");
307
308 /* Initialize CCP Call Control Server */
309 err = ccp_call_control_server_init();
310 if (err != 0) {
311 return err;
312 }
313 printk("CCP initialized\n");
314
315 /* Register scan callback and start scanning */
316 bt_le_scan_cb_register(&scan_callbacks);
317 err = scan_and_connect();
318 if (err != 0) {
319 return err;
320 }
321
322 err = bt_tmap_discover(default_conn, &tmap_callbacks);
323 if (err != 0) {
324 return err;
325 }
326
327 k_sem_take(&sem_discovery_done, K_FOREVER);
328
329 /* Send a VCP command */
330 err = vcp_vol_ctlr_mute();
331 if (err != 0) {
332 printk("Error sending mute command!\n");
333 }
334
335 /* Discover and configure unicast streams */
336 err = cap_initiator_setup(default_conn);
337 if (err != 0) {
338 return err;
339 }
340
341 return 0;
342 }
343