Skip to content

Commit

Permalink
Bluetooth: Host: Add BT_CONN_INTERVAL_TO_US
Browse files Browse the repository at this point in the history
The macro BT_CONN_INTERVAL_TO_MS was used a fair amount
of places, but it often was used with integers. This meant
that sometimes the resulting (integer) value would be
incorrect, as something like 7.5ms interval would not
be properly stored as a integer in millisecond units.

Adding BT_CONN_INTERVAL_TO_US allows users to still use
integers to store the result, but in a more accurate unit.

Signed-off-by: Emil Gydesen <[email protected]>
  • Loading branch information
Thalley authored and carlescufi committed Jan 8, 2023
1 parent 8a29ed9 commit 57218ee
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 41 deletions.
16 changes: 14 additions & 2 deletions include/zephyr/bluetooth/conn.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,20 @@ struct bt_conn_le_info {
#endif /* defined(CONFIG_BT_USER_DATA_LEN_UPDATE) */
};

/* Multiply bt 1.25 to get MS */
#define BT_CONN_INTERVAL_TO_MS(interval) ((interval) * 5 / 4)
/** @brief Convert connection interval to milliseconds
*
* Multiply by 1.25 to get milliseconds.
*
* Note that this may be inaccurate, as something like 7.5 ms cannot be
* accurately presented with integers.
*/
#define BT_CONN_INTERVAL_TO_MS(interval) ((interval) * 5U / 4U)

/** @brief Convert connection interval to microseconds
*
* Multiply by 1250 to get microseconds.
*/
#define BT_CONN_INTERVAL_TO_US(interval) ((interval) * 1250U)

