@@ -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
204209static 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 )
208216static 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
212345struct 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