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