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/BLEProtocol.h" 00021 #include "ble/Gap.h" 00022 #include "ble/pal/PalGap.h" 00023 #include "ble/pal/GapEvents.h" 00024 #include "ble/pal/GapTypes.h" 00025 #include "ble/pal/GenericAccessService.h" 00026 #include "ble/generic/GenericGap.h" 00027 00028 #include "drivers/Timeout.h" 00029 00030 namespace ble { 00031 namespace generic { 00032 00033 namespace { 00034 00035 // Constants 00036 static const uint16_t scan_interval_min = 0x0004; 00037 static const uint16_t scan_interval_max = 0x4000; 00038 static const uint16_t connection_interval_min = 0x0006; 00039 static const uint16_t connection_interval_max = 0x0C80; 00040 static const uint16_t slave_latency_min = 0x0000; 00041 static const uint16_t slave_latency_max = 0x01F3; 00042 static const uint16_t advertising_interval_min = 0x0020; 00043 static const uint16_t advertising_interval_max = 0x4000; 00044 static const uint16_t supervision_timeout_min = 0x000A; 00045 static const uint16_t supervision_timeout_max = 0x0C80; 00046 00047 static const Gap::ConnectionParams_t default_connection_params = { 00048 /* min conn interval */ 50, 00049 /* max conn interval */ 100, 00050 /* slave latency */ 0, 00051 /* supervision timeout */ 600 00052 }; 00053 00054 static const GapScanningParams default_scan_params; 00055 00056 /* 00057 * Return true if value is included in the range [lower_bound : higher_bound] 00058 */ 00059 template<typename T> 00060 static bool is_in_range(T value, T lower_bound, T higher_bound) { 00061 if (value < lower_bound || value > higher_bound) { 00062 return false; 00063 } 00064 return true; 00065 } 00066 00067 /* 00068 * Return true if the scan parameters are valid or false otherwise. 00069 */ 00070 static bool is_scan_params_valid(const GapScanningParams* params) 00071 { 00072 if (params == NULL) { 00073 return false; 00074 } 00075 00076 if (is_in_range(params->getInterval(), scan_interval_min, scan_interval_max) == false) { 00077 return false; 00078 } 00079 00080 if (is_in_range(params->getWindow(), scan_interval_min, params->getInterval()) == false) { 00081 return false; 00082 } 00083 00084 return true; 00085 } 00086 00087 /* 00088 * Return true if the connection parameters are valid or false otherwise. 00089 */ 00090 static bool is_connection_params_valid(const Gap::ConnectionParams_t* params) 00091 { 00092 if (params == NULL) { 00093 return false; 00094 } 00095 00096 if (is_in_range(params->slaveLatency, slave_latency_min, slave_latency_max) == false) { 00097 return false; 00098 } 00099 00100 if (is_in_range(params->maxConnectionInterval, connection_interval_min, connection_interval_max) == false) { 00101 return false; 00102 } 00103 00104 if (is_in_range(params->minConnectionInterval, connection_interval_min, params->maxConnectionInterval) == false) { 00105 return false; 00106 } 00107 00108 if (is_in_range(params->connectionSupervisionTimeout, supervision_timeout_min, supervision_timeout_max) == false) { 00109 return false; 00110 } 00111 00112 uint16_t max_connection_interval_ms = 00113 ((uint32_t)params->maxConnectionInterval * 125) / 100; 00114 uint16_t min_connection_supervision_timeout = 00115 ((1 + params->slaveLatency) * max_connection_interval_ms * 2) / 10; 00116 00117 if (params->connectionSupervisionTimeout < min_connection_supervision_timeout) { 00118 return false; 00119 } 00120 00121 return true; 00122 } 00123 00124 /* 00125 * Return true of the connection parameters are acceptable as preferred connection 00126 * parameters. 00127 * 00128 * Prefered connection parameters unlike actual connection parameters allow the 00129 * max connection interval, min connection interval and connection supervision 00130 * timeout to be equal to 0xFFFF. When it is the case that value can be 00131 * interpreted as "non specific". 00132 */ 00133 static bool is_preferred_connection_params_valid(const Gap::ConnectionParams_t* params) 00134 { 00135 if (params == NULL) { 00136 return false; 00137 } 00138 00139 if (is_in_range(params->slaveLatency, slave_latency_min, slave_latency_max) == false) { 00140 return false; 00141 } 00142 00143 if ((is_in_range(params->maxConnectionInterval, connection_interval_min, connection_interval_max) == false) && 00144 (params->maxConnectionInterval != 0xFFFF)) { 00145 return false; 00146 } 00147 00148 if ((is_in_range(params->minConnectionInterval, connection_interval_min, params->maxConnectionInterval) == false) && 00149 (params->minConnectionInterval != 0xFFFF)) { 00150 return false; 00151 } 00152 00153 if (params->connectionSupervisionTimeout == 0xFFFF) { 00154 return true; 00155 } 00156 00157 if ((is_in_range(params->connectionSupervisionTimeout, supervision_timeout_min, supervision_timeout_max) == false)) { 00158 return false; 00159 } 00160 00161 if (params->maxConnectionInterval == 0xFFFF) { 00162 return true; 00163 } 00164 00165 uint16_t max_connection_interval_ms = 00166 ((uint32_t)params->maxConnectionInterval * 125) / 100; 00167 uint16_t min_connection_supervision_timeout = 00168 ((1 + params->slaveLatency) * max_connection_interval_ms * 2) / 10; 00169 00170 if (params->connectionSupervisionTimeout < min_connection_supervision_timeout) { 00171 return false; 00172 } 00173 00174 return true; 00175 } 00176 00177 /** 00178 * Check if random bytes of an address are valid. 00179 */ 00180 static bool is_prand_valid(const uint8_t* bytes, size_t len) 00181 { 00182 // at least one bit of the random part of the static address shall be 00183 // equal to 0 and at least one bit of the random part of the static 00184 // address shall be equal to 1 00185 for (size_t i = 0; i < (len - 1); ++i) { 00186 if ((bytes[i] != 0x00) && (bytes[i] != 0xFF)) { 00187 return true; 00188 } 00189 00190 if ((i > 0) && (bytes[i] != bytes[i - 1])) { 00191 return true; 00192 } 00193 } 00194 00195 if (((bytes[len - 1] & 0x3F) == 0x3F) && (bytes[len - 2] == 0xFF)) { 00196 return false; 00197 } 00198 00199 if (((bytes[len - 1] & 0x3F) == 0x00) && (bytes[len - 2] == 0x00)) { 00200 return false; 00201 } 00202 00203 return true; 00204 } 00205 00206 /* 00207 * Check if the random part of a random address with 48 random bytes are valid 00208 * or not. 00209 * Return true if it is the case and false otherwise. 00210 */ 00211 static bool is_prand_48_bits_valid(const BLEProtocol::AddressBytes_t address) 00212 { 00213 return is_prand_valid(address, 6); 00214 } 00215 00216 /* 00217 * Check if the random part of a random address with 24 random bytes are valid 00218 * or not. 00219 * Return true if it is the case and false otherwise. 00220 */ 00221 static bool is_prand_24_bits_valid(const BLEProtocol::AddressBytes_t address) 00222 { 00223 return is_prand_valid(address + 3, 3); 00224 } 00225 00226 /* 00227 * Return true if address is a random static address. 00228 */ 00229 static bool is_random_static_address(const BLEProtocol::AddressBytes_t address) 00230 { 00231 // top two msb bits shall be equal to 1. 00232 if ((address[5] >> 6) != 0x03) { 00233 return false; 00234 } 00235 00236 return is_prand_48_bits_valid(address); 00237 } 00238 00239 /* 00240 * Return true if address is a random private non resolvable address. 00241 */ 00242 static bool is_random_private_non_resolvable_address( 00243 const BLEProtocol::AddressBytes_t address 00244 ) { 00245 // top two msb bits shall be equal to 0. 00246 if ((address[5] >> 6) != 0x00) { 00247 return false; 00248 } 00249 00250 return is_prand_48_bits_valid(address); 00251 } 00252 00253 /* 00254 * Return true if address is a random private resolvable address. 00255 */ 00256 static bool is_random_private_resolvable_address( 00257 const BLEProtocol::AddressBytes_t address 00258 ) { 00259 // top two msb bits shall be equal to 01. 00260 if ((address[5] >> 6) != 0x01) { 00261 return false; 00262 } 00263 00264 return is_prand_24_bits_valid(address); 00265 } 00266 00267 /* 00268 * Return true if the address is a random address. 00269 */ 00270 static bool is_random_address(const BLEProtocol::AddressBytes_t address) 00271 { 00272 return is_random_private_resolvable_address(address) || 00273 is_random_private_non_resolvable_address(address) || 00274 is_random_static_address(address); 00275 } 00276 00277 /* 00278 * Check disconnection reason validity. 00279 */ 00280 static bool is_disconnection_reason_valid (Gap::DisconnectionReason_t reason) 00281 { 00282 switch (reason) { 00283 /** 00284 * Note: accepted reasons are: 00285 typedef pal::disconnection_reason_t reason_t; 00286 case reason_t::AUTHENTICATION_FAILLURE: 00287 case reason_t::REMOTE_USER_TERMINATED_CONNECTION: 00288 case reason_t::REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_LOW_RESOURCES: 00289 case reason_t::REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_POWER_OFF: 00290 case reason_t::UNSUPPORTED_REMOTE_FEATURE: 00291 case reason_t::PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED: 00292 case reason_t::UNACCEPTABLE_CONNECTION_PARAMETERS: 00293 */ 00294 00295 // TODO Fix Disconnectionreason_t which expose invalid value 00296 case Gap::REMOTE_USER_TERMINATED_CONNECTION: 00297 case Gap::REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES: 00298 case Gap::REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF: 00299 case Gap::CONN_INTERVAL_UNACCEPTABLE: 00300 return true; 00301 default: 00302 return false; 00303 } 00304 } 00305 00306 /* 00307 * Return true if the whitelist in input is valid or false otherwise. 00308 */ 00309 static bool is_whitelist_valid(const Gap::Whitelist_t& whitelist) 00310 { 00311 if (whitelist.size > whitelist.capacity) { 00312 return false; 00313 } 00314 00315 for (size_t i = 0; i < whitelist.size; ++i) { 00316 const BLEProtocol::Address_t& address = whitelist.addresses[i]; 00317 if (address.type > BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE) { 00318 return false; 00319 } 00320 00321 if (address.type != BLEProtocol::AddressType::PUBLIC) { 00322 if (is_random_address(address.address) == false) { 00323 return false; 00324 } 00325 } 00326 } 00327 return true; 00328 } 00329 00330 /* 00331 * Return true if device is present in the whitelist. 00332 */ 00333 static bool is_in_whitelist( 00334 const BLEProtocol::Address_t& device, const Gap::Whitelist_t& whitelist 00335 ) { 00336 for (size_t i = 0; i < whitelist.size; ++i) { 00337 const BLEProtocol::Address_t& potential_device = whitelist.addresses[i]; 00338 00339 if (potential_device.type != device.type) { 00340 continue; 00341 } 00342 00343 if (memcmp(potential_device.address, device.address, sizeof(device.address)) == 0) { 00344 return true; 00345 } 00346 } 00347 return false; 00348 } 00349 00350 /* 00351 * Convert a BLEProtocol::AddressType_t into a pal::whitelist_address_type_t. 00352 */ 00353 static pal::whitelist_address_type_t to_device_address_type( 00354 BLEProtocol::AddressType_t address_type 00355 ) { 00356 return (address_type == BLEProtocol::AddressType::PUBLIC) ? 00357 pal::whitelist_address_type_t::PUBLIC_DEVICE_ADDRESS : 00358 pal::whitelist_address_type_t::RANDOM_DEVICE_ADDRESS; 00359 } 00360 00361 /* 00362 * Return true if the advertising parameters are valid. 00363 */ 00364 static bool is_advertising_params_valid(const GapAdvertisingParams& params) 00365 { 00366 if (is_in_range(params.getIntervalInADVUnits(), advertising_interval_min, advertising_interval_max) == false) { 00367 return false; 00368 } 00369 00370 if (params.getAdvertisingType() > GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED) { 00371 return false; 00372 } 00373 00374 return true; 00375 } 00376 00377 } // end of anonymous namespace 00378 00379 GenericGap::GenericGap( 00380 pal::EventQueue& event_queue, 00381 pal::Gap& pal_gap, 00382 pal::GenericAccessService& generic_access_service 00383 ) : _event_queue(event_queue), 00384 _pal_gap(pal_gap), 00385 _gap_service(generic_access_service), 00386 _address_type(BLEProtocol::AddressType::PUBLIC), 00387 _initiator_policy_mode(pal::initiator_policy_t::NO_FILTER), 00388 _scanning_filter_policy(pal::scanning_filter_policy_t::NO_FILTER), 00389 _advertising_filter_policy(pal::advertising_filter_policy_t::NO_FILTER), 00390 _whitelist(), 00391 _advertising_timeout(), 00392 _scan_timeout(), 00393 _connection_event_handler(NULL) 00394 { 00395 _pal_gap.when_gap_event_received( 00396 mbed::callback(this, &GenericGap::on_gap_event_received) 00397 ); 00398 } 00399 00400 GenericGap::~GenericGap () 00401 { 00402 } 00403 00404 ble_error_t GenericGap::setAddress ( 00405 BLEProtocol::AddressType_t type, 00406 const BLEProtocol::AddressBytes_t address 00407 ) { 00408 switch (type) { 00409 case BLEProtocol::AddressType::PUBLIC: 00410 // The public address cannot be set, just set the type to public 00411 _address_type = type; 00412 return BLE_ERROR_NONE; 00413 00414 case BLEProtocol::AddressType::RANDOM_STATIC: { 00415 if (is_random_static_address(address) == false) { 00416 return BLE_ERROR_INVALID_PARAM; 00417 } 00418 00419 ble_error_t err = _pal_gap.set_random_address( 00420 ble::address_t(address) 00421 ); 00422 if (err) { 00423 return err; 00424 } 00425 00426 _address_type = type; 00427 _address = ble::address_t(address); 00428 return BLE_ERROR_NONE; 00429 } 00430 00431 case BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE: 00432 // TODO: Fix with the privacy/security rework 00433 return BLE_ERROR_NOT_IMPLEMENTED; 00434 00435 case BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE: 00436 // TODO: add process to set the random private non resolvable 00437 // address (privacy/security work) 00438 return BLE_ERROR_NOT_IMPLEMENTED; 00439 00440 default: 00441 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00442 } 00443 } 00444 00445 ble_error_t GenericGap::getAddress ( 00446 BLEProtocol::AddressType_t *type, 00447 BLEProtocol::AddressBytes_t address 00448 ) { 00449 *type = _address_type; 00450 ble::address_t address_value; 00451 if (_address_type == BLEProtocol::AddressType::PUBLIC) { 00452 address_value = _pal_gap.get_device_address(); 00453 } else { 00454 address_value = _pal_gap.get_random_address(); 00455 } 00456 00457 memcpy(address, address_value.data(), address_value.size()); 00458 return BLE_ERROR_NONE; 00459 } 00460 00461 uint16_t GenericGap::getMinAdvertisingInterval () const 00462 { 00463 return GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN; 00464 } 00465 00466 uint16_t GenericGap::getMinNonConnectableAdvertisingInterval () const 00467 { 00468 return GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON; 00469 } 00470 00471 uint16_t GenericGap::getMaxAdvertisingInterval () const 00472 { 00473 return GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX; 00474 } 00475 00476 ble_error_t GenericGap::stopAdvertising () 00477 { 00478 ble_error_t err = _pal_gap.advertising_enable(false); 00479 if (err) { 00480 return err; 00481 } 00482 _advertising_timeout.detach(); 00483 state.advertising = false; 00484 return BLE_ERROR_NONE; 00485 } 00486 00487 ble_error_t GenericGap::stopScan () 00488 { 00489 ble_error_t err = _pal_gap.scan_enable(false, false); 00490 if (err) { 00491 return err; 00492 } 00493 00494 _scan_timeout.detach(); 00495 return BLE_ERROR_NONE; 00496 } 00497 00498 ble_error_t GenericGap::connect ( 00499 const BLEProtocol::AddressBytes_t peerAddr, 00500 BLEProtocol::AddressType_t peerAddrType, 00501 const ConnectionParams_t* connectionParams, 00502 const GapScanningParams* scanParams 00503 ) { 00504 if (connectionParams == NULL) { 00505 connectionParams = &default_connection_params; 00506 } 00507 00508 if (scanParams == NULL) { 00509 scanParams = &default_scan_params; 00510 } 00511 00512 if (is_scan_params_valid(scanParams) == false) { 00513 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00514 } 00515 00516 if (is_connection_params_valid(connectionParams) == false) { 00517 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00518 } 00519 00520 // TODO fix upper layer API, address type factorization is incorrect. 00521 00522 // Force scan stop before initiating the scan used for connection 00523 stopScan (); 00524 00525 return _pal_gap.create_connection( 00526 scanParams->getInterval(), 00527 scanParams->getWindow(), 00528 _initiator_policy_mode, 00529 (pal::connection_peer_address_type_t::type ) peerAddrType, 00530 ble::address_t(peerAddr), 00531 (pal::own_address_type_t::type ) _address_type, 00532 connectionParams->minConnectionInterval, 00533 connectionParams->maxConnectionInterval, 00534 connectionParams->slaveLatency, 00535 connectionParams->connectionSupervisionTimeout, 00536 /* minimum_connection_event_length */ 0, 00537 /* maximum_connection_event_length */ 0 00538 ); 00539 } 00540 00541 ble_error_t GenericGap::disconnect (Handle_t connectionHandle, DisconnectionReason_t reason) 00542 { 00543 if (is_disconnection_reason_valid(reason) == false) { 00544 return BLE_ERROR_INVALID_PARAM; 00545 } 00546 return _pal_gap.disconnect( 00547 connectionHandle, 00548 (pal::disconnection_reason_t::type) reason 00549 ); 00550 } 00551 00552 ble_error_t GenericGap::updateConnectionParams (Handle_t handle, const ConnectionParams_t *params) 00553 { 00554 if (is_connection_params_valid(params) == false) { 00555 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00556 } 00557 00558 return _pal_gap.connection_parameters_update( 00559 handle, 00560 params->minConnectionInterval, 00561 params->maxConnectionInterval, 00562 params->slaveLatency, 00563 params->connectionSupervisionTimeout, 00564 /* minimum_connection_event_length */ 0, 00565 /* maximum_connection_event_length */ 0 00566 ); 00567 } 00568 00569 ble_error_t GenericGap::getPreferredConnectionParams (ConnectionParams_t *params) 00570 { 00571 if (params == NULL) { 00572 return BLE_ERROR_INVALID_PARAM; 00573 } 00574 00575 return _gap_service.get_peripheral_prefered_connection_parameters( 00576 *params 00577 ); 00578 } 00579 00580 ble_error_t GenericGap::setPreferredConnectionParams (const ConnectionParams_t *params) 00581 { 00582 if(is_preferred_connection_params_valid(params) == false) { 00583 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00584 } 00585 00586 return _gap_service.set_peripheral_prefered_connection_parameters( 00587 *params 00588 ); 00589 } 00590 00591 ble_error_t GenericGap::setDeviceName (const uint8_t *deviceName) 00592 { 00593 return _gap_service.set_device_name(deviceName); 00594 } 00595 00596 ble_error_t GenericGap::getDeviceName (uint8_t *deviceName, unsigned *lengthP) 00597 { 00598 if (lengthP == NULL) { 00599 return BLE_ERROR_INVALID_PARAM; 00600 } 00601 00602 uint8_t length = 0; 00603 ble_error_t err = _gap_service.get_device_name_length(length); 00604 if (err) { 00605 return err; 00606 } 00607 00608 if (deviceName != NULL) { 00609 if (*lengthP < length) { 00610 return BLE_ERROR_INVALID_PARAM; 00611 } 00612 00613 ArrayView<uint8_t> name(deviceName, *lengthP); 00614 err = _gap_service.get_device_name(name); 00615 if (err) { 00616 return err; 00617 } 00618 } 00619 *lengthP = length; 00620 return BLE_ERROR_NONE; 00621 } 00622 00623 ble_error_t GenericGap::setAppearance (GapAdvertisingData::Appearance appearance) 00624 { 00625 return _gap_service.set_appearance(appearance); 00626 } 00627 00628 ble_error_t GenericGap::getAppearance (GapAdvertisingData::Appearance *appearanceP) 00629 { 00630 if (appearanceP == NULL) { 00631 return BLE_ERROR_INVALID_PARAM; 00632 } 00633 return _gap_service.get_appearance(*appearanceP); 00634 } 00635 00636 ble_error_t GenericGap::setTxPower (int8_t txPower) 00637 { 00638 // TODO: This is not standard, expose it as an extension API and document it 00639 // as such 00640 return BLE_ERROR_NOT_IMPLEMENTED; 00641 } 00642 00643 void GenericGap::getPermittedTxPowerValues (const int8_t **valueArrayPP, size_t *countP) 00644 { 00645 *countP = 0; 00646 } 00647 00648 uint8_t GenericGap::getMaxWhitelistSize (void) const 00649 { 00650 return _pal_gap.read_white_list_capacity(); 00651 } 00652 00653 ble_error_t GenericGap::getWhitelist (Whitelist_t &whitelist) const 00654 { 00655 if(initialize_whitelist() == false) { 00656 return BLE_ERROR_INVALID_STATE; 00657 } 00658 00659 if (whitelist.capacity < _whitelist.capacity) { 00660 return BLE_ERROR_INVALID_PARAM; 00661 } 00662 00663 for (size_t i = 0; i < _whitelist.size; ++i) { 00664 whitelist.addresses[i] = _whitelist.addresses[i]; 00665 } 00666 00667 whitelist.capacity = _whitelist.capacity; 00668 return BLE_ERROR_NONE; 00669 } 00670 00671 ble_error_t GenericGap::setWhitelist (const Whitelist_t &whitelist) 00672 { 00673 if (is_whitelist_valid(whitelist) == false) { 00674 return BLE_ERROR_INVALID_PARAM; 00675 } 00676 00677 if(initialize_whitelist() == false) { 00678 return BLE_ERROR_INVALID_STATE; 00679 } 00680 00681 if (whitelist.capacity > _whitelist.capacity) { 00682 return BLE_ERROR_INVALID_PARAM; 00683 } 00684 00685 // first evict devices not in the existing whitelist 00686 for (size_t i = 0; i < _whitelist.size; ++i) { 00687 const BLEProtocol::Address_t& device = _whitelist.addresses[i]; 00688 00689 if (is_in_whitelist(device, whitelist) == false) { 00690 ble_error_t err = _pal_gap.remove_device_from_whitelist( 00691 to_device_address_type(device.type), 00692 device.address 00693 ); 00694 00695 // try to restore the whitelist to its initial state 00696 if (err) { 00697 for (size_t j = 0; j < i; ++j) { 00698 const BLEProtocol::Address_t& device = _whitelist.addresses[j]; 00699 00700 if (is_in_whitelist(device, whitelist) == false) { 00701 _pal_gap.add_device_to_whitelist( 00702 to_device_address_type(device.type), 00703 device.address 00704 ); 00705 } 00706 } 00707 return err; 00708 } 00709 } 00710 } 00711 00712 // second add devices which were not in the initial whitelist 00713 for (size_t i = 0; i < whitelist.size; ++i) { 00714 const BLEProtocol::Address_t& device = whitelist.addresses[i]; 00715 00716 if (is_in_whitelist(device, _whitelist) == false) { 00717 ble_error_t err = _pal_gap.add_device_to_whitelist( 00718 to_device_address_type(device.type), 00719 device.address 00720 ); 00721 00722 // try to restore the whitelist to its initial state 00723 if (err) { 00724 // first remove the devices added 00725 for (size_t j = 0; j < i; ++j) { 00726 const BLEProtocol::Address_t& device = whitelist.addresses[j]; 00727 00728 if (is_in_whitelist(device, _whitelist) == false) { 00729 _pal_gap.remove_device_from_whitelist( 00730 to_device_address_type(device.type), 00731 device.address 00732 ); 00733 } 00734 } 00735 00736 // second add the devices of the initial list evicted 00737 for (size_t i = 0; i < _whitelist.size; ++i) { 00738 const BLEProtocol::Address_t& device = _whitelist.addresses[i]; 00739 00740 if (is_in_whitelist(device, whitelist) == false) { 00741 _pal_gap.add_device_to_whitelist( 00742 to_device_address_type(device.type), 00743 device.address 00744 ); 00745 } 00746 } 00747 00748 return err; 00749 } 00750 } 00751 } 00752 00753 // commit the devices into the whitelist 00754 for (size_t i = 0; i < whitelist.size; ++i) { 00755 _whitelist.addresses[i] = whitelist.addresses[i]; 00756 } 00757 00758 _whitelist.size = whitelist.size; 00759 00760 return BLE_ERROR_NONE; 00761 } 00762 00763 ble_error_t GenericGap::setAdvertisingPolicyMode (AdvertisingPolicyMode_t mode) 00764 { 00765 if (mode > Gap::ADV_POLICY_FILTER_ALL_REQS) { 00766 return BLE_ERROR_INVALID_PARAM; 00767 } 00768 00769 _advertising_filter_policy = (pal::advertising_filter_policy_t::type ) mode; 00770 return BLE_ERROR_NONE; 00771 } 00772 00773 ble_error_t GenericGap::setScanningPolicyMode (ScanningPolicyMode_t mode) 00774 { 00775 if (mode > Gap::SCAN_POLICY_FILTER_ALL_ADV) { 00776 return BLE_ERROR_INVALID_PARAM; 00777 } 00778 00779 _scanning_filter_policy = (pal::scanning_filter_policy_t::type ) mode; 00780 return BLE_ERROR_NONE; 00781 } 00782 00783 ble_error_t GenericGap::setInitiatorPolicyMode (InitiatorPolicyMode_t mode) 00784 { 00785 if (mode > Gap::INIT_POLICY_FILTER_ALL_ADV) { 00786 return BLE_ERROR_INVALID_PARAM; 00787 } 00788 00789 _initiator_policy_mode = (pal::initiator_policy_t::type ) mode; 00790 return BLE_ERROR_NONE; 00791 } 00792 00793 Gap::AdvertisingPolicyMode_t GenericGap::getAdvertisingPolicyMode (void) const 00794 { 00795 return (AdvertisingPolicyMode_t) _advertising_filter_policy.value(); 00796 } 00797 00798 Gap::ScanningPolicyMode_t GenericGap::getScanningPolicyMode (void) const 00799 { 00800 return (ScanningPolicyMode_t) _scanning_filter_policy.value(); 00801 } 00802 00803 Gap::InitiatorPolicyMode_t GenericGap::getInitiatorPolicyMode (void) const 00804 { 00805 return (InitiatorPolicyMode_t) _initiator_policy_mode.value(); 00806 } 00807 00808 ble_error_t GenericGap::startRadioScan (const GapScanningParams &scanningParams) 00809 { 00810 if (is_scan_params_valid(&scanningParams) == false) { 00811 return BLE_ERROR_INVALID_PARAM; 00812 } 00813 00814 if (_scanning_filter_policy == pal::scanning_filter_policy_t::FILTER_ADVERTISING && 00815 _whitelist.size == 0) { 00816 return BLE_ERROR_INVALID_STATE; 00817 } 00818 00819 ble_error_t err = _pal_gap.set_scan_parameters( 00820 scanningParams.getActiveScanning(), 00821 scanningParams.getInterval(), 00822 scanningParams.getWindow(), 00823 get_own_address_type(), 00824 _scanning_filter_policy 00825 ); 00826 00827 if (err) { 00828 return err; 00829 } 00830 00831 err = _pal_gap.scan_enable(true, false); 00832 00833 if (err) { 00834 return err; 00835 } 00836 00837 _scan_timeout.detach(); 00838 uint16_t timeout = scanningParams.getTimeout(); 00839 if (timeout) { 00840 _scan_timeout.attach_us( 00841 mbed::callback(this, &GenericGap::on_scan_timeout), 00842 scanningParams.getTimeout() * 1000000U 00843 ); 00844 } 00845 00846 return BLE_ERROR_NONE; 00847 } 00848 00849 ble_error_t GenericGap::initRadioNotification (void) 00850 { 00851 return BLE_ERROR_NOT_IMPLEMENTED; 00852 } 00853 00854 ble_error_t GenericGap::setAdvertisingData (const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) 00855 { 00856 ble_error_t err = _pal_gap.set_advertising_data( 00857 advData.getPayloadLen(), 00858 pal::advertising_data_t(advData.getPayload(), advData.getPayloadLen()) 00859 ); 00860 if (err) { 00861 return err; 00862 } 00863 00864 return _pal_gap.set_scan_response_data( 00865 scanResponse.getPayloadLen(), 00866 pal::advertising_data_t(scanResponse.getPayload(), scanResponse.getPayloadLen()) 00867 ); 00868 } 00869 00870 ble_error_t GenericGap::startAdvertising(const GapAdvertisingParams& params) 00871 { 00872 if (is_advertising_params_valid(params) == false) { 00873 return BLE_ERROR_INVALID_PARAM; 00874 } 00875 00876 // TODO: fix the high level API to have a min/max range 00877 // Going against recommendations (The Advertising_Interval_Min and 00878 // Advertising_Interval_Max should not be the same value to enable the 00879 // Controller to determine the best advertising interval given other activities.) 00880 // for now but not against specification: "The Advertising_Interval_Min 00881 // shall be less than or equal to the Advertising_Interval_Max" 00882 ble_error_t err = _pal_gap.set_advertising_parameters( 00883 /* advertising_interval_min */ params.getIntervalInADVUnits(), 00884 /* advertising_interval_max */ params.getIntervalInADVUnits(), 00885 (pal::advertising_type_t::type ) params.getAdvertisingType(), 00886 get_own_address_type(), 00887 pal::advertising_peer_address_type_t::PUBLIC_ADDRESS, 00888 ble::address_t(), 00889 pal::advertising_channel_map_t::ALL_ADVERTISING_CHANNELS, 00890 _advertising_filter_policy 00891 ); 00892 00893 if (err) { 00894 return err; 00895 } 00896 00897 err = _pal_gap.advertising_enable(true); 00898 if (err) { 00899 return err; 00900 } 00901 00902 state.advertising = true; 00903 00904 _advertising_timeout.detach(); 00905 uint16_t timeout = params.getTimeout(); 00906 if (timeout) { 00907 _advertising_timeout.attach_us( 00908 mbed::callback(this, &GenericGap::on_advertising_timeout), 00909 params.getTimeout() * 1000000U 00910 ); 00911 } 00912 00913 return BLE_ERROR_NONE; 00914 } 00915 00916 ble_error_t GenericGap::reset (void) 00917 { 00918 Gap::reset (); 00919 _advertising_timeout.detach(); 00920 _scan_timeout.detach(); 00921 00922 return BLE_ERROR_NONE; 00923 } 00924 00925 void GenericGap::processConnectionEvent ( 00926 Handle_t handle, 00927 Role_t role, 00928 BLEProtocol::AddressType_t peerAddrType, 00929 const BLEProtocol::AddressBytes_t peerAddr, 00930 BLEProtocol::AddressType_t ownAddrType, 00931 const BLEProtocol::AddressBytes_t ownAddr, 00932 const ConnectionParams_t *connectionParams 00933 ) { 00934 if (_connection_event_handler) { 00935 _connection_event_handler->on_connected( 00936 handle, 00937 role, 00938 peerAddrType, 00939 peerAddr, 00940 ownAddrType, 00941 ownAddr, 00942 connectionParams 00943 ); 00944 } 00945 00946 ::Gap::processConnectionEvent( 00947 handle, 00948 role, 00949 peerAddrType, 00950 peerAddr, 00951 ownAddrType, 00952 ownAddr, 00953 connectionParams 00954 ); 00955 } 00956 00957 void GenericGap::processDisconnectionEvent ( 00958 Handle_t handle, 00959 DisconnectionReason_t reason 00960 ) { 00961 if (_connection_event_handler) { 00962 _connection_event_handler->on_disconnected( 00963 handle, 00964 reason 00965 ); 00966 } 00967 00968 ::Gap::processDisconnectionEvent( 00969 handle, 00970 reason 00971 ); 00972 } 00973 00974 void GenericGap::on_scan_timeout() 00975 { 00976 _event_queue.post(mbed::callback(this, &GenericGap::process_scan_timeout)); 00977 } 00978 00979 void GenericGap::process_scan_timeout() 00980 { 00981 ble_error_t err = _pal_gap.scan_enable(false, false); 00982 if (err) { 00983 // TODO: define the mechanism signaling the error 00984 } 00985 processTimeoutEvent(Gap::TIMEOUT_SRC_SCAN); 00986 } 00987 00988 void GenericGap::on_advertising_timeout() 00989 { 00990 _event_queue.post(mbed::callback(this, &GenericGap::process_advertising_timeout)); 00991 } 00992 00993 void GenericGap::process_advertising_timeout() 00994 { 00995 ble_error_t err = _pal_gap.advertising_enable(false); 00996 if (err) { 00997 // TODO: define the mechanism signaling the error 00998 } 00999 processTimeoutEvent(Gap::TIMEOUT_SRC_ADVERTISING); 01000 } 01001 01002 void GenericGap::on_gap_event_received(const pal::GapEvent& e) 01003 { 01004 switch (e.type.value()) { 01005 case pal::GapEventType::ADVERTISING_REPORT: 01006 on_advertising_report(static_cast<const pal::GapAdvertisingReportEvent&>(e)); 01007 break; 01008 01009 case pal::GapEventType::CONNECTION_COMPLETE: 01010 on_connection_complete(static_cast<const pal::GapConnectionCompleteEvent&>(e)); 01011 break; 01012 01013 case pal::GapEventType::CONNECTION_UPDATE: 01014 on_connection_update(static_cast<const pal::GapConnectionUpdateEvent&>(e)); 01015 break; 01016 01017 case pal::GapEventType::DISCONNECTION_COMPLETE: 01018 on_disconnection_complete(static_cast<const pal::GapDisconnectionCompleteEvent&>(e)); 01019 break; 01020 01021 case pal::GapEventType::REMOTE_CONNECTION_PARAMETER_REQUEST: 01022 on_connection_parameter_request(static_cast<const pal::GapRemoteConnectionParameterRequestEvent&>(e)); 01023 break; 01024 01025 case pal::GapEventType::UNEXPECTED_ERROR: 01026 on_unexpected_error(static_cast<const pal::GapUnexpectedErrorEvent&>(e)); 01027 break; 01028 01029 default: 01030 break; 01031 } 01032 } 01033 01034 void GenericGap::on_advertising_report(const pal::GapAdvertisingReportEvent& e) 01035 { 01036 for (size_t i = 0; i < e.size(); ++i) { 01037 pal::GapAdvertisingReportEvent::advertising_t advertising = e[i]; 01038 01039 processAdvertisementReport( 01040 advertising.address.data(), 01041 advertising.rssi, 01042 advertising.type == pal::received_advertising_type_t::SCAN_RESPONSE, 01043 (GapAdvertisingParams::AdvertisingType_t) advertising.type.value(), 01044 advertising.data.size(), 01045 advertising.data.data(), 01046 (BLEProtocol::AddressType_t) advertising.address_type.value() 01047 ); 01048 } 01049 } 01050 01051 void GenericGap::on_connection_complete(const pal::GapConnectionCompleteEvent& e) 01052 { 01053 // TODO: deprecate ownAddrType and ownAddr, those are not specified 01054 // from the Bluetooth perspective 01055 if (e.status == pal::hci_error_code_t::SUCCESS) { 01056 if (e.role.value() == e.role.SLAVE) { 01057 _advertising_timeout.detach(); 01058 _pal_gap.advertising_enable(false); 01059 } 01060 01061 // using these parameters if stupid, there is no range for the 01062 // connection interval when the connection is established 01063 ConnectionParams_t connection_params = { 01064 /* minConnectionInterval */ e.connection_interval, 01065 /* maxConnectionInterval */ e.connection_interval, 01066 e.connection_latency, 01067 e.supervision_timeout 01068 }; 01069 ble::address_t address; 01070 if (_address_type == BLEProtocol::AddressType::PUBLIC) { 01071 address = _pal_gap.get_device_address(); 01072 } else { 01073 address = _pal_gap.get_random_address(); 01074 } 01075 01076 processConnectionEvent ( 01077 e.connection_handle, 01078 e.role.value() == e.role.MASTER ? ::Gap::CENTRAL : ::Gap::PERIPHERAL, 01079 (BLEProtocol::AddressType_t) e.peer_address_type.value(), 01080 e.peer_address.data(), 01081 _address_type, 01082 address.data(), 01083 &connection_params 01084 ); 01085 } else { 01086 // for now notify user that the connection failled by issuing a timeout 01087 // event 01088 01089 // TODO: Define events in case of connection faillure 01090 processTimeoutEvent(Gap::TIMEOUT_SRC_CONN); 01091 } 01092 } 01093 01094 void GenericGap::on_disconnection_complete(const pal::GapDisconnectionCompleteEvent& e) 01095 { 01096 if (e.status == pal::hci_error_code_t::SUCCESS) { 01097 processDisconnectionEvent ( 01098 e.connection_handle, 01099 (Gap::DisconnectionReason_t) e.reason 01100 ); 01101 } else { 01102 // TODO: define what to do in case of faillure 01103 } 01104 } 01105 01106 void GenericGap::on_connection_parameter_request(const pal::GapRemoteConnectionParameterRequestEvent& e) 01107 { 01108 // intern behavior, accept all new parameter requests 01109 // TODO: expose an API so user code can accept or reject such request 01110 _pal_gap.accept_connection_parameter_request( 01111 e.connection_handle, 01112 e.min_connection_interval, 01113 e.max_connection_interval, 01114 e.connection_latency, 01115 e.supervision_timeout, 01116 /* minimum_connection_event_length */ 0, 01117 /* maximum_connection_event_length */ 0 01118 ); 01119 } 01120 01121 void GenericGap::on_connection_update(const pal::GapConnectionUpdateEvent& e) 01122 { 01123 // TODO: add feature in interface to notify the user that the connection 01124 // has been updated. 01125 } 01126 01127 void GenericGap::on_unexpected_error(const pal::GapUnexpectedErrorEvent& e) 01128 { 01129 // TODO: add feature in interface to notify the user that the connection 01130 // has been updated. 01131 } 01132 01133 pal::own_address_type_t GenericGap::get_own_address_type() 01134 { 01135 switch (_address_type) { 01136 case BLEProtocol::AddressType::PUBLIC: 01137 return pal::own_address_type_t::PUBLIC_ADDRESS; 01138 case BLEProtocol::AddressType::RANDOM_STATIC: 01139 case BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE: 01140 return pal::own_address_type_t::RANDOM_ADDRESS; 01141 case BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE: 01142 return pal::own_address_type_t::RESOLVABLE_PRIVATE_ADDRESS_PUBLIC_FALLBACK; 01143 default: 01144 // not reachable 01145 return pal::own_address_type_t::PUBLIC_ADDRESS; 01146 } 01147 } 01148 01149 bool GenericGap::initialize_whitelist() const 01150 { 01151 if (_whitelist.addresses != NULL) { 01152 return true; 01153 } 01154 01155 uint8_t whitelist_capacity = _pal_gap.read_white_list_capacity(); 01156 01157 if (whitelist_capacity == 0) { 01158 return false; 01159 } 01160 01161 _whitelist.addresses = new (std::nothrow) BLEProtocol::Address_t[whitelist_capacity] ; 01162 if (_whitelist.addresses == NULL) { 01163 return false; 01164 } 01165 01166 _whitelist.size = 0; 01167 _whitelist.capacity = whitelist_capacity; 01168 01169 return true; 01170 } 01171 01172 void GenericGap::set_connection_event_handler(pal::ConnectionEventMonitor::EventHandler *connection_event_handler) 01173 { 01174 _connection_event_handler = connection_event_handler; 01175 } 01176 01177 } // namespace generic 01178 } // namespace ble
Generated on Tue Jul 12 2022 18:18:36 by
