Skip to content

tests: Bluetooth: ISO: Add validation of unicast info #81029

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions include/zephyr/bluetooth/hci_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -3375,6 +3375,15 @@ struct bt_hci_evt_le_past_received {
uint8_t clock_accuracy;
} __packed;

#define BT_HCI_LE_CIG_SYNC_DELAY_MIN 0x0000F2U
#define BT_HCI_LE_CIG_SYNC_DELAY_MAX 0x7FFFFFU
#define BT_HCI_LE_CIS_SYNC_DELAY_MIN 0x0000F2U
#define BT_HCI_LE_CIS_SYNC_DELAY_MAX 0x7FFFFFU
#define BT_HCI_LE_TRANSPORT_LATENCY_C_TO_P_MIN 0x0000F2U
#define BT_HCI_LE_TRANSPORT_LATENCY_C_TO_P_MAX 0x7FFFFFU
#define BT_HCI_LE_TRANSPORT_LATENCY_P_TO_C_MIN 0x0000F2U
#define BT_HCI_LE_TRANSPORT_LATENCY_P_TO_C_MAX 0x7FFFFFU

#define BT_HCI_EVT_LE_CIS_ESTABLISHED 0x19
struct bt_hci_evt_le_cis_established {
uint8_t status;
Expand Down
141 changes: 99 additions & 42 deletions tests/bsim/bluetooth/host/iso/cis/src/cis_central.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@
extern enum bst_result_t bst_result;
static struct bt_iso_chan iso_chans[CONFIG_BT_ISO_MAX_CHAN];
static struct bt_iso_chan *default_chan = &iso_chans[0];
static struct bt_iso_cig_param cig_param;
static struct bt_iso_cig *cig;
static uint16_t seq_num;
static volatile size_t enqueue_cnt;
static uint32_t latency_ms = 10U; /* 10ms */
static uint32_t latency_ms = 10U; /* 10ms */
static uint32_t interval_us = 10U * USEC_PER_MSEC; /* 10 ms */
NET_BUF_POOL_FIXED_DEFINE(tx_pool, ENQUEUE_COUNT, BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU),
CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
Expand Down Expand Up @@ -122,13 +123,72 @@ static void iso_connected(struct bt_iso_chan *chan)
.pid = BT_ISO_DATA_PATH_HCI,
.format = BT_HCI_CODING_FORMAT_TRANSPARENT,
};
struct bt_iso_info info;
int err;

printk("ISO Channel %p connected\n", chan);

seq_num = 0U;
enqueue_cnt = ENQUEUE_COUNT;

err = bt_iso_chan_get_info(chan, &info);
TEST_ASSERT(err == 0, "Failed to get CIS info: %d", err);

TEST_ASSERT(info.type == BT_ISO_CHAN_TYPE_CENTRAL);
TEST_ASSERT(info.can_send || info.can_recv);
TEST_ASSERT(IN_RANGE(info.iso_interval, BT_ISO_ISO_INTERVAL_MIN, BT_ISO_ISO_INTERVAL_MAX),
"Invalid ISO interval 0x%04x", info.iso_interval);
TEST_ASSERT(IN_RANGE(info.max_subevent, BT_ISO_NSE_MIN, BT_ISO_NSE_MAX),
"Invalid subevent number 0x%02x", info.max_subevent);
TEST_ASSERT(IN_RANGE(info.unicast.cig_sync_delay, BT_HCI_LE_CIG_SYNC_DELAY_MIN,
BT_HCI_LE_CIG_SYNC_DELAY_MAX),
"Invalid CIG sync delay 0x%06x", info.unicast.cig_sync_delay);
TEST_ASSERT(IN_RANGE(info.unicast.cis_sync_delay, BT_HCI_LE_CIS_SYNC_DELAY_MIN,
BT_HCI_LE_CIS_SYNC_DELAY_MAX),
"Invalid CIS sync delay 0x%06x", info.unicast.cis_sync_delay);

