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,
192 				BT_LE_CONN_PARAM_DEFAULT,
193 				&default_conn);
194 	if (err != 0) {
195 		printk("Create conn to failed (%u)\n", err);
196 		start_scan();
197 	}
198 
199 	return false; /* Stop parsing */
200 }
201 
scan_recv(const struct bt_le_scan_recv_info * info,struct net_buf_simple * buf)202 static void scan_recv(const struct bt_le_scan_recv_info *info,
203 					struct net_buf_simple *buf)
204 {
205 	char le_addr[BT_ADDR_LE_STR_LEN];
206 
207 	if (default_conn != NULL) {
208 		/* Already connected */
209 		return;
210 	}
211 
212 	/* Check for connectable, extended advertising */
213 	if (((info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0) ||
214 		((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE)) != 0) {
215 		bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
216 		printk("[DEVICE]: %s, ", le_addr);
217 		/* Check for TMAS support in advertising data */
218 		bt_data_parse(buf, check_audio_support_and_connect, (void *)info->addr);
219 	}
220 }
221 
222 static struct bt_le_scan_cb scan_callbacks = {
223 	.recv = scan_recv,
224 };
225 
start_scan(void)226 static void start_scan(void)
227 {
228 	int err;
229 
230 	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
231 	if (err != 0) {
232 		printk("Scanning failed to start (err %d)\n", err);
233 		return;
234 	}
235 
236 	printk("Scanning successfully started\n");
237 }
238 
scan_and_connect(void)239 static int scan_and_connect(void)
240 {
241 	int err;
242 
243 	start_scan();
244 
245 	err = k_sem_take(&sem_connected, K_FOREVER);
246 	if (err != 0) {
247 		printk("failed to take sem_connected (err %d)\n", err);
248 		return err;
249 	}
250 
251 	err = k_sem_take(&sem_mtu_exchanged, K_FOREVER);
252 	if (err != 0) {
253 		printk("failed to take sem_mtu_exchanged (err %d)\n", err);
254 		return err;
255 	}
256 
257 	err = bt_conn_set_security(default_conn, BT_SECURITY_L2);
258 	if (err != 0) {
259 		printk("failed to set security (err %d)\n", err);
260 		return err;
261 	}
262 
263 	err = k_sem_take(&sem_security_updated, K_FOREVER);
264 	if (err != 0) {
265 		printk("failed to take sem_security_updated (err %d)\n", err);
266 		return err;
267 	}
268 
269 	return 0;
270 }
271 
main(void)272 int main(void)
273 {
274 	int err;
275 
276 	err = init();
277 	if (err != 0) {
278 		return err;
279 	}
280 
281 	printk("Initializing TMAP and setting role\n");
282 	/* Initialize TMAP */
283 	err = bt_tmap_register(BT_TMAP_ROLE_CG | BT_TMAP_ROLE_UMS);
284 	if (err != 0) {
285 		return err;
286 	}
287 
288 	/* Initialize CAP Initiator */
289 	err = cap_initiator_init();
290 	if (err != 0) {
291 		return err;
292 	}
293 	printk("CAP initialized\n");
294 
295 	/* Initialize VCP Volume Controller */
296 	err = vcp_vol_ctlr_init();
297 	if (err != 0) {
298 		return err;
299 	}
300 	printk("VCP initialized\n");
301 
302 	/* Initialize MCP Server */
303 	err = mcp_server_init();
304 	if (err != 0) {
305 		return err;
306 	}
307 	printk("MCP initialized\n");
308 
309 	/* Initialize CCP Server */
310 	err = ccp_server_init();
311 	if (err != 0) {
312 		return err;
313 	}
314 	printk("CCP initialized\n");
315 
316 	/* Register scan callback and start scanning */
317 	bt_le_scan_cb_register(&scan_callbacks);
318 	err = scan_and_connect();
319 	if (err != 0) {
320 		return err;
321 	}
322 
323 	err = bt_tmap_discover(default_conn, &tmap_callbacks);
324 	if (err != 0) {
325 		return err;
326 	}
327 
328 	k_sem_take(&sem_discovery_done, K_FOREVER);
329 
330 	/* Send a VCP command */
331 	err = vcp_vol_ctlr_mute();
332 	if (err != 0) {
333 		printk("Error sending mute command!\n");
334 	}
335 
336 	/* Discover and configure unicast streams */
337 	err = cap_initiator_setup(default_conn);
338 	if (err != 0) {
339 		return err;
340 	}
341 
342 	return 0;
343 }
344