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