Skip to content

Commit 1eb9d36

Browse files
kapi-nofabiobaltieri
authored andcommitted
bluetooth: add api for changing rpa timeout in runtime
Added a new Bluetooth API and Kconfig option for overriding the RPA timeout in runtime. Signed-off-by: Kamil Piszczek <[email protected]>
1 parent 8bdf363 commit 1eb9d36

File tree

7 files changed

+96
-6
lines changed

7 files changed

+96
-6
lines changed

include/zephyr/bluetooth/bluetooth.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2021,6 +2021,26 @@ static inline int bt_le_whitelist_clear(void)
20212021
*/
20222022
int bt_le_set_chan_map(uint8_t chan_map[5]);
20232023

2024+
/**
2025+
* @brief Set the Resolvable Private Address timeout in runtime
2026+
*
2027+
* The new RPA timeout value will be used for the next RPA rotation
2028+
* and all subsequent rotations until another override is scheduled
2029+
* with this API.
2030+
*
2031+
* Initially, the if @kconfig{CONFIG_BT_RPA_TIMEOUT} is used as the
2032+
* RPA timeout.
2033+
*
2034+
* This symbol is linkable if @kconfig{CONFIG_BT_RPA_TIMEOUT_DYNAMIC}
2035+
* is enabled.
2036+
*
2037+
* @param new_rpa_timeout Resolvable Private Address timeout in seconds
2038+
*
2039+
* @retval 0 Success.
2040+
* @retval -EINVAL RPA timeout value is invalid. Valid range is 1s - 3600s.
2041+
*/
2042+
int bt_le_set_rpa_timeout(uint16_t new_rpa_timeout);
2043+
20242044
/**
20252045
* @brief Helper for parsing advertising (or EIR or OOB) data.
20262046
*

subsys/bluetooth/host/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,13 @@ config BT_RPA_TIMEOUT
350350
This option defines how often resolvable private address is rotated.
351351
Value is provided in seconds and defaults to 900 seconds (15 minutes).
352352

353+
config BT_RPA_TIMEOUT_DYNAMIC
354+
bool "Support setting the Resolvable Private Address timeout at runtime"
355+
depends on BT_PRIVACY
356+
help
357+
This option allows the user to override the default value of
358+
the Resolvable Private Address timeout using dedicated APIs.
359+
353360
config BT_SIGNING
354361
bool "Data signing support"
355362
help

subsys/bluetooth/host/conn.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2492,7 +2492,7 @@ static bool create_param_validate(const struct bt_conn_le_create_param *param)
24922492
{
24932493
#if defined(CONFIG_BT_PRIVACY)
24942494
/* Initiation timeout cannot be greater than the RPA timeout */
2495-
const uint32_t timeout_max = (MSEC_PER_SEC / 10) * CONFIG_BT_RPA_TIMEOUT;
2495+
const uint32_t timeout_max = (MSEC_PER_SEC / 10) * bt_dev.rpa_timeout;
24962496

24972497
if (param->timeout > timeout_max) {
24982498
return false;

subsys/bluetooth/host/hci_core.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ static void init_work(struct k_work *work);
7676

7777
struct bt_dev bt_dev = {
7878
.init = Z_WORK_INITIALIZER(init_work),
79+
#if defined(CONFIG_BT_PRIVACY)
80+
.rpa_timeout = CONFIG_BT_RPA_TIMEOUT,
81+
#endif
7982
#if defined(CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC)
8083
.appearance = CONFIG_BT_DEVICE_APPEARANCE,
8184
#endif
@@ -2975,7 +2978,7 @@ static int le_init(void)
29752978
}
29762979

29772980
cp = net_buf_add(buf, sizeof(*cp));
2978-
cp->rpa_timeout = sys_cpu_to_le16(CONFIG_BT_RPA_TIMEOUT);
2981+
cp->rpa_timeout = sys_cpu_to_le16(bt_dev.rpa_timeout);
29792982
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_RPA_TIMEOUT, buf,
29802983
NULL);
29812984
if (err) {
@@ -3933,6 +3936,24 @@ int bt_le_set_chan_map(uint8_t chan_map[5])
39333936
buf, NULL);
39343937
}
39353938