if (info.can_send) {
const struct bt_iso_unicast_tx_info *central = &info.unicast.central;

TEST_ASSERT((info.iso_interval % cig_param.c_to_p_interval) == 0U,
"ISO interval %u shall be a multiple of the SDU interval %u",
info.iso_interval, cig_param.c_to_p_interval);
TEST_ASSERT(IN_RANGE(central->latency, BT_HCI_LE_TRANSPORT_LATENCY_C_TO_P_MIN,
BT_HCI_LE_TRANSPORT_LATENCY_C_TO_P_MAX),
"Invalid transport latency 0x%06x", central->latency);
TEST_ASSERT((central->flush_timeout % info.iso_interval) == 0U,
"Flush timeout in ms %u shall be a multiple of the ISO interval %u",
central->flush_timeout, info.iso_interval);
TEST_ASSERT(IN_RANGE(central->max_pdu, BT_ISO_CONNECTED_PDU_MIN, BT_ISO_PDU_MAX),
"Invalid max PDU 0x%04x", central->max_pdu);
TEST_ASSERT(central->phy == BT_GAP_LE_PHY_1M || central->phy == BT_GAP_LE_PHY_2M ||
central->phy == BT_GAP_LE_PHY_CODED,
"Invalid PHY 0x%02x", central->phy);
TEST_ASSERT(IN_RANGE(central->bn, BT_ISO_BN_MIN, BT_ISO_BN_MAX),
"Invalid BN 0x%02x", central->bn);
}
if (info.can_recv) {
const struct bt_iso_unicast_tx_info *peripheral = &info.unicast.peripheral;

TEST_ASSERT((info.iso_interval % cig_param.p_to_c_interval) == 0U,
"ISO interval %u shall be a multiple of the SDU interval %u",
info.iso_interval, cig_param.p_to_c_interval);
TEST_ASSERT(IN_RANGE(peripheral->latency, BT_HCI_LE_TRANSPORT_LATENCY_P_TO_C_MIN,
BT_HCI_LE_TRANSPORT_LATENCY_P_TO_C_MAX),
"Invalid transport latency 0x%06x", peripheral->latency);
TEST_ASSERT((peripheral->flush_timeout % info.iso_interval) == 0U,
"Flush timeout in ms %u shall be a multiple of the ISO interval %u",
peripheral->flush_timeout, info.iso_interval);
TEST_ASSERT(IN_RANGE(peripheral->max_pdu, BT_ISO_CONNECTED_PDU_MIN, BT_ISO_PDU_MAX),
"Invalid max PDU 0x%04x", peripheral->max_pdu);
TEST_ASSERT(peripheral->phy == BT_GAP_LE_PHY_1M ||
peripheral->phy == BT_GAP_LE_PHY_2M ||
peripheral->phy == BT_GAP_LE_PHY_CODED,
"Invalid PHY 0x%02x", peripheral->phy);
TEST_ASSERT(IN_RANGE(peripheral->bn, BT_ISO_BN_MIN, BT_ISO_BN_MAX),
"Invalid BN 0x%02x", peripheral->bn);
}

if (chan == default_chan) {
/* Start send timer */
k_work_schedule(&iso_send_work, K_MSEC(0));
Expand Down Expand Up @@ -207,68 +267,66 @@ static void init(void)
}
}

static void set_cig_defaults(struct bt_iso_cig_param *param)
static void set_cig_defaults(void)
{
param->cis_channels = &default_chan;
param->num_cis = 1U;
param->sca = BT_GAP_SCA_UNKNOWN;
param->packing = BT_ISO_PACKING_SEQUENTIAL;
param->framing = BT_ISO_FRAMING_UNFRAMED;
param->c_to_p_latency = latency_ms; /* ms */
param->p_to_c_latency = latency_ms; /* ms */
param->c_to_p_interval = interval_us; /* us */
param->p_to_c_interval = interval_us; /* us */

cig_param.cis_channels = &default_chan;
cig_param.num_cis = 1U;
cig_param.sca = BT_GAP_SCA_UNKNOWN;
cig_param.packing = BT_ISO_PACKING_SEQUENTIAL;
cig_param.framing = BT_ISO_FRAMING_UNFRAMED;
cig_param.c_to_p_latency = latency_ms; /* ms */
cig_param.p_to_c_latency = latency_ms; /* ms */
cig_param.c_to_p_interval = interval_us; /* us */
cig_param.p_to_c_interval = interval_us; /* us */
}

static void create_cig(size_t iso_channels)
{
struct bt_iso_chan *channels[ARRAY_SIZE(iso_chans)];
struct bt_iso_cig_param param;
int err;

for (size_t i = 0U; i < iso_channels; i++) {
channels[i] = &iso_chans[i];
}

set_cig_defaults(&param);
param.num_cis = iso_channels;
param.cis_channels = channels;
set_cig_defaults();
cig_param.num_cis = iso_channels;
cig_param.cis_channels = channels;

err = bt_iso_cig_create(&param, &cig);
err = bt_iso_cig_create(&cig_param, &cig);
if (err != 0) {
TEST_FAIL("Failed to create CIG (%d)", err);

return;
}
}

