Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GenericGap.cpp Source File

GenericGap.cpp

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