2626 * THE SOFTWARE.
2727 */
2828
29+ #include <math.h>
2930#include <stdint.h>
3031#include <stdio.h>
3132#include <string.h>
@@ -594,7 +595,26 @@ STATIC void check_data_fit(size_t data_len, bool connectable) {
594595 }
595596}
596597
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 ) {
598618 if (self -> current_advertising_data != NULL && self -> current_advertising_data == self -> advertising_data ) {
599619 return NRF_ERROR_BUSY ;
600620 }
@@ -630,7 +650,11 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
630650 ble_gap_privacy_params_t privacy = {
631651 .privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY ,
632652 .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 ,
634658 .p_device_irk = NULL ,
635659 };
636660 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,
650674 ble_gap_adv_params_t adv_params = {
651675 .interval = SEC_TO_UNITS (interval , UNIT_0_625_MS ),
652676 .properties .type = adv_type ,
653- .duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED ,
677+ .duration = SEC_TO_UNITS ( timeout , UNIT_10_MS ) ,
654678 .filter_policy = BLE_GAP_ADV_FP_ANY ,
655679 .primary_phy = BLE_GAP_PHY_1MBPS ,
656680 };
@@ -667,6 +691,8 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
667691 return err_code ;
668692 }
669693
694+ ble_drv_add_event_handler (advertising_on_ble_evt , self );
695+
670696 vm_used_ble = true;
671697 err_code = sd_ble_gap_adv_start (adv_handle , BLE_CONN_CFG_TAG_CUSTOM );
672698 if (err_code != NRF_SUCCESS ) {
@@ -677,7 +703,7 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
677703}
678704
679705
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 ) {
681707 if (self -> current_advertising_data != NULL && self -> current_advertising_data == self -> advertising_data ) {
682708 mp_raise_bleio_BluetoothError (translate ("Already advertising." ));
683709 }
@@ -689,6 +715,27 @@ void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool
689715 if (advertising_data_bufinfo -> len > 31 && scan_response_data_bufinfo -> len > 0 ) {
690716 mp_raise_bleio_BluetoothError (translate ("Extended advertisements with scan response not supported." ));
691717 }
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+
692739 // The advertising data buffers must not move, because the SoftDevice depends on them.
693740 // So make them long-lived and reuse them onwards.
694741 if (self -> advertising_data == NULL ) {
@@ -701,7 +748,7 @@ void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool
701748 memcpy (self -> advertising_data , advertising_data_bufinfo -> buf , advertising_data_bufinfo -> len );
702749 memcpy (self -> scan_response_data , scan_response_data_bufinfo -> buf , scan_response_data_bufinfo -> len );
703750
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 ,
705752 self -> advertising_data ,
706753 advertising_data_bufinfo -> len ,
707754 self -> scan_response_data ,
@@ -721,6 +768,10 @@ void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) {
721768 }
722769}
723770
771+ bool common_hal_bleio_adapter_get_advertising (bleio_adapter_obj_t * self ) {
772+ return self -> current_advertising_data != NULL ;
773+ }
774+
724775bool common_hal_bleio_adapter_get_connected (bleio_adapter_obj_t * self ) {
725776 for (size_t i = 0 ; i < BLEIO_TOTAL_CONNECTION_COUNT ; i ++ ) {
726777 bleio_connection_internal_t * connection = & bleio_connections [i ];
0 commit comments