diff --git a/include/zephyr/bluetooth/conn.h b/include/zephyr/bluetooth/conn.h index 2b34e738c5a..2c6320444c6 100644 --- a/include/zephyr/bluetooth/conn.h +++ b/include/zephyr/bluetooth/conn.h @@ -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 { diff --git a/samples/bluetooth/iso_broadcast_benchmark/src/receiver.c b/samples/bluetooth/iso_broadcast_benchmark/src/receiver.c index 68470c6466f..419c3f5d994 100644 --- a/samples/bluetooth/iso_broadcast_benchmark/src/receiver.c +++ b/samples/bluetooth/iso_broadcast_benchmark/src/receiver.c @@ -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; @@ -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); @@ -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); @@ -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)", @@ -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); @@ -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 = { @@ -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++) { @@ -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; diff --git a/samples/bluetooth/iso_receive/src/main.c b/samples/bluetooth/iso_receive/src/main.c index 8078fc25fa5..ad59970806a 100644 --- a/samples/bluetooth/iso_receive/src/main.c +++ b/samples/bluetooth/iso_receive/src/main.c @@ -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); @@ -103,7 +103,7 @@ 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, @@ -111,13 +111,13 @@ static void scan_recv(const struct bt_le_scan_recv_info *info, (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); @@ -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"); @@ -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); @@ -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); @@ -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); diff --git a/subsys/bluetooth/host/att.c b/subsys/bluetooth/host/att.c index 65b443d04bc..8fee81fb735 100644 --- a/subsys/bluetooth/host/att.c +++ b/subsys/bluetooth/host/att.c @@ -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 */ diff --git a/subsys/bluetooth/shell/bt.c b/subsys/bluetooth/shell/bt.c index 2d381e22565..22b8e79e90b 100644 --- a/subsys/bluetooth/shell/bt.c +++ b/subsys/bluetooth/shell/bt.c @@ -221,7 +221,7 @@ 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, @@ -229,7 +229,7 @@ static void scan_recv(const struct bt_le_scan_recv_info *info, (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 */ @@ -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 */ @@ -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 "); @@ -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)