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

It also splits the latency parameter into one for
C_To_P and one for P_To_C

Signed-off-by: Andries Kruithof <[email protected]>

Bluetooth: ISO: update UI for extended API

The API for setting the SDU interval and latency have been updated.
This PR also updates the setting of these by the user in the shell
and the iso_connected_benchmark sample

Signed-off-by: Andries Kruithof <[email protected]>
  • Loading branch information
kruithofa authored and carlescufi committed Oct 23, 2023
1 parent 1f60c13 commit 8b3b8cf
Show file tree
Hide file tree
Showing 8 changed files with 323 additions and 117 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
7 changes: 5 additions & 2 deletions samples/bluetooth/central_iso/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ static struct bt_conn *default_conn;
static struct k_work_delayable iso_send_work;
static struct bt_iso_chan iso_chan;
static uint16_t seq_num;
static uint16_t latency_ms = 10U; /* 10ms */
static uint32_t interval_us = 10U * USEC_PER_MSEC; /* 10 ms */
NET_BUF_POOL_FIXED_DEFINE(tx_pool, 1, BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU),
CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
Expand Down Expand Up @@ -251,8 +252,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 = 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 */

err = bt_iso_cig_create(&param, &cig);

Expand Down
87 changes: 62 additions & 25 deletions samples/bluetooth/iso_connected_benchmark/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ enum benchmark_role {
ROLE_QUIT
};

enum sdu_dir {
DIR_C_TO_P,
DIR_P_TO_C
};

#define DEFAULT_CIS_RTN 2
#define DEFAULT_CIS_INTERVAL_US 7500
#define DEFAULT_CIS_LATENCY_MS 40
Expand Down Expand Up @@ -116,8 +121,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 +186,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 +212,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 @@ -535,22 +546,25 @@ static int parse_rtn_arg(struct bt_iso_chan_io_qos *qos)
return (int)rtn;
}

static int parse_interval_arg(void)
static int parse_interval_arg(enum sdu_dir direction)
{
char buffer[9];
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 = (direction == DIR_C_TO_P) ?
cig_create_param.c_to_p_interval : cig_create_param.p_to_c_interval;

printk("Set %s interval (us) (current %llu, default %u)\n",
(direction == DIR_C_TO_P) ? "C to P" : "P to C",
interval, DEFAULT_CIS_INTERVAL_US);

char_count = get_chars(buffer, sizeof(buffer) - 1);
if (char_count == 0) {
return DEFAULT_CIS_INTERVAL_US;
}

interval = strtoul(buffer, NULL, 0);
/* TODO: Replace literal ints with a #define once it has been created */
if (interval < BT_ISO_SDU_INTERVAL_MIN || interval > BT_ISO_SDU_INTERVAL_MAX) {
printk("Invalid interval %llu", interval);
return -EINVAL;
Expand All @@ -559,14 +573,18 @@ static int parse_interval_arg(void)
return (int)interval;
}

static int parse_latency_arg(void)
static int parse_latency_arg(enum sdu_dir direction)
{
char buffer[6];
size_t char_count;
uint64_t latency;

printk("Set latency (ms) (current %u, default %u)\n",
cig_create_param.latency, DEFAULT_CIS_LATENCY_MS);
latency = (direction == DIR_C_TO_P) ?
cig_create_param.c_to_p_latency : cig_create_param.p_to_c_latency;

printk("Set %s latency (ms) (current %llu, default %u)\n",
(direction == DIR_C_TO_P) ? "C to P" : "P to C",
latency, DEFAULT_CIS_LATENCY_MS);

char_count = get_chars(buffer, sizeof(buffer) - 1);
if (char_count == 0) {
Expand Down Expand Up @@ -805,8 +823,10 @@ static int parse_cis_count_arg(void)

static int parse_cig_args(void)
{
int interval;
int latency;
int c_to_p_interval;
int p_to_c_interval;
int c_to_p_latency;
int p_to_c_latency;
int cis_count;
#if defined(CONFIG_BT_ISO_TEST_PARAMS)
int c_to_p_ft;
Expand All @@ -822,13 +842,23 @@ static int parse_cig_args(void)
return -EINVAL;
}

interval = parse_interval_arg();
if (interval < 0) {
c_to_p_interval = parse_interval_arg(DIR_C_TO_P);
if (c_to_p_interval < 0) {
return -EINVAL;
}

p_to_c_interval = parse_interval_arg(DIR_P_TO_C);
if (p_to_c_interval < 0) {
return -EINVAL;
}

c_to_p_latency = parse_latency_arg(DIR_C_TO_P);
if (c_to_p_latency < 0) {
return -EINVAL;
}

latency = parse_latency_arg();
if (latency < 0) {
p_to_c_latency = parse_latency_arg(DIR_P_TO_C);
if (p_to_c_latency < 0) {
return -EINVAL;
}

Expand All @@ -854,8 +884,10 @@ static int parse_cig_args(void)
}
#endif /* CONFIG_BT_ISO_TEST_PARAMS */

cig_create_param.interval = interval;
cig_create_param.latency = latency;
cig_create_param.c_to_p_interval = c_to_p_interval;
cig_create_param.p_to_c_interval = p_to_c_interval;
cig_create_param.c_to_p_latency = c_to_p_latency;
cig_create_param.p_to_c_latency = p_to_c_latency;
cig_create_param.num_cis = cis_count;
#if defined(CONFIG_BT_ISO_TEST_PARAMS)
cig_create_param.c_to_p_ft = c_to_p_ft;
Expand Down Expand Up @@ -923,9 +955,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 +968,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 @@ -2090,8 +2090,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;

if (group_param != NULL) {
Expand Down
52 changes: 34 additions & 18 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 All @@ -1622,10 +1626,10 @@ static struct net_buf *hci_le_set_cig_test_params(const struct bt_iso_cig *cig,
req->framing = param->framing;
req->num_cis = param->num_cis;

LOG_DBG("id %u, SDU interval %u, c_ft %u, p_ft %u, iso_interval %u, "
"sca %u, packing %u, framing %u, num_cis %u",
cig->id, param->interval, param->c_to_p_ft, param->p_to_c_ft,
param->iso_interval, param->sca, param->packing,
LOG_DBG("id %u, SDU interval C to P %u, SDU interval P to C %u, c_ft %u, p_ft %u, "
"iso_interval %u, sca %u, packing %u, framing %u, num_cis %u",
cig->id, param->c_to_p_interval, param->p_to_c_interval, param->c_to_p_ft,
param->p_to_c_ft, param->iso_interval, param->sca, param->packing,
param->framing, param->num_cis);

/* Program the cis parameters */
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 C to P 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 P to C 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 P to C latency: %u", param->p_to_c_latency);
return false;
}

Expand Down
Loading

0 comments on commit 8b3b8cf

Please sign in to comment.