Skip to content

Commit b73add3

Browse files
nimble/host: Implement NRPA rotation
New functionality for NRPA rotation. NRPA will use RPA_TIMEOUT as refresh time. Only extended advertising set is affected by this change.
1 parent 60fae18 commit b73add3

1 file changed

Lines changed: 156 additions & 0 deletions

File tree

nimble/host/src/ble_gap.c

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,16 @@ struct ble_gap_slave_state {
186186
unsigned int high_duty_directed:1;
187187
unsigned int legacy_pdu:1;
188188
unsigned int rnd_addr_set:1;
189+
unsigned int nrpa_exp_set : 1;
189190
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
190191
unsigned int periodic_configured:1;
191192
uint8_t periodic_op;
192193
#endif
193194
uint8_t rnd_addr[6];
195+
ble_npl_time_t nrpa_exp_os_ticks;
196+
ble_npl_time_t adv_start_time;
197+
uint16_t adv_duration;
198+
uint8_t adv_max_events;
194199
#else
195200
/* timer is used only with legacy advertising */
196201
unsigned int exp_set:1;
@@ -202,11 +207,139 @@ struct ble_gap_slave_state {
202207
};
203208

204209
static bssnz_t struct ble_gap_slave_state ble_gap_slave[BLE_ADV_INSTANCES];
210+
static int ble_gap_ext_adv_set_addr_no_lock(uint8_t instance, const uint8_t *addr);
211+
static int ble_gap_ext_adv_stop_no_lock(uint8_t instance);
212+
int ble_gap_ext_adv_start(uint8_t instance, int duration, int max_events);
205213

206214
#if NIMBLE_BLE_ADVERTISE
207215
#if MYNEWT_VAL(BLE_EXT_ADV)
208216
static bool ext_adv_legacy_configured = false;
209217
#endif
218+
219+
static bool
220+
ble_gap_ext_adv_rnd_addr_is_nrpa(const uint8_t *addr)
221+
{
222+
return (addr[5] & 0xc0) == 0;
223+
}
224+
225+
static uint16_t
226+
ble_gap_ext_adv_remaining_duration(uint8_t instance)
227+
{
228+
ble_npl_time_t elapsed_ticks;
229+
uint32_t elapsed_ms;
230+
uint32_t elapsed_units;
231+
232+
if (ble_gap_slave[instance].adv_duration == 0) {
233+
return 0;
234+
}
235+
236+
elapsed_ticks = ble_npl_time_get() - ble_gap_slave[instance].adv_start_time;
237+
elapsed_ms = ble_npl_time_ticks_to_ms32(elapsed_ticks);
238+
elapsed_units = elapsed_ms / 10;
239+
240+
if (elapsed_units >= ble_gap_slave[instance].adv_duration) {
241+
return 1;
242+
}
243+
244+
return ble_gap_slave[instance].adv_duration - elapsed_units;
245+
}
246+
247+
static int
248+
ble_gap_ext_adv_nrpa_rotate(uint8_t instance, const uint8_t *addr)
249+
{
250+
uint16_t duration;
251+
uint8_t max_events;
252+
int rc;
253+
254+
duration = ble_gap_ext_adv_remaining_duration(instance);
255+
max_events = ble_gap_slave[instance].adv_max_events;
256+
257+
rc = ble_gap_ext_adv_stop_no_lock(instance);
258+
if (rc != 0) {
259+
return rc;
260+
}
261+
262+
rc = ble_gap_ext_adv_set_addr_no_lock(instance, addr);
263+
if (rc != 0) {
264+
return rc;
265+
}
266+
267+
rc = ble_gap_ext_adv_start(instance, duration, max_events);
268+
if (rc != 0) {
269+
return rc;
270+
}
271+
272+
return 0;
273+
}
274+
275+
static void
276+
ble_gap_ext_adv_nrpa_set_exp(uint8_t instance)
277+
{
278+
ble_npl_time_t timeout_ticks;
279+
uint32_t timeout_ms;
280+
int rc;
281+
282+
timeout_ms = MYNEWT_VAL(BLE_RPA_TIMEOUT) * 1000UL;
283+
284+
rc = ble_npl_time_ms_to_ticks(timeout_ms, &timeout_ticks);
285+
BLE_HS_DBG_ASSERT_EVAL(rc == 0);
286+
287+
ble_gap_slave[instance].nrpa_exp_os_ticks = ble_npl_time_get() + timeout_ticks;
288+
ble_gap_slave[instance].nrpa_exp_set = 1;
289+
ble_hs_timer_resched();
290+
}
291+
292+
static void
293+
ble_gap_ext_adv_nrpa_clear_exp(uint8_t instance)
294+
{
295+
ble_gap_slave[instance].nrpa_exp_set = 0;
296+
ble_hs_timer_resched();
297+
}
298+
299+
static uint32_t
300+
ble_gap_ext_adv_nrpa_timer(void)
301+
{
302+
ble_npl_stime_t ticks;
303+
uint32_t min_ticks;
304+
ble_addr_t addr;
305+
int rc;
306+
int i;
307+
308+
min_ticks = BLE_HS_FOREVER;
309+
310+
for (i = 0; i < BLE_ADV_INSTANCES; i++) {
311+
if (ble_gap_slave[i].op != BLE_GAP_OP_S_ADV ||
312+
!ble_gap_slave[i].rnd_addr_set ||
313+
!ble_gap_slave[i].nrpa_exp_set ||
314+
!ble_gap_ext_adv_rnd_addr_is_nrpa(ble_gap_slave[i].rnd_addr)) {
315+
continue;
316+
}
317+
318+
ticks = ble_gap_slave[i].nrpa_exp_os_ticks - ble_npl_time_get();
319+
if (ticks > 0) {
320+
min_ticks = min(min_ticks, ticks);
321+
continue;
322+
}
323+
324+
rc = ble_hs_id_gen_rnd(1, &addr);
325+
if (rc != 0) {
326+
min_ticks = min(min_ticks, ble_npl_time_ms_to_ticks32(BLE_GAP_CANCEL_RETRY_TIMEOUT_MS));
327+
continue;
328+
}
329+
330+
rc = ble_gap_ext_adv_nrpa_rotate(i, addr.val);
331+
if (rc != 0) {
332+
min_ticks = min(min_ticks, ble_npl_time_ms_to_ticks32(BLE_GAP_CANCEL_RETRY_TIMEOUT_MS));
333+
continue;
334+
}
335+
336+
ble_gap_ext_adv_nrpa_set_exp(i);
337+
ticks = ble_gap_slave[i].nrpa_exp_os_ticks - ble_npl_time_get();
338+
min_ticks = min(min_ticks, ticks);
339+
}
340+
341+
return min_ticks;
342+
}
210343
#endif
211344

212345
struct ble_gap_update_entry {
@@ -2385,6 +2518,10 @@ ble_gap_timer(void)
23852518
min_ticks = min(min_ticks, ble_gap_slave_timer());
23862519
#endif
23872520

2521+
#if NIMBLE_BLE_ADVERTISE && MYNEWT_VAL(BLE_EXT_ADV)
2522+
min_ticks = min(min_ticks, ble_gap_ext_adv_nrpa_timer());
2523+
#endif
2524+
23882525
return min_ticks;
23892526
}
23902527

@@ -3427,6 +3564,13 @@ ble_gap_ext_adv_set_addr_no_lock(uint8_t instance, const uint8_t *addr)
34273564
ble_gap_slave[instance].rnd_addr_set = 1;
34283565
memcpy(ble_gap_slave[instance].rnd_addr, addr, 6);
34293566

3567+
if (ble_gap_ext_adv_rnd_addr_is_nrpa(addr) &&
3568+
ble_gap_slave[instance].op == BLE_GAP_OP_S_ADV) {
3569+
ble_gap_ext_adv_nrpa_set_exp(instance);
3570+
} else if (!ble_gap_ext_adv_rnd_addr_is_nrpa(addr)) {
3571+
ble_gap_ext_adv_nrpa_clear_exp(instance);
3572+
}
3573+
34303574
return 0;
34313575
}
34323576

