Skip to content

Commit fdb80a1

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 45c31d2 commit fdb80a1

1 file changed

Lines changed: 158 additions & 0 deletions

File tree

nimble/host/src/ble_gap.c

Lines changed: 158 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,10 +207,141 @@ struct ble_gap_slave_state {
202207
};
203208

204209
static bssnz_t struct ble_gap_slave_state ble_gap_slave[BLE_ADV_INSTANCES];
210+
#if MYNEWT_VAL(BLE_EXT_ADV)
211+
static int ble_gap_ext_adv_set_addr_no_lock(uint8_t instance, const uint8_t *addr);
212+
static int ble_gap_ext_adv_stop_no_lock(uint8_t instance);
213+
int ble_gap_ext_adv_start(uint8_t instance, int duration, int max_events);
214+
#endif
205215

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

@@ -2388,6 +2524,10 @@ ble_gap_timer(void)
23882524
min_ticks = min(min_ticks, ble_gap_slave_timer());
23892525
#endif
23902526

2527+
#if NIMBLE_BLE_ADVERTISE && MYNEWT_VAL(BLE_EXT_ADV)
2528+
min_ticks = min(min_ticks, ble_gap_ext_adv_nrpa_timer());
2529+
#endif
2530+
23912531
return min_ticks;
23922532
}
23932533

@@ -3430,6 +3570,13 @@ ble_gap_ext_adv_set_addr_no_lock(uint8_t instance, const uint8_t *addr)
34303570
ble_gap_slave[instance].rnd_addr_set = 1;
34313571
memcpy(ble_gap_slave[instance].rnd_addr, addr, 6);
34323572

3573+
if (ble_gap_ext_adv_rnd_addr_is_nrpa(addr) &&
3574+
ble_gap_slave[instance].op == BLE_GAP_OP_S_ADV) {
3575+
ble_gap_ext_adv_nrpa_set_exp(instance);
3576+
} else if (!ble_gap_ext_adv_rnd_addr_is_nrpa(addr)) {
3577+
ble_gap_ext_adv_nrpa_clear_exp(instance);
3578+
}
3579+
34333580
return 0;
34343581
}
34353582

@@ -3551,8 +3698,18 @@ ble_gap_ext_adv_start(uint8_t instance, int duration, int max_events)
35513698
}
35523699

35533700
ble_gap_slave[instance].op = BLE_GAP_OP_S_ADV;
3701+
ble_gap_slave[instance].adv_start_time = ble_npl_time_get();
3702+
ble_gap_slave[instance].adv_duration = duration;
3703+
ble_gap_slave[instance].adv_max_events = max_events;
35543704

3705+
if (ble_gap_slave[instance].rnd_addr_set &&
3706+
ble_gap_ext_adv_rnd_addr_is_nrpa(ble_gap_slave[instance].rnd_addr)) {
3707+
ble_gap_ext_adv_nrpa_set_exp(instance);
3708+
} else {
3709+
ble_gap_ext_adv_nrpa_clear_exp(instance);
3710+
}
35553711
ble_hs_unlock();
3712+
35563713
return 0;
35573714
}
35583715

@@ -3587,6 +3744,7 @@ ble_gap_ext_adv_stop_no_lock(uint8_t instance)
35873744
}
35883745

35893746
ble_gap_slave[instance].op = BLE_GAP_OP_NULL;
3747+
ble_gap_ext_adv_nrpa_clear_exp(instance);
35903748

35913749
if (!active) {
35923750
return BLE_HS_EALREADY;

0 commit comments

Comments
 (0)