takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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