@@ -3548,6 +3692,17 @@ ble_gap_ext_adv_start(uint8_t instance, int duration, int max_events)
35483692
}
35493693

35503694
ble_gap_slave[instance].op = BLE_GAP_OP_S_ADV;
3695+
ble_gap_slave[instance].adv_start_time = ble_npl_time_get();
3696+
ble_gap_slave[instance].adv_duration = duration;
3697+
ble_gap_slave[instance].adv_max_events = max_events;
3698+
3699+
if (ble_gap_slave[instance].rnd_addr_set &&
3700+
ble_gap_ext_adv_rnd_addr_is_nrpa(ble_gap_slave[instance].rnd_addr)) {
3701+
ble_gap_ext_adv_nrpa_set_exp(instance);
3702+
} else {
3703+
ble_gap_ext_adv_nrpa_clear_exp(instance);
3704+
}
3705+
35513706

35523707
ble_hs_unlock();
35533708
return 0;
@@ -3584,6 +3739,7 @@ ble_gap_ext_adv_stop_no_lock(uint8_t instance)
35843739
}
35853740

35863741
ble_gap_slave[instance].op = BLE_GAP_OP_NULL;
3742+
ble_gap_ext_adv_nrpa_clear_exp(instance);
35873743

35883744
if (!active) {
35893745
return BLE_HS_EALREADY;

0 commit comments

Comments
 (0)