static int reconfigure_cig_interval(struct bt_iso_cig_param *param)
static int reconfigure_cig_interval(void)
{
int err;

/* Test modifying CIG parameter without any CIS */
param->num_cis = 0U;
param->c_to_p_interval = 7500; /* us */
param->p_to_c_interval = param->c_to_p_interval;
err = bt_iso_cig_reconfigure(cig, param);
cig_param.num_cis = 0U;
cig_param.c_to_p_interval = 7500; /* us */
cig_param.p_to_c_interval = cig_param.c_to_p_interval;
err = bt_iso_cig_reconfigure(cig, &cig_param);
if (err != 0) {
TEST_FAIL("Failed to reconfigure CIG to new interval (%d)", err);

return err;
}

err = bt_iso_cig_reconfigure(cig, param);
err = bt_iso_cig_reconfigure(cig, &cig_param);
if (err != 0) {
TEST_FAIL("Failed to reconfigure CIG to same interval (%d)", err);

return err;
}

/* Test modifying to different values for both intervals */
param->c_to_p_interval = 5000; /* us */
param->p_to_c_interval = 2500; /* us */
err = bt_iso_cig_reconfigure(cig, param);
cig_param.c_to_p_interval = 5000; /* us */
cig_param.p_to_c_interval = 2500; /* us */
err = bt_iso_cig_reconfigure(cig, &cig_param);
if (err != 0) {
TEST_FAIL("Failed to reconfigure CIG to new interval (%d)", err);

Expand All @@ -278,24 +336,24 @@ static int reconfigure_cig_interval(struct bt_iso_cig_param *param)
return 0;
}

static int reconfigure_cig_latency(struct bt_iso_cig_param *param)
static int reconfigure_cig_latency(void)
{
int err;

/* Test modifying CIG latency without any CIS */
param->num_cis = 0U;
param->c_to_p_latency = 20; /* ms */
param->p_to_c_latency = param->c_to_p_latency;
err = bt_iso_cig_reconfigure(cig, param);
cig_param.num_cis = 0U;
cig_param.c_to_p_latency = 20; /* ms */
cig_param.p_to_c_latency = cig_param.c_to_p_latency;
err = bt_iso_cig_reconfigure(cig, &cig_param);
if (err != 0) {
TEST_FAIL("Failed to reconfigure CIG latency (%d)", err);

return err;
}

param->c_to_p_latency = 30; /* ms */
param->p_to_c_latency = 40; /* ms */
err = bt_iso_cig_reconfigure(cig, param);
cig_param.c_to_p_latency = 30; /* ms */
cig_param.p_to_c_latency = 40; /* ms */
err = bt_iso_cig_reconfigure(cig, &cig_param);
if (err != 0) {
TEST_FAIL("Failed to reconfigure CIG for different latencies (%d)", err);

Expand All @@ -308,42 +366,41 @@ static int reconfigure_cig_latency(struct bt_iso_cig_param *param)
static void reconfigure_cig(void)
{
struct bt_iso_chan *channels[2];
struct bt_iso_cig_param param;
int err;

for (size_t i = 0U; i < ARRAY_SIZE(channels); i++) {
channels[i] = &iso_chans[i];
}

set_cig_defaults(&param);
set_cig_defaults();

/* Test modifying existing CIS */
default_chan->qos->tx->rtn++;

err = bt_iso_cig_reconfigure(cig, &param);
err = bt_iso_cig_reconfigure(cig, &cig_param);
if (err != 0) {
TEST_FAIL("Failed to reconfigure CIS to new RTN (%d)", err);

return;
}

/* Test modifying interval parameter */
err = reconfigure_cig_interval(&param);
err = reconfigure_cig_interval();
if (err != 0) {
return;
}

/* Test modifying latency parameter */
err = reconfigure_cig_latency(&param);
err = reconfigure_cig_latency();
if (err != 0) {
return;
}

/* Add CIS to the CIG and restore all other parameters */
set_cig_defaults(&param);
param.cis_channels = &channels[1];
set_cig_defaults();
cig_param.cis_channels = &channels[1];

err = bt_iso_cig_reconfigure(cig, &param);
err = bt_iso_cig_reconfigure(cig, &cig_param);
if (err != 0) {
TEST_FAIL("Failed to reconfigure CIG with new CIS and original parameters (%d)",
err);
Expand Down
53 changes: 53 additions & 0 deletions tests/bsim/bluetooth/host/iso/cis/src/cis_peripheral.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,65 @@ static void iso_connected(struct bt_iso_chan *chan)
.pid = BT_ISO_DATA_PATH_HCI,
.format = BT_HCI_CODING_FORMAT_TRANSPARENT,
};
struct bt_iso_info info;
int err;

printk("ISO Channel %p connected\n", chan);

err = bt_iso_setup_data_path(chan, BT_HCI_DATAPATH_DIR_CTLR_TO_HOST, &hci_path);
TEST_ASSERT(err == 0, "Failed to set ISO data path: %d", err);

err = bt_iso_chan_get_info(chan, &info);
TEST_ASSERT(err == 0, "Failed to get CIS info: %d", err);

TEST_ASSERT(info.type == BT_ISO_CHAN_TYPE_PERIPHERAL);
TEST_ASSERT(IN_RANGE(info.iso_interval, BT_ISO_ISO_INTERVAL_MIN, BT_ISO_ISO_INTERVAL_MAX),
"Invalid ISO interval 0x%04x", info.iso_interval);
TEST_ASSERT(IN_RANGE(info.max_subevent, BT_ISO_NSE_MIN, BT_ISO_NSE_MAX),
"Invalid subevent number 0x%02x", info.max_subevent);
TEST_ASSERT(IN_RANGE(info.unicast.cig_sync_delay, BT_HCI_LE_CIG_SYNC_DELAY_MIN,
BT_HCI_LE_CIG_SYNC_DELAY_MAX),
"Invalid CIG sync delay 0x%06x", info.unicast.cig_sync_delay);
TEST_ASSERT(IN_RANGE(info.unicast.cis_sync_delay, BT_HCI_LE_CIS_SYNC_DELAY_MIN,
BT_HCI_LE_CIS_SYNC_DELAY_MAX),
"Invalid CIS sync delay 0x%06x", info.unicast.cis_sync_delay);

if (info.can_send) {
const struct bt_iso_unicast_tx_info *peripheral = &info.unicast.peripheral;

TEST_ASSERT(IN_RANGE(peripheral->latency, BT_HCI_LE_TRANSPORT_LATENCY_P_TO_C_MIN,
BT_HCI_LE_TRANSPORT_LATENCY_P_TO_C_MAX),
"Invalid transport latency 0x%06x", peripheral->latency);
TEST_ASSERT((peripheral->flush_timeout % info.iso_interval) == 0U,
"Flush timeout in ms %u shall be a multiple of the ISO interval %u",
peripheral->flush_timeout, info.iso_interval);
TEST_ASSERT(IN_RANGE(peripheral->max_pdu, BT_ISO_CONNECTED_PDU_MIN, BT_ISO_PDU_MAX),
"Invalid max PDU 0x%04x", peripheral->max_pdu);
TEST_ASSERT(peripheral->phy == BT_GAP_LE_PHY_1M ||
peripheral->phy == BT_GAP_LE_PHY_2M ||
peripheral->phy == BT_GAP_LE_PHY_CODED,
"Invalid PHY 0x%02x", peripheral->phy);
TEST_ASSERT(IN_RANGE(peripheral->bn, BT_ISO_BN_MIN, BT_ISO_BN_MAX),
"Invalid BN 0x%02x", peripheral->bn);
}

if (info.can_recv) {
const struct bt_iso_unicast_tx_info *central = &info.unicast.central;

TEST_ASSERT(IN_RANGE(central->latency, BT_HCI_LE_TRANSPORT_LATENCY_C_TO_P_MIN,
BT_HCI_LE_TRANSPORT_LATENCY_C_TO_P_MAX),
"Invalid transport latency 0x%06x", central->latency);
TEST_ASSERT((central->flush_timeout % info.iso_interval) == 0U,
"Flush timeout in ms %u shall be a multiple of the ISO interval %u",
central->flush_timeout, info.iso_interval);
TEST_ASSERT(IN_RANGE(central->max_pdu, BT_ISO_CONNECTED_PDU_MIN, BT_ISO_PDU_MAX),
"Invalid max PDU 0x%04x", central->max_pdu);
TEST_ASSERT(central->phy == BT_GAP_LE_PHY_1M || central->phy == BT_GAP_LE_PHY_2M ||
central->phy == BT_GAP_LE_PHY_CODED,
"Invalid PHY 0x%02x", central->phy);
TEST_ASSERT(IN_RANGE(central->bn, BT_ISO_BN_MIN, BT_ISO_BN_MAX),
"Invalid BN 0x%02x", central->bn);
}
}

static void iso_disconnected(struct bt_iso_chan *chan, uint8_t reason)
Expand Down
Loading