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.initialize(); 00421 00422 _pal_gap.when_gap_event_received( 00423 mbed::callback(this, &GenericGap::on_gap_event_received) 00424 ); 00425 00426 // Recover static random identity 00427 _random_static_identity_address = _pal_gap.get_random_address(); 00428 00429 _pal_gap.set_event_handler(this); 00430 } 00431 00432 GenericGap::~GenericGap () 00433 { 00434 } 00435 00436 ble_error_t GenericGap::setAddress ( 00437 LegacyAddressType_t type, 00438 const Address_t address 00439 ) { 00440 switch (type) { 00441 case LegacyAddressType::PUBLIC: 00442 // The public address cannot be set, just set the type to public 00443 _address_type = type; 00444 return BLE_ERROR_NONE; 00445 00446 case LegacyAddressType::RANDOM_STATIC: { 00447 if (is_random_static_address(address) == false) { 00448 return BLE_ERROR_INVALID_PARAM; 00449 } 00450 00451 ble_error_t err = _pal_gap.set_random_address( 00452 ble::address_t(address) 00453 ); 00454 if (err) { 00455 return err; 00456 } 00457 00458 _address_type = type; 00459 _address = ble::address_t(address); 00460 _random_static_identity_address = ble::address_t(address); 00461 return BLE_ERROR_NONE; 00462 } 00463 00464 case LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE: 00465 case LegacyAddressType::RANDOM_PRIVATE_NON_RESOLVABLE: 00466 // Note: it is not allowed to set directly these addresses 00467 // privacy management handled it for users. 00468 return BLE_ERROR_INVALID_PARAM; 00469 00470 default: 00471 return BLE_ERROR_INVALID_PARAM; 00472 } 00473 } 00474 00475 ble_error_t GenericGap::getAddress ( 00476 LegacyAddressType_t *type, 00477 Address_t address 00478 ) { 00479 *type = _address_type; 00480 ble::address_t address_value; 00481 00482 if (_address_type == LegacyAddressType::PUBLIC) { 00483 address_value = _pal_gap.get_device_address(); 00484 } else { 00485 address_value = _pal_gap.get_random_address(); 00486 } 00487 00488 memcpy(address, address_value.data(), address_value.size()); 00489 return BLE_ERROR_NONE; 00490 } 00491 00492 uint16_t GenericGap::getMinAdvertisingInterval () const 00493 { 00494 return GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN; 00495 } 00496 00497 uint16_t GenericGap::getMinNonConnectableAdvertisingInterval () const 00498 { 00499 return GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON; 00500 } 00501 00502 uint16_t GenericGap::getMaxAdvertisingInterval () const 00503 { 00504 return GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX; 00505 } 00506 00507 ble_error_t GenericGap::stopAdvertising () 00508 { 00509 ble_error_t err = _pal_gap.advertising_enable(false); 00510 if (err) { 00511 return err; 00512 } 00513 _advertising_timeout.detach(); 00514 state.advertising = false; 00515 00516 // Stop address rotation if required 00517 set_random_address_rotation(false); 00518 00519 return BLE_ERROR_NONE; 00520 } 00521 00522 ble_error_t GenericGap::stopScan () 00523 { 00524 ble_error_t err = _pal_gap.scan_enable(false, false); 00525 if (err) { 00526 return err; 00527 } 00528 00529 // Stop address rotation if required 00530 set_random_address_rotation(false); 00531 00532 _scan_timeout.detach(); 00533 return BLE_ERROR_NONE; 00534 } 00535 00536 ble_error_t GenericGap::connect ( 00537 const Address_t peerAddr, 00538 PeerAddressType_t peerAddrType, 00539 const ConnectionParams_t *connectionParams, 00540 const GapScanningParams *scanParams 00541 ) { 00542 if (connectionParams == NULL) { 00543 connectionParams = &default_connection_params; 00544 } 00545 00546 if (scanParams == NULL) { 00547 scanParams = &default_scan_params; 00548 } 00549 00550 if (is_scan_params_valid(scanParams) == false) { 00551 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00552 } 00553 00554 if (is_connection_params_valid(connectionParams) == false) { 00555 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00556 } 00557 00558 // Force scan stop before initiating the scan used for connection 00559 stopScan (); 00560 00561 return _pal_gap.create_connection( 00562 scanParams->getInterval(), 00563 scanParams->getWindow(), 00564 _initiator_policy_mode, 00565 (pal::connection_peer_address_type_t::type ) peerAddrType.value(), 00566 ble::address_t(peerAddr), 00567 get_own_address_type(CENTRAL_CONNECTION /* requires resolvable address */), 00568 connectionParams->minConnectionInterval, 00569 connectionParams->maxConnectionInterval, 00570 connectionParams->slaveLatency, 00571 connectionParams->connectionSupervisionTimeout, 00572 /* minimum_connection_event_length */ 0, 00573 /* maximum_connection_event_length */ 0 00574 ); 00575 } 00576 00577 00578 ble_error_t GenericGap::connect ( 00579 const Address_t peerAddr, 00580 LegacyAddressType_t peerAddrType, 00581 const ConnectionParams_t* connectionParams, 00582 const GapScanningParams* scanParams 00583 ) { 00584 return connect ( 00585 peerAddr, 00586 to_peer_address_type(peerAddrType), 00587 connectionParams, 00588 scanParams 00589 ); 00590 } 00591 00592 ble_error_t GenericGap::readPhy (Handle_t connection) { 00593 return _pal_gap.read_phy (connection); 00594 } 00595 00596 ble_error_t GenericGap::setPreferredPhys ( 00597 const phy_set_t* txPhys, 00598 const phy_set_t* rxPhys 00599 ) { 00600 phy_set_t tx_phys(txPhys? txPhys->value() : 0); 00601 phy_set_t rx_phys(rxPhys? rxPhys->value() : 0); 00602 return _pal_gap.set_preferred_phys (tx_phys, rx_phys); 00603 } 00604 00605 ble_error_t GenericGap::setPhy ( 00606 Handle_t connection, 00607 const phy_set_t* txPhys, 00608 const phy_set_t* rxPhys, 00609 CodedSymbolPerBit_t codedSymbol 00610 ) { 00611 phy_set_t tx_phys(txPhys? txPhys->value() : 0); 00612 phy_set_t rx_phys(rxPhys? rxPhys->value() : 0); 00613 return _pal_gap.set_phy (connection, tx_phys, rx_phys, codedSymbol); 00614 } 00615 00616 00617 void GenericGap::on_read_phy( 00618 pal::hci_error_code_t hci_status, 00619 Handle_t connection_handle, 00620 ble::phy_t tx_phy, 00621 ble::phy_t rx_phy 00622 ) { 00623 ble_error_t status = BLE_ERROR_NONE; 00624 if (pal::hci_error_code_t::SUCCESS != hci_status) { 00625 status = BLE_ERROR_UNSPECIFIED; 00626 } 00627 00628 if (_eventHandler) { 00629 _eventHandler->onPhyUpdateComplete(status, connection_handle, tx_phy, rx_phy); 00630 } 00631 } 00632 00633 void GenericGap::on_phy_update_complete( 00634 pal::hci_error_code_t hci_status, 00635 Handle_t connection_handle, 00636 ble::phy_t tx_phy, 00637 ble::phy_t rx_phy 00638 ) { 00639 ble_error_t status = BLE_ERROR_NONE; 00640 if (pal::hci_error_code_t::SUCCESS != hci_status) { 00641 status = BLE_ERROR_UNSPECIFIED; 00642 } 00643 00644 if (_eventHandler) { 00645 _eventHandler->onPhyUpdateComplete(status, connection_handle, tx_phy, rx_phy); 00646 } 00647 } 00648 00649 ble_error_t GenericGap::disconnect (Handle_t connectionHandle, DisconnectionReason_t reason) 00650 { 00651 if (is_disconnection_reason_valid(reason) == false) { 00652 return BLE_ERROR_INVALID_PARAM; 00653 } 00654 return _pal_gap.disconnect( 00655 connectionHandle, 00656 (pal::disconnection_reason_t::type) reason 00657 ); 00658 } 00659 00660 ble_error_t GenericGap::updateConnectionParams (Handle_t handle, const ConnectionParams_t *params) 00661 { 00662 if (is_connection_params_valid(params) == false) { 00663 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00664 } 00665 00666 return _pal_gap.connection_parameters_update( 00667 handle, 00668 params->minConnectionInterval, 00669 params->maxConnectionInterval, 00670 params->slaveLatency, 00671 params->connectionSupervisionTimeout, 00672 /* minimum_connection_event_length */ 0, 00673 /* maximum_connection_event_length */ 0 00674 ); 00675 } 00676 00677 ble_error_t GenericGap::getPreferredConnectionParams (ConnectionParams_t *params) 00678 { 00679 if (params == NULL) { 00680 return BLE_ERROR_INVALID_PARAM; 00681 } 00682 00683 return _gap_service.get_peripheral_prefered_connection_parameters( 00684 *params 00685 ); 00686 } 00687 00688 ble_error_t GenericGap::setPreferredConnectionParams (const ConnectionParams_t *params) 00689 { 00690 if(is_preferred_connection_params_valid(params) == false) { 00691 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00692 } 00693 00694 return _gap_service.set_peripheral_prefered_connection_parameters( 00695 *params 00696 ); 00697 } 00698 00699 ble_error_t GenericGap::setDeviceName (const uint8_t *deviceName) 00700 { 00701 return _gap_service.set_device_name(deviceName); 00702 } 00703 00704 ble_error_t GenericGap::getDeviceName (uint8_t *deviceName, unsigned *lengthP) 00705 { 00706 if (lengthP == NULL) { 00707 return BLE_ERROR_INVALID_PARAM; 00708 } 00709 00710 uint8_t length = 0; 00711 ble_error_t err = _gap_service.get_device_name_length(length); 00712 if (err) { 00713 return err; 00714 } 00715 00716 if (deviceName != NULL) { 00717 if (*lengthP < length) { 00718 return BLE_ERROR_INVALID_PARAM; 00719 } 00720 00721 ArrayView<uint8_t> name(deviceName, *lengthP); 00722 err = _gap_service.get_device_name(name); 00723 if (err) { 00724 return err; 00725 } 00726 } 00727 *lengthP = length; 00728 return BLE_ERROR_NONE; 00729 } 00730 00731 ble_error_t GenericGap::setAppearance (GapAdvertisingData::Appearance appearance) 00732 { 00733 return _gap_service.set_appearance(appearance); 00734 } 00735 00736 ble_error_t GenericGap::getAppearance (GapAdvertisingData::Appearance *appearanceP) 00737 { 00738 if (appearanceP == NULL) { 00739 return BLE_ERROR_INVALID_PARAM; 00740 } 00741 return _gap_service.get_appearance(*appearanceP); 00742 } 00743 00744 ble_error_t GenericGap::setTxPower (int8_t txPower) 00745 { 00746 // TODO: This is not standard, expose it as an extension API and document it 00747 // as such 00748 return BLE_ERROR_NOT_IMPLEMENTED; 00749 } 00750 00751 void GenericGap::getPermittedTxPowerValues (const int8_t **valueArrayPP, size_t *countP) 00752 { 00753 *countP = 0; 00754 } 00755 00756 uint8_t GenericGap::getMaxWhitelistSize (void) const 00757 { 00758 return _pal_gap.read_white_list_capacity(); 00759 } 00760 00761 ble_error_t GenericGap::getWhitelist (Whitelist_t &whitelist) const 00762 { 00763 if(initialize_whitelist() == false) { 00764 return BLE_ERROR_INVALID_STATE; 00765 } 00766 00767 if (whitelist.capacity < _whitelist.capacity) { 00768 return BLE_ERROR_INVALID_PARAM; 00769 } 00770 00771 for (size_t i = 0; i < _whitelist.size; ++i) { 00772 whitelist.addresses[i] = _whitelist.addresses[i]; 00773 } 00774 00775 whitelist.capacity = _whitelist.capacity; 00776 return BLE_ERROR_NONE; 00777 } 00778 00779 ble_error_t GenericGap::setWhitelist (const Whitelist_t &whitelist) 00780 { 00781 if (is_whitelist_valid(whitelist) == false) { 00782 return BLE_ERROR_INVALID_PARAM; 00783 } 00784 00785 if(initialize_whitelist() == false) { 00786 return BLE_ERROR_INVALID_STATE; 00787 } 00788 00789 if (whitelist.capacity > _whitelist.capacity) { 00790 return BLE_ERROR_INVALID_PARAM; 00791 } 00792 00793 // first evict devices not in the existing whitelist 00794 for (size_t i = 0; i < _whitelist.size; ++i) { 00795 const BLEProtocol::Address_t& device = _whitelist.addresses[i]; 00796 00797 if (is_in_whitelist(device, whitelist) == false) { 00798 ble_error_t err = _pal_gap.remove_device_from_whitelist( 00799 to_whitelist_address_type(device.type), 00800 device.address 00801 ); 00802 00803 // try to restore the whitelist to its initial state 00804 if (err) { 00805 for (size_t j = 0; j < i; ++j) { 00806 const BLEProtocol::Address_t& device = _whitelist.addresses[j]; 00807 00808 if (is_in_whitelist(device, whitelist) == false) { 00809 _pal_gap.add_device_to_whitelist( 00810 to_whitelist_address_type(device.type), 00811 device.address 00812 ); 00813 } 00814 } 00815 return err; 00816 } 00817 } 00818 } 00819 00820 // second add devices which were not in the initial whitelist 00821 for (size_t i = 0; i < whitelist.size; ++i) { 00822 const BLEProtocol::Address_t& device = whitelist.addresses[i]; 00823 00824 if (is_in_whitelist(device, _whitelist) == false) { 00825 ble_error_t err = _pal_gap.add_device_to_whitelist( 00826 to_whitelist_address_type(device.type), 00827 device.address 00828 ); 00829 00830 // try to restore the whitelist to its initial state 00831 if (err) { 00832 // first remove the devices added 00833 for (size_t j = 0; j < i; ++j) { 00834 const BLEProtocol::Address_t& device = whitelist.addresses[j]; 00835 00836 if (is_in_whitelist(device, _whitelist) == false) { 00837 _pal_gap.remove_device_from_whitelist( 00838 to_whitelist_address_type(device.type), 00839 device.address 00840 ); 00841 } 00842 } 00843 00844 // second add the devices of the initial list evicted 00845 for (size_t i = 0; i < _whitelist.size; ++i) { 00846 const BLEProtocol::Address_t& device = _whitelist.addresses[i]; 00847 00848 if (is_in_whitelist(device, whitelist) == false) { 00849 _pal_gap.add_device_to_whitelist( 00850 to_whitelist_address_type(device.type), 00851 device.address 00852 ); 00853 } 00854 } 00855 00856 return err; 00857 } 00858 } 00859 } 00860 00861 // commit the devices into the whitelist 00862 for (size_t i = 0; i < whitelist.size; ++i) { 00863 _whitelist.addresses[i] = whitelist.addresses[i]; 00864 } 00865 00866 _whitelist.size = whitelist.size; 00867 00868 return BLE_ERROR_NONE; 00869 } 00870 00871 ble_error_t GenericGap::setAdvertisingPolicyMode (AdvertisingPolicyMode_t mode) 00872 { 00873 if (mode > Gap::ADV_POLICY_FILTER_ALL_REQS) { 00874 return BLE_ERROR_INVALID_PARAM; 00875 } 00876 00877 _advertising_filter_policy = (pal::advertising_filter_policy_t::type ) mode; 00878 return BLE_ERROR_NONE; 00879 } 00880 00881 ble_error_t GenericGap::setScanningPolicyMode (ScanningPolicyMode_t mode) 00882 { 00883 if (mode > Gap::SCAN_POLICY_FILTER_ALL_ADV) { 00884 return BLE_ERROR_INVALID_PARAM; 00885 } 00886 00887 _scanning_filter_policy = (pal::scanning_filter_policy_t::type ) mode; 00888 return BLE_ERROR_NONE; 00889 } 00890 00891 ble_error_t GenericGap::setInitiatorPolicyMode (InitiatorPolicyMode_t mode) 00892 { 00893 if (mode > Gap::INIT_POLICY_FILTER_ALL_ADV) { 00894 return BLE_ERROR_INVALID_PARAM; 00895 } 00896 00897 _initiator_policy_mode = (pal::initiator_policy_t::type ) mode; 00898 return BLE_ERROR_NONE; 00899 } 00900 00901 Gap::AdvertisingPolicyMode_t GenericGap::getAdvertisingPolicyMode (void) const 00902 { 00903 return (AdvertisingPolicyMode_t) _advertising_filter_policy.value(); 00904 } 00905 00906 Gap::ScanningPolicyMode_t GenericGap::getScanningPolicyMode (void) const 00907 { 00908 return (ScanningPolicyMode_t) _scanning_filter_policy.value(); 00909 } 00910 00911 Gap::InitiatorPolicyMode_t GenericGap::getInitiatorPolicyMode (void) const 00912 { 00913 return (InitiatorPolicyMode_t) _initiator_policy_mode.value(); 00914 } 00915 00916 ble_error_t GenericGap::startRadioScan (const GapScanningParams &scanningParams) 00917 { 00918 if (is_scan_params_valid(&scanningParams) == false) { 00919 return BLE_ERROR_INVALID_PARAM; 00920 } 00921 00922 if (_scanning_filter_policy == pal::scanning_filter_policy_t::FILTER_ADVERTISING && 00923 _whitelist.size == 0) { 00924 return BLE_ERROR_INVALID_STATE; 00925 } 00926 00927 pal::own_address_type_t own_address_type = get_own_address_type(CENTRAL_SCAN /* central, can use non resolvable address for scan requests */); 00928 00929 if(_privacy_enabled && (own_address_type == pal::own_address_type_t::RANDOM_ADDRESS)) 00930 { 00931 // Use non-resolvable static random address 00932 set_random_address_rotation(true); 00933 } 00934 00935 ble_error_t err = _pal_gap.set_scan_parameters( 00936 scanningParams.getActiveScanning(), 00937 scanningParams.getInterval(), 00938 scanningParams.getWindow(), 00939 own_address_type, 00940 _scanning_filter_policy 00941 ); 00942 00943 if (err) { 00944 return err; 00945 } 00946 00947 err = _pal_gap.scan_enable(true, false); 00948 00949 if (err) { 00950 return err; 00951 } 00952 00953 _scan_timeout.detach(); 00954 uint16_t timeout = scanningParams.getTimeout(); 00955 if (timeout) { 00956 _scan_timeout.attach_us( 00957 mbed::callback(this, &GenericGap::on_scan_timeout), 00958 scanningParams.getTimeout() * 1000000U 00959 ); 00960 } 00961 00962 return BLE_ERROR_NONE; 00963 } 00964 00965 ble_error_t GenericGap::initRadioNotification (void) 00966 { 00967 return BLE_ERROR_NOT_IMPLEMENTED; 00968 } 00969 00970 ble_error_t GenericGap::enablePrivacy (bool enable) 00971 { 00972 if(enable == _privacy_enabled) { 00973 // No change 00974 return BLE_ERROR_NONE; 00975 } 00976 00977 if(enable && !_pal_gap.is_privacy_supported()) 00978 { 00979 // Privacy is not supported by the implementation 00980 return BLE_ERROR_NOT_IMPLEMENTED; 00981 } 00982 00983 _privacy_enabled = enable; 00984 00985 update_address_resolution_setting(); 00986 00987 return BLE_ERROR_NONE; 00988 } 00989 00990 ble_error_t GenericGap::setPeripheralPrivacyConfiguration ( 00991 const PeripheralPrivacyConfiguration_t *configuration 00992 ) 00993 { 00994 _peripheral_privacy_configuration = *configuration; 00995 00996 update_address_resolution_setting(); 00997 00998 return BLE_ERROR_NONE; 00999 } 01000 01001 ble_error_t GenericGap::getPeripheralPrivacyConfiguration ( 01002 PeripheralPrivacyConfiguration_t *configuration 01003 ) 01004 { 01005 *configuration = _peripheral_privacy_configuration; 01006 01007 return BLE_ERROR_NONE; 01008 } 01009 01010 ble_error_t GenericGap::setCentralPrivacyConfiguration ( 01011 const CentralPrivacyConfiguration_t *configuration 01012 ) 01013 { 01014 _central_privacy_configuration = *configuration; 01015 01016 update_address_resolution_setting(); 01017 01018 return BLE_ERROR_NONE; 01019 } 01020 01021 ble_error_t GenericGap::getCentralPrivacyConfiguration ( 01022 CentralPrivacyConfiguration_t *configuration 01023 ) 01024 { 01025 *configuration = _central_privacy_configuration; 01026 01027 return BLE_ERROR_NONE; 01028 } 01029 01030 ble_error_t GenericGap::setAdvertisingData (const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) 01031 { 01032 ble_error_t err = _pal_gap.set_advertising_data( 01033 advData.getPayloadLen(), 01034 pal::advertising_data_t(advData.getPayload(), advData.getPayloadLen()) 01035 ); 01036 if (err) { 01037 return err; 01038 } 01039 01040 return _pal_gap.set_scan_response_data( 01041 scanResponse.getPayloadLen(), 01042 pal::advertising_data_t(scanResponse.getPayload(), scanResponse.getPayloadLen()) 01043 ); 01044 } 01045 01046 ble_error_t GenericGap::startAdvertising(const GapAdvertisingParams& params) 01047 { 01048 if (is_advertising_params_valid(params) == false) { 01049 return BLE_ERROR_INVALID_PARAM; 01050 } 01051 01052 // We can only use non resolvable addresses if the device is non connectable 01053 AddressUseType_t address_use_type = 01054 ((params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED) || 01055 (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED)) ? 01056 PERIPHERAL_NON_CONNECTABLE : 01057 PERIPHERAL_CONNECTABLE; 01058 01059 pal::own_address_type_t own_address_type = get_own_address_type(address_use_type); 01060 01061 if(_privacy_enabled && (own_address_type == pal::own_address_type_t::RANDOM_ADDRESS)) 01062 { 01063 // Use non-resolvable static random address 01064 set_random_address_rotation(true); 01065 } 01066 01067 // TODO: fix the high level API to have a min/max range 01068 // Going against recommendations (The Advertising_Interval_Min and 01069 // Advertising_Interval_Max should not be the same value to enable the 01070 // Controller to determine the best advertising interval given other activities.) 01071 // for now but not against specification: "The Advertising_Interval_Min 01072 // shall be less than or equal to the Advertising_Interval_Max" 01073 ble_error_t err = _pal_gap.set_advertising_parameters( 01074 /* advertising_interval_min */ params.getIntervalInADVUnits(), 01075 /* advertising_interval_max */ params.getIntervalInADVUnits(), 01076 (pal::advertising_type_t::type ) params.getAdvertisingType(), 01077 own_address_type, 01078 pal::advertising_peer_address_type_t::PUBLIC_ADDRESS, 01079 ble::address_t(), 01080 pal::advertising_channel_map_t::ALL_ADVERTISING_CHANNELS, 01081 _advertising_filter_policy 01082 ); 01083 01084 if (err) { 01085 return err; 01086 } 01087 01088 err = _pal_gap.advertising_enable(true); 01089 if (err) { 01090 return err; 01091 } 01092 01093 state.advertising = true; 01094 01095 _advertising_timeout.detach(); 01096 uint16_t timeout = params.getTimeout(); 01097 if (timeout) { 01098 _advertising_timeout.attach_us( 01099 mbed::callback(this, &GenericGap::on_advertising_timeout), 01100 params.getTimeout() * 1000000U 01101 ); 01102 } 01103 01104 return BLE_ERROR_NONE; 01105 } 01106 01107 ble_error_t GenericGap::reset (void) 01108 { 01109 Gap::reset (); 01110 _advertising_timeout.detach(); 01111 _scan_timeout.detach(); 01112 01113 return BLE_ERROR_NONE; 01114 } 01115 01116 void GenericGap::processConnectionEvent ( 01117 Handle_t handle, 01118 Role_t role, 01119 PeerAddressType_t peerAddrType, 01120 const BLEProtocol::AddressBytes_t peerAddr, 01121 BLEProtocol::AddressType_t ownAddrType, 01122 const BLEProtocol::AddressBytes_t ownAddr, 01123 const ConnectionParams_t *connectionParams, 01124 const uint8_t *peerResolvableAddr, 01125 const uint8_t *localResolvableAddr 01126 ) { 01127 if (_connection_event_handler) { 01128 _connection_event_handler->on_connected( 01129 handle, 01130 role, 01131 peerAddrType, 01132 peerAddr, 01133 ownAddrType, 01134 ownAddr, 01135 connectionParams 01136 ); 01137 } 01138 01139 ::Gap::processConnectionEvent( 01140 handle, 01141 role, 01142 peerAddrType, 01143 peerAddr, 01144 ownAddrType, 01145 ownAddr, 01146 connectionParams, 01147 peerResolvableAddr, 01148 localResolvableAddr 01149 ); 01150 } 01151 01152 void GenericGap::processDisconnectionEvent ( 01153 Handle_t handle, 01154 DisconnectionReason_t reason 01155 ) { 01156 if (_connection_event_handler) { 01157 _connection_event_handler->on_disconnected( 01158 handle, 01159 reason 01160 ); 01161 } 01162 01163 ::Gap::processDisconnectionEvent( 01164 handle, 01165 reason 01166 ); 01167 } 01168 01169 void GenericGap::on_scan_timeout() 01170 { 01171 _event_queue.post(mbed::callback(this, &GenericGap::process_scan_timeout)); 01172 } 01173 01174 void GenericGap::process_scan_timeout() 01175 { 01176 ble_error_t err = _pal_gap.scan_enable(false, false); 01177 if (err) { 01178 // TODO: define the mechanism signaling the error 01179 } 01180 processTimeoutEvent(Gap::TIMEOUT_SRC_SCAN); 01181 } 01182 01183 void GenericGap::on_advertising_timeout() 01184 { 01185 _event_queue.post(mbed::callback(this, &GenericGap::process_advertising_timeout)); 01186 } 01187 01188 void GenericGap::process_advertising_timeout() 01189 { 01190 ble_error_t err = _pal_gap.advertising_enable(false); 01191 if (err) { 01192 // TODO: define the mechanism signaling the error 01193 } 01194 01195 // Stop address rotation if required 01196 set_random_address_rotation(false); 01197 01198 processTimeoutEvent(Gap::TIMEOUT_SRC_ADVERTISING); 01199 } 01200 01201 void GenericGap::on_gap_event_received(const pal::GapEvent& e) 01202 { 01203 switch (e.type.value()) { 01204 case pal::GapEventType::ADVERTISING_REPORT: 01205 on_advertising_report(static_cast<const pal::GapAdvertisingReportEvent&>(e)); 01206 break; 01207 01208 case pal::GapEventType::CONNECTION_COMPLETE: 01209 on_connection_complete(static_cast<const pal::GapConnectionCompleteEvent&>(e)); 01210 break; 01211 01212 case pal::GapEventType::CONNECTION_UPDATE: 01213 on_connection_update(static_cast<const pal::GapConnectionUpdateEvent&>(e)); 01214 break; 01215 01216 case pal::GapEventType::DISCONNECTION_COMPLETE: 01217 on_disconnection_complete(static_cast<const pal::GapDisconnectionCompleteEvent&>(e)); 01218 break; 01219 01220 case pal::GapEventType::REMOTE_CONNECTION_PARAMETER_REQUEST: 01221 on_connection_parameter_request(static_cast<const pal::GapRemoteConnectionParameterRequestEvent&>(e)); 01222 break; 01223 01224 case pal::GapEventType::UNEXPECTED_ERROR: 01225 on_unexpected_error(static_cast<const pal::GapUnexpectedErrorEvent&>(e)); 01226 break; 01227 01228 default: 01229 break; 01230 } 01231 } 01232 01233 void GenericGap::on_advertising_report(const pal::GapAdvertisingReportEvent& e) 01234 { 01235 for (size_t i = 0; i < e.size(); ++i) { 01236 pal::GapAdvertisingReportEvent::advertising_t advertising = e[i]; 01237 01238 // Check if the address hasn't been resolved 01239 if(_privacy_enabled && 01240 _central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::RESOLVE_AND_FILTER && 01241 advertising.address_type == pal::connection_peer_address_type_t::RANDOM_ADDRESS && 01242 is_random_private_resolvable_address(advertising.address.data()) 01243 ) { 01244 // Filter it out 01245 continue; 01246 } 01247 01248 // note 1-to-1 conversion between connection_peer_address_type_t and 01249 // peer_address_type_t 01250 peer_address_type_t peer_address_type = 01251 static_cast<peer_address_type_t::type>(advertising.address_type.value()); 01252 01253 processAdvertisementReport( 01254 advertising.address.data(), 01255 advertising.rssi, 01256 advertising.type == pal::received_advertising_type_t::SCAN_RESPONSE, 01257 (GapAdvertisingParams::AdvertisingType_t) advertising.type.value(), 01258 advertising.data.size(), 01259 advertising.data.data(), 01260 peer_address_type 01261 ); 01262 } 01263 } 01264 01265 void GenericGap::on_connection_complete(const pal::GapConnectionCompleteEvent& e) 01266 { 01267 if (e.status != pal::hci_error_code_t::SUCCESS) { 01268 // for now notify user that the connection failled by issuing a timeout 01269 // event 01270 01271 // TODO: Define events in case of connection faillure 01272 processTimeoutEvent(Gap::TIMEOUT_SRC_CONN); 01273 return; 01274 } 01275 01276 bool needs_pairing = false; 01277 bool needs_authentication = false; 01278 01279 if (_privacy_enabled && 01280 e.role.value() == e.role.SLAVE && 01281 e.peer_address_type == peer_address_type_t::RANDOM 01282 ) { 01283 // Apply privacy policy if in peripheral mode for non-resolved addresses 01284 RandomAddressType_t random_address_type(RandomAddressType_t::RESOLVABLE_PRIVATE); 01285 ble_error_t err = getRandomAddressType(e.peer_address.data(), &random_address_type); 01286 if (err) { 01287 // FIXME: return for now; needs to report the error ? 01288 return; 01289 } 01290 01291 if (random_address_type == RandomAddressType_t::RESOLVABLE_PRIVATE) { 01292 switch(_peripheral_privacy_configuration.resolution_strategy) { 01293 case PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS: 01294 // Reject connection request - the user will get notified through a callback 01295 _pal_gap.disconnect( 01296 e.connection_handle, 01297 pal::disconnection_reason_t::AUTHENTICATION_FAILLURE 01298 ); 01299 return; 01300 01301 case PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE: 01302 needs_pairing = true; 01303 break; 01304 01305 case PeripheralPrivacyConfiguration_t::PERFORM_AUTHENTICATION_PROCEDURE: 01306 needs_authentication = true; 01307 break; 01308 01309 default: 01310 break; 01311 } 01312 } 01313 } 01314 01315 if (e.role.value() == e.role.SLAVE) { 01316 _advertising_timeout.detach(); 01317 _pal_gap.advertising_enable(false); 01318 01319 // Stop address rotation if required 01320 set_random_address_rotation(false); 01321 } 01322 01323 // using these parameters if stupid, there is no range for the 01324 // connection interval when the connection is established 01325 ConnectionParams_t connection_params = { 01326 /* minConnectionInterval */ e.connection_interval, 01327 /* maxConnectionInterval */ e.connection_interval, 01328 e.connection_latency, 01329 e.supervision_timeout 01330 }; 01331 01332 ble::address_t address; 01333 if (_address_type == LegacyAddressType::PUBLIC) { 01334 address = _pal_gap.get_device_address(); 01335 } else { 01336 address = _pal_gap.get_random_address(); 01337 } 01338 01339 processConnectionEvent ( 01340 e.connection_handle, 01341 e.role.value() == e.role.MASTER ? ::Gap::CENTRAL : ::Gap::PERIPHERAL, 01342 e.peer_address_type, 01343 e.peer_address.data(), 01344 _address_type, 01345 address.data(), 01346 &connection_params, 01347 e.local_resolvable_private_address.data(), 01348 e.peer_resolvable_private_address.data() 01349 ); 01350 01351 // Now starts pairing or authentication procedures if required 01352 if(needs_pairing) { 01353 SecurityManager &sm = createBLEInstance()->getSecurityManager(); 01354 // Request authentication to start pairing procedure 01355 sm.requestAuthentication(e.connection_handle); 01356 } else if(needs_authentication) { 01357 // TODO: GAP Authentication != Security Manager authentication 01358 // Needs to be implemented 01359 } 01360 } 01361 01362 void GenericGap::on_disconnection_complete(const pal::GapDisconnectionCompleteEvent& e) 01363 { 01364 if (e.status == pal::hci_error_code_t::SUCCESS) { 01365 processDisconnectionEvent ( 01366 e.connection_handle, 01367 (Gap::DisconnectionReason_t) e.reason 01368 ); 01369 } else { 01370 // TODO: define what to do in case of faillure 01371 } 01372 } 01373 01374 void GenericGap::on_connection_parameter_request(const pal::GapRemoteConnectionParameterRequestEvent& e) 01375 { 01376 // intern behavior, accept all new parameter requests 01377 // TODO: expose an API so user code can accept or reject such request 01378 _pal_gap.accept_connection_parameter_request( 01379 e.connection_handle, 01380 e.min_connection_interval, 01381 e.max_connection_interval, 01382 e.connection_latency, 01383 e.supervision_timeout, 01384 /* minimum_connection_event_length */ 0, 01385 /* maximum_connection_event_length */ 0 01386 ); 01387 } 01388 01389 void GenericGap::on_connection_update(const pal::GapConnectionUpdateEvent& e) 01390 { 01391 // TODO: add feature in interface to notify the user that the connection 01392 // has been updated. 01393 } 01394 01395 void GenericGap::on_unexpected_error(const pal::GapUnexpectedErrorEvent& e) 01396 { 01397 // TODO: add feature in interface to notify the user that the connection 01398 // has been updated. 01399 } 01400 01401 pal::own_address_type_t GenericGap::get_own_address_type(AddressUseType_t address_use_type) 01402 { 01403 if(_privacy_enabled) { 01404 bool use_non_resolvable_address = false; 01405 if(address_use_type == CENTRAL_SCAN) { 01406 use_non_resolvable_address = _central_privacy_configuration.use_non_resolvable_random_address; 01407 } else if (address_use_type == PERIPHERAL_NON_CONNECTABLE) { 01408 use_non_resolvable_address = _peripheral_privacy_configuration.use_non_resolvable_random_address; 01409 } 01410 01411 // An non resolvable private address should be generated 01412 if(use_non_resolvable_address) { 01413 return pal::own_address_type_t::RANDOM_ADDRESS; 01414 } 01415 01416 switch (_address_type) { 01417 case BLEProtocol::AddressType::PUBLIC: 01418 return pal::own_address_type_t::RESOLVABLE_PRIVATE_ADDRESS_PUBLIC_FALLBACK; 01419 default: 01420 return pal::own_address_type_t::RESOLVABLE_PRIVATE_ADDRESS_RANDOM_FALLBACK; 01421 } 01422 } 01423 01424 switch (_address_type) { 01425 case BLEProtocol::AddressType::PUBLIC: 01426 return pal::own_address_type_t::PUBLIC_ADDRESS; 01427 default: 01428 return pal::own_address_type_t::RANDOM_ADDRESS; 01429 } 01430 } 01431 01432 bool GenericGap::initialize_whitelist() const 01433 { 01434 if (_whitelist.addresses != NULL) { 01435 return true; 01436 } 01437 01438 uint8_t whitelist_capacity = _pal_gap.read_white_list_capacity(); 01439 01440 if (whitelist_capacity == 0) { 01441 return false; 01442 } 01443 01444 _whitelist.addresses = new (std::nothrow) BLEProtocol::Address_t[whitelist_capacity] ; 01445 if (_whitelist.addresses == NULL) { 01446 return false; 01447 } 01448 01449 _whitelist.size = 0; 01450 _whitelist.capacity = whitelist_capacity; 01451 01452 return true; 01453 } 01454 01455 ble_error_t GenericGap::update_address_resolution_setting() 01456 { 01457 // Only disable if privacy is disabled or resolution is not requested in either central or peripheral mode 01458 bool enable = true; 01459 01460 if(!_privacy_enabled) { 01461 enable = false; 01462 } 01463 else if( (_peripheral_privacy_configuration.resolution_strategy == PeripheralPrivacyConfiguration_t::DO_NOT_RESOLVE) 01464 && (_central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::DO_NOT_RESOLVE) ) { 01465 enable = false; 01466 } 01467 01468 return _pal_gap.set_address_resolution(enable); 01469 } 01470 01471 void GenericGap::set_random_address_rotation(bool enable) 01472 { 01473 if(enable == _random_address_rotating) { 01474 return; 01475 } 01476 01477 _random_address_rotating = enable; 01478 01479 if(enable) { 01480 // Set first address 01481 update_random_address(); 01482 01483 // Schedule rotations every 15 minutes as recomended by the spec 01484 _address_rotation_ticker.attach_us( 01485 mbed::callback(this, &GenericGap::on_address_rotation_timeout), 01486 15 * 60 * 1000000U 01487 ); 01488 } 01489 else { 01490 // Stop ticker 01491 _address_rotation_ticker.detach(); 01492 01493 // Set static random identity address 01494 _pal_gap.set_random_address( 01495 _random_static_identity_address 01496 ); 01497 } 01498 } 01499 01500 void GenericGap::update_random_address() 01501 { 01502 if(!_random_address_rotating) 01503 { 01504 // This event might have been queued before we disabled address rotation 01505 return; 01506 } 01507 01508 ble::address_t address; 01509 01510 do { 01511 byte_array_t<8> random_data; 01512 01513 ble_error_t ret = _pal_sm.get_random_data(random_data); 01514 if (ret != BLE_ERROR_NONE) { 01515 // Abort 01516 return; 01517 } 01518 01519 // Build a non-resolvable private address as specified in the Core 4.2 spec, Vol 6, Part B, 1.3.2.2 01520 // Mask out two MSbs 01521 random_data[5] &= 0x3F; 01522 01523 // Copy to address - will copy first 6 bytes 01524 address = ble::address_t(random_data.data()); 01525 01526 if(!is_random_private_non_resolvable_address(address.data())) 01527 { 01528 // If address is invalid, which is unlikely (all 0s or all 1s), try again 01529 // If implementation is faulty, we'll get stuck here 01530 continue; 01531 } 01532 01533 // Address is valid 01534 break; 01535 } while(true); 01536 01537 ble_error_t err = _pal_gap.set_random_address( 01538 address 01539 ); 01540 if (err) { 01541 return; 01542 } 01543 01544 _address_type = LegacyAddressType::RANDOM_PRIVATE_NON_RESOLVABLE; 01545 _address = address; 01546 } 01547 01548 void GenericGap::on_address_rotation_timeout() 01549 { 01550 _event_queue.post(mbed::callback(this, &GenericGap::update_random_address)); 01551 } 01552 01553 void GenericGap::set_connection_event_handler(pal::ConnectionEventMonitor::EventHandler *connection_event_handler) 01554 { 01555 _connection_event_handler = connection_event_handler; 01556 } 01557 01558 } // namespace generic 01559 } // namespace ble
Generated on Tue Aug 9 2022 00:37:08 by
