| /* |
| * Copyright (c) 2021 Nordic Semiconductor ASA |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <bluetooth/bluetooth.h> |
| #include <bluetooth/iso.h> |
| #include <sys/byteorder.h> |
| |
| #define BIG_TERMINATE_TIMEOUT 60 /* seconds */ |
| |
| #define BIS_ISO_CHAN_COUNT 1 |
| NET_BUF_POOL_FIXED_DEFINE(bis_tx_pool, BIS_ISO_CHAN_COUNT, |
| BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), 8, NULL); |
| |
| static K_SEM_DEFINE(sem_big_cmplt, 0, 1); |
| static K_SEM_DEFINE(sem_big_term, 0, 1); |
| |
| static void iso_connected(struct bt_iso_chan *chan) |
| { |
| printk("ISO Channel %p connected\n", chan); |
| k_sem_give(&sem_big_cmplt); |
| } |
| |
| static void iso_disconnected(struct bt_iso_chan *chan, uint8_t reason) |
| { |
| printk("ISO Channel %p disconnected with reason 0x%02x\n", |
| chan, reason); |
| k_sem_give(&sem_big_term); |
| } |
| |
| static struct bt_iso_chan_ops iso_ops = { |
| .connected = iso_connected, |
| .disconnected = iso_disconnected, |
| }; |
| |
| static struct bt_iso_chan_io_qos iso_tx_qos = { |
| .sdu = sizeof(uint32_t), /* bytes */ |
| .rtn = 2, |
| .phy = BT_GAP_LE_PHY_2M, |
| }; |
| |
| static struct bt_iso_chan_qos bis_iso_qos = { |
| .tx = &iso_tx_qos, |
| }; |
| |
| static struct bt_iso_chan bis_iso_chan = { |
| .ops = &iso_ops, |
| .qos = &bis_iso_qos, |
| }; |
| |
| static struct bt_iso_chan *bis[BIS_ISO_CHAN_COUNT] = { &bis_iso_chan }; |
| |
| static struct bt_iso_big_create_param big_create_param = { |
| .num_bis = BIS_ISO_CHAN_COUNT, |
| .bis_channels = bis, |
| .interval = 10000, /* in microseconds */ |
| .latency = 10, /* milliseconds */ |
| .packing = 0, /* 0 - sequential, 1 - interleaved */ |
| .framing = 0, /* 0 - unframed, 1 - framed */ |
| }; |
| |
| void main(void) |
| { |
| struct bt_le_ext_adv *adv; |
| struct bt_iso_big *big; |
| int err; |
| uint32_t iso_send_count = 0; |
| uint8_t iso_data[sizeof(iso_send_count)] = { 0 }; |
| struct net_buf *buf; |
| |
| printk("Starting ISO Broadcast Demo\n"); |
| |
| /* Initialize the Bluetooth Subsystem */ |
| err = bt_enable(NULL); |
| if (err) { |
| printk("Bluetooth init failed (err %d)\n", err); |
| return; |
| } |
| |
| /* Create a non-connectable non-scannable advertising set */ |
| err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN_NAME, NULL, &adv); |
| if (err) { |
| printk("Failed to create advertising set (err %d)\n", err); |
| return; |
| } |
| |
| /* Set periodic advertising parameters */ |
| err = bt_le_per_adv_set_param(adv, BT_LE_PER_ADV_DEFAULT); |
| if (err) { |
| printk("Failed to set periodic advertising parameters" |
| " (err %d)\n", err); |
| return; |
| } |
| |
| /* Enable Periodic Advertising */ |
| err = bt_le_per_adv_start(adv); |
| if (err) { |
| printk("Failed to enable periodic advertising (err %d)\n", err); |
| return; |
| } |
| |
| /* Start extended advertising */ |
| err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); |
| if (err) { |
| printk("Failed to start extended advertising (err %d)\n", err); |
| return; |
| } |
| |
| /* Create BIG */ |
| err = bt_iso_big_create(adv, &big_create_param, &big); |
| if (err) { |
| printk("Failed to create BIG (err %d)\n", err); |
| return; |
| } |
| |
| printk("Waiting for BIG complete..."); |
| err = k_sem_take(&sem_big_cmplt, K_FOREVER); |
| if (err) { |
| printk("failed (err %d)\n", err); |
| return; |
| } |
| printk("done.\n"); |
| |
| while (true) { |
| static uint8_t timeout = BIG_TERMINATE_TIMEOUT; |
| int ret; |
| |
| k_sleep(K_SECONDS(1)); |
| |
| buf = net_buf_alloc(&bis_tx_pool, K_FOREVER); |
| net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); |
| sys_put_le32(++iso_send_count, iso_data); |
| net_buf_add_mem(buf, iso_data, sizeof(iso_data)); |
| ret = bt_iso_chan_send(&bis_iso_chan, buf); |
| if (ret < 0) { |
| printk("Unable to broadcast data: %d", ret); |
| net_buf_unref(buf); |
| return; |
| } |
| printk("Sending value %u\n", iso_send_count); |
| |
| timeout--; |
| if (!timeout) { |
| timeout = BIG_TERMINATE_TIMEOUT; |
| |
| printk("BIG Terminate..."); |
| err = bt_iso_big_terminate(big); |
| if (err) { |
| printk("failed (err %d)\n", err); |
| return; |
| } |
| printk("done.\n"); |
| |
| printk("Waiting for BIG terminate complete..."); |
| err = k_sem_take(&sem_big_term, K_FOREVER); |
| if (err) { |
| printk("failed (err %d)\n", err); |
| return; |
| } |
| printk("done.\n"); |
| |
| printk("Create BIG..."); |
| err = bt_iso_big_create(adv, &big_create_param, &big); |
| if (err) { |
| printk("failed (err %d)\n", err); |
| return; |
| } |
| printk("done.\n"); |
| |
| printk("Waiting for BIG complete..."); |
| err = k_sem_take(&sem_big_cmplt, K_FOREVER); |
| if (err) { |
| printk("failed (err %d)\n", err); |
| return; |
| } |
| printk("done.\n"); |
| } |
| } |
| } |