Skip to content

Commit

Permalink
Bluetooth: ISO: extend API for setting SDU interval
Browse files Browse the repository at this point in the history
The BT Core Spec v5.4 allows separate SDU_Interval to
be set on C_To_P and P_To_C directions,
but this is not possible with the existing interface.

This PR splits the interval parameter in the call to
bt_iso_sig_create into one for C_To_P
and one for P_To_C

Signed-off-by: Andries Kruithof <[email protected]>
  • Loading branch information
kruithofa committed Oct 17, 2023
1 parent 5cf6218 commit ab17012
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 49 deletions.
22 changes: 18 additions & 4 deletions include/zephyr/bluetooth/iso.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,19 +335,33 @@ struct bt_iso_cig_param {
*/
uint8_t num_cis;

/** @brief Channel interval in us.
/** @brief Channel interval in us for SDUs sent from Central to Peripheral.
*
* Value range BT_ISO_SDU_INTERVAL_MIN - BT_ISO_SDU_INTERVAL_MAX.
*/
uint32_t interval;
uint32_t c_to_p_interval;

/** @brief Channel Latency in ms.
/** @brief Channel interval in us for SDUs sent from Peripheral to Central.
*
* Value range BT_ISO_SDU_INTERVAL_MIN - BT_ISO_SDU_INTERVAL_MAX.
*/
uint32_t p_to_c_interval;

/** @brief Channel Latency in ms for SDUs sent from Central to Peripheral
*
* Value range BT_ISO_LATENCY_MIN - BT_ISO_LATENCY_MAX.
*
* This value is ignored if any advanced ISO parameters are set.
*/
uint16_t latency;
uint16_t c_to_p_latency;

/** @brief Channel Latency in ms for SDUs sent from Peripheral to Central
*
* Value range BT_ISO_LATENCY_MIN - BT_ISO_LATENCY_MAX.
*
* This value is ignored if any advanced ISO parameters are set.
*/
uint16_t p_to_c_latency;

/** @brief Channel peripherals sleep clock accuracy Only for CIS
*
Expand Down
6 changes: 4 additions & 2 deletions samples/bluetooth/central_iso/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,10 @@ int main(void)
param.sca = BT_GAP_SCA_UNKNOWN;
param.packing = 0;
param.framing = 0;
param.latency = 10; /* ms */
param.interval = interval_us; /* us */
param.c_to_p_latency = 10; /* ms */
param.p_to_c_latency = 10; /* ms */
param.c_to_p_interval = interval_us; /* us */
param.p_to_c_interval = interval_us; /* us */

err = bt_iso_cig_create(&param, &cig);

Expand Down
46 changes: 31 additions & 15 deletions samples/bluetooth/iso_connected_benchmark/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,10 @@ static struct bt_iso_chan_qos iso_qos = {
};

static struct bt_iso_cig_param cig_create_param = {
.interval = DEFAULT_CIS_INTERVAL_US, /* in microseconds */
.latency = DEFAULT_CIS_LATENCY_MS, /* milliseconds */
.c_to_p_interval = DEFAULT_CIS_INTERVAL_US, /* in microseconds */
.p_to_c_interval = DEFAULT_CIS_INTERVAL_US, /* in microseconds */
.c_to_p_latency = DEFAULT_CIS_LATENCY_MS, /* milliseconds */
.p_to_c_latency = DEFAULT_CIS_LATENCY_MS, /* milliseconds */
.sca = BT_GAP_SCA_UNKNOWN,
.packing = DEFAULT_CIS_PACKING,
.framing = DEFAULT_CIS_FRAMING,
Expand Down Expand Up @@ -179,17 +181,21 @@ static void iso_send(struct bt_iso_chan *chan)
int ret;
struct net_buf *buf;
struct iso_chan_work *chan_work;
uint32_t interval;

chan_work = CONTAINER_OF(chan, struct iso_chan_work, chan);

if (!chan_work->info.can_send) {
return;
}

interval = (role == ROLE_CENTRAL) ?
cig_create_param.c_to_p_interval : cig_create_param.p_to_c_interval;

buf = net_buf_alloc(&tx_pool, K_FOREVER);
if (buf == NULL) {
LOG_ERR("Could not allocate buffer");
k_work_reschedule(&chan_work->send_work, K_USEC(cig_create_param.interval));
k_work_reschedule(&chan_work->send_work, K_USEC(interval));
return;
}

Expand All @@ -201,7 +207,7 @@ static void iso_send(struct bt_iso_chan *chan)
if (ret < 0) {
LOG_ERR("Unable to send data: %d", ret);
net_buf_unref(buf);
k_work_reschedule(&chan_work->send_work, K_USEC(cig_create_param.interval));
k_work_reschedule(&chan_work->send_work, K_USEC(interval));
return;
}

Expand Down Expand Up @@ -541,8 +547,11 @@ static int parse_interval_arg(void)
size_t char_count;
uint64_t interval;

printk("Set interval (us) (current %u, default %u)\n",
cig_create_param.interval, DEFAULT_CIS_INTERVAL_US);
interval = (role == ROLE_CENTRAL) ?
cig_create_param.c_to_p_interval : cig_create_param.p_to_c_interval;

printk("Set interval (us) (current %llu, default %u)\n",
interval, DEFAULT_CIS_INTERVAL_US);

char_count = get_chars(buffer, sizeof(buffer) - 1);
if (char_count == 0) {
Expand All @@ -566,7 +575,7 @@ static int parse_latency_arg(void)
uint64_t latency;

printk("Set latency (ms) (current %u, default %u)\n",
cig_create_param.latency, DEFAULT_CIS_LATENCY_MS);
cig_create_param.c_to_p_latency, DEFAULT_CIS_LATENCY_MS);

char_count = get_chars(buffer, sizeof(buffer) - 1);
if (char_count == 0) {
Expand Down Expand Up @@ -854,8 +863,10 @@ static int parse_cig_args(void)
}
#endif /* CONFIG_BT_ISO_ADVANCED */

cig_create_param.interval = interval;
cig_create_param.latency = latency;
cig_create_param.c_to_p_interval = interval;
cig_create_param.p_to_c_interval = interval;
cig_create_param.c_to_p_latency = latency;
cig_create_param.p_to_c_latency = latency;
cig_create_param.num_cis = cis_count;
#if defined(CONFIG_BT_ISO_ADVANCED)
cig_create_param.c_to_p_ft = c_to_p_ft;
Expand Down Expand Up @@ -923,9 +934,11 @@ static int change_central_settings(void)
int err;

printk("Change CIG settings (y/N)? (Current settings: cis_count=%u, "
"interval=%u, latency=%u)\n",
cig_create_param.num_cis, cig_create_param.interval,
cig_create_param.latency);
"C to P interval=%u, P to C interval=%u "
"C to P latency=%u, P to C latency=%u)\n",
cig_create_param.num_cis, cig_create_param.c_to_p_interval,
cig_create_param.p_to_c_interval, cig_create_param.c_to_p_latency,
cig_create_param.p_to_c_latency);

c = tolower(console_getchar());
if (c == 'y') {
Expand All @@ -934,9 +947,12 @@ static int change_central_settings(void)
return err;
}

printk("New settings: cis_count=%u, inteval=%u, latency=%u\n",
cig_create_param.num_cis, cig_create_param.interval,
cig_create_param.latency);
printk("New settings: cis_count=%u, C to P interval=%u, "
"P TO C interval=%u, C to P latency=%u "
"P TO C latency=%u\n",
cig_create_param.num_cis, cig_create_param.c_to_p_interval,
cig_create_param.p_to_c_interval, cig_create_param.c_to_p_latency,
cig_create_param.p_to_c_latency);
}

