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