3939+
#if defined(CONFIG_BT_RPA_TIMEOUT_DYNAMIC)
3940+
int bt_le_set_rpa_timeout(uint16_t new_rpa_timeout)
3941+
{
3942+
if ((new_rpa_timeout == 0) || (new_rpa_timeout > 3600)) {
3943+
return -EINVAL;
3944+
}
3945+
3946+
if (new_rpa_timeout == bt_dev.rpa_timeout) {
3947+
return 0;
3948+
}
3949+
3950+
bt_dev.rpa_timeout = new_rpa_timeout;
3951+
atomic_set_bit(bt_dev.flags, BT_DEV_RPA_TIMEOUT_CHANGED);
3952+
3953+
return 0;
3954+
}
3955+
#endif
3956+
39363957
void bt_data_parse(struct net_buf_simple *ad,
39373958
bool (*func)(struct bt_data *data, void *user_data),
39383959
void *user_data)

subsys/bluetooth/host/hci_core.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ enum {
4444
BT_DEV_INITIATING,
4545

4646
BT_DEV_RPA_VALID,
47+
BT_DEV_RPA_TIMEOUT_CHANGED,
4748

4849
BT_DEV_ID_PENDING,
4950
BT_DEV_STORE_ID,
@@ -358,6 +359,9 @@ struct bt_dev {
358359

359360
/* Work used for RPA rotation */
360361
struct k_work_delayable rpa_update;
362+
363+
/* The RPA timeout value. */
364+
uint16_t rpa_timeout;
361365
#endif
362366

363367
/* Local Name */

subsys/bluetooth/host/id.c

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
#include <zephyr/settings/settings.h>
9+
#include <zephyr/sys/byteorder.h>
910

1011
#include <zephyr/bluetooth/bluetooth.h>
1112
#include <zephyr/bluetooth/hci_vs.h>
@@ -204,9 +205,47 @@ static void le_rpa_invalidate(void)
204205
}
205206

206207
#if defined(CONFIG_BT_PRIVACY)
208+
209+
#if defined(CONFIG_BT_RPA_TIMEOUT_DYNAMIC)
210+
static void le_rpa_timeout_update(void)
211+
{
212+
int err = 0;
213+
214+
if (atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_RPA_TIMEOUT_CHANGED)) {
215+
struct net_buf *buf;
216+
struct bt_hci_cp_le_set_rpa_timeout *cp;
217+
218+
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RPA_TIMEOUT,
219+
sizeof(*cp));
220+
if (!buf) {
221+
BT_ERR("Failed to create HCI RPA timeout command");
222+
err = -ENOBUFS;
223+
goto submit;
224+
}
225+
226+
cp = net_buf_add(buf, sizeof(*cp));
227+
cp->rpa_timeout = sys_cpu_to_le16(bt_dev.rpa_timeout);
228+
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_RPA_TIMEOUT, buf, NULL);
229+
if (err) {
230+
BT_ERR("Failed to send HCI RPA timeout command");
231+
goto submit;
232+
}
233+
}
234+
235+
submit:
236+
if (err) {
237+
atomic_set_bit(bt_dev.flags, BT_DEV_RPA_TIMEOUT_CHANGED);
238+
}
239+
}
240+
#endif
241+
207242
static void le_rpa_timeout_submit(void)
208243
{
209-
(void)k_work_schedule(&bt_dev.rpa_update, RPA_TIMEOUT);
244+
#if defined(CONFIG_BT_RPA_TIMEOUT_DYNAMIC)
245+
le_rpa_timeout_update();
246+
#endif
247+
248+
(void)k_work_schedule(&bt_dev.rpa_update, K_SECONDS(bt_dev.rpa_timeout));
210249
}
211250

212251
/* this function sets new RPA only if current one is no longer valid */

subsys/bluetooth/host/id.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
* SPDX-License-Identifier: Apache-2.0
66
*/
77

8-
#define RPA_TIMEOUT_MS (CONFIG_BT_RPA_TIMEOUT * MSEC_PER_SEC)
9-
#define RPA_TIMEOUT K_MSEC(RPA_TIMEOUT_MS)
8+
#define RPA_TIMEOUT_MS(_rpa_timeout) (_rpa_timeout * MSEC_PER_SEC)
109

1110
static inline bool bt_id_rpa_is_new(void)
1211
{
@@ -16,7 +15,7 @@ static inline bool bt_id_rpa_is_new(void)
1615
/* RPA is considered new if there is less than half a second since the
1716
* timeout was started.
1817
*/
19-
return remaining_ms > (RPA_TIMEOUT_MS - 500);
18+
return remaining_ms > (RPA_TIMEOUT_MS(bt_dev.rpa_timeout) - 500);
2019
#else
2120
return false;
2221
#endif

0 commit comments

Comments
 (0)