1 /*
2  * Copyright (c) 2021-2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/device.h>
8 #include <zephyr/devicetree.h>
9 #include <zephyr/drivers/gpio.h>
10 #include <zephyr/bluetooth/bluetooth.h>
11 #include <zephyr/bluetooth/conn.h>
12 #include <zephyr/bluetooth/hci_types.h>
13 #include <zephyr/bluetooth/iso.h>
14 #include <zephyr/sys/byteorder.h>
15 
16 #define TIMEOUT_SYNC_CREATE K_SECONDS(10)
17 #define NAME_LEN            30
18 
19 #define BT_LE_SCAN_CUSTOM BT_LE_SCAN_PARAM(BT_LE_SCAN_TYPE_ACTIVE, \
20 					   BT_LE_SCAN_OPT_NONE, \
21 					   BT_GAP_SCAN_FAST_INTERVAL, \
22 					   BT_GAP_SCAN_FAST_WINDOW)
23 
24 #define PA_RETRY_COUNT 6
25 
26 #define BIS_ISO_CHAN_COUNT MIN(2U, CONFIG_BT_ISO_MAX_CHAN)
27 
28 static bool         per_adv_found;
29 static bool         per_adv_lost;
30 static bt_addr_le_t per_addr;
31 static uint8_t      per_sid;
32 static uint32_t     per_interval_us;
33 
34 static uint32_t     iso_recv_count;
35 
36 static K_SEM_DEFINE(sem_per_adv, 0, 1);
37 static K_SEM_DEFINE(sem_per_sync, 0, 1);
38 static K_SEM_DEFINE(sem_per_sync_lost, 0, 1);
39 static K_SEM_DEFINE(sem_per_big_info, 0, 1);
40 static K_SEM_DEFINE(sem_big_sync, 0, BIS_ISO_CHAN_COUNT);
41 static K_SEM_DEFINE(sem_big_sync_lost, 0, BIS_ISO_CHAN_COUNT);
42 
43 /* The devicetree node identifier for the "led0" alias. */
44 #define LED0_NODE DT_ALIAS(led0)
45 
46 #ifdef CONFIG_ISO_BLINK_LED0
47 static const struct gpio_dt_spec led_gpio = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
48 #define BLINK_ONOFF K_MSEC(500)
49 
50 static struct k_work_delayable blink_work;
51 static bool                    led_is_on;
52 static bool                    blink;
53 
blink_timeout(struct k_work * work)54 static void blink_timeout(struct k_work *work)
55 {
56 	if (!blink) {
57 		return;
58 	}
59 
60 	led_is_on = !led_is_on;
61 	gpio_pin_set_dt(&led_gpio, (int)led_is_on);
62 
63 	k_work_schedule(&blink_work, BLINK_ONOFF);
64 }
65 #endif
66 
data_cb(struct bt_data * data,void * user_data)67 static bool data_cb(struct bt_data *data, void *user_data)
68 {
69 	char *name = user_data;
70 	uint8_t len;
71 
72 	switch (data->type) {
73 	case BT_DATA_NAME_SHORTENED:
74 	case BT_DATA_NAME_COMPLETE:
75 		len = MIN(data->data_len, NAME_LEN - 1);
76 		memcpy(name, data->data, len);
77 		name[len] = '\0';
78 		return false;
79 	default:
80 		return true;
81 	}
82 }
83 
phy2str(uint8_t phy)84 static const char *phy2str(uint8_t phy)
85 {
86 	switch (phy) {
87 	case 0: return "No packets";
88 	case BT_GAP_LE_PHY_1M: return "LE 1M";
89 	case BT_GAP_LE_PHY_2M: return "LE 2M";
90 	case BT_GAP_LE_PHY_CODED: return "LE Coded";
91 	default: return "Unknown";
92 	}
93 }
94 
scan_recv(const struct bt_le_scan_recv_info * info,struct net_buf_simple * buf)95 static void scan_recv(const struct bt_le_scan_recv_info *info,
96 		      struct net_buf_simple *buf)
97 {
98 	char le_addr[BT_ADDR_LE_STR_LEN];
99 	char name[NAME_LEN];
100 
101 	(void)memset(name, 0, sizeof(name));
102 
103 	bt_data_parse(buf, data_cb, name);
104 
105 	bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
106 	printk("[DEVICE]: %s, AD evt type %u, Tx Pwr: %i, RSSI %i %s "
107 	       "C:%u S:%u D:%u SR:%u E:%u Prim: %s, Secn: %s, "
108 	       "Interval: 0x%04x (%u us), SID: %u\n",
109 	       le_addr, info->adv_type, info->tx_power, info->rssi, name,
110 	       (info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0,
111 	       (info->adv_props & BT_GAP_ADV_PROP_SCANNABLE) != 0,
112 	       (info->adv_props & BT_GAP_ADV_PROP_DIRECTED) != 0,
113 	       (info->adv_props & BT_GAP_ADV_PROP_SCAN_RESPONSE) != 0,
114 	       (info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0,
115 	       phy2str(info->primary_phy), phy2str(info->secondary_phy),
116 	       info->interval, BT_CONN_INTERVAL_TO_US(info->interval), info->sid);
117 
118 	if (!per_adv_found && info->interval) {
119 		per_adv_found = true;
120 
121 		per_sid = info->sid;
122 		per_interval_us = BT_CONN_INTERVAL_TO_US(info->interval);
123 		bt_addr_le_copy(&per_addr, info->addr);
124 
125 		k_sem_give(&sem_per_adv);
126 	}
127 }
128 
129 static struct bt_le_scan_cb scan_callbacks = {
130 	.recv = scan_recv,
131 };
132 
sync_cb(struct bt_le_per_adv_sync * sync,struct bt_le_per_adv_sync_synced_info * info)133 static void sync_cb(struct bt_le_per_adv_sync *sync,
134 		    struct bt_le_per_adv_sync_synced_info *info)
135 {
136 	char le_addr[BT_ADDR_LE_STR_LEN];
137 
138 	bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
139 
140 	printk("PER_ADV_SYNC[%u]: [DEVICE]: %s synced, "
141 	       "Interval 0x%04x (%u ms), PHY %s\n",
142 	       bt_le_per_adv_sync_get_index(sync), le_addr,
143 	       info->interval, info->interval * 5 / 4, phy2str(info->phy));
144 
145 	k_sem_give(&sem_per_sync);
146 }
147 
term_cb(struct bt_le_per_adv_sync * sync,const struct bt_le_per_adv_sync_term_info * info)148 static void term_cb(struct bt_le_per_adv_sync *sync,
149 		    const struct bt_le_per_adv_sync_term_info *info)
150 {
151 	char le_addr[BT_ADDR_LE_STR_LEN];
152 
153 	bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
154 
155 	printk("PER_ADV_SYNC[%u]: [DEVICE]: %s sync terminated\n",
156 	       bt_le_per_adv_sync_get_index(sync), le_addr);
157 
158 	per_adv_lost = true;
159 	k_sem_give(&sem_per_sync_lost);
160 }
161 
recv_cb(struct bt_le_per_adv_sync * sync,const struct bt_le_per_adv_sync_recv_info * info,struct net_buf_simple * buf)162 static void recv_cb(struct bt_le_per_adv_sync *sync,
163 		    const struct bt_le_per_adv_sync_recv_info *info,
164 		    struct net_buf_simple *buf)
165 {
166 	char le_addr[BT_ADDR_LE_STR_LEN];
167 	char data_str[129];
168 
169 	bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
170 	bin2hex(buf->data, buf->len, data_str, sizeof(data_str));
171 
172 	printk("PER_ADV_SYNC[%u]: [DEVICE]: %s, tx_power %i, "
173 	       "RSSI %i, CTE %u, data length %u, data: %s\n",
174 	       bt_le_per_adv_sync_get_index(sync), le_addr, info->tx_power,
175 	       info->rssi, info->cte_type, buf->len, data_str);
176 }
177 
biginfo_cb(struct bt_le_per_adv_sync * sync,const struct bt_iso_biginfo * biginfo)178 static void biginfo_cb(struct bt_le_per_adv_sync *sync,
179 		       const struct bt_iso_biginfo *biginfo)
180 {
181 	char le_addr[BT_ADDR_LE_STR_LEN];
182 
183 	bt_addr_le_to_str(biginfo->addr, le_addr, sizeof(le_addr));
184 
185 	printk("BIG INFO[%u]: [DEVICE]: %s, sid 0x%02x, "
186 	       "num_bis %u, nse %u, interval 0x%04x (%u ms), "
187 	       "bn %u, pto %u, irc %u, max_pdu %u, "
188 	       "sdu_interval %u us, max_sdu %u, phy %s, "
189 	       "%s framing, %sencrypted\n",
190 	       bt_le_per_adv_sync_get_index(sync), le_addr, biginfo->sid,
191 	       biginfo->num_bis, biginfo->sub_evt_count,
192 	       biginfo->iso_interval,
193 	       (biginfo->iso_interval * 5 / 4),
194 	       biginfo->burst_number, biginfo->offset,
195 	       biginfo->rep_count, biginfo->max_pdu, biginfo->sdu_interval,
196 	       biginfo->max_sdu, phy2str(biginfo->phy),
197 	       biginfo->framing ? "with" : "without",
198 	       biginfo->encryption ? "" : "not ");
199 
200 
201 	k_sem_give(&sem_per_big_info);
202 }
203 
204 static struct bt_le_per_adv_sync_cb sync_callbacks = {
205 	.synced = sync_cb,
206 	.term = term_cb,
207 	.recv = recv_cb,
208 	.biginfo = biginfo_cb,
209 };
210 
iso_recv(struct bt_iso_chan * chan,const struct bt_iso_recv_info * info,struct net_buf * buf)211 static void iso_recv(struct bt_iso_chan *chan, const struct bt_iso_recv_info *info,
212 		struct net_buf *buf)
213 {
214 	char data_str[128];
215 	size_t str_len;
216 	uint32_t count = 0; /* only valid if the data is a counter */
217 
218 	if (buf->len == sizeof(count)) {
219 		count = sys_get_le32(buf->data);
220 		if (IS_ENABLED(CONFIG_ISO_ALIGN_PRINT_INTERVALS)) {
221 			iso_recv_count = count;
222 		}
223 	}
224 
225 	if ((iso_recv_count % CONFIG_ISO_PRINT_INTERVAL) == 0) {
226 		str_len = bin2hex(buf->data, buf->len, data_str, sizeof(data_str));
227 		printk("Incoming data channel %p flags 0x%x seq_num %u ts %u len %u: "
228 		       "%s (counter value %u)\n", chan, info->flags, info->seq_num,
229 		       info->ts, buf->len, data_str, count);
230 	}
231 
232 	iso_recv_count++;
233 }
234 
iso_connected(struct bt_iso_chan * chan)235 static void iso_connected(struct bt_iso_chan *chan)
236 {
237 	const struct bt_iso_chan_path hci_path = {
238 		.pid = BT_ISO_DATA_PATH_HCI,
239 		.format = BT_HCI_CODING_FORMAT_TRANSPARENT,
240 	};
241 	int err;
242 
243 	printk("ISO Channel %p connected\n", chan);
244 
245 	err = bt_iso_setup_data_path(chan, BT_HCI_DATAPATH_DIR_CTLR_TO_HOST, &hci_path);
246 	if (err != 0) {
247 		printk("Failed to setup ISO RX data path: %d\n", err);
248 	}
249 
250 	k_sem_give(&sem_big_sync);
251 }
252 
iso_disconnected(struct bt_iso_chan * chan,uint8_t reason)253 static void iso_disconnected(struct bt_iso_chan *chan, uint8_t reason)
254 {
255 	printk("ISO Channel %p disconnected with reason 0x%02x\n",
256 	       chan, reason);
257 
258 	if (reason != BT_HCI_ERR_OP_CANCELLED_BY_HOST) {
259 		k_sem_give(&sem_big_sync_lost);
260 	}
261 }
262 
263 static struct bt_iso_chan_ops iso_ops = {
264 	.recv		= iso_recv,
265 	.connected	= iso_connected,
266 	.disconnected	= iso_disconnected,
267 };
268 
269 static struct bt_iso_chan_io_qos iso_rx_qos[BIS_ISO_CHAN_COUNT];
270 
271 static struct bt_iso_chan_qos bis_iso_qos[] = {
272 	{ .rx = &iso_rx_qos[0], },
273 	{ .rx = &iso_rx_qos[1], },
274 };
275 
276 static struct bt_iso_chan bis_iso_chan[] = {
277 	{ .ops = &iso_ops,
278 	  .qos = &bis_iso_qos[0], },
279 	{ .ops = &iso_ops,
280 	  .qos = &bis_iso_qos[1], },
281 };
282 
283 static struct bt_iso_chan *bis[] = {
284 	&bis_iso_chan[0],
285 	&bis_iso_chan[1],
286 };
287 
288 static struct bt_iso_big_sync_param big_sync_param = {
289 	.bis_channels = bis,
290 	.num_bis = BIS_ISO_CHAN_COUNT,
291 	.bis_bitfield = (BIT_MASK(BIS_ISO_CHAN_COUNT)),
292 	.mse = BT_ISO_SYNC_MSE_ANY, /* any number of subevents */
293 	.sync_timeout = 100, /* in 10 ms units */
294 };
295 
reset_semaphores(void)296 static void reset_semaphores(void)
297 {
298 	k_sem_reset(&sem_per_adv);
299 	k_sem_reset(&sem_per_sync);
300 	k_sem_reset(&sem_per_sync_lost);
301 	k_sem_reset(&sem_per_big_info);
302 	k_sem_reset(&sem_big_sync);
303 	k_sem_reset(&sem_big_sync_lost);
304 }
305 
main(void)306 int main(void)
307 {
308 	struct bt_le_per_adv_sync_param sync_create_param;
309 	struct bt_le_per_adv_sync *sync;
310 	struct bt_iso_big *big;
311 	uint32_t sem_timeout_us;
312 	int err;
313 
314 	iso_recv_count = 0;
315 
316 	printk("Starting Synchronized Receiver Demo\n");
317 
318 #ifdef CONFIG_ISO_BLINK_LED0
319 	printk("Get reference to LED device...");
320 
321 	if (!gpio_is_ready_dt(&led_gpio)) {
322 		printk("LED gpio device not ready.\n");
323 		return 0;
324 	}
325 	printk("done.\n");
326 
327 	printk("Configure GPIO pin...");
328 	err = gpio_pin_configure_dt(&led_gpio, GPIO_OUTPUT_ACTIVE);
329 	if (err) {
330 		return 0;
331 	}
332 	printk("done.\n");
333 
334 	k_work_init_delayable(&blink_work, blink_timeout);
335 #endif /* CONFIG_ISO_BLINK_LED0 */
336 
337 	/* Initialize the Bluetooth Subsystem */
338 	err = bt_enable(NULL);
339 	if (err) {
340 		printk("Bluetooth init failed (err %d)\n", err);
341 		return 0;
342 	}
343 
344 	printk("Scan callbacks register...");
345 	bt_le_scan_cb_register(&scan_callbacks);
346 	printk("success.\n");
347 
348 	printk("Periodic Advertising callbacks register...");
349 	bt_le_per_adv_sync_cb_register(&sync_callbacks);
350 	printk("Success.\n");
351 
352 	do {
353 		reset_semaphores();
354 		per_adv_lost = false;
355 
356 		printk("Start scanning...");
357 		err = bt_le_scan_start(BT_LE_SCAN_CUSTOM, NULL);
358 		if (err) {
359 			printk("failed (err %d)\n", err);
360 			return 0;
361 		}
362 		printk("success.\n");
363 
364 #ifdef CONFIG_ISO_BLINK_LED0
365 		printk("Start blinking LED...\n");
366 		led_is_on = false;
367 		blink = true;
368 		gpio_pin_set_dt(&led_gpio, (int)led_is_on);
369 		k_work_reschedule(&blink_work, BLINK_ONOFF);
370 #endif /* CONFIG_ISO_BLINK_LED0 */
371 
372 		printk("Waiting for periodic advertising...\n");
373 		per_adv_found = false;
374 		err = k_sem_take(&sem_per_adv, K_FOREVER);
375 		if (err) {
376 			printk("failed (err %d)\n", err);
377 			return 0;
378 		}
379 		printk("Found periodic advertising.\n");
380 
381 		printk("Stop scanning...");
382 		err = bt_le_scan_stop();
383 		if (err) {
384 			printk("failed (err %d)\n", err);
385 			return 0;
386 		}
387 		printk("success.\n");
388 
389 		printk("Creating Periodic Advertising Sync...");
390 		bt_addr_le_copy(&sync_create_param.addr, &per_addr);
391 		sync_create_param.options = 0;
392 		sync_create_param.sid = per_sid;
393 		sync_create_param.skip = 0;
394 		/* Multiple PA interval with retry count and convert to unit of 10 ms */
395 		sync_create_param.timeout = (per_interval_us * PA_RETRY_COUNT) /
396 						(10 * USEC_PER_MSEC);
397 		sem_timeout_us = per_interval_us * PA_RETRY_COUNT;
398 		err = bt_le_per_adv_sync_create(&sync_create_param, &sync);
399 		if (err) {
400 			printk("failed (err %d)\n", err);
401 			return 0;
402 		}
403 		printk("success.\n");
404 
405 		printk("Waiting for periodic sync...\n");
406 		err = k_sem_take(&sem_per_sync, K_USEC(sem_timeout_us));
407 		if (err) {
408 			printk("failed (err %d)\n", err);
409 
410 			printk("Deleting Periodic Advertising Sync...");
411 			err = bt_le_per_adv_sync_delete(sync);
412 			if (err) {
413 				printk("failed (err %d)\n", err);
414 				return 0;
415 			}
416 			continue;
417 		}
418 		printk("Periodic sync established.\n");
419 
420 		printk("Waiting for BIG info...\n");
421 		err = k_sem_take(&sem_per_big_info, K_USEC(sem_timeout_us));
422 		if (err) {
423 			printk("failed (err %d)\n", err);
424 
425 			if (per_adv_lost) {
426 				continue;
427 			}
428 
429 			printk("Deleting Periodic Advertising Sync...");
430 			err = bt_le_per_adv_sync_delete(sync);
431 			if (err) {
432 				printk("failed (err %d)\n", err);
433 				return 0;
434 			}
435 			continue;
436 		}
437 		printk("Periodic sync established.\n");
438 
439 big_sync_create:
440 		printk("Create BIG Sync...\n");
441 		err = bt_iso_big_sync(sync, &big_sync_param, &big);
442 		if (err) {
443 			printk("failed (err %d)\n", err);
444 			return 0;
445 		}
446 		printk("success.\n");
447 
448 		for (uint8_t chan = 0U; chan < BIS_ISO_CHAN_COUNT; chan++) {
449 			printk("Waiting for BIG sync chan %u...\n", chan);
450 			err = k_sem_take(&sem_big_sync, TIMEOUT_SYNC_CREATE);
451 			if (err) {
452 				break;
453 			}
454 			printk("BIG sync chan %u successful.\n", chan);
455 		}
456 		if (err) {
457 			printk("failed (err %d)\n", err);
458 
459 			printk("BIG Sync Terminate...");
460 			err = bt_iso_big_terminate(big);
461 			if (err) {
462 				printk("failed (err %d)\n", err);
463 				return 0;
464 			}
465 			printk("done.\n");
466 
467 			goto per_sync_lost_check;
468 		}
469 		printk("BIG sync established.\n");
470 
471 #ifdef CONFIG_ISO_BLINK_LED0
472 		printk("Stop blinking LED.\n");
473 		blink = false;
474 		/* If this fails, we'll exit early in the handler because blink
475 		 * is false.
476 		 */
477 		k_work_cancel_delayable(&blink_work);
478 
479 		/* Keep LED on */
480 		led_is_on = true;
481 		gpio_pin_set_dt(&led_gpio, (int)led_is_on);
482 #endif /* CONFIG_ISO_BLINK_LED0 */
483 
484 		for (uint8_t chan = 0U; chan < BIS_ISO_CHAN_COUNT; chan++) {
485 			printk("Waiting for BIG sync lost chan %u...\n", chan);
486 			err = k_sem_take(&sem_big_sync_lost, K_FOREVER);
487 			if (err) {
488 				printk("failed (err %d)\n", err);
489 				return 0;
490 			}
491 			printk("BIG sync lost chan %u.\n", chan);
492 		}
493 		printk("BIG sync lost.\n");
494 
495 per_sync_lost_check:
496 		printk("Check for periodic sync lost...\n");
497 		err = k_sem_take(&sem_per_sync_lost, K_NO_WAIT);
498 		if (err) {
499 			/* Periodic Sync active, go back to creating BIG Sync */
500 			goto big_sync_create;
501 		}
502 		printk("Periodic sync lost.\n");
503 	} while (true);
504 }
505