Nathan Yonkee / Mbed 2 deprecated Nucleo_sinewave_output_copy

Dependencies:   mbed

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