@@ -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
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 || !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