Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
GenericGap.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2017-2017 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include <algorithm> 00018 #include <stdint.h> 00019 00020 #include "ble/BLEInstanceBase.h " 00021 #include "ble/BLEProtocol.h" 00022 #include "ble/Gap.h" 00023 #include "ble/pal/PalGap.h" 00024 #include "ble/pal/GapEvents.h" 00025 #include "ble/pal/GapTypes.h" 00026 #include "ble/pal/GenericAccessService.h" 00027 #include "ble/generic/GenericGap.h" 00028 00029 #include "drivers/Timeout.h" 00030 00031 namespace ble { 00032 namespace generic { 00033 00034 using pal::connection_peer_address_type_t; 00035 typedef BLEProtocol::AddressType_t LegacyAddressType_t; 00036 typedef BLEProtocol::AddressType LegacyAddressType; 00037 00038 namespace { 00039 00040 // Constants 00041 static const uint16_t scan_interval_min = 0x0004; 00042 static const uint16_t scan_interval_max = 0x4000; 00043 static const uint16_t connection_interval_min = 0x0006; 00044 static const uint16_t connection_interval_max = 0x0C80; 00045 static const uint16_t slave_latency_min = 0x0000; 00046 static const uint16_t slave_latency_max = 0x01F3; 00047 static const uint16_t advertising_interval_min = 0x0020; 00048 static const uint16_t advertising_interval_max = 0x4000; 00049 static const uint16_t supervision_timeout_min = 0x000A; 00050 static const uint16_t supervision_timeout_max = 0x0C80; 00051 00052 static const Gap::ConnectionParams_t default_connection_params = { 00053 /* min conn interval */ 50, 00054 /* max conn interval */ 100, 00055 /* slave latency */ 0, 00056 /* supervision timeout */ 600 00057 }; 00058 00059 static const GapScanningParams default_scan_params; 00060 00061 /* 00062 * Return true if value is included in the range [lower_bound : higher_bound] 00063 */ 00064 template<typename T> 00065 static bool is_in_range(T value, T lower_bound, T higher_bound) { 00066 if (value < lower_bound || value > higher_bound) { 00067 return false; 00068 } 00069 return true; 00070 } 00071 00072 /* 00073 * Return true if the scan parameters are valid or false otherwise. 00074 */ 00075 static bool is_scan_params_valid(const GapScanningParams* params) 00076 { 00077 if (params == NULL) { 00078 return false; 00079 } 00080 00081 if (is_in_range(params->getInterval(), scan_interval_min, scan_interval_max) == false) { 00082 return false; 00083 } 00084 00085 if (is_in_range(params->getWindow(), scan_interval_min, params->getInterval()) == false) { 00086 return false; 00087 } 00088 00089 return true; 00090 } 00091 00092 /* 00093 * Return true if the connection parameters are valid or false otherwise. 00094 */ 00095 static bool is_connection_params_valid(const Gap::ConnectionParams_t* params) 00096 { 00097 if (params == NULL) { 00098 return false; 00099 } 00100 00101 if (is_in_range(params->slaveLatency, slave_latency_min, slave_latency_max) == false) { 00102 return false; 00103 } 00104 00105 if (is_in_range(params->maxConnectionInterval, connection_interval_min, connection_interval_max) == false) { 00106 return false; 00107 } 00108 00109 if (is_in_range(params->minConnectionInterval, connection_interval_min, params->maxConnectionInterval) == false) { 00110 return false; 00111 } 00112 00113 if (is_in_range(params->connectionSupervisionTimeout, supervision_timeout_min, supervision_timeout_max) == false) { 00114 return false; 00115 } 00116 00117 uint16_t max_connection_interval_ms = 00118 ((uint32_t)params->maxConnectionInterval * 125) / 100; 00119 uint16_t min_connection_supervision_timeout = 00120 ((1 + params->slaveLatency) * max_connection_interval_ms * 2) / 10; 00121 00122 if (params->connectionSupervisionTimeout < min_connection_supervision_timeout) { 00123 return false; 00124 } 00125 00126 return true; 00127 } 00128 00129 /* 00130 * Return true of the connection parameters are acceptable as preferred connection 00131 * parameters. 00132 * 00133 * Prefered connection parameters unlike actual connection parameters allow the 00134 * max connection interval, min connection interval and connection supervision 00135 * timeout to be equal to 0xFFFF. When it is the case that value can be 00136 * interpreted as "non specific". 00137 */ 00138 static bool is_preferred_connection_params_valid(const Gap::ConnectionParams_t* params) 00139 { 00140 if (params == NULL) { 00141 return false; 00142 } 00143 00144 if (is_in_range(params->slaveLatency, slave_latency_min, slave_latency_max) == false) { 00145 return false; 00146 } 00147 00148 if ((is_in_range(params->maxConnectionInterval, connection_interval_min, connection_interval_max) == false) && 00149 (params->maxConnectionInterval != 0xFFFF)) { 00150 return false; 00151 } 00152 00153 if ((is_in_range(params->minConnectionInterval, connection_interval_min, params->maxConnectionInterval) == false) && 00154 (params->minConnectionInterval != 0xFFFF)) { 00155 return false; 00156 } 00157 00158 if (params->connectionSupervisionTimeout == 0xFFFF) { 00159 return true; 00160 } 00161 00162 if ((is_in_range(params->connectionSupervisionTimeout, supervision_timeout_min, supervision_timeout_max) == false)) { 00163 return false; 00164 } 00165 00166 if (params->maxConnectionInterval == 0xFFFF) { 00167 return true; 00168 } 00169 00170 uint16_t max_connection_interval_ms = 00171 ((uint32_t)params->maxConnectionInterval * 125) / 100; 00172 uint16_t min_connection_supervision_timeout = 00173 ((1 + params->slaveLatency) * max_connection_interval_ms * 2) / 10; 00174 00175 if (params->connectionSupervisionTimeout < min_connection_supervision_timeout) { 00176 return false; 00177 } 00178 00179 return true; 00180 } 00181 00182 /** 00183 * Check if random bytes of an address are valid. 00184 */ 00185 static bool is_prand_valid(const uint8_t* bytes, size_t len) 00186 { 00187 // at least one bit of the random part of the static address shall be 00188 // equal to 0 and at least one bit of the random part of the static 00189 // address shall be equal to 1 00190 for (size_t i = 0; i < (len - 1); ++i) { 00191 if ((bytes[i] != 0x00) && (bytes[i] != 0xFF)) { 00192 return true; 00193 } 00194 00195 if ((i > 0) && (bytes[i] != bytes[i - 1])) { 00196 return true; 00197 } 00198 } 00199 00200 if (((bytes[len - 1] & 0x3F) == 0x3F) && (bytes[len - 2] == 0xFF)) { 00201 return false; 00202 } 00203 00204 if (((bytes[len - 1] & 0x3F) == 0x00) && (bytes[len - 2] == 0x00)) { 00205 return false; 00206 } 00207 00208 return true; 00209 } 00210 00211 /* 00212 * Check if the random part of a random address with 48 random bytes are valid 00213 * or not. 00214 * Return true if it is the case and false otherwise. 00215 */ 00216 static bool is_prand_48_bits_valid(const BLEProtocol::AddressBytes_t address) 00217 { 00218 return is_prand_valid(address, 6); 00219 } 00220 00221 /* 00222 * Check if the random part of a random address with 24 random bytes are valid 00223 * or not. 00224 * Return true if it is the case and false otherwise. 00225 */ 00226 static bool is_prand_24_bits_valid(const BLEProtocol::AddressBytes_t address) 00227 { 00228 return is_prand_valid(address + 3, 3); 00229 } 00230 00231 /* 00232 * Return true if address is a random static address. 00233 */ 00234 static bool is_random_static_address(const BLEProtocol::AddressBytes_t address) 00235 { 00236 // top two msb bits shall be equal to 0b11. 00237 if ((address[5] & 0xC0) != 0xC0) { 00238 return false; 00239 } 00240 00241 return is_prand_48_bits_valid(address); 00242 } 00243 00244 /* 00245 * Return true if address is a random private non resolvable address. 00246 */ 00247 static bool is_random_private_non_resolvable_address( 00248 const BLEProtocol::AddressBytes_t address 00249 ) { 00250 // top two msb bits shall be equal to 0b00. 00251 if ((address[5] & 0xC0) != 0x00) { 00252 return false; 00253 } 00254 00255 return is_prand_48_bits_valid(address); 00256 } 00257 00258 /* 00259 * Return true if address is a random private resolvable address. 00260 */ 00261 static bool is_random_private_resolvable_address( 00262 const BLEProtocol::AddressBytes_t address 00263 ) { 00264 // top two msb bits shall be equal to 0b01. 00265 if ((address[5] & 0xC0) != 0x40) { 00266 return false; 00267 } 00268 00269 return is_prand_24_bits_valid(address); 00270 } 00271 00272 /* 00273 * Return true if the address is a random address. 00274 */ 00275 static bool is_random_address(const BLEProtocol::AddressBytes_t address) 00276 { 00277 return is_random_private_resolvable_address(address) || 00278 is_random_private_non_resolvable_address(address) || 00279 is_random_static_address(address); 00280 } 00281 00282 /* 00283 * Check disconnection reason validity. 00284 */ 00285 static bool is_disconnection_reason_valid (Gap::DisconnectionReason_t reason) 00286 { 00287 switch (reason) { 00288 /** 00289 * Note: accepted reasons are: 00290 typedef pal::disconnection_reason_t reason_t; 00291 case reason_t::AUTHENTICATION_FAILLURE: 00292 case reason_t::REMOTE_USER_TERMINATED_CONNECTION: 00293 case reason_t::REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_LOW_RESOURCES: 00294 case reason_t::REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_POWER_OFF: 00295 case reason_t::UNSUPPORTED_REMOTE_FEATURE: 00296 case reason_t::PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED: 00297 case reason_t::UNACCEPTABLE_CONNECTION_PARAMETERS: 00298 */ 00299 00300 // TODO Fix Disconnectionreason_t which expose invalid value 00301 case Gap::REMOTE_USER_TERMINATED_CONNECTION: 00302 case Gap::REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES: 00303 case Gap::REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF: 00304 case Gap::CONN_INTERVAL_UNACCEPTABLE: 00305 return true; 00306 default: 00307 return false; 00308 } 00309 } 00310 00311 /* 00312 * Return true if the whitelist in input is valid or false otherwise. 00313 */ 00314 static bool is_whitelist_valid(const Gap::Whitelist_t& whitelist) 00315 { 00316 if (whitelist.size > whitelist.capacity) { 00317 return false; 00318 } 00319 00320 for (size_t i = 0; i < whitelist.size; ++i) { 00321 const BLEProtocol::Address_t& address = whitelist.addresses[i]; 00322 if (address.type != BLEProtocol::AddressType::PUBLIC && 00323 address.type != BLEProtocol::AddressType::RANDOM_STATIC 00324 ) { 00325 return false; 00326 } 00327 00328 if (address.type != BLEProtocol::AddressType::PUBLIC) { 00329 if (is_random_address(address.address) == false) { 00330 return false; 00331 } 00332 } 00333 } 00334 return true; 00335 } 00336 00337 /* 00338 * Return true if device is present in the whitelist. 00339 */ 00340 static bool is_in_whitelist( 00341 const BLEProtocol::Address_t& device, const Gap::Whitelist_t& whitelist 00342 ) { 00343 for (size_t i = 0; i < whitelist.size; ++i) { 00344 const BLEProtocol::Address_t& potential_device = whitelist.addresses[i]; 00345 00346 if (potential_device.type != device.type) { 00347 continue; 00348 } 00349 00350 if (memcmp(potential_device.address, device.address, sizeof(device.address)) == 0) { 00351 return true; 00352 } 00353 } 00354 return false; 00355 } 00356 00357 /* 00358 * Convert a BLEProtocol::AddressType_t into a pal::whitelist_address_type_t. 00359 */ 00360 static pal::whitelist_address_type_t to_whitelist_address_type( 00361 BLEProtocol::AddressType_t address_type 00362 ) { 00363 return (address_type == BLEProtocol::AddressType::PUBLIC) ? 00364 pal::whitelist_address_type_t::PUBLIC_DEVICE_ADDRESS : 00365 pal::whitelist_address_type_t::RANDOM_DEVICE_ADDRESS; 00366 } 00367 00368 /* 00369 * Convert a BLEProtocol::AddressType_t into a pal::peer_address_type 00370 */ 00371 static peer_address_type_t to_peer_address_type( 00372 LegacyAddressType_t address_type 00373 ) { 00374 return (address_type == LegacyAddressType::PUBLIC) ? 00375 peer_address_type_t::PUBLIC : 00376 peer_address_type_t::RANDOM; 00377 } 00378 00379 00380 /* 00381 * Return true if the advertising parameters are valid. 00382 */ 00383 static bool is_advertising_params_valid(const GapAdvertisingParams& params) 00384 { 00385 if (is_in_range(params.getIntervalInADVUnits(), advertising_interval_min, advertising_interval_max) == false) { 00386 return false; 00387 } 00388 00389 if (params.getAdvertisingType() > GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED) { 00390 return false; 00391 } 00392 00393 return true; 00394 } 00395 00396 } // end of anonymous namespace 00397 00398 GenericGap::GenericGap( 00399 pal::EventQueue& event_queue, 00400 pal::Gap& pal_gap, 00401 pal::GenericAccessService& generic_access_service, 00402 pal::SecurityManager& pal_sm 00403 ) : _event_queue(event_queue), 00404 _pal_gap(pal_gap), 00405 _gap_service(generic_access_service), 00406 _pal_sm(pal_sm), 00407 _address_type(LegacyAddressType::PUBLIC), 00408 _initiator_policy_mode(pal::initiator_policy_t::NO_FILTER), 00409 _scanning_filter_policy(pal::scanning_filter_policy_t::NO_FILTER), 00410 _advertising_filter_policy(pal::advertising_filter_policy_t::NO_FILTER), 00411 _whitelist(), 00412 _privacy_enabled(false), 00413 _peripheral_privacy_configuration(default_peripheral_privacy_configuration), 00414 _central_privacy_configuration(default_central_privacy_configuration), 00415 _random_address_rotating(false), 00416 _advertising_timeout(), 00417 _scan_timeout(), 00418 _connection_event_handler(NULL) 00419 { 00420 _pal_gap.when_gap_event_received( 00421 mbed::callback(this, &GenericGap::on_gap_event_received) 00422 ); 00423 00424 // Recover static random identity 00425 _random_static_identity_address = _pal_gap.get_random_address(); 00426 } 00427 00428 GenericGap::~GenericGap () 00429 { 00430 } 00431 00432 ble_error_t GenericGap::setAddress ( 00433 LegacyAddressType_t type, 00434 const Address_t address 00435 ) { 00436 switch (type) { 00437 case LegacyAddressType::PUBLIC: 00438 // The public address cannot be set, just set the type to public 00439 _address_type = type; 00440 return BLE_ERROR_NONE; 00441 00442 case LegacyAddressType::RANDOM_STATIC: { 00443 if (is_random_static_address(address) == false) { 00444 return BLE_ERROR_INVALID_PARAM; 00445 } 00446 00447 ble_error_t err = _pal_gap.set_random_address( 00448 ble::address_t(address) 00449 ); 00450 if (err) { 00451 return err; 00452 } 00453 00454 _address_type = type; 00455 _address = ble::address_t(address); 00456 _random_static_identity_address = ble::address_t(address); 00457 return BLE_ERROR_NONE; 00458 } 00459 00460 case LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE: 00461 case LegacyAddressType::RANDOM_PRIVATE_NON_RESOLVABLE: 00462 // Note: it is not allowed to set directly these addresses 00463 // privacy management handled it for users. 00464 return BLE_ERROR_INVALID_PARAM; 00465 00466 default: 00467 return BLE_ERROR_INVALID_PARAM; 00468 } 00469 } 00470 00471 ble_error_t GenericGap::getAddress ( 00472 LegacyAddressType_t *type, 00473 Address_t address 00474 ) { 00475 *type = _address_type; 00476 ble::address_t address_value; 00477 00478 if (_address_type == LegacyAddressType::PUBLIC) { 00479 address_value = _pal_gap.get_device_address(); 00480 } else { 00481 address_value = _pal_gap.get_random_address(); 00482 } 00483 00484 memcpy(address, address_value.data(), address_value.size()); 00485 return BLE_ERROR_NONE; 00486 } 00487 00488 uint16_t GenericGap::getMinAdvertisingInterval () const 00489 { 00490 return GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN; 00491 } 00492 00493 uint16_t GenericGap::getMinNonConnectableAdvertisingInterval () const 00494 { 00495 return GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON; 00496 } 00497 00498 uint16_t GenericGap::getMaxAdvertisingInterval () const 00499 { 00500 return GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX; 00501 } 00502 00503 ble_error_t GenericGap::stopAdvertising () 00504 { 00505 ble_error_t err = _pal_gap.advertising_enable(false); 00506 if (err) { 00507 return err; 00508 } 00509 _advertising_timeout.detach(); 00510 state.advertising = false; 00511 00512 // Stop address rotation if required 00513 set_random_address_rotation(false); 00514 00515 return BLE_ERROR_NONE; 00516 } 00517 00518 ble_error_t GenericGap::stopScan () 00519 { 00520 ble_error_t err = _pal_gap.scan_enable(false, false); 00521 if (err) { 00522 return err; 00523 } 00524 00525 // Stop address rotation if required 00526 set_random_address_rotation(false); 00527 00528 _scan_timeout.detach(); 00529 return BLE_ERROR_NONE; 00530 } 00531 00532 ble_error_t GenericGap::connect ( 00533 const Address_t peerAddr, 00534 PeerAddressType_t peerAddrType, 00535 const ConnectionParams_t *connectionParams, 00536 const GapScanningParams *scanParams 00537 ) { 00538 if (connectionParams == NULL) { 00539 connectionParams = &default_connection_params; 00540 } 00541 00542 if (scanParams == NULL) { 00543 scanParams = &default_scan_params; 00544 } 00545 00546 if (is_scan_params_valid(scanParams) == false) { 00547 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00548 } 00549 00550 if (is_connection_params_valid(connectionParams) == false) { 00551 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00552 } 00553 00554 // Force scan stop before initiating the scan used for connection 00555 stopScan (); 00556 00557 return _pal_gap.create_connection( 00558 scanParams->getInterval(), 00559 scanParams->getWindow(), 00560 _initiator_policy_mode, 00561 (pal::connection_peer_address_type_t::type ) peerAddrType.value(), 00562 ble::address_t(peerAddr), 00563 get_own_address_type(CENTRAL_CONNECTION /* requires resolvable address */), 00564 connectionParams->minConnectionInterval, 00565 connectionParams->maxConnectionInterval, 00566 connectionParams->slaveLatency, 00567 connectionParams->connectionSupervisionTimeout, 00568 /* minimum_connection_event_length */ 0, 00569 /* maximum_connection_event_length */ 0 00570 ); 00571 } 00572 00573 00574 ble_error_t GenericGap::connect ( 00575 const Address_t peerAddr, 00576 LegacyAddressType_t peerAddrType, 00577 const ConnectionParams_t* connectionParams, 00578 const GapScanningParams* scanParams 00579 ) { 00580 return connect ( 00581 peerAddr, 00582 to_peer_address_type(peerAddrType), 00583 connectionParams, 00584 scanParams 00585 ); 00586 } 00587 00588 ble_error_t GenericGap::disconnect (Handle_t connectionHandle, DisconnectionReason_t reason) 00589 { 00590 if (is_disconnection_reason_valid(reason) == false) { 00591 return BLE_ERROR_INVALID_PARAM; 00592 } 00593 return _pal_gap.disconnect( 00594 connectionHandle, 00595 (pal::disconnection_reason_t::type) reason 00596 ); 00597 } 00598 00599 ble_error_t GenericGap::updateConnectionParams (Handle_t handle, const ConnectionParams_t *params) 00600 { 00601 if (is_connection_params_valid(params) == false) { 00602 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00603 } 00604 00605 return _pal_gap.connection_parameters_update( 00606 handle, 00607 params->minConnectionInterval, 00608 params->maxConnectionInterval, 00609 params->slaveLatency, 00610 params->connectionSupervisionTimeout, 00611 /* minimum_connection_event_length */ 0, 00612 /* maximum_connection_event_length */ 0 00613 ); 00614 } 00615 00616 ble_error_t GenericGap::getPreferredConnectionParams (ConnectionParams_t *params) 00617 { 00618 if (params == NULL) { 00619 return BLE_ERROR_INVALID_PARAM; 00620 } 00621 00622 return _gap_service.get_peripheral_prefered_connection_parameters( 00623 *params 00624 ); 00625 } 00626 00627 ble_error_t GenericGap::setPreferredConnectionParams (const ConnectionParams_t *params) 00628 { 00629 if(is_preferred_connection_params_valid(params) == false) { 00630 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00631 } 00632 00633 return _gap_service.set_peripheral_prefered_connection_parameters( 00634 *params 00635 ); 00636 } 00637 00638 ble_error_t GenericGap::setDeviceName (const uint8_t *deviceName) 00639 { 00640 return _gap_service.set_device_name(deviceName); 00641 } 00642 00643 ble_error_t GenericGap::getDeviceName (uint8_t *deviceName, unsigned *lengthP) 00644 { 00645 if (lengthP == NULL) { 00646 return BLE_ERROR_INVALID_PARAM; 00647 } 00648 00649 uint8_t length = 0; 00650 ble_error_t err = _gap_service.get_device_name_length(length); 00651 if (err) { 00652 return err; 00653 } 00654 00655 if (deviceName != NULL) { 00656 if (*lengthP < length) { 00657 return BLE_ERROR_INVALID_PARAM; 00658 } 00659 00660 ArrayView<uint8_t> name(deviceName, *lengthP); 00661 err = _gap_service.get_device_name(name); 00662 if (err) { 00663 return err; 00664 } 00665 } 00666 *lengthP = length; 00667 return BLE_ERROR_NONE; 00668 } 00669 00670 ble_error_t GenericGap::setAppearance (GapAdvertisingData::Appearance appearance) 00671 { 00672 return _gap_service.set_appearance(appearance); 00673 } 00674 00675 ble_error_t GenericGap::getAppearance (GapAdvertisingData::Appearance *appearanceP) 00676 { 00677 if (appearanceP == NULL) { 00678 return BLE_ERROR_INVALID_PARAM; 00679 } 00680 return _gap_service.get_appearance(*appearanceP); 00681 } 00682 00683 ble_error_t GenericGap::setTxPower (int8_t txPower) 00684 { 00685 // TODO: This is not standard, expose it as an extension API and document it 00686 // as such 00687 return BLE_ERROR_NOT_IMPLEMENTED; 00688 } 00689 00690 void GenericGap::getPermittedTxPowerValues (const int8_t **valueArrayPP, size_t *countP) 00691 { 00692 *countP = 0; 00693 } 00694 00695 uint8_t GenericGap::getMaxWhitelistSize (void) const 00696 { 00697 return _pal_gap.read_white_list_capacity(); 00698 } 00699 00700 ble_error_t GenericGap::getWhitelist (Whitelist_t &whitelist) const 00701 { 00702 if(initialize_whitelist() == false) { 00703 return BLE_ERROR_INVALID_STATE; 00704 } 00705 00706 if (whitelist.capacity < _whitelist.capacity) { 00707 return BLE_ERROR_INVALID_PARAM; 00708 } 00709 00710 for (size_t i = 0; i < _whitelist.size; ++i) { 00711 whitelist.addresses[i] = _whitelist.addresses[i]; 00712 } 00713 00714 whitelist.capacity = _whitelist.capacity; 00715 return BLE_ERROR_NONE; 00716 } 00717 00718 ble_error_t GenericGap::setWhitelist (const Whitelist_t &whitelist) 00719 { 00720 if (is_whitelist_valid(whitelist) == false) { 00721 return BLE_ERROR_INVALID_PARAM; 00722 } 00723 00724 if(initialize_whitelist() == false) { 00725 return BLE_ERROR_INVALID_STATE; 00726 } 00727 00728 if (whitelist.capacity > _whitelist.capacity) { 00729 return BLE_ERROR_INVALID_PARAM; 00730 } 00731 00732 // first evict devices not in the existing whitelist 00733 for (size_t i = 0; i < _whitelist.size; ++i) { 00734 const BLEProtocol::Address_t& device = _whitelist.addresses[i]; 00735 00736 if (is_in_whitelist(device, whitelist) == false) { 00737 ble_error_t err = _pal_gap.remove_device_from_whitelist( 00738 to_whitelist_address_type(device.type), 00739 device.address 00740 ); 00741 00742 // try to restore the whitelist to its initial state 00743 if (err) { 00744 for (size_t j = 0; j < i; ++j) { 00745 const BLEProtocol::Address_t& device = _whitelist.addresses[j]; 00746 00747 if (is_in_whitelist(device, whitelist) == false) { 00748 _pal_gap.add_device_to_whitelist( 00749 to_whitelist_address_type(device.type), 00750 device.address 00751 ); 00752 } 00753 } 00754 return err; 00755 } 00756 } 00757 } 00758 00759 // second add devices which were not in the initial whitelist 00760 for (size_t i = 0; i < whitelist.size; ++i) { 00761 const BLEProtocol::Address_t& device = whitelist.addresses[i]; 00762 00763 if (is_in_whitelist(device, _whitelist) == false) { 00764 ble_error_t err = _pal_gap.add_device_to_whitelist( 00765 to_whitelist_address_type(device.type), 00766 device.address 00767 ); 00768 00769 // try to restore the whitelist to its initial state 00770 if (err) { 00771 // first remove the devices added 00772 for (size_t j = 0; j < i; ++j) { 00773 const BLEProtocol::Address_t& device = whitelist.addresses[j]; 00774 00775 if (is_in_whitelist(device, _whitelist) == false) { 00776 _pal_gap.remove_device_from_whitelist( 00777 to_whitelist_address_type(device.type), 00778 device.address 00779 ); 00780 } 00781 } 00782 00783 // second add the devices of the initial list evicted 00784 for (size_t i = 0; i < _whitelist.size; ++i) { 00785 const BLEProtocol::Address_t& device = _whitelist.addresses[i]; 00786 00787 if (is_in_whitelist(device, whitelist) == false) { 00788 _pal_gap.add_device_to_whitelist( 00789 to_whitelist_address_type(device.type), 00790 device.address 00791 ); 00792 } 00793 } 00794 00795 return err; 00796 } 00797 } 00798 } 00799 00800 // commit the devices into the whitelist 00801 for (size_t i = 0; i < whitelist.size; ++i) { 00802 _whitelist.addresses[i] = whitelist.addresses[i]; 00803 } 00804 00805 _whitelist.size = whitelist.size; 00806 00807 return BLE_ERROR_NONE; 00808 } 00809 00810 ble_error_t GenericGap::setAdvertisingPolicyMode (AdvertisingPolicyMode_t mode) 00811 { 00812 if (mode > Gap::ADV_POLICY_FILTER_ALL_REQS) { 00813 return BLE_ERROR_INVALID_PARAM; 00814 } 00815 00816 _advertising_filter_policy = (pal::advertising_filter_policy_t::type ) mode; 00817 return BLE_ERROR_NONE; 00818 } 00819 00820 ble_error_t GenericGap::setScanningPolicyMode (ScanningPolicyMode_t mode) 00821 { 00822 if (mode > Gap::SCAN_POLICY_FILTER_ALL_ADV) { 00823 return BLE_ERROR_INVALID_PARAM; 00824 } 00825 00826 _scanning_filter_policy = (pal::scanning_filter_policy_t::type ) mode; 00827 return BLE_ERROR_NONE; 00828 } 00829 00830 ble_error_t GenericGap::setInitiatorPolicyMode (InitiatorPolicyMode_t mode) 00831 { 00832 if (mode > Gap::INIT_POLICY_FILTER_ALL_ADV) { 00833 return BLE_ERROR_INVALID_PARAM; 00834 } 00835 00836 _initiator_policy_mode = (pal::initiator_policy_t::type ) mode; 00837 return BLE_ERROR_NONE; 00838 } 00839 00840 Gap::AdvertisingPolicyMode_t GenericGap::getAdvertisingPolicyMode (void) const 00841 { 00842 return (AdvertisingPolicyMode_t) _advertising_filter_policy.value(); 00843 } 00844 00845 Gap::ScanningPolicyMode_t GenericGap::getScanningPolicyMode (void) const 00846 { 00847 return (ScanningPolicyMode_t) _scanning_filter_policy.value(); 00848 } 00849 00850 Gap::InitiatorPolicyMode_t GenericGap::getInitiatorPolicyMode (void) const 00851 { 00852 return (InitiatorPolicyMode_t) _initiator_policy_mode.value(); 00853 } 00854 00855 ble_error_t GenericGap::startRadioScan (const GapScanningParams &scanningParams) 00856 { 00857 if (is_scan_params_valid(&scanningParams) == false) { 00858 return BLE_ERROR_INVALID_PARAM; 00859 } 00860 00861 if (_scanning_filter_policy == pal::scanning_filter_policy_t::FILTER_ADVERTISING && 00862 _whitelist.size == 0) { 00863 return BLE_ERROR_INVALID_STATE; 00864 } 00865 00866 pal::own_address_type_t own_address_type = get_own_address_type(CENTRAL_SCAN /* central, can use non resolvable address for scan requests */); 00867 00868 if(_privacy_enabled && (own_address_type == pal::own_address_type_t::RANDOM_ADDRESS)) 00869 { 00870 // Use non-resolvable static random address 00871 set_random_address_rotation(true); 00872 } 00873 00874 ble_error_t err = _pal_gap.set_scan_parameters( 00875 scanningParams.getActiveScanning(), 00876 scanningParams.getInterval(), 00877 scanningParams.getWindow(), 00878 own_address_type, 00879 _scanning_filter_policy 00880 ); 00881 00882 if (err) { 00883 return err; 00884 } 00885 00886 err = _pal_gap.scan_enable(true, false); 00887 00888 if (err) { 00889 return err; 00890 } 00891 00892 _scan_timeout.detach(); 00893 uint16_t timeout = scanningParams.getTimeout(); 00894 if (timeout) { 00895 _scan_timeout.attach_us( 00896 mbed::callback(this, &GenericGap::on_scan_timeout), 00897 scanningParams.getTimeout() * 1000000U 00898 ); 00899 } 00900 00901 return BLE_ERROR_NONE; 00902 } 00903 00904 ble_error_t GenericGap::initRadioNotification (void) 00905 { 00906 return BLE_ERROR_NOT_IMPLEMENTED; 00907 } 00908 00909 ble_error_t GenericGap::enablePrivacy (bool enable) 00910 { 00911 if(enable == _privacy_enabled) { 00912 // No change 00913 return BLE_ERROR_NONE; 00914 } 00915 00916 if(enable && !_pal_gap.is_privacy_supported()) 00917 { 00918 // Privacy is not supported by the implementation 00919 return BLE_ERROR_NOT_IMPLEMENTED; 00920 } 00921 00922 _privacy_enabled = enable; 00923 00924 update_address_resolution_setting(); 00925 00926 return BLE_ERROR_NONE; 00927 } 00928 00929 ble_error_t GenericGap::setPeripheralPrivacyConfiguration ( 00930 const PeripheralPrivacyConfiguration_t *configuration 00931 ) 00932 { 00933 _peripheral_privacy_configuration = *configuration; 00934 00935 update_address_resolution_setting(); 00936 00937 return BLE_ERROR_NONE; 00938 } 00939 00940 ble_error_t GenericGap::getPeripheralPrivacyConfiguration ( 00941 PeripheralPrivacyConfiguration_t *configuration 00942 ) 00943 { 00944 *configuration = _peripheral_privacy_configuration; 00945 00946 return BLE_ERROR_NONE; 00947 } 00948 00949 ble_error_t GenericGap::setCentralPrivacyConfiguration ( 00950 const CentralPrivacyConfiguration_t *configuration 00951 ) 00952 { 00953 _central_privacy_configuration = *configuration; 00954 00955 update_address_resolution_setting(); 00956 00957 return BLE_ERROR_NONE; 00958 } 00959 00960 ble_error_t GenericGap::getCentralPrivacyConfiguration ( 00961 CentralPrivacyConfiguration_t *configuration 00962 ) 00963 { 00964 *configuration = _central_privacy_configuration; 00965 00966 return BLE_ERROR_NONE; 00967 } 00968 00969 ble_error_t GenericGap::setAdvertisingData (const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) 00970 { 00971 ble_error_t err = _pal_gap.set_advertising_data( 00972 advData.getPayloadLen(), 00973 pal::advertising_data_t(advData.getPayload(), advData.getPayloadLen()) 00974 ); 00975 if (err) { 00976 return err; 00977 } 00978 00979 return _pal_gap.set_scan_response_data( 00980 scanResponse.getPayloadLen(), 00981 pal::advertising_data_t(scanResponse.getPayload(), scanResponse.getPayloadLen()) 00982 ); 00983 } 00984 00985 ble_error_t GenericGap::startAdvertising(const GapAdvertisingParams& params) 00986 { 00987 if (is_advertising_params_valid(params) == false) { 00988 return BLE_ERROR_INVALID_PARAM; 00989 } 00990 00991 // We can only use non resolvable addresses if the device is non connectable 00992 AddressUseType_t address_use_type = 00993 ((params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED) || 00994 (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED)) ? 00995 PERIPHERAL_NON_CONNECTABLE : 00996 PERIPHERAL_CONNECTABLE; 00997 00998 pal::own_address_type_t own_address_type = get_own_address_type(address_use_type); 00999 01000 if(_privacy_enabled && (own_address_type == pal::own_address_type_t::RANDOM_ADDRESS)) 01001 { 01002 // Use non-resolvable static random address 01003 set_random_address_rotation(true); 01004 } 01005 01006 // TODO: fix the high level API to have a min/max range 01007 // Going against recommendations (The Advertising_Interval_Min and 01008 // Advertising_Interval_Max should not be the same value to enable the 01009 // Controller to determine the best advertising interval given other activities.) 01010 // for now but not against specification: "The Advertising_Interval_Min 01011 // shall be less than or equal to the Advertising_Interval_Max" 01012 ble_error_t err = _pal_gap.set_advertising_parameters( 01013 /* advertising_interval_min */ params.getIntervalInADVUnits(), 01014 /* advertising_interval_max */ params.getIntervalInADVUnits(), 01015 (pal::advertising_type_t::type ) params.getAdvertisingType(), 01016 own_address_type, 01017 pal::advertising_peer_address_type_t::PUBLIC_ADDRESS, 01018 ble::address_t(), 01019 pal::advertising_channel_map_t::ALL_ADVERTISING_CHANNELS, 01020 _advertising_filter_policy 01021 ); 01022 01023 if (err) { 01024 return err; 01025 } 01026 01027 err = _pal_gap.advertising_enable(true); 01028 if (err) { 01029 return err; 01030 } 01031 01032 state.advertising = true; 01033 01034 _advertising_timeout.detach(); 01035 uint16_t timeout = params.getTimeout(); 01036 if (timeout) { 01037 _advertising_timeout.attach_us( 01038 mbed::callback(this, &GenericGap::on_advertising_timeout), 01039 params.getTimeout() * 1000000U 01040 ); 01041 } 01042 01043 return BLE_ERROR_NONE; 01044 } 01045 01046 ble_error_t GenericGap::reset (void) 01047 { 01048 Gap::reset (); 01049 _advertising_timeout.detach(); 01050 _scan_timeout.detach(); 01051 01052 return BLE_ERROR_NONE; 01053 } 01054 01055 void GenericGap::processConnectionEvent ( 01056 Handle_t handle, 01057 Role_t role, 01058 PeerAddressType_t peerAddrType, 01059 const BLEProtocol::AddressBytes_t peerAddr, 01060 BLEProtocol::AddressType_t ownAddrType, 01061 const BLEProtocol::AddressBytes_t ownAddr, 01062 const ConnectionParams_t *connectionParams, 01063 const uint8_t *peerResolvableAddr, 01064 const uint8_t *localResolvableAddr 01065 ) { 01066 if (_connection_event_handler) { 01067 _connection_event_handler->on_connected( 01068 handle, 01069 role, 01070 peerAddrType, 01071 peerAddr, 01072 ownAddrType, 01073 ownAddr, 01074 connectionParams 01075 ); 01076 } 01077 01078 ::Gap::processConnectionEvent( 01079 handle, 01080 role, 01081 peerAddrType, 01082 peerAddr, 01083 ownAddrType, 01084 ownAddr, 01085 connectionParams, 01086 peerResolvableAddr, 01087 localResolvableAddr 01088 ); 01089 } 01090 01091 void GenericGap::processDisconnectionEvent ( 01092 Handle_t handle, 01093 DisconnectionReason_t reason 01094 ) { 01095 if (_connection_event_handler) { 01096 _connection_event_handler->on_disconnected( 01097 handle, 01098 reason 01099 ); 01100 } 01101 01102 ::Gap::processDisconnectionEvent( 01103 handle, 01104 reason 01105 ); 01106 } 01107 01108 void GenericGap::on_scan_timeout() 01109 { 01110 _event_queue.post(mbed::callback(this, &GenericGap::process_scan_timeout)); 01111 } 01112 01113 void GenericGap::process_scan_timeout() 01114 { 01115 ble_error_t err = _pal_gap.scan_enable(false, false); 01116 if (err) { 01117 // TODO: define the mechanism signaling the error 01118 } 01119 processTimeoutEvent(Gap::TIMEOUT_SRC_SCAN); 01120 } 01121 01122 void GenericGap::on_advertising_timeout() 01123 { 01124 _event_queue.post(mbed::callback(this, &GenericGap::process_advertising_timeout)); 01125 } 01126 01127 void GenericGap::process_advertising_timeout() 01128 { 01129 ble_error_t err = _pal_gap.advertising_enable(false); 01130 if (err) { 01131 // TODO: define the mechanism signaling the error 01132 } 01133 01134 // Stop address rotation if required 01135 set_random_address_rotation(false); 01136 01137 processTimeoutEvent(Gap::TIMEOUT_SRC_ADVERTISING); 01138 } 01139 01140 void GenericGap::on_gap_event_received(const pal::GapEvent& e) 01141 { 01142 switch (e.type.value()) { 01143 case pal::GapEventType::ADVERTISING_REPORT: 01144 on_advertising_report(static_cast<const pal::GapAdvertisingReportEvent&>(e)); 01145 break; 01146 01147 case pal::GapEventType::CONNECTION_COMPLETE: 01148 on_connection_complete(static_cast<const pal::GapConnectionCompleteEvent&>(e)); 01149 break; 01150 01151 case pal::GapEventType::CONNECTION_UPDATE: 01152 on_connection_update(static_cast<const pal::GapConnectionUpdateEvent&>(e)); 01153 break; 01154 01155 case pal::GapEventType::DISCONNECTION_COMPLETE: 01156 on_disconnection_complete(static_cast<const pal::GapDisconnectionCompleteEvent&>(e)); 01157 break; 01158 01159 case pal::GapEventType::REMOTE_CONNECTION_PARAMETER_REQUEST: 01160 on_connection_parameter_request(static_cast<const pal::GapRemoteConnectionParameterRequestEvent&>(e)); 01161 break; 01162 01163 case pal::GapEventType::UNEXPECTED_ERROR: 01164 on_unexpected_error(static_cast<const pal::GapUnexpectedErrorEvent&>(e)); 01165 break; 01166 01167 default: 01168 break; 01169 } 01170 } 01171 01172 void GenericGap::on_advertising_report(const pal::GapAdvertisingReportEvent& e) 01173 { 01174 for (size_t i = 0; i < e.size(); ++i) { 01175 pal::GapAdvertisingReportEvent::advertising_t advertising = e[i]; 01176 01177 // Check if the address hasn't been resolved 01178 if(_privacy_enabled && 01179 _central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::RESOLVE_AND_FILTER && 01180 advertising.address_type == pal::connection_peer_address_type_t::RANDOM_ADDRESS && 01181 is_random_private_resolvable_address(advertising.address.data()) 01182 ) { 01183 // Filter it out 01184 continue; 01185 } 01186 01187 // note 1-to-1 conversion between connection_peer_address_type_t and 01188 // peer_address_type_t 01189 peer_address_type_t peer_address_type = 01190 static_cast<peer_address_type_t::type>(advertising.address_type.value()); 01191 01192 processAdvertisementReport( 01193 advertising.address.data(), 01194 advertising.rssi, 01195 advertising.type == pal::received_advertising_type_t::SCAN_RESPONSE, 01196 (GapAdvertisingParams::AdvertisingType_t) advertising.type.value(), 01197 advertising.data.size(), 01198 advertising.data.data(), 01199 peer_address_type 01200 ); 01201 } 01202 } 01203 01204 void GenericGap::on_connection_complete(const pal::GapConnectionCompleteEvent& e) 01205 { 01206 if (e.status != pal::hci_error_code_t::SUCCESS) { 01207 // for now notify user that the connection failled by issuing a timeout 01208 // event 01209 01210 // TODO: Define events in case of connection faillure 01211 processTimeoutEvent(Gap::TIMEOUT_SRC_CONN); 01212 return; 01213 } 01214 01215 bool needs_pairing = false; 01216 bool needs_authentication = false; 01217 01218 if (_privacy_enabled && 01219 e.role.value() == e.role.SLAVE && 01220 e.peer_address_type == peer_address_type_t::RANDOM 01221 ) { 01222 // Apply privacy policy if in peripheral mode for non-resolved addresses 01223 RandomAddressType_t random_address_type(RandomAddressType_t::RESOLVABLE_PRIVATE); 01224 ble_error_t err = getRandomAddressType(e.peer_address.data(), &random_address_type); 01225 if (err) { 01226 // FIXME: return for now; needs to report the error ? 01227 return; 01228 } 01229 01230 if (random_address_type == RandomAddressType_t::RESOLVABLE_PRIVATE) { 01231 switch(_peripheral_privacy_configuration.resolution_strategy) { 01232 case PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS: 01233 // Reject connection request - the user will get notified through a callback 01234 _pal_gap.disconnect( 01235 e.connection_handle, 01236 pal::disconnection_reason_t::AUTHENTICATION_FAILLURE 01237 ); 01238 return; 01239 01240 case PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE: 01241 needs_pairing = true; 01242 break; 01243 01244 case PeripheralPrivacyConfiguration_t::PERFORM_AUTHENTICATION_PROCEDURE: 01245 needs_authentication = true; 01246 break; 01247 01248 default: 01249 break; 01250 } 01251 } 01252 } 01253 01254 if (e.role.value() == e.role.SLAVE) { 01255 _advertising_timeout.detach(); 01256 _pal_gap.advertising_enable(false); 01257 01258 // Stop address rotation if required 01259 set_random_address_rotation(false); 01260 } 01261 01262 // using these parameters if stupid, there is no range for the 01263 // connection interval when the connection is established 01264 ConnectionParams_t connection_params = { 01265 /* minConnectionInterval */ e.connection_interval, 01266 /* maxConnectionInterval */ e.connection_interval, 01267 e.connection_latency, 01268 e.supervision_timeout 01269 }; 01270 01271 ble::address_t address; 01272 if (_address_type == LegacyAddressType::PUBLIC) { 01273 address = _pal_gap.get_device_address(); 01274 } else { 01275 address = _pal_gap.get_random_address(); 01276 } 01277 01278 processConnectionEvent ( 01279 e.connection_handle, 01280 e.role.value() == e.role.MASTER ? ::Gap::CENTRAL : ::Gap::PERIPHERAL, 01281 e.peer_address_type, 01282 e.peer_address.data(), 01283 _address_type, 01284 address.data(), 01285 &connection_params, 01286 e.local_resolvable_private_address.data(), 01287 e.peer_resolvable_private_address.data() 01288 ); 01289 01290 // Now starts pairing or authentication procedures if required 01291 if(needs_pairing) { 01292 SecurityManager &sm = createBLEInstance()->getSecurityManager(); 01293 // Request authentication to start pairing procedure 01294 sm.requestAuthentication(e.connection_handle); 01295 } else if(needs_authentication) { 01296 // TODO: GAP Authentication != Security Manager authentication 01297 // Needs to be implemented 01298 } 01299 } 01300 01301 void GenericGap::on_disconnection_complete(const pal::GapDisconnectionCompleteEvent& e) 01302 { 01303 if (e.status == pal::hci_error_code_t::SUCCESS) { 01304 processDisconnectionEvent ( 01305 e.connection_handle, 01306 (Gap::DisconnectionReason_t) e.reason 01307 ); 01308 } else { 01309 // TODO: define what to do in case of faillure 01310 } 01311 } 01312 01313 void GenericGap::on_connection_parameter_request(const pal::GapRemoteConnectionParameterRequestEvent& e) 01314 { 01315 // intern behavior, accept all new parameter requests 01316 // TODO: expose an API so user code can accept or reject such request 01317 _pal_gap.accept_connection_parameter_request( 01318 e.connection_handle, 01319 e.min_connection_interval, 01320 e.max_connection_interval, 01321 e.connection_latency, 01322 e.supervision_timeout, 01323 /* minimum_connection_event_length */ 0, 01324 /* maximum_connection_event_length */ 0 01325 ); 01326 } 01327 01328 void GenericGap::on_connection_update(const pal::GapConnectionUpdateEvent& e) 01329 { 01330 // TODO: add feature in interface to notify the user that the connection 01331 // has been updated. 01332 } 01333 01334 void GenericGap::on_unexpected_error(const pal::GapUnexpectedErrorEvent& e) 01335 { 01336 // TODO: add feature in interface to notify the user that the connection 01337 // has been updated. 01338 } 01339 01340 pal::own_address_type_t GenericGap::get_own_address_type(AddressUseType_t address_use_type) 01341 { 01342 if(_privacy_enabled) { 01343 bool use_non_resolvable_address = false; 01344 if(address_use_type == CENTRAL_SCAN) { 01345 use_non_resolvable_address = _central_privacy_configuration.use_non_resolvable_random_address; 01346 } else if (address_use_type == PERIPHERAL_NON_CONNECTABLE) { 01347 use_non_resolvable_address = _peripheral_privacy_configuration.use_non_resolvable_random_address; 01348 } 01349 01350 // An non resolvable private address should be generated 01351 if(use_non_resolvable_address) { 01352 return pal::own_address_type_t::RANDOM_ADDRESS; 01353 } 01354 01355 switch (_address_type) { 01356 case BLEProtocol::AddressType::PUBLIC: 01357 return pal::own_address_type_t::RESOLVABLE_PRIVATE_ADDRESS_PUBLIC_FALLBACK; 01358 default: 01359 return pal::own_address_type_t::RESOLVABLE_PRIVATE_ADDRESS_RANDOM_FALLBACK; 01360 } 01361 } 01362 01363 switch (_address_type) { 01364 case BLEProtocol::AddressType::PUBLIC: 01365 return pal::own_address_type_t::PUBLIC_ADDRESS; 01366 default: 01367 return pal::own_address_type_t::RANDOM_ADDRESS; 01368 } 01369 } 01370 01371 bool GenericGap::initialize_whitelist() const 01372 { 01373 if (_whitelist.addresses != NULL) { 01374 return true; 01375 } 01376 01377 uint8_t whitelist_capacity = _pal_gap.read_white_list_capacity(); 01378 01379 if (whitelist_capacity == 0) { 01380 return false; 01381 } 01382 01383 _whitelist.addresses = new (std::nothrow) BLEProtocol::Address_t[whitelist_capacity] ; 01384 if (_whitelist.addresses == NULL) { 01385 return false; 01386 } 01387 01388 _whitelist.size = 0; 01389 _whitelist.capacity = whitelist_capacity; 01390 01391 return true; 01392 } 01393 01394 ble_error_t GenericGap::update_address_resolution_setting() 01395 { 01396 // Only disable if privacy is disabled or resolution is not requested in either central or peripheral mode 01397 bool enable = true; 01398 01399 if(!_privacy_enabled) { 01400 enable = false; 01401 } 01402 else if( (_peripheral_privacy_configuration.resolution_strategy == PeripheralPrivacyConfiguration_t::DO_NOT_RESOLVE) 01403 && (_central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::DO_NOT_RESOLVE) ) { 01404 enable = false; 01405 } 01406 01407 return _pal_gap.set_address_resolution(enable); 01408 } 01409 01410 void GenericGap::set_random_address_rotation(bool enable) 01411 { 01412 if(enable == _random_address_rotating) { 01413 return; 01414 } 01415 01416 _random_address_rotating = enable; 01417 01418 if(enable) { 01419 // Set first address 01420 update_random_address(); 01421 01422 // Schedule rotations every 15 minutes as recomended by the spec 01423 _address_rotation_ticker.attach_us( 01424 mbed::callback(this, &GenericGap::on_address_rotation_timeout), 01425 15 * 60 * 1000000U 01426 ); 01427 } 01428 else { 01429 // Stop ticker 01430 _address_rotation_ticker.detach(); 01431 01432 // Set static random identity address 01433 _pal_gap.set_random_address( 01434 _random_static_identity_address 01435 ); 01436 } 01437 } 01438 01439 void GenericGap::update_random_address() 01440 { 01441 if(!_random_address_rotating) 01442 { 01443 // This event might have been queued before we disabled address rotation 01444 return; 01445 } 01446 01447 ble::address_t address; 01448 01449 do { 01450 byte_array_t<8> random_data; 01451 01452 ble_error_t ret = _pal_sm.get_random_data(random_data); 01453 if (ret != BLE_ERROR_NONE) { 01454 // Abort 01455 return; 01456 } 01457 01458 // Build a non-resolvable private address as specified in the Core 4.2 spec, Vol 6, Part B, 1.3.2.2 01459 // Mask out two MSbs 01460 random_data[5] &= 0x3F; 01461 01462 // Copy to address - will copy first 6 bytes 01463 address = ble::address_t(random_data.data()); 01464 01465 if(!is_random_private_non_resolvable_address(address.data())) 01466 { 01467 // If address is invalid, which is unlikely (all 0s or all 1s), try again 01468 // If implementation is faulty, we'll get stuck here 01469 continue; 01470 } 01471 01472 // Address is valid 01473 break; 01474 } while(true); 01475 01476 ble_error_t err = _pal_gap.set_random_address( 01477 address 01478 ); 01479 if (err) { 01480 return; 01481 } 01482 01483 _address_type = LegacyAddressType::RANDOM_PRIVATE_NON_RESOLVABLE; 01484 _address = address; 01485 } 01486 01487 void GenericGap::on_address_rotation_timeout() 01488 { 01489 _event_queue.post(mbed::callback(this, &GenericGap::update_random_address)); 01490 } 01491 01492 void GenericGap::set_connection_event_handler(pal::ConnectionEventMonitor::EventHandler *connection_event_handler) 01493 { 01494 _connection_event_handler = connection_event_handler; 01495 } 01496 01497 } // namespace generic 01498 } // namespace ble
Generated on Tue Jul 12 2022 12:44:17 by