/** BR/EDR Connection Info Structure */
struct bt_conn_br_info {
Expand Down
36 changes: 20 additions & 16 deletions samples/bluetooth/iso_broadcast_benchmark/src/receiver.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ static bool big_sync_lost;
static bool biginfo_received;
static bt_addr_le_t per_addr;
static uint8_t per_sid;
static uint16_t per_interval_ms;
static uint16_t iso_interval_ms;
static uint32_t per_interval_us;
static uint32_t iso_interval_us;
static uint8_t bis_count;
static uint32_t last_received_counter;
static int64_t big_sync_start_time;
Expand Down Expand Up @@ -107,7 +107,7 @@ static void scan_recv(const struct bt_le_scan_recv_info *info,
broadcaster_found = true;

per_sid = info->sid;
per_interval_ms = BT_CONN_INTERVAL_TO_MS(info->interval);
per_interval_us = BT_CONN_INTERVAL_TO_US(info->interval);
bt_addr_le_copy(&per_addr, info->addr);

k_sem_give(&sem_per_adv);
Expand Down Expand Up @@ -141,17 +141,17 @@ static void biginfo_cb(struct bt_le_per_adv_sync *sync,
return;
}

LOG_INF("BIGinfo received: num_bis %u, nse %u, interval %.2f ms, "
LOG_INF("BIGinfo received: num_bis %u, nse %u, interval %u us, "
"bn %u, pto %u, irc %u, max_pdu %u, sdu_interval %u us, "
"max_sdu %u, phy %s, %s framing, %sencrypted",
biginfo->num_bis, biginfo->sub_evt_count,
BT_CONN_INTERVAL_TO_MS((float)biginfo->iso_interval),
BT_CONN_INTERVAL_TO_US(biginfo->iso_interval),
biginfo->burst_number, biginfo->offset, biginfo->rep_count,
biginfo->max_pdu, biginfo->sdu_interval, biginfo->max_sdu,
phy2str(biginfo->phy), biginfo->framing ? "with" : "without",
biginfo->encryption ? "" : "not ");

iso_interval_ms = BT_CONN_INTERVAL_TO_MS(biginfo->iso_interval);
iso_interval_us = BT_CONN_INTERVAL_TO_US(biginfo->iso_interval);
bis_count = MIN(biginfo->num_bis, CONFIG_BT_ISO_MAX_CHAN);
biginfo_received = true;
k_sem_give(&sem_per_big_info);
Expand Down Expand Up @@ -302,15 +302,16 @@ static int create_pa_sync(struct bt_le_per_adv_sync **sync)
{
struct bt_le_per_adv_sync_param sync_create_param;
int err;
uint32_t sem_timeout;
uint32_t sem_timeout_us;

LOG_INF("Creating Periodic Advertising Sync");
bt_addr_le_copy(&sync_create_param.addr, &per_addr);
sync_create_param.options = 0;
sync_create_param.sid = per_sid;
sync_create_param.skip = 0;
sync_create_param.timeout = (per_interval_ms * PA_RETRY_COUNT) / 10;
sem_timeout = per_interval_ms * PA_RETRY_COUNT;
/* Multiple PA interval with retry count and convert to unit of 10 ms */
sync_create_param.timeout = (per_interval_us * PA_RETRY_COUNT) / (10 * USEC_PER_MSEC);
sem_timeout_us = per_interval_us * PA_RETRY_COUNT;
err = bt_le_per_adv_sync_create(&sync_create_param, sync);
if (err != 0) {
LOG_ERR("Periodic advertisement sync create failed (err %d)",
Expand All @@ -319,7 +320,7 @@ static int create_pa_sync(struct bt_le_per_adv_sync **sync)
}

LOG_INF("Waiting for periodic sync");
err = k_sem_take(&sem_per_sync, K_MSEC(sem_timeout));
err = k_sem_take(&sem_per_sync, K_USEC(sem_timeout_us));
if (err != 0) {
LOG_INF("failed to take sem_per_sync (err %d)", err);

Expand All @@ -340,8 +341,8 @@ static int create_pa_sync(struct bt_le_per_adv_sync **sync)
static int create_big_sync(struct bt_iso_big **big, struct bt_le_per_adv_sync *sync)
{
int err;
uint32_t sem_timeout = per_interval_ms * PA_RETRY_COUNT;
uint32_t sync_timeout_ms;
uint32_t sem_timeout_us = per_interval_us * PA_RETRY_COUNT;
uint32_t sync_timeout_us;
static struct bt_iso_chan bis_iso_chan[CONFIG_BT_ISO_MAX_CHAN];
struct bt_iso_chan *bis[CONFIG_BT_ISO_MAX_CHAN];
struct bt_iso_big_sync_param big_sync_param = {
Expand All @@ -359,14 +360,17 @@ static int create_big_sync(struct bt_iso_big **big, struct bt_le_per_adv_sync *s
}

LOG_INF("Waiting for BIG info");
err = k_sem_take(&sem_per_big_info, K_MSEC(sem_timeout));
err = k_sem_take(&sem_per_big_info, K_USEC(sem_timeout_us));
if (err != 0) {
LOG_ERR("failed to take sem_per_big_info (err %d)", err);
return err;
}

sync_timeout_ms = iso_interval_ms * ISO_RETRY_COUNT;
big_sync_param.sync_timeout = CLAMP(sync_timeout_ms / 10, 0x000A, 0x4000); /* 10 ms units */
sync_timeout_us = iso_interval_us * ISO_RETRY_COUNT;
/* timeout is in 10 ms units */
big_sync_param.sync_timeout = CLAMP(sync_timeout_us / (10 * USEC_PER_MSEC),
BT_ISO_SYNC_TIMEOUT_MIN,
BT_ISO_SYNC_TIMEOUT_MAX);
big_sync_param.num_bis = bis_count;
/* BIS indexes start from 0x01, so add one to `i` */
for (int i = 1; i <= big_sync_param.num_bis; i++) {
Expand All @@ -381,7 +385,7 @@ static int create_big_sync(struct bt_iso_big **big, struct bt_le_per_adv_sync *s
}

LOG_INF("Waiting for BIG sync");
err = k_sem_take(&sem_big_sync, K_MSEC(sem_timeout));
err = k_sem_take(&sem_big_sync, K_USEC(sem_timeout_us));
if (err != 0) {
LOG_ERR("failed to take sem_big_sync (err %d)", err);
return err;
Expand Down
20 changes: 11 additions & 9 deletions samples/bluetooth/iso_receive/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ static bool per_adv_found;
static bool per_adv_lost;
static bt_addr_le_t per_addr;
static uint8_t per_sid;
static uint16_t per_interval_ms;
static uint32_t per_interval_us;

static K_SEM_DEFINE(sem_per_adv, 0, 1);
static K_SEM_DEFINE(sem_per_sync, 0, 1);
Expand Down Expand Up @@ -103,21 +103,21 @@ static void scan_recv(const struct bt_le_scan_recv_info *info,
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
printk("[DEVICE]: %s, AD evt type %u, Tx Pwr: %i, RSSI %i %s "
"C:%u S:%u D:%u SR:%u E:%u Prim: %s, Secn: %s, "
"Interval: 0x%04x (%u ms), SID: %u\n",
"Interval: 0x%04x (%u us), SID: %u\n",
le_addr, info->adv_type, info->tx_power, info->rssi, name,
(info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0,
(info->adv_props & BT_GAP_ADV_PROP_SCANNABLE) != 0,
(info->adv_props & BT_GAP_ADV_PROP_DIRECTED) != 0,
(info->adv_props & BT_GAP_ADV_PROP_SCAN_RESPONSE) != 0,
(info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0,
phy2str(info->primary_phy), phy2str(info->secondary_phy),
info->interval, BT_CONN_INTERVAL_TO_MS(info->interval), info->sid);
info->interval, BT_CONN_INTERVAL_TO_US(info->interval), info->sid);

if (!per_adv_found && info->interval) {
per_adv_found = true;

per_sid = info->sid;
per_interval_ms = BT_CONN_INTERVAL_TO_MS(info->interval);
per_interval_us = BT_CONN_INTERVAL_TO_US(info->interval);
bt_addr_le_copy(&per_addr, info->addr);

k_sem_give(&sem_per_adv);
Expand Down Expand Up @@ -277,7 +277,7 @@ void main(void)
struct bt_le_per_adv_sync_param sync_create_param;
struct bt_le_per_adv_sync *sync;
struct bt_iso_big *big;
uint32_t sem_timeout;
uint32_t sem_timeout_us;
int err;

printk("Starting Synchronized Receiver Demo\n");
Expand Down Expand Up @@ -357,8 +357,10 @@ void main(void)
sync_create_param.options = 0;
sync_create_param.sid = per_sid;
sync_create_param.skip = 0;
sync_create_param.timeout = (per_interval_ms * PA_RETRY_COUNT) / 10;
sem_timeout = per_interval_ms * PA_RETRY_COUNT;
/* Multiple PA interval with retry count and convert to unit of 10 ms */
sync_create_param.timeout = (per_interval_us * PA_RETRY_COUNT) /
(10 * USEC_PER_MSEC);
sem_timeout_us = per_interval_us * PA_RETRY_COUNT;
err = bt_le_per_adv_sync_create(&sync_create_param, &sync);
if (err) {
printk("failed (err %d)\n", err);
Expand All @@ -367,7 +369,7 @@ void main(void)
printk("success.\n");

printk("Waiting for periodic sync...\n");
err = k_sem_take(&sem_per_sync, K_MSEC(sem_timeout));
err = k_sem_take(&sem_per_sync, K_USEC(sem_timeout_us));
if (err) {
printk("failed (err %d)\n", err);

Expand All @@ -382,7 +384,7 @@ void main(void)
printk("Periodic sync established.\n");

printk("Waiting for BIG info...\n");
err = k_sem_take(&sem_per_big_info, K_MSEC(sem_timeout));
err = k_sem_take(&sem_per_big_info, K_USEC(sem_timeout_us));
if (err) {
printk("failed (err %d)\n", err);

Expand Down
12 changes: 9 additions & 3 deletions subsys/bluetooth/host/att.c
Original file line number Diff line number Diff line change
Expand Up @@ -3358,10 +3358,16 @@ static k_timeout_t credit_based_connection_delay(struct bt_conn *conn)
}

const uint8_t rand_delay = random & 0x7; /* Small random delay for IOP */
const uint32_t calculated_delay =
2 * (conn->le.latency + 1) * BT_CONN_INTERVAL_TO_MS(conn->le.interval);
/* The maximum value of (latency + 1) * 2 multipled with the
* maximum connection interval has a maximum value of
* 4000000000 which can be stored in 32-bits, so this won't
* result in an overflow
*/
const uint32_t calculated_delay_us =
2 * (conn->le.latency + 1) * BT_CONN_INTERVAL_TO_US(conn->le.interval);
const uint32_t calculated_delay_ms = calculated_delay_us / USEC_PER_MSEC;

return K_MSEC(MAX(100, calculated_delay + rand_delay));
return K_MSEC(MAX(100, calculated_delay_ms + rand_delay));
}

/* Must be either central or peripheral */
Expand Down
21 changes: 10 additions & 11 deletions subsys/bluetooth/shell/bt.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,15 +221,15 @@ static void scan_recv(const struct bt_le_scan_recv_info *info,

shell_print(ctx_shell, "[DEVICE]: %s, AD evt type %u, RSSI %i %s "
"C:%u S:%u D:%d SR:%u E:%u Prim: %s, Secn: %s, "
"Interval: 0x%04x (%u ms), SID: 0x%x",
"Interval: 0x%04x (%u us), SID: 0x%x",
le_addr, info->adv_type, info->rssi, name,
(info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0,
(info->adv_props & BT_GAP_ADV_PROP_SCANNABLE) != 0,
(info->adv_props & BT_GAP_ADV_PROP_DIRECTED) != 0,
(info->adv_props & BT_GAP_ADV_PROP_SCAN_RESPONSE) != 0,
(info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0,
phy2str(info->primary_phy), phy2str(info->secondary_phy),
info->interval, BT_CONN_INTERVAL_TO_MS(info->interval),
info->interval, BT_CONN_INTERVAL_TO_US(info->interval),
info->sid);

/* Store address for later use */
Expand Down Expand Up @@ -631,9 +631,9 @@ static void per_adv_sync_sync_cb(struct bt_le_per_adv_sync *sync,
}

shell_print(ctx_shell, "PER_ADV_SYNC[%u]: [DEVICE]: %s synced, "
"Interval 0x%04x (%u ms), PHY %s, SD 0x%04X, PAST peer %s",
"Interval 0x%04x (%u us), PHY %s, SD 0x%04X, PAST peer %s",
bt_le_per_adv_sync_get_index(sync), le_addr,
info->interval, BT_CONN_INTERVAL_TO_MS(info->interval),
info->interval, BT_CONN_INTERVAL_TO_US(info->interval),
phy2str(info->phy), info->service_data, past_peer);

if (info->conn) { /* if from PAST */
Expand Down Expand Up @@ -685,12 +685,12 @@ static void per_adv_sync_biginfo_cb(struct bt_le_per_adv_sync *sync,

bt_addr_le_to_str(biginfo->addr, le_addr, sizeof(le_addr));
shell_print(ctx_shell, "BIG_INFO PER_ADV_SYNC[%u]: [DEVICE]: %s, sid 0x%02x, num_bis %u, "
"nse 0x%02x, interval 0x%04x (%u ms), bn 0x%02x, pto 0x%02x, irc 0x%02x, "
"nse 0x%02x, interval 0x%04x (%u us), bn 0x%02x, pto 0x%02x, irc 0x%02x, "
"max_pdu 0x%04x, sdu_interval 0x%04x, max_sdu 0x%04x, phy %s, framing 0x%02x, "
"%sencrypted",
bt_le_per_adv_sync_get_index(sync), le_addr, biginfo->sid, biginfo->num_bis,
biginfo->sub_evt_count, biginfo->iso_interval,
BT_CONN_INTERVAL_TO_MS(biginfo->iso_interval), biginfo->burst_number,
BT_CONN_INTERVAL_TO_US(biginfo->iso_interval), biginfo->burst_number,
biginfo->offset, biginfo->rep_count, biginfo->max_pdu, biginfo->sdu_interval,
biginfo->max_sdu, phy2str(biginfo->phy), biginfo->framing,
biginfo->encryption ? "" : "not ");
Expand Down Expand Up @@ -2541,12 +2541,11 @@ static int cmd_info(const struct shell *sh, size_t argc, char *argv[])
print_le_addr("Remote on-air", info.le.remote);
print_le_addr("Local on-air", info.le.local);

shell_print(ctx_shell, "Interval: 0x%04x (%u ms)",
shell_print(ctx_shell, "Interval: 0x%04x (%u us)",
info.le.interval,
BT_CONN_INTERVAL_TO_MS(info.le.interval));
shell_print(ctx_shell, "Latency: 0x%04x (%u ms)",
info.le.latency,
BT_CONN_INTERVAL_TO_MS(info.le.latency));
BT_CONN_INTERVAL_TO_US(info.le.interval));
shell_print(ctx_shell, "Latency: 0x%04x",
info.le.latency);
shell_print(ctx_shell, "Supervision timeout: 0x%04x (%d ms)",
info.le.timeout, info.le.timeout * 10);
#if defined(CONFIG_BT_USER_PHY_UPDATE)
Expand Down

0 comments on commit 57218ee

Please sign in to comment.