diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 329e16e0908..6654a7c0666 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -305,6 +305,12 @@ microsecond_t minSupervisionTimeout( return (1 + slaveLatency.value()) * maxConnectionInterval * 2; } +bool is_connectable_advertising(const AdvertisingParameters ¶ms) +{ + advertising_event_properties_t event_properties(params.getType()); + return event_properties.connectable; +} + } // end of anonymous namespace const peripheral_privacy_configuration_t Gap::default_peripheral_privacy_configuration = { @@ -337,7 +343,6 @@ Gap::Gap( _privacy_enabled(false), _peripheral_privacy_configuration(default_peripheral_privacy_configuration), _central_privacy_configuration(default_central_privacy_configuration), - _random_address_rotating(false), _scan_enabled(false), _advertising_timeout(), _scan_timeout(), @@ -349,9 +354,6 @@ Gap::Gap( mbed::callback(this, &Gap::on_gap_event_received) ); - // Recover static random identity - _random_static_identity_address = _pal_gap.get_random_address(); - _pal_gap.set_event_handler(this); _address_registry.set_event_handler(this); } @@ -400,14 +402,17 @@ ble_error_t Gap::setRandomStaticAddress( return BLE_ERROR_INVALID_PARAM; } - ble_error_t err = _pal_gap.set_random_address(address); - if (err) { - return err; + if (!_privacy_enabled) { + ble_error_t err = _pal_gap.set_random_address(address); + if (err) { + return err; + } + + // FIXME: set random address for active sets + + _address_type = own_address_type_t::RANDOM; } - _address_type = own_address_type_t::RANDOM; - _address = address; - _random_static_identity_address = address; return BLE_ERROR_NONE; } @@ -473,11 +478,6 @@ ble_error_t Gap::stopScan() return err; } -#if BLE_FEATURE_PRIVACY - // Stop address rotation if required - set_random_address_rotation(false); -#endif - _scan_timeout.detach(); return BLE_ERROR_NONE; @@ -509,6 +509,8 @@ ble_error_t Gap::connect( } } + ble_error_t ret = BLE_ERROR_INTERNAL_STACK_FAILURE; + if (is_extended_advertising_available() == false) { phy_set_t set(connectionParams.getPhySet()); if (set.count() != 1 || set.get_1m() == false) { @@ -518,7 +520,7 @@ ble_error_t Gap::connect( // ensure scan is stopped. _pal_gap.scan_enable(false, false); - return _pal_gap.create_connection( + ret = _pal_gap.create_connection( connectionParams.getScanIntervalArray()[0], connectionParams.getScanWindowArray()[0], connectionParams.getFilter(), @@ -532,35 +534,39 @@ ble_error_t Gap::connect( connectionParams.getMinEventLengthArray()[0], connectionParams.getMaxConnectionIntervalArray()[0] ); - } + } else { + // ensure scan is stopped. + _pal_gap.extended_scan_enable(false, duplicates_filter_t::DISABLE, 0, 0); - // ensure scan is stopped. - _pal_gap.extended_scan_enable(false, duplicates_filter_t::DISABLE, 0, 0); + // reduce the address type to public or random + peer_address_type_t adjusted_address_type(peer_address_type_t::PUBLIC); - // reduce the address type to public or random - peer_address_type_t adjusted_address_type(peer_address_type_t::PUBLIC); + if (peerAddressType == peer_address_type_t::RANDOM || + peerAddressType == peer_address_type_t::RANDOM_STATIC_IDENTITY) { + adjusted_address_type = peer_address_type_t::RANDOM; + } - if (peerAddressType == peer_address_type_t::RANDOM || - peerAddressType == peer_address_type_t::RANDOM_STATIC_IDENTITY - ) { - adjusted_address_type = peer_address_type_t::RANDOM; + ret = _pal_gap.extended_create_connection( + connectionParams.getFilter(), + connectionParams.getOwnAddressType(), + adjusted_address_type, + peerAddress, + connectionParams.getPhySet(), + connectionParams.getScanIntervalArray(), + connectionParams.getScanWindowArray(), + connectionParams.getMinConnectionIntervalArray(), + connectionParams.getMaxConnectionIntervalArray(), + connectionParams.getSlaveLatencyArray(), + connectionParams.getConnectionSupervisionTimeoutArray(), + connectionParams.getMinEventLengthArray(), + connectionParams.getMaxEventLengthArray() + ); } - return _pal_gap.extended_create_connection( - connectionParams.getFilter(), - connectionParams.getOwnAddressType(), - adjusted_address_type, - peerAddress, - connectionParams.getPhySet(), - connectionParams.getScanIntervalArray(), - connectionParams.getScanWindowArray(), - connectionParams.getMinConnectionIntervalArray(), - connectionParams.getMaxConnectionIntervalArray(), - connectionParams.getSlaveLatencyArray(), - connectionParams.getConnectionSupervisionTimeoutArray(), - connectionParams.getMinEventLengthArray(), - connectionParams.getMaxEventLengthArray() - ); + if (ret == BLE_ERROR_NONE) { + _initiating = true; + } + return ret; } @@ -859,14 +865,21 @@ ble_error_t Gap::enablePrivacy(bool enable) return BLE_ERROR_NONE; } - if (enable && !_pal_gap.is_privacy_supported()) { - // Privacy is not supported by the implementation - return BLE_ERROR_NOT_IMPLEMENTED; + if (is_radio_active()) { + return BLE_ERROR_INVALID_STATE; } _privacy_enabled = enable; - update_address_resolution_setting(); + if (_privacy_enabled) { + _address_registry.start_private_address_generation(); + } else { + _address_registry.stop_private_address_generation(); + } + + if (_address_registry.is_controller_privacy_supported()) { + update_ll_address_resolution_setting(); + } return BLE_ERROR_NONE; } @@ -878,7 +891,7 @@ ble_error_t Gap::setPeripheralPrivacyConfiguration( { _peripheral_privacy_configuration = *configuration; - update_address_resolution_setting(); + update_ll_address_resolution_setting(); return BLE_ERROR_NONE; } @@ -900,7 +913,7 @@ ble_error_t Gap::setCentralPrivacyConfiguration( { _central_privacy_configuration = *configuration; - update_address_resolution_setting(); + update_ll_address_resolution_setting(); return BLE_ERROR_NONE; } @@ -970,6 +983,9 @@ ble_error_t Gap::reset() ); } _active_sets.clear(); + _pending_sets.clear(); + _address_refresh_sets.clear(); + _interruptible_sets.clear(); _connectable_payload_size_exceeded.clear(); _set_is_connectable.clear(); @@ -1022,9 +1038,7 @@ void Gap::process_legacy_scan_timeout() { /* legacy scanning timed out is based on timer so we need to stop the scan manually */ _pal_gap.scan_enable(false, false); -#if BLE_FEATURE_PRIVACY - set_random_address_rotation(false); -#endif + _scan_enabled = false; if (_event_handler) { _event_handler->onScanTimeout(ScanTimeoutEvent()); @@ -1040,16 +1054,11 @@ void Gap::on_advertising_timeout() void Gap::process_advertising_timeout() { - // This will signal timeout via onAdvertisingEnd() - ble_error_t err = _pal_gap.advertising_enable(false); - if (err) { - // TODO: define the mechanism signaling the error + if (!_active_sets.get(LEGACY_ADVERTISING_HANDLE)) { + return; } -#if BLE_FEATURE_PRIVACY - // Stop address rotation if required - set_random_address_rotation(false); -#endif + stopAdvertising(LEGACY_ADVERTISING_HANDLE); } @@ -1100,6 +1109,7 @@ void Gap::on_advertising_report(const GapAdvertisingReportEvent &e) advertising.address_type == connection_peer_address_type_t::RANDOM_ADDRESS && is_random_private_resolvable_address(advertising.address.data()) ) { + // FIXME: implement // Filter it out continue; } @@ -1186,6 +1196,12 @@ void Gap::on_connection_complete(const GapConnectionCompleteEvent &e) bool needs_pairing = false; bool needs_authentication = false; + // There is no need to check for extending advertising availability as this + // handler is for 4.x controllers + if (e.role == connection_role_t::PERIPHERAL) { + _active_sets.clear(LEGACY_ADVERTISING_HANDLE); + } + #if BLE_ROLE_PERIPHERAL #if BLE_FEATURE_PRIVACY if (_privacy_enabled && @@ -1228,11 +1244,6 @@ void Gap::on_connection_complete(const GapConnectionCompleteEvent &e) if (e.role.value() == e.role.PERIPHERAL) { _advertising_timeout.detach(); _pal_gap.advertising_enable(false); - -#if BLE_FEATURE_PRIVACY - // Stop address rotation if required - set_random_address_rotation(false); -#endif } #endif // BLE_ROLE_PERIPHERAL @@ -1432,7 +1443,7 @@ bool Gap::initialize_whitelist() const } -ble_error_t Gap::update_address_resolution_setting() +ble_error_t Gap::update_ll_address_resolution_setting() { // enable if privacy is enabled and resolution is requested in either central or peripheral mode bool enable = false; @@ -1451,123 +1462,7 @@ ble_error_t Gap::update_address_resolution_setting() #endif // BLE_ROLE_OBSERVER } - return _pal_gap.set_address_resolution(enable); -} - - -void Gap::set_random_address_rotation(bool enable) -{ - if (enable == _random_address_rotating) { - return; - } - - _random_address_rotating = enable; - - if (enable) { - // Set first address - update_random_address(); - - // Schedule rotations every 15 minutes as recomended by the spec - _address_rotation_ticker.attach( - mbed::callback(this, &Gap::on_address_rotation_timeout), - 15min - ); - } else { - // Stop ticker - _address_rotation_ticker.detach(); - - // Set static random identity address - _pal_gap.set_random_address( - _random_static_identity_address - ); - } -} - - -void Gap::update_random_address() -{ - if (!_random_address_rotating) { - // This event might have been queued before we disabled address rotation - return; - } -#if BLE_FEATURE_EXTENDED_ADVERTISING - if (is_extended_advertising_available()) { - for (uint8_t i = 0; i < BLE_GAP_MAX_ADVERTISING_SETS; ++i) { - if (_existing_sets.get(i)) { - ble::address_t address; - - if (!getUnresolvableRandomAddress(address)) { - return; - } - - /* ignore the error, if it fails to cycle because it's connectable */ - _pal_gap.set_advertising_set_random_address( - (advertising_handle_t) i, - address - ); - } - } - } -#endif // BLE_FEATURE_EXTENDED_ADVERTISING - - ble::address_t address; - - if (!getUnresolvableRandomAddress(address)) { - return; - } - - ble_error_t err = _pal_gap.set_random_address( - address - ); - - if (err) { - return; - } - - _address_type = own_address_type_t::RANDOM; - _address = address; -} - - -bool Gap::getUnresolvableRandomAddress(ble::address_t &address) -{ - do { - byte_array_t<8> random_data; -#if BLE_FEATURE_SECURITY - ble_error_t ret = _pal_sm.get_random_data(random_data); -#else - ble_error_t ret = BLE_ERROR_NOT_IMPLEMENTED; -#endif // BLE_FEATURE_SECURITY - if (ret != BLE_ERROR_NONE) { - // Abort - return false; - } - - // Build a non-resolvable private address as specified in the Core 4.2 spec, Vol 6, Part B, 1.3.2.2 - // Mask out two MSbs - random_data[5] &= 0x3F; - - // Copy to address - will copy first 6 bytes - address = ble::address_t(random_data.data()); - - if (!is_random_private_non_resolvable_address(address.data())) { - // If address is invalid, which is unlikely (all 0s or all 1s), try again - // If implementation is faulty, we'll get stuck here - continue; - } - - // Address is valid - break; - } - while (true); - - return true; -} - - -void Gap::on_address_rotation_timeout() -{ - _event_queue.post(mbed::callback(this, &Gap::update_random_address)); + return _address_registry.enable_controller_address_resolution(enable); } uint8_t Gap::getMaxAdvertisingSetNumber() @@ -1618,18 +1513,22 @@ ble_error_t Gap::createAdvertisingSet( for (; new_handle < end; ++new_handle) { if (!_existing_sets.get(new_handle)) { - ble_error_t err = setExtendedAdvertisingParameters( + // Note: we use setAdvertisingParameters instead of + // setExtendedAdvertisingParameters as it checks all the inputs. + // We need to indicate the set existing before making the request + // in case of failure we mark it back as not existing. + _existing_sets.set(new_handle); + ble_error_t err = setAdvertisingParameters( new_handle, parameters ); + if (err) { - return err; + _existing_sets.clear(new_handle); + } else { + *handle = new_handle; } - - _existing_sets.set(new_handle); - *handle = new_handle; - - return BLE_ERROR_NONE; + return err; } } @@ -1655,7 +1554,7 @@ ble_error_t Gap::destroyAdvertisingSet(advertising_handle_t handle) return BLE_ERROR_INVALID_PARAM; } - if (_active_sets.get(handle)) { + if (_pending_sets.get(handle) || _active_sets.get(handle)) { return BLE_ERROR_OPERATION_NOT_PERMITTED; } #if BLE_FEATURE_PERIODIC_ADVERTISING @@ -1681,20 +1580,30 @@ ble_error_t Gap::setAdvertisingParameters( const AdvertisingParameters ¶ms ) { -#if BLE_FEATURE_EXTENDED_ADVERTISING if (handle >= getMaxAdvertisingSetNumber()) { return BLE_ERROR_INVALID_PARAM; } + // It is not permited to reconfigure an advertising set while advertising + if (_pending_sets.get(handle) || _active_sets.get(handle)) { + return BLE_ERROR_OPERATION_NOT_PERMITTED; + } + +#if BLE_FEATURE_PRIVACY + // If privacy is enabled, alter the own address type used during advertising + if (_privacy_enabled && params.getOwnAddressType() != own_address_type_t::RANDOM) { + return BLE_ERROR_INVALID_PARAM; + } +#endif + +#if BLE_FEATURE_EXTENDED_ADVERTISING if (!_existing_sets.get(handle)) { if (handle == LEGACY_ADVERTISING_HANDLE) { - prepare_legacy_advertising_set(); + return prepare_legacy_advertising_set(params); } else { return BLE_ERROR_INVALID_PARAM; } - } - - if (is_extended_advertising_available()) { + } else if (is_extended_advertising_available()) { return setExtendedAdvertisingParameters(handle, params); } else #endif // BLE_FEATURE_EXTENDED_ADVERTISING @@ -1709,7 +1618,7 @@ ble_error_t Gap::setAdvertisingParameters( params.getChannel39() ); - return _pal_gap.set_advertising_parameters( + auto err = _pal_gap.set_advertising_parameters( params.getMinPrimaryInterval().value(), params.getMaxPrimaryInterval().value(), params.getType(), @@ -1719,29 +1628,24 @@ ble_error_t Gap::setAdvertisingParameters( channel_map, params.getFilter() ); + + if (!err) { + update_advertising_set_connectable_attribute(handle, params); + } + return err; } } - ble_error_t Gap::setExtendedAdvertisingParameters( advertising_handle_t handle, const AdvertisingParameters ¶ms ) { - if (handle >= getMaxAdvertisingSetNumber()) { - return BLE_ERROR_INVALID_PARAM; - } - - if (_active_sets.get(handle)) { - return BLE_ERROR_OPERATION_NOT_PERMITTED; - } - /* check for illegal parameter combination */ - if (( - params.getType() == advertising_type_t::CONNECTABLE_UNDIRECTED || - params.getType() == advertising_type_t::CONNECTABLE_DIRECTED - ) && - params.getUseLegacyPDU() == false) { + if ((params.getType() == advertising_type_t::CONNECTABLE_UNDIRECTED || + params.getType() == advertising_type_t::CONNECTABLE_DIRECTED) && + params.getUseLegacyPDU() == false + ) { /* these types can only be used with legacy PDUs */ return BLE_ERROR_INVALID_PARAM; } @@ -1757,7 +1661,7 @@ ble_error_t Gap::setExtendedAdvertisingParameters( params.getChannel39() ); - ble_error_t err = _pal_gap.set_extended_advertising_parameters( + auto err = _pal_gap.set_extended_advertising_parameters( handle, event_properties, params.getMinPrimaryInterval().value(), @@ -1775,20 +1679,11 @@ ble_error_t Gap::setExtendedAdvertisingParameters( params.getScanRequestNotification() ); - if (err) { - return err; - } - - if (event_properties.connectable) { - _set_is_connectable.set(handle); - } else { - _set_is_connectable.clear(handle); + if (!err) { + update_advertising_set_connectable_attribute(handle, params); } - return _pal_gap.set_advertising_set_random_address( - handle, - _random_static_identity_address - ); + return err; } @@ -1848,7 +1743,7 @@ ble_error_t Gap::setAdvertisingData( if (!_existing_sets.get(handle)) { if (handle == LEGACY_ADVERTISING_HANDLE) { - prepare_legacy_advertising_set(); + prepare_legacy_advertising_set(AdvertisingParameters{}); } else { return BLE_ERROR_INVALID_PARAM; } @@ -1883,7 +1778,7 @@ ble_error_t Gap::setAdvertisingData( return BLE_ERROR_INVALID_PARAM; } - if (!_active_sets.get(handle) && payload.size() > this->getMaxActiveSetAdvertisingDataLength()) { + if ((_pending_sets.get(handle) || _active_sets.get(handle)) && payload.size() > this->getMaxActiveSetAdvertisingDataLength()) { MBED_WARNING(MBED_ERROR_INVALID_SIZE, "Payload size for active sets needs to fit in a single operation" " - not greater than getMaxActiveSetAdvertisingDataLength()."); return BLE_ERROR_INVALID_PARAM; @@ -1891,7 +1786,7 @@ ble_error_t Gap::setAdvertisingData( if (!scan_response) { if (payload.size() > this->getMaxConnectableAdvertisingDataLength()) { - if (_active_sets.get(handle) && _set_is_connectable.get(handle)) { + if ((_pending_sets.get(handle) || _active_sets.get(handle)) && _set_is_connectable.get(handle)) { MBED_WARNING(MBED_ERROR_INVALID_SIZE, "Payload size for connectable advertising" " exceeds getMaxAdvertisingDataLength()."); return BLE_ERROR_INVALID_PARAM; @@ -1953,6 +1848,11 @@ ble_error_t Gap::startAdvertising( { ble_error_t error = BLE_ERROR_NONE; + // invalid state because it is starting or stopping. + if (_pending_sets.get(handle)) { + return BLE_ERROR_INVALID_STATE; + } + #if BLE_FEATURE_EXTENDED_ADVERTISING if (handle >= getMaxAdvertisingSetNumber()) { return BLE_ERROR_INVALID_PARAM; @@ -1968,6 +1868,21 @@ ble_error_t Gap::startAdvertising( } if (is_extended_advertising_available()) { + // Select the advertising address to use + address_t adv_address; + if (_privacy_enabled) { + if (_set_is_connectable.get(handle)) { + adv_address= _address_registry.get_resolvable_private_address(); + } else { + adv_address = _address_registry.get_non_resolvable_private_address(); + } + } else { + adv_address = _pal_gap.get_random_address(); + } + + // apply it + _pal_gap.set_advertising_set_random_address(handle, adv_address); + error = _pal_gap.extended_advertising_enable( /* enable */ true, /* number of advertising sets */ 1, @@ -1979,6 +1894,13 @@ ble_error_t Gap::startAdvertising( if (error) { return error; } + + if (maxDuration.value() || maxEvents) { + _interruptible_sets.clear(handle); + } else { + _interruptible_sets.set(handle); + } + } else #endif // BLE_FEATURE_EXTENDED_ADVERTISING { @@ -1986,6 +1908,32 @@ ble_error_t Gap::startAdvertising( return BLE_ERROR_INVALID_PARAM; } + // Select the advertising address to use + address_t adv_address; + if (_privacy_enabled) { + if (_scan_enabled) { + if (_central_privacy_configuration.use_non_resolvable_random_address == + _set_is_connectable.get(handle)) + { + // Conflicting state with the address currently used + return BLE_ERROR_INVALID_STATE; + } + } else { + // select the address to set + if (_set_is_connectable.get(handle)) { + adv_address= _address_registry.get_resolvable_private_address(); + } else { + adv_address = _address_registry.get_non_resolvable_private_address(); + } + } + } else { + adv_address = _pal_gap.get_random_address(); + } + + if (!_scan_enabled) { + _pal_gap.set_random_address(adv_address); + } + error = _pal_gap.advertising_enable(true); if (error) { return error; @@ -1998,9 +1946,11 @@ ble_error_t Gap::startAdvertising( maxDuration.valueChrono() ); } + + _interruptible_sets.set(LEGACY_ADVERTISING_HANDLE); } - _active_sets.set(handle); + _pending_sets.set(handle); return error; } @@ -2020,7 +1970,7 @@ ble_error_t Gap::stopAdvertising(advertising_handle_t handle) } #endif // BLE_FEATURE_EXTENDED_ADVERTISING - if (!_active_sets.get(handle)) { + if (!_active_sets.get(handle) || _pending_sets.get(handle)) { return BLE_ERROR_INVALID_STATE; } @@ -2053,7 +2003,7 @@ ble_error_t Gap::stopAdvertising(advertising_handle_t handle) _advertising_timeout.detach(); } - _active_sets.clear(handle); + _pending_sets.set(handle); return status; } @@ -2299,6 +2249,7 @@ void Gap::on_extended_advertising_report( *address_type == connection_peer_address_type_t::RANDOM_ADDRESS && is_random_private_resolvable_address(address.data()) ) { + // FIXME: Implement return; } #endif // BLE_FEATURE_PRIVACY @@ -2396,14 +2347,31 @@ void Gap::on_periodic_advertising_sync_loss(sync_handle_t sync_handle) void Gap::on_legacy_advertising_started() { + _active_sets.set(LEGACY_ADVERTISING_HANDLE); + _pending_sets.clear(LEGACY_ADVERTISING_HANDLE); + _address_refresh_sets.clear(LEGACY_ADVERTISING_HANDLE); } void Gap::on_legacy_advertising_stopped() { + + _active_sets.clear(LEGACY_ADVERTISING_HANDLE); + _pending_sets.clear(LEGACY_ADVERTISING_HANDLE); + + // restart advertising if it was stopped to refresh the address + if (_address_refresh_sets.get(LEGACY_ADVERTISING_HANDLE)) { + startAdvertising(LEGACY_ADVERTISING_HANDLE); + } } void Gap::on_advertising_set_started(const mbed::Span& handles) { + for (const auto &handle : handles) { + printf("advertising set %d started\r\n", handle); + _active_sets.set(handle); + _pending_sets.clear(handle); + _address_refresh_sets.clear(handle); + } } void Gap::on_advertising_set_terminated( @@ -2414,6 +2382,14 @@ void Gap::on_advertising_set_terminated( ) { _active_sets.clear(advertising_handle); + _pending_sets.clear(advertising_handle); + + // If this is part of the address refresh start advertising again. + if (_address_refresh_sets.get(advertising_handle) && !connection_handle) { + printf("restarting advertising set %d\r\n", advertising_handle); + startAdvertising(advertising_handle); + return; + } if (!_event_handler) { return; @@ -2506,7 +2482,6 @@ void Gap::on_remote_connection_parameter( } } - ble_error_t Gap::setScanParameters(const ScanParameters ¶ms) { if (is_extended_advertising_available()) { @@ -2558,11 +2533,6 @@ ble_error_t Gap::startScan( scan_period_t period ) { -#if BLE_FEATURE_PRIVACY - if (_privacy_enabled && _central_privacy_configuration.use_non_resolvable_random_address) { - set_random_address_rotation(true); - } -#endif // BLE_FEATURE_PRIVACY #if BLE_FEATURE_EXTENDED_ADVERTISING if (is_extended_advertising_available()) { ble_error_t err = _pal_gap.extended_scan_enable( @@ -2766,18 +2736,22 @@ bool Gap::is_extended_advertising_available() #endif // BLE_FEATURE_EXTENDED_ADVERTISING } - -void Gap::prepare_legacy_advertising_set() +ble_error_t Gap::prepare_legacy_advertising_set(const AdvertisingParameters& parameters) { if (_existing_sets.get(LEGACY_ADVERTISING_HANDLE)) { - return; + return BLE_ERROR_NONE; } - setExtendedAdvertisingParameters( + auto err = setExtendedAdvertisingParameters( LEGACY_ADVERTISING_HANDLE, - AdvertisingParameters() + parameters ); - _existing_sets.set(LEGACY_ADVERTISING_HANDLE); + + if (!err) { + _existing_sets.set(LEGACY_ADVERTISING_HANDLE); + } + + return err; } void Gap::setEventHandler(Gap::EventHandler *handler) @@ -2788,14 +2762,34 @@ void Gap::setEventHandler(Gap::EventHandler *handler) void Gap::on_resolvable_private_addresses_generated(const address_t &address) { + on_private_address_generated(true); } void Gap::on_non_resolvable_private_addresses_generated(const address_t &address) { + on_private_address_generated(false); } void Gap::on_private_address_generated(bool connectable) { + if (!_privacy_enabled) { + return; + } + + // refresh for address for all connectable advertising sets + for (size_t i = 0; i < BLE_GAP_MAX_ADVERTISING_SETS; ++i) { + if (!_pending_sets.get(i) && _active_sets.get(i) && + _set_is_connectable.get(i) == connectable && _interruptible_sets.get(i) + ) { + printf("stop advertising set %d\r\n", i); + auto err = stopAdvertising(i); + if (err) { + printf("failed to stop advertising set %d\r\n", i); + continue; + } + _address_refresh_sets.set(i); + } + } } @@ -2808,6 +2802,40 @@ void Gap::on_address_resolution_completion( { // FIXME: Implement } + + +bool Gap::is_advertising() const +{ + for (size_t i = 0; i < BLE_GAP_MAX_ADVERTISING_SETS; ++i) { + if (_pending_sets.get(i)) { + return true; + } + if (_active_sets.get(i)) { + return true; + } + if (_active_periodic_sets.get(i)) { + return true; + } + } + return false; +} + +bool Gap::is_radio_active() const { + return _initiating || _scan_enabled || is_advertising(); +} + +void Gap::update_advertising_set_connectable_attribute( + advertising_handle_t handle, + const AdvertisingParameters& parameters +) +{ + if (is_connectable_advertising(parameters)) { + _set_is_connectable.set(handle); + } else { + _set_is_connectable.clear(handle); + } } + + } // impl } // ble diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index 0d9ccab86b1..fedcff80904 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -405,15 +405,7 @@ class Gap : bool initialize_whitelist() const; - ble_error_t update_address_resolution_setting(); - - void set_random_address_rotation(bool enable); - - void update_random_address(); - - bool getUnresolvableRandomAddress(ble::address_t &address); - - void on_address_rotation_timeout(); + ble_error_t update_ll_address_resolution_setting(); ble_error_t setExtendedAdvertisingParameters( advertising_handle_t handle, @@ -422,7 +414,7 @@ class Gap : bool is_extended_advertising_available(); - void prepare_legacy_advertising_set(); + ble_error_t prepare_legacy_advertising_set(const AdvertisingParameters& parameters); /* implements PalGap::EventHandler */ private: @@ -551,6 +543,17 @@ class Gap : target_peer_address_type_t identity_address_type, const address_t &identity_address ) final; + +private: + bool is_advertising() const; + + bool is_radio_active() const; + + void update_advertising_set_connectable_attribute( + advertising_handle_t handle, + const AdvertisingParameters& parameters + ); + private: /** * Callchain containing all registered callback handlers for shutdown @@ -569,7 +572,6 @@ class Gap : PalSecurityManager &_pal_sm; PrivateAddressController &_address_registry; ble::own_address_type_t _address_type; - ble::address_t _address; initiator_policy_t _initiator_policy_mode; scanning_filter_policy_t _scanning_filter_policy; advertising_filter_policy_t _advertising_filter_policy; @@ -578,8 +580,6 @@ class Gap : bool _privacy_enabled; peripheral_privacy_configuration_t _peripheral_privacy_configuration; central_privacy_configuration_t _central_privacy_configuration; - ble::address_t _random_static_identity_address; - bool _random_address_rotating; bool _scan_enabled; mbed::LowPowerTimeout _advertising_timeout; @@ -587,6 +587,7 @@ class Gap : mbed::LowPowerTicker _address_rotation_ticker; bool _initiating = false; + template struct BitArray { BitArray() : data() @@ -638,6 +639,10 @@ class Gap : BitArray _active_periodic_sets; BitArray _connectable_payload_size_exceeded; BitArray _set_is_connectable; + BitArray _pending_sets; + BitArray _address_refresh_sets; + BitArray _interruptible_sets; + bool _user_manage_connection_parameter_requests : 1; };