Skip to content

Commit a7eeea1

Browse files
lylezhu2012kartben
authored andcommitted
Bluetooth: tester: Support feature ISO broadcaster
Add command `BTP_GAP_CREATE_BIG` to create BIG. Add command `BTP_GAP_BIS_BROADCAST` to send broadcast data. Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
1 parent 33fc4a8 commit a7eeea1

File tree

2 files changed

+225
-4
lines changed

2 files changed

+225
-4
lines changed

tests/bluetooth/tester/src/btp/btp_gap.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,30 @@ struct btp_gap_big_create_sync_cmd {
363363
uint8_t broadcast_code[0];
364364
} __packed;
365365

366+
#define BTP_GAP_CREATE_BIG_ENC_DISABLE 0x00
367+
#define BTP_GAP_CREATE_BIG_ENC_ENABLE 0x01
368+
369+
#define BTP_GAP_CREATE_BIG 0x2d
370+
struct btp_gap_create_big_cmd {
371+
uint8_t id;
372+
uint8_t num_bis;
373+
uint32_t interval;
374+
uint16_t latency;
375+
uint8_t rtn;
376+
uint8_t phy;
377+
uint8_t packing;
378+
uint8_t framing;
379+
uint8_t encryption;
380+
uint8_t broadcast_code[0];
381+
} __packed;
382+
383+
#define BTP_GAP_BIS_BROADCAST 0x2e
384+
struct btp_gap_bis_broadcast_cmd {
385+
uint8_t bis_id;
386+
uint8_t data_len;
387+
uint8_t data[];
388+
} __packed;
389+
366390
#define BTP_GAP_SET_RPA_TIMEOUT 0x30
367391
struct btp_gap_set_rpa_timeout_cmd {
368392
uint16_t rpa_timeout;

tests/bluetooth/tester/src/btp_gap.c

Lines changed: 201 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2365,6 +2365,10 @@ static uint8_t set_rpa_timeout(const void *cmd, uint16_t cmd_len, void *rsp, uin
23652365
}
23662366
#endif /* defined(CONFIG_BT_RPA_TIMEOUT_DYNAMIC) */
23672367

2368+
#if defined(CONFIG_BT_ISO_SYNC_RECEIVER) || defined(CONFIG_BT_ISO_BROADCASTER)
2369+
static int bt_iso_chan_get_index(struct bt_iso_chan *chan);
2370+
#endif /* defined(CONFIG_BT_ISO_SYNC_RECEIVER) || defined(CONFIG_BT_ISO_BROADCASTER) */
2371+
23682372
#if defined(CONFIG_BT_ISO_SYNC_RECEIVER)
23692373
static struct bt_iso_big *iso_sync_receiver_big;
23702374

@@ -2442,8 +2446,6 @@ BUILD_ASSERT(BIS_STREAM_DATA_LEN < BTP_DATA_MAX_SIZE, "BIS stream data length ex
24422446

24432447
static struct net_buf_simple *iso_sync_receiver_buf = NET_BUF_SIMPLE(BIS_STREAM_DATA_LEN);
24442448

2445-
static int bt_iso_chan_get_index(struct bt_iso_chan *chan);
2446-
24472449
static void iso_sync_receiver_recv(struct bt_iso_chan *chan, const struct bt_iso_recv_info *info,
24482450
struct net_buf *buf)
24492451
{
@@ -2525,7 +2527,57 @@ static struct bt_iso_chan_ops iso_sync_receiver_ops = {
25252527
.connected = iso_sync_receiver_connected,
25262528
.disconnected = iso_sync_receiver_disconnected,
25272529
};
2530+
#endif /* defined(CONFIG_BT_ISO_SYNC_RECEIVER) */
2531+
2532+
#if defined(CONFIG_BT_ISO_BROADCASTER)
2533+
static uint32_t bis_sn_last;
2534+
static int64_t bis_sn_last_updated_ticks;
2535+
static uint32_t bis_sdu_interval_us;
2536+
2537+
static void iso_broadcaster_connected(struct bt_iso_chan *chan)
2538+
{
2539+
int err;
2540+
const struct bt_iso_chan_path hci_path = {
2541+
.pid = BT_ISO_DATA_PATH_HCI,
2542+
.format = BT_HCI_CODING_FORMAT_TRANSPARENT,
2543+
};
2544+
struct btp_gap_bis_data_path_setup_ev ev;
2545+
struct bt_le_ext_adv *ext_adv = tester_gap_ext_adv_get(0);
25282546

2547+
err = bt_iso_chan_get_index(chan);
2548+
if (err < 0) {
2549+
LOG_ERR("Failed to get BIS channel index: %d", err);
2550+
return;
2551+
}
2552+
ev.bis_id = (uint8_t)err;
2553+
2554+
bis_sn_last = 0;
2555+
bis_sn_last_updated_ticks = k_uptime_ticks();
2556+
2557+
err = bt_iso_setup_data_path(chan, BT_HCI_DATAPATH_DIR_HOST_TO_CTLR, &hci_path);
2558+
if (err != 0) {
2559+
LOG_ERR("Failed to setup ISO TX data path: %d", err);
2560+
return;
2561+
}
2562+
2563+
bt_addr_le_copy(&ev.address, &ext_adv->random_addr);
2564+
2565+
tester_event(BTP_SERVICE_ID_GAP, BTP_GAP_EV_BIS_DATA_PATH_SETUP, &ev, sizeof(ev));
2566+
}
2567+
2568+
static void iso_broadcaster_disconnected(struct bt_iso_chan *chan, uint8_t reason)
2569+
{
2570+
ARG_UNUSED(chan);
2571+
ARG_UNUSED(reason);
2572+
}
2573+
2574+
static struct bt_iso_chan_ops iso_broadcaster_ops = {
2575+
.connected = iso_broadcaster_connected,
2576+
.disconnected = iso_broadcaster_disconnected,
2577+
};
2578+
#endif /* defined(CONFIG_BT_ISO_BROADCASTER) */
2579+
2580+
#if defined(CONFIG_BT_ISO_SYNC_RECEIVER) || defined(CONFIG_BT_ISO_BROADCASTER)
25292581
static struct bt_iso_chan_qos bis_iso_qos;
25302582

25312583
static struct bt_iso_chan bis_iso_chan = {
@@ -2534,8 +2586,6 @@ static struct bt_iso_chan bis_iso_chan = {
25342586

25352587
#define DEFAULT_IO_QOS {.sdu = 40u, .phy = BT_GAP_LE_PHY_2M, .rtn = 2u,}
25362588

2537-
static struct bt_iso_chan_io_qos iso_sync_receiver_qos = DEFAULT_IO_QOS;
2538-
25392589
#define BIS_ISO_CHAN_COUNT 1
25402590

25412591
static struct bt_iso_chan *bis_channels[BIS_ISO_CHAN_COUNT] = { &bis_iso_chan };
@@ -2549,6 +2599,10 @@ static int bt_iso_chan_get_index(struct bt_iso_chan *chan)
25492599
}
25502600
return -EINVAL;
25512601
}
2602+
#endif /* defined(CONFIG_BT_ISO_SYNC_RECEIVER) || defined(CONFIG_BT_ISO_BROADCASTER) */
2603+
2604+
#if defined(CONFIG_BT_ISO_SYNC_RECEIVER)
2605+
static struct bt_iso_chan_io_qos iso_sync_receiver_qos = DEFAULT_IO_QOS;
25522606

25532607
static uint8_t big_create_sync(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
25542608
{
@@ -2606,6 +2660,137 @@ static uint8_t big_create_sync(const void *cmd, uint16_t cmd_len, void *rsp, uin
26062660
}
26072661
#endif /* defined(CONFIG_BT_ISO_SYNC_RECEIVER) */
26082662

2663+
#if defined(CONFIG_BT_ISO_BROADCASTER)
2664+
static struct bt_iso_chan_io_qos iso_broadcaster_qos = DEFAULT_IO_QOS;
2665+
2666+
static struct bt_iso_big *iso_broadcaster_big;
2667+
2668+
static uint8_t create_big(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
2669+
{
2670+
int err;
2671+
const struct btp_gap_create_big_cmd *cp = cmd;
2672+
struct bt_iso_big_create_param param = {0};
2673+
struct bt_le_ext_adv *ext_adv = tester_gap_ext_adv_get(0);
2674+
2675+
if ((cmd_len < sizeof(*cp)) ||
2676+
(cmd_len != (sizeof(*cp) + sizeof(param.bcode) * cp->encryption))) {
2677+
LOG_ERR("Invalid cmd len");
2678+
return BTP_STATUS_FAILED;
2679+
}
2680+
2681+
if (!(cp->encryption == BTP_GAP_CREATE_BIG_ENC_DISABLE ||
2682+
cp->encryption == BTP_GAP_CREATE_BIG_ENC_ENABLE)) {
2683+
LOG_ERR("Invalid encryption %u", cp->encryption);
2684+
return BTP_STATUS_FAILED;
2685+
}
2686+
2687+
if ((ext_adv == NULL) || (cp->id != ext_adv->id)) {
2688+
LOG_ERR("Invalid extended adv");
2689+
return BTP_STATUS_FAILED;
2690+
}
2691+
2692+
if (cp->num_bis > ARRAY_SIZE(bis_channels)) {
2693+
LOG_ERR("BIS num exceeds %u > %u", cp->num_bis, ARRAY_SIZE(bis_channels));
2694+
return BTP_STATUS_FAILED;
2695+
}
2696+
2697+
bis_iso_qos.rx = NULL;
2698+
bis_iso_qos.tx = &iso_broadcaster_qos;
2699+
bis_iso_qos.tx->phy = cp->phy;
2700+
bis_iso_qos.tx->rtn = cp->rtn;
2701+
bis_iso_qos.tx->sdu = CONFIG_BT_ISO_TX_MTU;
2702+
2703+
bis_iso_chan.ops = &iso_broadcaster_ops;
2704+
2705+
param.bis_channels = bis_channels;
2706+
param.num_bis = cp->num_bis;
2707+
param.interval = sys_le32_to_cpu(cp->interval);
2708+
param.packing = cp->packing;
2709+
param.framing = cp->framing;
2710+
param.latency = sys_le16_to_cpu(cp->latency);
2711+
2712+
param.encryption = cp->encryption == BTP_GAP_CREATE_BIG_ENC_ENABLE;
2713+
if (param.encryption) {
2714+
memcpy(param.bcode, cp->broadcast_code, sizeof(param.bcode));
2715+
}
2716+
2717+
bis_sdu_interval_us = param.interval;
2718+
2719+
err = bt_iso_big_create(ext_adv, &param, &iso_broadcaster_big);
2720+
if (err != 0) {
2721+
LOG_ERR("Unable to create BIG (err %d)", err);
2722+
return BTP_STATUS_FAILED;
2723+
}
2724+
2725+
LOG_DBG("BIG created");
2726+
2727+
return BTP_STATUS_SUCCESS;
2728+
}
2729+
2730+
NET_BUF_POOL_FIXED_DEFINE(bis_tx_pool, BIS_ISO_CHAN_COUNT,
2731+
BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU),
2732+
CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
2733+
2734+
static uint32_t get_next_sn(uint32_t last_sn, int64_t *last_ticks,
2735+
uint32_t interval_us)
2736+
{
2737+
int64_t uptime_ticks, delta_ticks;
2738+
uint64_t delta_us;
2739+
uint64_t sn_incr;
2740+
uint64_t next_sn;
2741+
2742+
/* Note: This does not handle wrapping of ticks when they go above
2743+
* 2^(62-1)
2744+
*/
2745+
uptime_ticks = k_uptime_ticks();
2746+
delta_ticks = uptime_ticks - *last_ticks;
2747+
*last_ticks = uptime_ticks;
2748+
2749+
delta_us = k_ticks_to_us_near64((uint64_t)delta_ticks);
2750+
sn_incr = delta_us / interval_us;
2751+
next_sn = (sn_incr + last_sn);
2752+
2753+
return (uint32_t)next_sn;
2754+
}
2755+
2756+
static uint8_t bis_broadcast(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
2757+
{
2758+
int err;
2759+
const struct btp_gap_bis_broadcast_cmd *cp = cmd;
2760+
struct net_buf *buf;
2761+
2762+
buf = net_buf_alloc(&bis_tx_pool, K_NO_WAIT);
2763+
if (buf == NULL) {
2764+
LOG_ERR("Failed to allocate buffer");
2765+
return BTP_STATUS_FAILED;
2766+
}
2767+
2768+
net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
2769+
2770+
if (cp->data_len > net_buf_tailroom(buf)) {
2771+
net_buf_unref(buf);
2772+
LOG_ERR("Data length exceeds buffer tailroom");
2773+
return BTP_STATUS_FAILED;
2774+
}
2775+
2776+
bis_sn_last = get_next_sn(bis_sn_last, &bis_sn_last_updated_ticks,
2777+
bis_sdu_interval_us);
2778+
2779+
net_buf_add_mem(buf, cp->data, cp->data_len);
2780+
2781+
err = bt_iso_chan_send(&bis_iso_chan, buf, bis_sn_last);
2782+
if (err < 0) {
2783+
LOG_ERR("Unable to broadcast: %d", -err);
2784+
net_buf_unref(buf);
2785+
return BTP_STATUS_FAILED;
2786+
}
2787+
2788+
LOG_DBG("ISO broadcasting..., sn %u len %u", bis_sn_last, cp->data_len);
2789+
2790+
return BTP_STATUS_SUCCESS;
2791+
}
2792+
#endif /* defined(CONFIG_BT_ISO_BROADCASTER) */
2793+
26092794
static const struct btp_handler handlers[] = {
26102795
{
26112796
.opcode = BTP_GAP_READ_SUPPORTED_COMMANDS,
@@ -2808,6 +2993,18 @@ static const struct btp_handler handlers[] = {
28082993
.func = big_create_sync,
28092994
},
28102995
#endif /* defined(CONFIG_BT_ISO_SYNC_RECEIVER) */
2996+
#if defined(CONFIG_BT_ISO_BROADCASTER)
2997+
{
2998+
.opcode = BTP_GAP_CREATE_BIG,
2999+
.expect_len = BTP_HANDLER_LENGTH_VARIABLE,
3000+
.func = create_big,
3001+
},
3002+
{
3003+
.opcode = BTP_GAP_BIS_BROADCAST,
3004+
.expect_len = BTP_HANDLER_LENGTH_VARIABLE,
3005+
.func = bis_broadcast,
3006+
},
3007+
#endif /* defined(CONFIG_BT_ISO_BROADCASTER) */
28113008
};
28123009

28133010
uint8_t tester_init_gap(void)

0 commit comments

Comments
 (0)