init
Embed:
(wiki syntax)
Show/hide line numbers
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