26
26
* THE SOFTWARE.
27
27
*/
28
28
29
+ #include <math.h>
29
30
#include <stdint.h>
30
31
#include <stdio.h>
31
32
#include <string.h>
@@ -594,7 +595,26 @@ STATIC void check_data_fit(size_t data_len, bool connectable) {
594
595
}
595
596
}
596
597
597
- uint32_t _common_hal_bleio_adapter_start_advertising (bleio_adapter_obj_t * self , bool connectable , bool anonymous , float interval , uint8_t * advertising_data , uint16_t advertising_data_len , uint8_t * scan_response_data , uint16_t scan_response_data_len ) {
598
+ STATIC bool advertising_on_ble_evt (ble_evt_t * ble_evt , void * self_in ) {
599
+ bleio_adapter_obj_t * self = (bleio_adapter_obj_t * )self_in ;
600
+
601
+ switch (ble_evt -> header .evt_id ) {
602
+ case BLE_GAP_EVT_ADV_SET_TERMINATED :
603
+ mp_printf (& mp_plat_print , "Advertising set terminated - %d advertising events were completed - reason: %d\n" , ble_evt -> evt .gap_evt .params .adv_set_terminated .num_completed_adv_events , ble_evt -> evt .gap_evt .params .adv_set_terminated .reason );
604
+ common_hal_bleio_adapter_stop_advertising (self );
605
+ ble_drv_remove_event_handler (advertising_on_ble_evt , self_in );
606
+ break ;
607
+
608
+ default :
609
+ // For debugging.
610
+ mp_printf (& mp_plat_print , "Unhandled Advertising etvent: 0x%04x\n" , ble_evt -> header .evt_id );
611
+ return false;
612
+ break ;
613
+ }
614
+ return true;
615
+ }
616
+
617
+ uint32_t _common_hal_bleio_adapter_start_advertising (bleio_adapter_obj_t * self , bool connectable , bool anonymous , uint32_t timeout , float interval , uint8_t * advertising_data , uint16_t advertising_data_len , uint8_t * scan_response_data , uint16_t scan_response_data_len ) {
598
618
if (self -> current_advertising_data != NULL && self -> current_advertising_data == self -> advertising_data ) {
599
619
return NRF_ERROR_BUSY ;
600
620
}
@@ -630,7 +650,11 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
630
650
ble_gap_privacy_params_t privacy = {
631
651
.privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY ,
632
652
.private_addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE ,
633
- .private_addr_cycle_s = 0 ,
653
+ // Rotate the keys one second after we're scheduled to stop
654
+ // advertising. This prevents a potential race condition where we
655
+ // fire off a beacon with the same advertising data but a new MAC
656
+ // address just as we tear down the connection.
657
+ .private_addr_cycle_s = timeout + 1 ,
634
658
.p_device_irk = NULL ,
635
659
};
636
660
err_code = sd_ble_gap_privacy_set (& privacy );
@@ -650,7 +674,7 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
650
674
ble_gap_adv_params_t adv_params = {
651
675
.interval = SEC_TO_UNITS (interval , UNIT_0_625_MS ),
652
676
.properties .type = adv_type ,
653
- .duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED ,
677
+ .duration = SEC_TO_UNITS ( timeout , UNIT_10_MS ) ,
654
678
.filter_policy = BLE_GAP_ADV_FP_ANY ,
655
679
.primary_phy = BLE_GAP_PHY_1MBPS ,
656
680
};
@@ -667,6 +691,8 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
667
691
return err_code ;
668
692
}
669
693
694
+ ble_drv_add_event_handler (advertising_on_ble_evt , self );
695
+
670
696
vm_used_ble = true;
671
697
err_code = sd_ble_gap_adv_start (adv_handle , BLE_CONN_CFG_TAG_CUSTOM );
672
698
if (err_code != NRF_SUCCESS ) {
@@ -677,7 +703,7 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
677
703
}
678
704
679
705
680
- void common_hal_bleio_adapter_start_advertising (bleio_adapter_obj_t * self , bool connectable , bool anonymous , mp_float_t interval , mp_buffer_info_t * advertising_data_bufinfo , mp_buffer_info_t * scan_response_data_bufinfo ) {
706
+ void common_hal_bleio_adapter_start_advertising (bleio_adapter_obj_t * self , bool connectable , bool anonymous , uint32_t timeout , mp_float_t interval , mp_buffer_info_t * advertising_data_bufinfo , mp_buffer_info_t * scan_response_data_bufinfo ) {
681
707
if (self -> current_advertising_data != NULL && self -> current_advertising_data == self -> advertising_data ) {
682
708
mp_raise_bleio_BluetoothError (translate ("Already advertising." ));
683
709
}
@@ -689,6 +715,27 @@ void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool
689
715
if (advertising_data_bufinfo -> len > 31 && scan_response_data_bufinfo -> len > 0 ) {
690
716
mp_raise_bleio_BluetoothError (translate ("Extended advertisements with scan response not supported." ));
691
717
}
718
+
719
+ // Anonymous mode requires a timeout so that we don't continue to broadcast
720
+ // the same data while cycling the MAC address -- otherwise, what's the
721
+ // point of randomizing the MAC address?
722
+ if (!timeout ) {
723
+ if (anonymous ) {
724
+ // The Nordic macro is in units of 10ms. Convert to seconds.
725
+ uint32_t adv_timeout_max_secs = BLE_GAP_ADV_TIMEOUT_LIMITED_MAX / 100 ;
726
+ uint32_t rotate_timeout_max_secs = BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S ;
727
+ timeout = MIN (adv_timeout_max_secs , rotate_timeout_max_secs );
728
+ }
729
+ else {
730
+ timeout = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED ;
731
+ }
732
+ } else {
733
+ if (SEC_TO_UNITS (timeout , UNIT_10_MS ) > BLE_GAP_ADV_TIMEOUT_LIMITED_MAX ) {
734
+ mp_raise_bleio_BluetoothError (translate ("Timeout is too long: Maximum timeout length is %d seconds" ),
735
+ BLE_GAP_ADV_TIMEOUT_LIMITED_MAX / 100 );
736
+ }
737
+ }
738
+
692
739
// The advertising data buffers must not move, because the SoftDevice depends on them.
693
740
// So make them long-lived and reuse them onwards.
694
741
if (self -> advertising_data == NULL ) {
@@ -701,7 +748,7 @@ void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool
701
748
memcpy (self -> advertising_data , advertising_data_bufinfo -> buf , advertising_data_bufinfo -> len );
702
749
memcpy (self -> scan_response_data , scan_response_data_bufinfo -> buf , scan_response_data_bufinfo -> len );
703
750
704
- check_nrf_error (_common_hal_bleio_adapter_start_advertising (self , connectable , anonymous , interval ,
751
+ check_nrf_error (_common_hal_bleio_adapter_start_advertising (self , connectable , anonymous , timeout , interval ,
705
752
self -> advertising_data ,
706
753
advertising_data_bufinfo -> len ,
707
754
self -> scan_response_data ,
@@ -721,6 +768,10 @@ void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) {
721
768
}
722
769
}
723
770
771
+ bool common_hal_bleio_adapter_get_advertising (bleio_adapter_obj_t * self ) {
772
+ return self -> current_advertising_data != NULL ;
773
+ }
774
+
724
775
bool common_hal_bleio_adapter_get_connected (bleio_adapter_obj_t * self ) {
725
776
for (size_t i = 0 ; i < BLEIO_TOTAL_CONNECTION_COUNT ; i ++ ) {
726
777
bleio_connection_internal_t * connection = & bleio_connections [i ];
0 commit comments