printk("Change TX settings (y/N)? (Current settings: rtn=%u, "
Expand Down
6 changes: 4 additions & 2 deletions subsys/bluetooth/audio/bap_unicast_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -2089,8 +2089,10 @@ static void bt_audio_codec_qos_to_cig_param(struct bt_iso_cig_param *cig_param,
{
cig_param->framing = qos->framing;
cig_param->packing = BT_ISO_PACKING_SEQUENTIAL; /* TODO: Add to QoS struct */
cig_param->interval = qos->interval;
cig_param->latency = qos->latency;
cig_param->c_to_p_interval = qos->interval;
cig_param->p_to_c_interval = qos->interval;
cig_param->c_to_p_latency = qos->latency;
cig_param->p_to_c_latency = qos->latency;
cig_param->sca = BT_GAP_SCA_UNKNOWN;
}

Expand Down
44 changes: 30 additions & 14 deletions subsys/bluetooth/host/iso.c
Original file line number Diff line number Diff line change
Expand Up @@ -1524,18 +1524,22 @@ static struct net_buf *hci_le_set_cig_params(const struct bt_iso_cig *cig,
memset(req, 0, sizeof(*req));

req->cig_id = cig->id;
req->c_latency = sys_cpu_to_le16(param->latency);
req->p_latency = sys_cpu_to_le16(param->latency);
sys_put_le24(param->interval, req->c_interval);
sys_put_le24(param->interval, req->p_interval);
req->c_latency = sys_cpu_to_le16(param->c_to_p_latency);
req->p_latency = sys_cpu_to_le16(param->p_to_c_latency);
sys_put_le24(param->c_to_p_interval, req->c_interval);
sys_put_le24(param->p_to_c_interval, req->p_interval);

req->sca = param->sca;
req->packing = param->packing;
req->framing = param->framing;
req->num_cis = param->num_cis;

LOG_DBG("id %u, latency %u, interval %u, sca %u, packing %u, framing %u, num_cis %u",
cig->id, param->latency, param->interval, param->sca, param->packing,
LOG_DBG("id %u, latency C to P %u, latency P to C %u, "
"interval C to P %u, interval P to C %u, "
"sca %u, packing %u, framing %u, num_cis %u",
cig->id, param->c_to_p_latency, param->p_to_c_latency,
param->c_to_p_interval, param->p_to_c_interval,
param->sca, param->packing,
param->framing, param->num_cis);

/* Program the cis parameters */
Expand Down Expand Up @@ -1611,8 +1615,8 @@ static struct net_buf *hci_le_set_cig_test_params(const struct bt_iso_cig *cig,
memset(req, 0, sizeof(*req));

req->cig_id = cig->id;
sys_put_le24(param->interval, req->c_interval);
sys_put_le24(param->interval, req->p_interval);
sys_put_le24(param->c_to_p_interval, req->c_interval);
sys_put_le24(param->p_to_c_interval, req->p_interval);

req->c_ft = param->c_to_p_ft;
req->p_ft = param->p_to_c_ft;
Expand Down Expand Up @@ -1859,16 +1863,28 @@ static bool valid_cig_param(const struct bt_iso_cig_param *param, bool advanced,
return false;
}

if (param->interval < BT_ISO_SDU_INTERVAL_MIN ||
param->interval > BT_ISO_SDU_INTERVAL_MAX) {
LOG_DBG("Invalid interval: %u", param->interval);
if (param->c_to_p_interval < BT_ISO_SDU_INTERVAL_MIN ||
param->c_to_p_interval > BT_ISO_SDU_INTERVAL_MAX) {
LOG_DBG("Invalid interval: %u", param->c_to_p_interval);
return false;
}

if (param->p_to_c_interval < BT_ISO_SDU_INTERVAL_MIN ||
param->p_to_c_interval > BT_ISO_SDU_INTERVAL_MAX) {
LOG_DBG("Invalid interval: %u", param->p_to_c_interval);
return false;
}

if (!advanced &&
(param->latency < BT_ISO_LATENCY_MIN ||
param->latency > BT_ISO_LATENCY_MAX)) {
LOG_DBG("Invalid latency: %u", param->latency);
(param->c_to_p_latency < BT_ISO_LATENCY_MIN ||
param->c_to_p_latency > BT_ISO_LATENCY_MAX)) {
LOG_DBG("Invalid C to P latency: %u", param->c_to_p_latency);
return false;
}
if (!advanced &&
(param->p_to_c_latency < BT_ISO_LATENCY_MIN ||
param->p_to_c_latency > BT_ISO_LATENCY_MAX)) {
LOG_DBG("Invalid latency: %u", param->p_to_c_latency);
return false;
}

Expand Down
12 changes: 9 additions & 3 deletions subsys/bluetooth/shell/iso.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,17 @@ static int cmd_cig_create(const struct shell *sh, size_t argc, char *argv[])
return -ENOEXEC;
}

param.interval = interval;
param.c_to_p_interval = interval;
param.p_to_c_interval = interval;
} else {
param.interval = 10000;
param.c_to_p_interval = 10000;
param.p_to_c_interval = 10000;
}
cis_sdu_interval_us = param.interval;
/* cis_sdu_internal_us is used to increase the sequence number
* setting it to the lowest interval number ensures that it
* is increased at least once per interval
*/
cis_sdu_interval_us = MIN(param.c_to_p_interval, param.p_to_c_interval);

if (argc > 3) {
unsigned long packing;
Expand Down
31 changes: 25 additions & 6 deletions tests/bsim/bluetooth/host/iso/cis/src/cis_central.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,10 @@ static void create_cig(void)
param.sca = BT_GAP_SCA_UNKNOWN;
param.packing = BT_ISO_PACKING_SEQUENTIAL;
param.framing = BT_ISO_FRAMING_UNFRAMED;
param.latency = 10U; /* ms */
param.interval = interval_us; /* us */
param.c_to_p_latency = 10U; /* ms */
param.p_to_c_latency = 10U; /* ms */
param.c_to_p_interval = interval_us; /* us */
param.p_to_c_interval = interval_us; /* us */

err = bt_iso_cig_create(&param, &cig);
if (err != 0) {
Expand All @@ -210,8 +212,10 @@ static void reconfigure_cig(void)
param.sca = BT_GAP_SCA_UNKNOWN;
param.packing = BT_ISO_PACKING_SEQUENTIAL;
param.framing = BT_ISO_FRAMING_UNFRAMED;
param.latency = 10U; /* ms */
param.interval = interval_us; /* us */
param.c_to_p_latency = 10U; /* ms */
param.p_to_c_latency = 10U; /* ms */
param.c_to_p_interval = interval_us; /* us */
param.p_to_c_interval = interval_us; /* us */

/* Test modifying existing CIS */
default_chan->qos->tx->rtn++;
Expand All @@ -225,7 +229,8 @@ static void reconfigure_cig(void)

/* Test modifying CIG parameter without any CIS */
param.num_cis = 0U;
param.interval = 7500U; /* us */
param.c_to_p_interval = 7500U; /* us */
param.p_to_c_interval = 7500U; /* us */

err = bt_iso_cig_reconfigure(cig, &param);
if (err != 0) {
Expand All @@ -234,10 +239,24 @@ static void reconfigure_cig(void)
return;
}

/* Test modifying to different values for both intervals */
param.num_cis = 0U;
param.c_to_p_interval = 5000U; /* us */
param.p_to_c_interval = 2500U; /* us */

err = bt_iso_cig_reconfigure(cig, &param);
if (err != 0) {
FAIL("Failed to reconfigure CIG to different intervals (%d)\n", err);

return;
}


/* Add CIS to the CIG and restore interval to 10ms */
param.cis_channels = &channels[1];
param.num_cis = 1U;
param.interval = interval_us; /* us */
param.c_to_p_interval = interval_us; /* us */
param.p_to_c_interval = interval_us; /* us */

err = bt_iso_cig_reconfigure(cig, &param);
if (err != 0) {
Expand Down
9 changes: 6 additions & 3 deletions tests/bsim/bluetooth/ll/cis/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,11 +413,14 @@ static void test_cis_central(void)
cig_param.sca = BT_GAP_SCA_UNKNOWN;
cig_param.packing = 0U;
cig_param.framing = 0U;
cig_param.interval = ISO_INTERVAL_US;
cig_param.c_to_p_interval = ISO_INTERVAL_US;
cig_param.p_to_c_interval = ISO_INTERVAL_US;
if (IS_ENABLED(CONFIG_TEST_FT_SKIP_SUBEVENTS)) {
cig_param.latency = ISO_LATENCY_FT_MS;
cig_param.c_to_p_latency = ISO_LATENCY_FT_MS;
cig_param.p_to_c_latency = ISO_LATENCY_FT_MS;
} else {
cig_param.latency = ISO_LATENCY_MS;
cig_param.c_to_p_latency = ISO_LATENCY_MS;
cig_param.p_to_c_latency = ISO_LATENCY_MS;
}

printk("Create CIG...");
Expand Down

0 comments on commit ab17012

Please sign in to comment.