@@ -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,140 @@ struct ble_gap_slave_state {
202207};
203208
204209static 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 )
208218static 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 ||
314+ !ble_gap_slave [i ].nrpa_exp_set ||
315+ !ble_gap_ext_adv_rnd_addr_is_nrpa (ble_gap_slave [i ].rnd_addr )) {
316+ continue ;
317+ }
318+
319+ ticks = ble_gap_slave [i ].nrpa_exp_os_ticks - ble_npl_time_get ();
320+ if (ticks > 0 ) {
321+ min_ticks = min (min_ticks , ticks );
322+ continue ;
323+ }
324+
325+ rc = ble_hs_id_gen_rnd (1 , & addr );
326+ if (rc != 0 ) {
327+ min_ticks = min (min_ticks , ble_npl_time_ms_to_ticks32 (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 (BLE_GAP_CANCEL_RETRY_TIMEOUT_MS ));
334+ continue ;
335+ }
336+
337+ ble_gap_ext_adv_nrpa_set_exp (i );
338+ ticks = ble_gap_slave [i ].nrpa_exp_os_ticks - ble_npl_time_get ();
339+ min_ticks = min (min_ticks , ticks );
340+ }
341+
342+ return min_ticks ;
343+ }
209344#endif
210345#endif
211346
@@ -2385,6 +2520,10 @@ ble_gap_timer(void)
23852520 min_ticks = min (min_ticks , ble_gap_slave_timer ());
23862521#endif
23872522
2523+ #if NIMBLE_BLE_ADVERTISE && MYNEWT_VAL (BLE_EXT_ADV )
2524+ min_ticks = min (min_ticks , ble_gap_ext_adv_nrpa_timer ());
2525+ #endif
2526+
23882527 return min_ticks ;
23892528}
23902529
@@ -3427,6 +3566,13 @@ ble_gap_ext_adv_set_addr_no_lock(uint8_t instance, const uint8_t *addr)
34273566 ble_gap_slave [instance ].rnd_addr_set = 1 ;
34283567 memcpy (ble_gap_slave [instance ].rnd_addr , addr , 6 );
34293568
3569+ if (ble_gap_ext_adv_rnd_addr_is_nrpa (addr ) &&
3570+ ble_gap_slave [instance ].op == BLE_GAP_OP_S_ADV ) {
3571+ ble_gap_ext_adv_nrpa_set_exp (instance );
3572+ } else if (!ble_gap_ext_adv_rnd_addr_is_nrpa (addr )) {
3573+ ble_gap_ext_adv_nrpa_clear_exp (instance );
3574+ }
3575+
34303576 return 0 ;
34313577}
34323578
@@ -3548,6 +3694,17 @@ ble_gap_ext_adv_start(uint8_t instance, int duration, int max_events)
35483694 }
35493695
35503696 ble_gap_slave [instance ].op = BLE_GAP_OP_S_ADV ;
3697+ ble_gap_slave [instance ].adv_start_time = ble_npl_time_get ();
3698+ ble_gap_slave [instance ].adv_duration = duration ;
3699+ ble_gap_slave [instance ].adv_max_events = max_events ;
3700+
3701+ if (ble_gap_slave [instance ].rnd_addr_set &&
3702+ ble_gap_ext_adv_rnd_addr_is_nrpa (ble_gap_slave [instance ].rnd_addr )) {
3703+ ble_gap_ext_adv_nrpa_set_exp (instance );
3704+ } else {
3705+ ble_gap_ext_adv_nrpa_clear_exp (instance );
3706+ }
3707+
35513708
35523709 ble_hs_unlock ();
35533710 return 0 ;
@@ -3584,6 +3741,7 @@ ble_gap_ext_adv_stop_no_lock(uint8_t instance)
35843741 }
35853742
35863743 ble_gap_slave [instance ].op = BLE_GAP_OP_NULL ;
3744+ ble_gap_ext_adv_nrpa_clear_exp (instance );
35873745
35883746 if (!active ) {
35893747 return BLE_HS_EALREADY ;
0 commit comments