BA / SerialCom

Fork of OmniWheels by Gustav Atmel

Committer:
gustavatmel
Date:
Tue May 01 15:47:08 2018 +0000
Revision:
1:9c5af431a1f1
sdf

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gustavatmel 1:9c5af431a1f1 1 /* mbed Microcontroller Library
gustavatmel 1:9c5af431a1f1 2 * Copyright (c) 2017-2017 ARM Limited
gustavatmel 1:9c5af431a1f1 3 *
gustavatmel 1:9c5af431a1f1 4 * Licensed under the Apache License, Version 2.0 (the "License");
gustavatmel 1:9c5af431a1f1 5 * you may not use this file except in compliance with the License.
gustavatmel 1:9c5af431a1f1 6 * You may obtain a copy of the License at
gustavatmel 1:9c5af431a1f1 7 *
gustavatmel 1:9c5af431a1f1 8 * http://www.apache.org/licenses/LICENSE-2.0
gustavatmel 1:9c5af431a1f1 9 *
gustavatmel 1:9c5af431a1f1 10 * Unless required by applicable law or agreed to in writing, software
gustavatmel 1:9c5af431a1f1 11 * distributed under the License is distributed on an "AS IS" BASIS,
gustavatmel 1:9c5af431a1f1 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
gustavatmel 1:9c5af431a1f1 13 * See the License for the specific language governing permissions and
gustavatmel 1:9c5af431a1f1 14 * limitations under the License.
gustavatmel 1:9c5af431a1f1 15 */
gustavatmel 1:9c5af431a1f1 16
gustavatmel 1:9c5af431a1f1 17 #include <algorithm>
gustavatmel 1:9c5af431a1f1 18 #include <stdint.h>
gustavatmel 1:9c5af431a1f1 19
gustavatmel 1:9c5af431a1f1 20 #include "ble/BLEProtocol.h"
gustavatmel 1:9c5af431a1f1 21 #include "ble/Gap.h"
gustavatmel 1:9c5af431a1f1 22 #include "ble/pal/PalGap.h"
gustavatmel 1:9c5af431a1f1 23 #include "ble/pal/GapEvents.h"
gustavatmel 1:9c5af431a1f1 24 #include "ble/pal/GapTypes.h"
gustavatmel 1:9c5af431a1f1 25 #include "ble/pal/GenericAccessService.h"
gustavatmel 1:9c5af431a1f1 26 #include "ble/generic/GenericGap.h"
gustavatmel 1:9c5af431a1f1 27
gustavatmel 1:9c5af431a1f1 28 #include "drivers/Timeout.h"
gustavatmel 1:9c5af431a1f1 29
gustavatmel 1:9c5af431a1f1 30 namespace ble {
gustavatmel 1:9c5af431a1f1 31 namespace generic {
gustavatmel 1:9c5af431a1f1 32
gustavatmel 1:9c5af431a1f1 33 namespace {
gustavatmel 1:9c5af431a1f1 34
gustavatmel 1:9c5af431a1f1 35 // Constants
gustavatmel 1:9c5af431a1f1 36 static const uint16_t scan_interval_min = 0x0004;
gustavatmel 1:9c5af431a1f1 37 static const uint16_t scan_interval_max = 0x4000;
gustavatmel 1:9c5af431a1f1 38 static const uint16_t connection_interval_min = 0x0006;
gustavatmel 1:9c5af431a1f1 39 static const uint16_t connection_interval_max = 0x0C80;
gustavatmel 1:9c5af431a1f1 40 static const uint16_t slave_latency_min = 0x0000;
gustavatmel 1:9c5af431a1f1 41 static const uint16_t slave_latency_max = 0x01F3;
gustavatmel 1:9c5af431a1f1 42 static const uint16_t advertising_interval_min = 0x0020;
gustavatmel 1:9c5af431a1f1 43 static const uint16_t advertising_interval_max = 0x4000;
gustavatmel 1:9c5af431a1f1 44 static const uint16_t supervision_timeout_min = 0x000A;
gustavatmel 1:9c5af431a1f1 45 static const uint16_t supervision_timeout_max = 0x0C80;
gustavatmel 1:9c5af431a1f1 46
gustavatmel 1:9c5af431a1f1 47 static const Gap::ConnectionParams_t default_connection_params = {
gustavatmel 1:9c5af431a1f1 48 /* min conn interval */ 50,
gustavatmel 1:9c5af431a1f1 49 /* max conn interval */ 100,
gustavatmel 1:9c5af431a1f1 50 /* slave latency */ 0,
gustavatmel 1:9c5af431a1f1 51 /* supervision timeout */ 600
gustavatmel 1:9c5af431a1f1 52 };
gustavatmel 1:9c5af431a1f1 53
gustavatmel 1:9c5af431a1f1 54 static const GapScanningParams default_scan_params;
gustavatmel 1:9c5af431a1f1 55
gustavatmel 1:9c5af431a1f1 56 /*
gustavatmel 1:9c5af431a1f1 57 * Return true if value is included in the range [lower_bound : higher_bound]
gustavatmel 1:9c5af431a1f1 58 */
gustavatmel 1:9c5af431a1f1 59 template<typename T>
gustavatmel 1:9c5af431a1f1 60 static bool is_in_range(T value, T lower_bound, T higher_bound) {
gustavatmel 1:9c5af431a1f1 61 if (value < lower_bound || value > higher_bound) {
gustavatmel 1:9c5af431a1f1 62 return false;
gustavatmel 1:9c5af431a1f1 63 }
gustavatmel 1:9c5af431a1f1 64 return true;
gustavatmel 1:9c5af431a1f1 65 }
gustavatmel 1:9c5af431a1f1 66
gustavatmel 1:9c5af431a1f1 67 /*
gustavatmel 1:9c5af431a1f1 68 * Return true if the scan parameters are valid or false otherwise.
gustavatmel 1:9c5af431a1f1 69 */
gustavatmel 1:9c5af431a1f1 70 static bool is_scan_params_valid(const GapScanningParams* params)
gustavatmel 1:9c5af431a1f1 71 {
gustavatmel 1:9c5af431a1f1 72 if (params == NULL) {
gustavatmel 1:9c5af431a1f1 73 return false;
gustavatmel 1:9c5af431a1f1 74 }
gustavatmel 1:9c5af431a1f1 75
gustavatmel 1:9c5af431a1f1 76 if (is_in_range(params->getInterval(), scan_interval_min, scan_interval_max) == false) {
gustavatmel 1:9c5af431a1f1 77 return false;
gustavatmel 1:9c5af431a1f1 78 }
gustavatmel 1:9c5af431a1f1 79
gustavatmel 1:9c5af431a1f1 80 if (is_in_range(params->getWindow(), scan_interval_min, params->getInterval()) == false) {
gustavatmel 1:9c5af431a1f1 81 return false;
gustavatmel 1:9c5af431a1f1 82 }
gustavatmel 1:9c5af431a1f1 83
gustavatmel 1:9c5af431a1f1 84 return true;
gustavatmel 1:9c5af431a1f1 85 }
gustavatmel 1:9c5af431a1f1 86
gustavatmel 1:9c5af431a1f1 87 /*
gustavatmel 1:9c5af431a1f1 88 * Return true if the connection parameters are valid or false otherwise.
gustavatmel 1:9c5af431a1f1 89 */
gustavatmel 1:9c5af431a1f1 90 static bool is_connection_params_valid(const Gap::ConnectionParams_t* params)
gustavatmel 1:9c5af431a1f1 91 {
gustavatmel 1:9c5af431a1f1 92 if (params == NULL) {
gustavatmel 1:9c5af431a1f1 93 return false;
gustavatmel 1:9c5af431a1f1 94 }
gustavatmel 1:9c5af431a1f1 95
gustavatmel 1:9c5af431a1f1 96 if (is_in_range(params->slaveLatency, slave_latency_min, slave_latency_max) == false) {
gustavatmel 1:9c5af431a1f1 97 return false;
gustavatmel 1:9c5af431a1f1 98 }
gustavatmel 1:9c5af431a1f1 99
gustavatmel 1:9c5af431a1f1 100 if (is_in_range(params->maxConnectionInterval, connection_interval_min, connection_interval_max) == false) {
gustavatmel 1:9c5af431a1f1 101 return false;
gustavatmel 1:9c5af431a1f1 102 }
gustavatmel 1:9c5af431a1f1 103
gustavatmel 1:9c5af431a1f1 104 if (is_in_range(params->minConnectionInterval, connection_interval_min, params->maxConnectionInterval) == false) {
gustavatmel 1:9c5af431a1f1 105 return false;
gustavatmel 1:9c5af431a1f1 106 }
gustavatmel 1:9c5af431a1f1 107
gustavatmel 1:9c5af431a1f1 108 if (is_in_range(params->connectionSupervisionTimeout, supervision_timeout_min, supervision_timeout_max) == false) {
gustavatmel 1:9c5af431a1f1 109 return false;
gustavatmel 1:9c5af431a1f1 110 }
gustavatmel 1:9c5af431a1f1 111
gustavatmel 1:9c5af431a1f1 112 uint16_t max_connection_interval_ms =
gustavatmel 1:9c5af431a1f1 113 ((uint32_t)params->maxConnectionInterval * 125) / 100;
gustavatmel 1:9c5af431a1f1 114 uint16_t min_connection_supervision_timeout =
gustavatmel 1:9c5af431a1f1 115 ((1 + params->slaveLatency) * max_connection_interval_ms * 2) / 10;
gustavatmel 1:9c5af431a1f1 116
gustavatmel 1:9c5af431a1f1 117 if (params->connectionSupervisionTimeout < min_connection_supervision_timeout) {
gustavatmel 1:9c5af431a1f1 118 return false;
gustavatmel 1:9c5af431a1f1 119 }
gustavatmel 1:9c5af431a1f1 120
gustavatmel 1:9c5af431a1f1 121 return true;
gustavatmel 1:9c5af431a1f1 122 }
gustavatmel 1:9c5af431a1f1 123
gustavatmel 1:9c5af431a1f1 124 /*
gustavatmel 1:9c5af431a1f1 125 * Return true of the connection parameters are acceptable as preferred connection
gustavatmel 1:9c5af431a1f1 126 * parameters.
gustavatmel 1:9c5af431a1f1 127 *
gustavatmel 1:9c5af431a1f1 128 * Prefered connection parameters unlike actual connection parameters allow the
gustavatmel 1:9c5af431a1f1 129 * max connection interval, min connection interval and connection supervision
gustavatmel 1:9c5af431a1f1 130 * timeout to be equal to 0xFFFF. When it is the case that value can be
gustavatmel 1:9c5af431a1f1 131 * interpreted as "non specific".
gustavatmel 1:9c5af431a1f1 132 */
gustavatmel 1:9c5af431a1f1 133 static bool is_preferred_connection_params_valid(const Gap::ConnectionParams_t* params)
gustavatmel 1:9c5af431a1f1 134 {
gustavatmel 1:9c5af431a1f1 135 if (params == NULL) {
gustavatmel 1:9c5af431a1f1 136 return false;
gustavatmel 1:9c5af431a1f1 137 }
gustavatmel 1:9c5af431a1f1 138
gustavatmel 1:9c5af431a1f1 139 if (is_in_range(params->slaveLatency, slave_latency_min, slave_latency_max) == false) {
gustavatmel 1:9c5af431a1f1 140 return false;
gustavatmel 1:9c5af431a1f1 141 }
gustavatmel 1:9c5af431a1f1 142
gustavatmel 1:9c5af431a1f1 143 if ((is_in_range(params->maxConnectionInterval, connection_interval_min, connection_interval_max) == false) &&
gustavatmel 1:9c5af431a1f1 144 (params->maxConnectionInterval != 0xFFFF)) {
gustavatmel 1:9c5af431a1f1 145 return false;
gustavatmel 1:9c5af431a1f1 146 }
gustavatmel 1:9c5af431a1f1 147
gustavatmel 1:9c5af431a1f1 148 if ((is_in_range(params->minConnectionInterval, connection_interval_min, params->maxConnectionInterval) == false) &&
gustavatmel 1:9c5af431a1f1 149 (params->minConnectionInterval != 0xFFFF)) {
gustavatmel 1:9c5af431a1f1 150 return false;
gustavatmel 1:9c5af431a1f1 151 }
gustavatmel 1:9c5af431a1f1 152
gustavatmel 1:9c5af431a1f1 153 if (params->connectionSupervisionTimeout == 0xFFFF) {
gustavatmel 1:9c5af431a1f1 154 return true;
gustavatmel 1:9c5af431a1f1 155 }
gustavatmel 1:9c5af431a1f1 156
gustavatmel 1:9c5af431a1f1 157 if ((is_in_range(params->connectionSupervisionTimeout, supervision_timeout_min, supervision_timeout_max) == false)) {
gustavatmel 1:9c5af431a1f1 158 return false;
gustavatmel 1:9c5af431a1f1 159 }
gustavatmel 1:9c5af431a1f1 160
gustavatmel 1:9c5af431a1f1 161 if (params->maxConnectionInterval == 0xFFFF) {
gustavatmel 1:9c5af431a1f1 162 return true;
gustavatmel 1:9c5af431a1f1 163 }
gustavatmel 1:9c5af431a1f1 164
gustavatmel 1:9c5af431a1f1 165 uint16_t max_connection_interval_ms =
gustavatmel 1:9c5af431a1f1 166 ((uint32_t)params->maxConnectionInterval * 125) / 100;
gustavatmel 1:9c5af431a1f1 167 uint16_t min_connection_supervision_timeout =
gustavatmel 1:9c5af431a1f1 168 ((1 + params->slaveLatency) * max_connection_interval_ms * 2) / 10;
gustavatmel 1:9c5af431a1f1 169
gustavatmel 1:9c5af431a1f1 170 if (params->connectionSupervisionTimeout < min_connection_supervision_timeout) {
gustavatmel 1:9c5af431a1f1 171 return false;
gustavatmel 1:9c5af431a1f1 172 }
gustavatmel 1:9c5af431a1f1 173
gustavatmel 1:9c5af431a1f1 174 return true;
gustavatmel 1:9c5af431a1f1 175 }
gustavatmel 1:9c5af431a1f1 176
gustavatmel 1:9c5af431a1f1 177 /**
gustavatmel 1:9c5af431a1f1 178 * Check if random bytes of an address are valid.
gustavatmel 1:9c5af431a1f1 179 */
gustavatmel 1:9c5af431a1f1 180 static bool is_prand_valid(const uint8_t* bytes, size_t len)
gustavatmel 1:9c5af431a1f1 181 {
gustavatmel 1:9c5af431a1f1 182 // at least one bit of the random part of the static address shall be
gustavatmel 1:9c5af431a1f1 183 // equal to 0 and at least one bit of the random part of the static
gustavatmel 1:9c5af431a1f1 184 // address shall be equal to 1
gustavatmel 1:9c5af431a1f1 185 for (size_t i = 0; i < (len - 1); ++i) {
gustavatmel 1:9c5af431a1f1 186 if ((bytes[i] != 0x00) && (bytes[i] != 0xFF)) {
gustavatmel 1:9c5af431a1f1 187 return true;
gustavatmel 1:9c5af431a1f1 188 }
gustavatmel 1:9c5af431a1f1 189
gustavatmel 1:9c5af431a1f1 190 if ((i > 0) && (bytes[i] != bytes[i - 1])) {
gustavatmel 1:9c5af431a1f1 191 return true;
gustavatmel 1:9c5af431a1f1 192 }
gustavatmel 1:9c5af431a1f1 193 }
gustavatmel 1:9c5af431a1f1 194
gustavatmel 1:9c5af431a1f1 195 if (((bytes[len - 1] & 0x3F) == 0x3F) && (bytes[len - 2] == 0xFF)) {
gustavatmel 1:9c5af431a1f1 196 return false;
gustavatmel 1:9c5af431a1f1 197 }
gustavatmel 1:9c5af431a1f1 198
gustavatmel 1:9c5af431a1f1 199 if (((bytes[len - 1] & 0x3F) == 0x00) && (bytes[len - 2] == 0x00)) {
gustavatmel 1:9c5af431a1f1 200 return false;
gustavatmel 1:9c5af431a1f1 201 }
gustavatmel 1:9c5af431a1f1 202
gustavatmel 1:9c5af431a1f1 203 return true;
gustavatmel 1:9c5af431a1f1 204 }
gustavatmel 1:9c5af431a1f1 205
gustavatmel 1:9c5af431a1f1 206 /*
gustavatmel 1:9c5af431a1f1 207 * Check if the random part of a random address with 48 random bytes are valid
gustavatmel 1:9c5af431a1f1 208 * or not.
gustavatmel 1:9c5af431a1f1 209 * Return true if it is the case and false otherwise.
gustavatmel 1:9c5af431a1f1 210 */
gustavatmel 1:9c5af431a1f1 211 static bool is_prand_48_bits_valid(const BLEProtocol::AddressBytes_t address)
gustavatmel 1:9c5af431a1f1 212 {
gustavatmel 1:9c5af431a1f1 213 return is_prand_valid(address, 6);
gustavatmel 1:9c5af431a1f1 214 }
gustavatmel 1:9c5af431a1f1 215
gustavatmel 1:9c5af431a1f1 216 /*
gustavatmel 1:9c5af431a1f1 217 * Check if the random part of a random address with 24 random bytes are valid
gustavatmel 1:9c5af431a1f1 218 * or not.
gustavatmel 1:9c5af431a1f1 219 * Return true if it is the case and false otherwise.
gustavatmel 1:9c5af431a1f1 220 */
gustavatmel 1:9c5af431a1f1 221 static bool is_prand_24_bits_valid(const BLEProtocol::AddressBytes_t address)
gustavatmel 1:9c5af431a1f1 222 {
gustavatmel 1:9c5af431a1f1 223 return is_prand_valid(address + 3, 3);
gustavatmel 1:9c5af431a1f1 224 }
gustavatmel 1:9c5af431a1f1 225
gustavatmel 1:9c5af431a1f1 226 /*
gustavatmel 1:9c5af431a1f1 227 * Return true if address is a random static address.
gustavatmel 1:9c5af431a1f1 228 */
gustavatmel 1:9c5af431a1f1 229 static bool is_random_static_address(const BLEProtocol::AddressBytes_t address)
gustavatmel 1:9c5af431a1f1 230 {
gustavatmel 1:9c5af431a1f1 231 // top two msb bits shall be equal to 1.
gustavatmel 1:9c5af431a1f1 232 if ((address[5] >> 6) != 0x03) {
gustavatmel 1:9c5af431a1f1 233 return false;
gustavatmel 1:9c5af431a1f1 234 }
gustavatmel 1:9c5af431a1f1 235
gustavatmel 1:9c5af431a1f1 236 return is_prand_48_bits_valid(address);
gustavatmel 1:9c5af431a1f1 237 }
gustavatmel 1:9c5af431a1f1 238
gustavatmel 1:9c5af431a1f1 239 /*
gustavatmel 1:9c5af431a1f1 240 * Return true if address is a random private non resolvable address.
gustavatmel 1:9c5af431a1f1 241 */
gustavatmel 1:9c5af431a1f1 242 static bool is_random_private_non_resolvable_address(
gustavatmel 1:9c5af431a1f1 243 const BLEProtocol::AddressBytes_t address
gustavatmel 1:9c5af431a1f1 244 ) {
gustavatmel 1:9c5af431a1f1 245 // top two msb bits shall be equal to 0.
gustavatmel 1:9c5af431a1f1 246 if ((address[5] >> 6) != 0x00) {
gustavatmel 1:9c5af431a1f1 247 return false;
gustavatmel 1:9c5af431a1f1 248 }
gustavatmel 1:9c5af431a1f1 249
gustavatmel 1:9c5af431a1f1 250 return is_prand_48_bits_valid(address);
gustavatmel 1:9c5af431a1f1 251 }
gustavatmel 1:9c5af431a1f1 252
gustavatmel 1:9c5af431a1f1 253 /*
gustavatmel 1:9c5af431a1f1 254 * Return true if address is a random private resolvable address.
gustavatmel 1:9c5af431a1f1 255 */
gustavatmel 1:9c5af431a1f1 256 static bool is_random_private_resolvable_address(
gustavatmel 1:9c5af431a1f1 257 const BLEProtocol::AddressBytes_t address
gustavatmel 1:9c5af431a1f1 258 ) {
gustavatmel 1:9c5af431a1f1 259 // top two msb bits shall be equal to 01.
gustavatmel 1:9c5af431a1f1 260 if ((address[5] >> 6) != 0x01) {
gustavatmel 1:9c5af431a1f1 261 return false;
gustavatmel 1:9c5af431a1f1 262 }
gustavatmel 1:9c5af431a1f1 263
gustavatmel 1:9c5af431a1f1 264 return is_prand_24_bits_valid(address);
gustavatmel 1:9c5af431a1f1 265 }
gustavatmel 1:9c5af431a1f1 266
gustavatmel 1:9c5af431a1f1 267 /*
gustavatmel 1:9c5af431a1f1 268 * Return true if the address is a random address.
gustavatmel 1:9c5af431a1f1 269 */
gustavatmel 1:9c5af431a1f1 270 static bool is_random_address(const BLEProtocol::AddressBytes_t address)
gustavatmel 1:9c5af431a1f1 271 {
gustavatmel 1:9c5af431a1f1 272 return is_random_private_resolvable_address(address) ||
gustavatmel 1:9c5af431a1f1 273 is_random_private_non_resolvable_address(address) ||
gustavatmel 1:9c5af431a1f1 274 is_random_static_address(address);
gustavatmel 1:9c5af431a1f1 275 }
gustavatmel 1:9c5af431a1f1 276
gustavatmel 1:9c5af431a1f1 277 /*
gustavatmel 1:9c5af431a1f1 278 * Check disconnection reason validity.
gustavatmel 1:9c5af431a1f1 279 */
gustavatmel 1:9c5af431a1f1 280 static bool is_disconnection_reason_valid(Gap::DisconnectionReason_t reason)
gustavatmel 1:9c5af431a1f1 281 {
gustavatmel 1:9c5af431a1f1 282 switch (reason) {
gustavatmel 1:9c5af431a1f1 283 /**
gustavatmel 1:9c5af431a1f1 284 * Note: accepted reasons are:
gustavatmel 1:9c5af431a1f1 285 typedef pal::disconnection_reason_t reason_t;
gustavatmel 1:9c5af431a1f1 286 case reason_t::AUTHENTICATION_FAILLURE:
gustavatmel 1:9c5af431a1f1 287 case reason_t::REMOTE_USER_TERMINATED_CONNECTION:
gustavatmel 1:9c5af431a1f1 288 case reason_t::REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_LOW_RESOURCES:
gustavatmel 1:9c5af431a1f1 289 case reason_t::REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_POWER_OFF:
gustavatmel 1:9c5af431a1f1 290 case reason_t::UNSUPPORTED_REMOTE_FEATURE:
gustavatmel 1:9c5af431a1f1 291 case reason_t::PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED:
gustavatmel 1:9c5af431a1f1 292 case reason_t::UNACCEPTABLE_CONNECTION_PARAMETERS:
gustavatmel 1:9c5af431a1f1 293 */
gustavatmel 1:9c5af431a1f1 294
gustavatmel 1:9c5af431a1f1 295 // TODO Fix Disconnectionreason_t which expose invalid value
gustavatmel 1:9c5af431a1f1 296 case Gap::REMOTE_USER_TERMINATED_CONNECTION:
gustavatmel 1:9c5af431a1f1 297 case Gap::REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES:
gustavatmel 1:9c5af431a1f1 298 case Gap::REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF:
gustavatmel 1:9c5af431a1f1 299 case Gap::CONN_INTERVAL_UNACCEPTABLE:
gustavatmel 1:9c5af431a1f1 300 return true;
gustavatmel 1:9c5af431a1f1 301 default:
gustavatmel 1:9c5af431a1f1 302 return false;
gustavatmel 1:9c5af431a1f1 303 }
gustavatmel 1:9c5af431a1f1 304 }
gustavatmel 1:9c5af431a1f1 305
gustavatmel 1:9c5af431a1f1 306 /*
gustavatmel 1:9c5af431a1f1 307 * Return true if the whitelist in input is valid or false otherwise.
gustavatmel 1:9c5af431a1f1 308 */
gustavatmel 1:9c5af431a1f1 309 static bool is_whitelist_valid(const Gap::Whitelist_t& whitelist)
gustavatmel 1:9c5af431a1f1 310 {
gustavatmel 1:9c5af431a1f1 311 if (whitelist.size > whitelist.capacity) {
gustavatmel 1:9c5af431a1f1 312 return false;
gustavatmel 1:9c5af431a1f1 313 }
gustavatmel 1:9c5af431a1f1 314
gustavatmel 1:9c5af431a1f1 315 for (size_t i = 0; i < whitelist.size; ++i) {
gustavatmel 1:9c5af431a1f1 316 const BLEProtocol::Address_t& address = whitelist.addresses[i];
gustavatmel 1:9c5af431a1f1 317 if (address.type > BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE) {
gustavatmel 1:9c5af431a1f1 318 return false;
gustavatmel 1:9c5af431a1f1 319 }
gustavatmel 1:9c5af431a1f1 320
gustavatmel 1:9c5af431a1f1 321 if (address.type != BLEProtocol::AddressType::PUBLIC) {
gustavatmel 1:9c5af431a1f1 322 if (is_random_address(address.address) == false) {
gustavatmel 1:9c5af431a1f1 323 return false;
gustavatmel 1:9c5af431a1f1 324 }
gustavatmel 1:9c5af431a1f1 325 }
gustavatmel 1:9c5af431a1f1 326 }
gustavatmel 1:9c5af431a1f1 327 return true;
gustavatmel 1:9c5af431a1f1 328 }
gustavatmel 1:9c5af431a1f1 329
gustavatmel 1:9c5af431a1f1 330 /*
gustavatmel 1:9c5af431a1f1 331 * Return true if device is present in the whitelist.
gustavatmel 1:9c5af431a1f1 332 */
gustavatmel 1:9c5af431a1f1 333 static bool is_in_whitelist(
gustavatmel 1:9c5af431a1f1 334 const BLEProtocol::Address_t& device, const Gap::Whitelist_t& whitelist
gustavatmel 1:9c5af431a1f1 335 ) {
gustavatmel 1:9c5af431a1f1 336 for (size_t i = 0; i < whitelist.size; ++i) {
gustavatmel 1:9c5af431a1f1 337 const BLEProtocol::Address_t& potential_device = whitelist.addresses[i];
gustavatmel 1:9c5af431a1f1 338
gustavatmel 1:9c5af431a1f1 339 if (potential_device.type != device.type) {
gustavatmel 1:9c5af431a1f1 340 continue;
gustavatmel 1:9c5af431a1f1 341 }
gustavatmel 1:9c5af431a1f1 342
gustavatmel 1:9c5af431a1f1 343 if (memcmp(potential_device.address, device.address, sizeof(device.address)) == 0) {
gustavatmel 1:9c5af431a1f1 344 return true;
gustavatmel 1:9c5af431a1f1 345 }
gustavatmel 1:9c5af431a1f1 346 }
gustavatmel 1:9c5af431a1f1 347 return false;
gustavatmel 1:9c5af431a1f1 348 }
gustavatmel 1:9c5af431a1f1 349
gustavatmel 1:9c5af431a1f1 350 /*
gustavatmel 1:9c5af431a1f1 351 * Convert a BLEProtocol::AddressType_t into a pal::whitelist_address_type_t.
gustavatmel 1:9c5af431a1f1 352 */
gustavatmel 1:9c5af431a1f1 353 static pal::whitelist_address_type_t to_device_address_type(
gustavatmel 1:9c5af431a1f1 354 BLEProtocol::AddressType_t address_type
gustavatmel 1:9c5af431a1f1 355 ) {
gustavatmel 1:9c5af431a1f1 356 return (address_type == BLEProtocol::AddressType::PUBLIC) ?
gustavatmel 1:9c5af431a1f1 357 pal::whitelist_address_type_t::PUBLIC_DEVICE_ADDRESS :
gustavatmel 1:9c5af431a1f1 358 pal::whitelist_address_type_t::RANDOM_DEVICE_ADDRESS;
gustavatmel 1:9c5af431a1f1 359 }
gustavatmel 1:9c5af431a1f1 360
gustavatmel 1:9c5af431a1f1 361 /*
gustavatmel 1:9c5af431a1f1 362 * Return true if the advertising parameters are valid.
gustavatmel 1:9c5af431a1f1 363 */
gustavatmel 1:9c5af431a1f1 364 static bool is_advertising_params_valid(const GapAdvertisingParams& params)
gustavatmel 1:9c5af431a1f1 365 {
gustavatmel 1:9c5af431a1f1 366 if (is_in_range(params.getIntervalInADVUnits(), advertising_interval_min, advertising_interval_max) == false) {
gustavatmel 1:9c5af431a1f1 367 return false;
gustavatmel 1:9c5af431a1f1 368 }
gustavatmel 1:9c5af431a1f1 369
gustavatmel 1:9c5af431a1f1 370 if (params.getAdvertisingType() > GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED) {
gustavatmel 1:9c5af431a1f1 371 return false;
gustavatmel 1:9c5af431a1f1 372 }
gustavatmel 1:9c5af431a1f1 373
gustavatmel 1:9c5af431a1f1 374 return true;
gustavatmel 1:9c5af431a1f1 375 }
gustavatmel 1:9c5af431a1f1 376
gustavatmel 1:9c5af431a1f1 377 } // end of anonymous namespace
gustavatmel 1:9c5af431a1f1 378
gustavatmel 1:9c5af431a1f1 379 GenericGap::GenericGap(
gustavatmel 1:9c5af431a1f1 380 pal::EventQueue& event_queue,
gustavatmel 1:9c5af431a1f1 381 pal::Gap& pal_gap,
gustavatmel 1:9c5af431a1f1 382 pal::GenericAccessService& generic_access_service
gustavatmel 1:9c5af431a1f1 383 ) : _event_queue(event_queue),
gustavatmel 1:9c5af431a1f1 384 _pal_gap(pal_gap),
gustavatmel 1:9c5af431a1f1 385 _gap_service(generic_access_service),
gustavatmel 1:9c5af431a1f1 386 _address_type(BLEProtocol::AddressType::PUBLIC),
gustavatmel 1:9c5af431a1f1 387 _initiator_policy_mode(pal::initiator_policy_t::NO_FILTER),
gustavatmel 1:9c5af431a1f1 388 _scanning_filter_policy(pal::scanning_filter_policy_t::NO_FILTER),
gustavatmel 1:9c5af431a1f1 389 _advertising_filter_policy(pal::advertising_filter_policy_t::NO_FILTER),
gustavatmel 1:9c5af431a1f1 390 _whitelist(),
gustavatmel 1:9c5af431a1f1 391 _advertising_timeout(),
gustavatmel 1:9c5af431a1f1 392 _scan_timeout(),
gustavatmel 1:9c5af431a1f1 393 _connection_event_handler(NULL)
gustavatmel 1:9c5af431a1f1 394 {
gustavatmel 1:9c5af431a1f1 395 _pal_gap.when_gap_event_received(
gustavatmel 1:9c5af431a1f1 396 mbed::callback(this, &GenericGap::on_gap_event_received)
gustavatmel 1:9c5af431a1f1 397 );
gustavatmel 1:9c5af431a1f1 398 }
gustavatmel 1:9c5af431a1f1 399
gustavatmel 1:9c5af431a1f1 400 GenericGap::~GenericGap()
gustavatmel 1:9c5af431a1f1 401 {
gustavatmel 1:9c5af431a1f1 402 }
gustavatmel 1:9c5af431a1f1 403
gustavatmel 1:9c5af431a1f1 404 ble_error_t GenericGap::setAddress(
gustavatmel 1:9c5af431a1f1 405 BLEProtocol::AddressType_t type,
gustavatmel 1:9c5af431a1f1 406 const BLEProtocol::AddressBytes_t address
gustavatmel 1:9c5af431a1f1 407 ) {
gustavatmel 1:9c5af431a1f1 408 switch (type) {
gustavatmel 1:9c5af431a1f1 409 case BLEProtocol::AddressType::PUBLIC:
gustavatmel 1:9c5af431a1f1 410 // The public address cannot be set, just set the type to public
gustavatmel 1:9c5af431a1f1 411 _address_type = type;
gustavatmel 1:9c5af431a1f1 412 return BLE_ERROR_NONE;
gustavatmel 1:9c5af431a1f1 413
gustavatmel 1:9c5af431a1f1 414 case BLEProtocol::AddressType::RANDOM_STATIC: {
gustavatmel 1:9c5af431a1f1 415 if (is_random_static_address(address) == false) {
gustavatmel 1:9c5af431a1f1 416 return BLE_ERROR_INVALID_PARAM;
gustavatmel 1:9c5af431a1f1 417 }
gustavatmel 1:9c5af431a1f1 418
gustavatmel 1:9c5af431a1f1 419 ble_error_t err = _pal_gap.set_random_address(
gustavatmel 1:9c5af431a1f1 420 ble::address_t(address)
gustavatmel 1:9c5af431a1f1 421 );
gustavatmel 1:9c5af431a1f1 422 if (err) {
gustavatmel 1:9c5af431a1f1 423 return err;
gustavatmel 1:9c5af431a1f1 424 }
gustavatmel 1:9c5af431a1f1 425
gustavatmel 1:9c5af431a1f1 426 _address_type = type;
gustavatmel 1:9c5af431a1f1 427 _address = ble::address_t(address);
gustavatmel 1:9c5af431a1f1 428 return BLE_ERROR_NONE;
gustavatmel 1:9c5af431a1f1 429 }
gustavatmel 1:9c5af431a1f1 430
gustavatmel 1:9c5af431a1f1 431 case BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE:
gustavatmel 1:9c5af431a1f1 432 // TODO: Fix with the privacy/security rework
gustavatmel 1:9c5af431a1f1 433 return BLE_ERROR_NOT_IMPLEMENTED;
gustavatmel 1:9c5af431a1f1 434
gustavatmel 1:9c5af431a1f1 435 case BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE:
gustavatmel 1:9c5af431a1f1 436 // TODO: add process to set the random private non resolvable
gustavatmel 1:9c5af431a1f1 437 // address (privacy/security work)
gustavatmel 1:9c5af431a1f1 438 return BLE_ERROR_NOT_IMPLEMENTED;
gustavatmel 1:9c5af431a1f1 439
gustavatmel 1:9c5af431a1f1 440 default:
gustavatmel 1:9c5af431a1f1 441 return BLE_ERROR_PARAM_OUT_OF_RANGE;
gustavatmel 1:9c5af431a1f1 442 }
gustavatmel 1:9c5af431a1f1 443 }
gustavatmel 1:9c5af431a1f1 444
gustavatmel 1:9c5af431a1f1 445 ble_error_t GenericGap::getAddress(
gustavatmel 1:9c5af431a1f1 446 BLEProtocol::AddressType_t *type,
gustavatmel 1:9c5af431a1f1 447 BLEProtocol::AddressBytes_t address
gustavatmel 1:9c5af431a1f1 448 ) {
gustavatmel 1:9c5af431a1f1 449 *type = _address_type;
gustavatmel 1:9c5af431a1f1 450 ble::address_t address_value;
gustavatmel 1:9c5af431a1f1 451 if (_address_type == BLEProtocol::AddressType::PUBLIC) {
gustavatmel 1:9c5af431a1f1 452 address_value = _pal_gap.get_device_address();
gustavatmel 1:9c5af431a1f1 453 } else {
gustavatmel 1:9c5af431a1f1 454 address_value = _pal_gap.get_random_address();
gustavatmel 1:9c5af431a1f1 455 }
gustavatmel 1:9c5af431a1f1 456
gustavatmel 1:9c5af431a1f1 457 memcpy(address, address_value.data(), address_value.size());
gustavatmel 1:9c5af431a1f1 458 return BLE_ERROR_NONE;
gustavatmel 1:9c5af431a1f1 459 }
gustavatmel 1:9c5af431a1f1 460
gustavatmel 1:9c5af431a1f1 461 uint16_t GenericGap::getMinAdvertisingInterval() const
gustavatmel 1:9c5af431a1f1 462 {
gustavatmel 1:9c5af431a1f1 463 return GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN;
gustavatmel 1:9c5af431a1f1 464 }
gustavatmel 1:9c5af431a1f1 465
gustavatmel 1:9c5af431a1f1 466 uint16_t GenericGap::getMinNonConnectableAdvertisingInterval() const
gustavatmel 1:9c5af431a1f1 467 {
gustavatmel 1:9c5af431a1f1 468 return GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON;
gustavatmel 1:9c5af431a1f1 469 }
gustavatmel 1:9c5af431a1f1 470
gustavatmel 1:9c5af431a1f1 471 uint16_t GenericGap::getMaxAdvertisingInterval() const
gustavatmel 1:9c5af431a1f1 472 {
gustavatmel 1:9c5af431a1f1 473 return GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX;
gustavatmel 1:9c5af431a1f1 474 }
gustavatmel 1:9c5af431a1f1 475
gustavatmel 1:9c5af431a1f1 476 ble_error_t GenericGap::stopAdvertising()
gustavatmel 1:9c5af431a1f1 477 {
gustavatmel 1:9c5af431a1f1 478 ble_error_t err = _pal_gap.advertising_enable(false);
gustavatmel 1:9c5af431a1f1 479 if (err) {
gustavatmel 1:9c5af431a1f1 480 return err;
gustavatmel 1:9c5af431a1f1 481 }
gustavatmel 1:9c5af431a1f1 482 _advertising_timeout.detach();
gustavatmel 1:9c5af431a1f1 483 state.advertising = false;
gustavatmel 1:9c5af431a1f1 484 return BLE_ERROR_NONE;
gustavatmel 1:9c5af431a1f1 485 }
gustavatmel 1:9c5af431a1f1 486
gustavatmel 1:9c5af431a1f1 487 ble_error_t GenericGap::stopScan()
gustavatmel 1:9c5af431a1f1 488 {
gustavatmel 1:9c5af431a1f1 489 ble_error_t err = _pal_gap.scan_enable(false, false);
gustavatmel 1:9c5af431a1f1 490 if (err) {
gustavatmel 1:9c5af431a1f1 491 return err;
gustavatmel 1:9c5af431a1f1 492 }
gustavatmel 1:9c5af431a1f1 493
gustavatmel 1:9c5af431a1f1 494 _scan_timeout.detach();
gustavatmel 1:9c5af431a1f1 495 return BLE_ERROR_NONE;
gustavatmel 1:9c5af431a1f1 496 }
gustavatmel 1:9c5af431a1f1 497
gustavatmel 1:9c5af431a1f1 498 ble_error_t GenericGap::connect(
gustavatmel 1:9c5af431a1f1 499 const BLEProtocol::AddressBytes_t peerAddr,
gustavatmel 1:9c5af431a1f1 500 BLEProtocol::AddressType_t peerAddrType,
gustavatmel 1:9c5af431a1f1 501 const ConnectionParams_t* connectionParams,
gustavatmel 1:9c5af431a1f1 502 const GapScanningParams* scanParams
gustavatmel 1:9c5af431a1f1 503 ) {
gustavatmel 1:9c5af431a1f1 504 if (connectionParams == NULL) {
gustavatmel 1:9c5af431a1f1 505 connectionParams = &default_connection_params;
gustavatmel 1:9c5af431a1f1 506 }
gustavatmel 1:9c5af431a1f1 507
gustavatmel 1:9c5af431a1f1 508 if (scanParams == NULL) {
gustavatmel 1:9c5af431a1f1 509 scanParams = &default_scan_params;
gustavatmel 1:9c5af431a1f1 510 }
gustavatmel 1:9c5af431a1f1 511
gustavatmel 1:9c5af431a1f1 512 if (is_scan_params_valid(scanParams) == false) {
gustavatmel 1:9c5af431a1f1 513 return BLE_ERROR_PARAM_OUT_OF_RANGE;
gustavatmel 1:9c5af431a1f1 514 }
gustavatmel 1:9c5af431a1f1 515
gustavatmel 1:9c5af431a1f1 516 if (is_connection_params_valid(connectionParams) == false) {
gustavatmel 1:9c5af431a1f1 517 return BLE_ERROR_PARAM_OUT_OF_RANGE;
gustavatmel 1:9c5af431a1f1 518 }
gustavatmel 1:9c5af431a1f1 519
gustavatmel 1:9c5af431a1f1 520 // TODO fix upper layer API, address type factorization is incorrect.
gustavatmel 1:9c5af431a1f1 521
gustavatmel 1:9c5af431a1f1 522 // Force scan stop before initiating the scan used for connection
gustavatmel 1:9c5af431a1f1 523 stopScan();
gustavatmel 1:9c5af431a1f1 524
gustavatmel 1:9c5af431a1f1 525 return _pal_gap.create_connection(
gustavatmel 1:9c5af431a1f1 526 scanParams->getInterval(),
gustavatmel 1:9c5af431a1f1 527 scanParams->getWindow(),
gustavatmel 1:9c5af431a1f1 528 _initiator_policy_mode,
gustavatmel 1:9c5af431a1f1 529 (pal::connection_peer_address_type_t::type) peerAddrType,
gustavatmel 1:9c5af431a1f1 530 ble::address_t(peerAddr),
gustavatmel 1:9c5af431a1f1 531 (pal::own_address_type_t::type) _address_type,
gustavatmel 1:9c5af431a1f1 532 connectionParams->minConnectionInterval,
gustavatmel 1:9c5af431a1f1 533 connectionParams->maxConnectionInterval,
gustavatmel 1:9c5af431a1f1 534 connectionParams->slaveLatency,
gustavatmel 1:9c5af431a1f1 535 connectionParams->connectionSupervisionTimeout,
gustavatmel 1:9c5af431a1f1 536 /* minimum_connection_event_length */ 0,
gustavatmel 1:9c5af431a1f1 537 /* maximum_connection_event_length */ 0
gustavatmel 1:9c5af431a1f1 538 );
gustavatmel 1:9c5af431a1f1 539 }
gustavatmel 1:9c5af431a1f1 540
gustavatmel 1:9c5af431a1f1 541 ble_error_t GenericGap::disconnect(Handle_t connectionHandle, DisconnectionReason_t reason)
gustavatmel 1:9c5af431a1f1 542 {
gustavatmel 1:9c5af431a1f1 543 if (is_disconnection_reason_valid(reason) == false) {
gustavatmel 1:9c5af431a1f1 544 return BLE_ERROR_INVALID_PARAM;
gustavatmel 1:9c5af431a1f1 545 }
gustavatmel 1:9c5af431a1f1 546 return _pal_gap.disconnect(
gustavatmel 1:9c5af431a1f1 547 connectionHandle,
gustavatmel 1:9c5af431a1f1 548 (pal::disconnection_reason_t::type) reason
gustavatmel 1:9c5af431a1f1 549 );
gustavatmel 1:9c5af431a1f1 550 }
gustavatmel 1:9c5af431a1f1 551
gustavatmel 1:9c5af431a1f1 552 ble_error_t GenericGap::updateConnectionParams(Handle_t handle, const ConnectionParams_t *params)
gustavatmel 1:9c5af431a1f1 553 {
gustavatmel 1:9c5af431a1f1 554 if (is_connection_params_valid(params) == false) {
gustavatmel 1:9c5af431a1f1 555 return BLE_ERROR_PARAM_OUT_OF_RANGE;
gustavatmel 1:9c5af431a1f1 556 }
gustavatmel 1:9c5af431a1f1 557
gustavatmel 1:9c5af431a1f1 558 return _pal_gap.connection_parameters_update(
gustavatmel 1:9c5af431a1f1 559 handle,
gustavatmel 1:9c5af431a1f1 560 params->minConnectionInterval,
gustavatmel 1:9c5af431a1f1 561 params->maxConnectionInterval,
gustavatmel 1:9c5af431a1f1 562 params->slaveLatency,
gustavatmel 1:9c5af431a1f1 563 params->connectionSupervisionTimeout,
gustavatmel 1:9c5af431a1f1 564 /* minimum_connection_event_length */ 0,
gustavatmel 1:9c5af431a1f1 565 /* maximum_connection_event_length */ 0
gustavatmel 1:9c5af431a1f1 566 );
gustavatmel 1:9c5af431a1f1 567 }
gustavatmel 1:9c5af431a1f1 568
gustavatmel 1:9c5af431a1f1 569 ble_error_t GenericGap::getPreferredConnectionParams(ConnectionParams_t *params)
gustavatmel 1:9c5af431a1f1 570 {
gustavatmel 1:9c5af431a1f1 571 if (params == NULL) {
gustavatmel 1:9c5af431a1f1 572 return BLE_ERROR_INVALID_PARAM;
gustavatmel 1:9c5af431a1f1 573 }
gustavatmel 1:9c5af431a1f1 574
gustavatmel 1:9c5af431a1f1 575 return _gap_service.get_peripheral_prefered_connection_parameters(
gustavatmel 1:9c5af431a1f1 576 *params
gustavatmel 1:9c5af431a1f1 577 );
gustavatmel 1:9c5af431a1f1 578 }
gustavatmel 1:9c5af431a1f1 579
gustavatmel 1:9c5af431a1f1 580 ble_error_t GenericGap::setPreferredConnectionParams(const ConnectionParams_t *params)
gustavatmel 1:9c5af431a1f1 581 {
gustavatmel 1:9c5af431a1f1 582 if(is_preferred_connection_params_valid(params) == false) {
gustavatmel 1:9c5af431a1f1 583 return BLE_ERROR_PARAM_OUT_OF_RANGE;
gustavatmel 1:9c5af431a1f1 584 }
gustavatmel 1:9c5af431a1f1 585
gustavatmel 1:9c5af431a1f1 586 return _gap_service.set_peripheral_prefered_connection_parameters(
gustavatmel 1:9c5af431a1f1 587 *params
gustavatmel 1:9c5af431a1f1 588 );
gustavatmel 1:9c5af431a1f1 589 }
gustavatmel 1:9c5af431a1f1 590
gustavatmel 1:9c5af431a1f1 591 ble_error_t GenericGap::setDeviceName(const uint8_t *deviceName)
gustavatmel 1:9c5af431a1f1 592 {
gustavatmel 1:9c5af431a1f1 593 return _gap_service.set_device_name(deviceName);
gustavatmel 1:9c5af431a1f1 594 }
gustavatmel 1:9c5af431a1f1 595
gustavatmel 1:9c5af431a1f1 596 ble_error_t GenericGap::getDeviceName(uint8_t *deviceName, unsigned *lengthP)
gustavatmel 1:9c5af431a1f1 597 {
gustavatmel 1:9c5af431a1f1 598 if (lengthP == NULL) {
gustavatmel 1:9c5af431a1f1 599 return BLE_ERROR_INVALID_PARAM;
gustavatmel 1:9c5af431a1f1 600 }
gustavatmel 1:9c5af431a1f1 601
gustavatmel 1:9c5af431a1f1 602 uint8_t length = 0;
gustavatmel 1:9c5af431a1f1 603 ble_error_t err = _gap_service.get_device_name_length(length);
gustavatmel 1:9c5af431a1f1 604 if (err) {
gustavatmel 1:9c5af431a1f1 605 return err;
gustavatmel 1:9c5af431a1f1 606 }
gustavatmel 1:9c5af431a1f1 607
gustavatmel 1:9c5af431a1f1 608 if (deviceName != NULL) {
gustavatmel 1:9c5af431a1f1 609 if (*lengthP < length) {
gustavatmel 1:9c5af431a1f1 610 return BLE_ERROR_INVALID_PARAM;
gustavatmel 1:9c5af431a1f1 611 }
gustavatmel 1:9c5af431a1f1 612
gustavatmel 1:9c5af431a1f1 613 ArrayView<uint8_t> name(deviceName, *lengthP);
gustavatmel 1:9c5af431a1f1 614 err = _gap_service.get_device_name(name);
gustavatmel 1:9c5af431a1f1 615 if (err) {
gustavatmel 1:9c5af431a1f1 616 return err;
gustavatmel 1:9c5af431a1f1 617 }
gustavatmel 1:9c5af431a1f1 618 }
gustavatmel 1:9c5af431a1f1 619 *lengthP = length;
gustavatmel 1:9c5af431a1f1 620 return BLE_ERROR_NONE;
gustavatmel 1:9c5af431a1f1 621 }
gustavatmel 1:9c5af431a1f1 622
gustavatmel 1:9c5af431a1f1 623 ble_error_t GenericGap::setAppearance(GapAdvertisingData::Appearance appearance)
gustavatmel 1:9c5af431a1f1 624 {
gustavatmel 1:9c5af431a1f1 625 return _gap_service.set_appearance(appearance);
gustavatmel 1:9c5af431a1f1 626 }
gustavatmel 1:9c5af431a1f1 627
gustavatmel 1:9c5af431a1f1 628 ble_error_t GenericGap::getAppearance(GapAdvertisingData::Appearance *appearanceP)
gustavatmel 1:9c5af431a1f1 629 {
gustavatmel 1:9c5af431a1f1 630 if (appearanceP == NULL) {
gustavatmel 1:9c5af431a1f1 631 return BLE_ERROR_INVALID_PARAM;
gustavatmel 1:9c5af431a1f1 632 }
gustavatmel 1:9c5af431a1f1 633 return _gap_service.get_appearance(*appearanceP);
gustavatmel 1:9c5af431a1f1 634 }
gustavatmel 1:9c5af431a1f1 635
gustavatmel 1:9c5af431a1f1 636 ble_error_t GenericGap::setTxPower(int8_t txPower)
gustavatmel 1:9c5af431a1f1 637 {
gustavatmel 1:9c5af431a1f1 638 // TODO: This is not standard, expose it as an extension API and document it
gustavatmel 1:9c5af431a1f1 639 // as such
gustavatmel 1:9c5af431a1f1 640 return BLE_ERROR_NOT_IMPLEMENTED;
gustavatmel 1:9c5af431a1f1 641 }
gustavatmel 1:9c5af431a1f1 642
gustavatmel 1:9c5af431a1f1 643 void GenericGap::getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP)
gustavatmel 1:9c5af431a1f1 644 {
gustavatmel 1:9c5af431a1f1 645 *countP = 0;
gustavatmel 1:9c5af431a1f1 646 }
gustavatmel 1:9c5af431a1f1 647
gustavatmel 1:9c5af431a1f1 648 uint8_t GenericGap::getMaxWhitelistSize(void) const
gustavatmel 1:9c5af431a1f1 649 {
gustavatmel 1:9c5af431a1f1 650 return _pal_gap.read_white_list_capacity();
gustavatmel 1:9c5af431a1f1 651 }
gustavatmel 1:9c5af431a1f1 652
gustavatmel 1:9c5af431a1f1 653 ble_error_t GenericGap::getWhitelist(Whitelist_t &whitelist) const
gustavatmel 1:9c5af431a1f1 654 {
gustavatmel 1:9c5af431a1f1 655 if(initialize_whitelist() == false) {
gustavatmel 1:9c5af431a1f1 656 return BLE_ERROR_INVALID_STATE;
gustavatmel 1:9c5af431a1f1 657 }
gustavatmel 1:9c5af431a1f1 658
gustavatmel 1:9c5af431a1f1 659 if (whitelist.capacity < _whitelist.capacity) {
gustavatmel 1:9c5af431a1f1 660 return BLE_ERROR_INVALID_PARAM;
gustavatmel 1:9c5af431a1f1 661 }
gustavatmel 1:9c5af431a1f1 662
gustavatmel 1:9c5af431a1f1 663 for (size_t i = 0; i < _whitelist.size; ++i) {
gustavatmel 1:9c5af431a1f1 664 whitelist.addresses[i] = _whitelist.addresses[i];
gustavatmel 1:9c5af431a1f1 665 }
gustavatmel 1:9c5af431a1f1 666
gustavatmel 1:9c5af431a1f1 667 whitelist.capacity = _whitelist.capacity;
gustavatmel 1:9c5af431a1f1 668 return BLE_ERROR_NONE;
gustavatmel 1:9c5af431a1f1 669 }
gustavatmel 1:9c5af431a1f1 670
gustavatmel 1:9c5af431a1f1 671 ble_error_t GenericGap::setWhitelist(const Whitelist_t &whitelist)
gustavatmel 1:9c5af431a1f1 672 {
gustavatmel 1:9c5af431a1f1 673 if (is_whitelist_valid(whitelist) == false) {
gustavatmel 1:9c5af431a1f1 674 return BLE_ERROR_INVALID_PARAM;
gustavatmel 1:9c5af431a1f1 675 }
gustavatmel 1:9c5af431a1f1 676
gustavatmel 1:9c5af431a1f1 677 if(initialize_whitelist() == false) {
gustavatmel 1:9c5af431a1f1 678 return BLE_ERROR_INVALID_STATE;
gustavatmel 1:9c5af431a1f1 679 }
gustavatmel 1:9c5af431a1f1 680
gustavatmel 1:9c5af431a1f1 681 if (whitelist.capacity > _whitelist.capacity) {
gustavatmel 1:9c5af431a1f1 682 return BLE_ERROR_INVALID_PARAM;
gustavatmel 1:9c5af431a1f1 683 }
gustavatmel 1:9c5af431a1f1 684
gustavatmel 1:9c5af431a1f1 685 // first evict devices not in the existing whitelist
gustavatmel 1:9c5af431a1f1 686 for (size_t i = 0; i < _whitelist.size; ++i) {
gustavatmel 1:9c5af431a1f1 687 const BLEProtocol::Address_t& device = _whitelist.addresses[i];
gustavatmel 1:9c5af431a1f1 688
gustavatmel 1:9c5af431a1f1 689 if (is_in_whitelist(device, whitelist) == false) {
gustavatmel 1:9c5af431a1f1 690 ble_error_t err = _pal_gap.remove_device_from_whitelist(
gustavatmel 1:9c5af431a1f1 691 to_device_address_type(device.type),
gustavatmel 1:9c5af431a1f1 692 device.address
gustavatmel 1:9c5af431a1f1 693 );
gustavatmel 1:9c5af431a1f1 694
gustavatmel 1:9c5af431a1f1 695 // try to restore the whitelist to its initial state
gustavatmel 1:9c5af431a1f1 696 if (err) {
gustavatmel 1:9c5af431a1f1 697 for (size_t j = 0; j < i; ++j) {
gustavatmel 1:9c5af431a1f1 698 const BLEProtocol::Address_t& device = _whitelist.addresses[j];
gustavatmel 1:9c5af431a1f1 699
gustavatmel 1:9c5af431a1f1 700 if (is_in_whitelist(device, whitelist) == false) {
gustavatmel 1:9c5af431a1f1 701 _pal_gap.add_device_to_whitelist(
gustavatmel 1:9c5af431a1f1 702 to_device_address_type(device.type),
gustavatmel 1:9c5af431a1f1 703 device.address
gustavatmel 1:9c5af431a1f1 704 );
gustavatmel 1:9c5af431a1f1 705 }
gustavatmel 1:9c5af431a1f1 706 }
gustavatmel 1:9c5af431a1f1 707 return err;
gustavatmel 1:9c5af431a1f1 708 }
gustavatmel 1:9c5af431a1f1 709 }
gustavatmel 1:9c5af431a1f1 710 }
gustavatmel 1:9c5af431a1f1 711
gustavatmel 1:9c5af431a1f1 712 // second add devices which were not in the initial whitelist
gustavatmel 1:9c5af431a1f1 713 for (size_t i = 0; i < whitelist.size; ++i) {
gustavatmel 1:9c5af431a1f1 714 const BLEProtocol::Address_t& device = whitelist.addresses[i];
gustavatmel 1:9c5af431a1f1 715
gustavatmel 1:9c5af431a1f1 716 if (is_in_whitelist(device, _whitelist) == false) {
gustavatmel 1:9c5af431a1f1 717 ble_error_t err = _pal_gap.add_device_to_whitelist(
gustavatmel 1:9c5af431a1f1 718 to_device_address_type(device.type),
gustavatmel 1:9c5af431a1f1 719 device.address
gustavatmel 1:9c5af431a1f1 720 );
gustavatmel 1:9c5af431a1f1 721
gustavatmel 1:9c5af431a1f1 722 // try to restore the whitelist to its initial state
gustavatmel 1:9c5af431a1f1 723 if (err) {
gustavatmel 1:9c5af431a1f1 724 // first remove the devices added
gustavatmel 1:9c5af431a1f1 725 for (size_t j = 0; j < i; ++j) {
gustavatmel 1:9c5af431a1f1 726 const BLEProtocol::Address_t& device = whitelist.addresses[j];
gustavatmel 1:9c5af431a1f1 727
gustavatmel 1:9c5af431a1f1 728 if (is_in_whitelist(device, _whitelist) == false) {
gustavatmel 1:9c5af431a1f1 729 _pal_gap.remove_device_from_whitelist(
gustavatmel 1:9c5af431a1f1 730 to_device_address_type(device.type),
gustavatmel 1:9c5af431a1f1 731 device.address
gustavatmel 1:9c5af431a1f1 732 );
gustavatmel 1:9c5af431a1f1 733 }
gustavatmel 1:9c5af431a1f1 734 }
gustavatmel 1:9c5af431a1f1 735
gustavatmel 1:9c5af431a1f1 736 // second add the devices of the initial list evicted
gustavatmel 1:9c5af431a1f1 737 for (size_t i = 0; i < _whitelist.size; ++i) {
gustavatmel 1:9c5af431a1f1 738 const BLEProtocol::Address_t& device = _whitelist.addresses[i];
gustavatmel 1:9c5af431a1f1 739
gustavatmel 1:9c5af431a1f1 740 if (is_in_whitelist(device, whitelist) == false) {
gustavatmel 1:9c5af431a1f1 741 _pal_gap.add_device_to_whitelist(
gustavatmel 1:9c5af431a1f1 742 to_device_address_type(device.type),
gustavatmel 1:9c5af431a1f1 743 device.address
gustavatmel 1:9c5af431a1f1 744 );
gustavatmel 1:9c5af431a1f1 745 }
gustavatmel 1:9c5af431a1f1 746 }
gustavatmel 1:9c5af431a1f1 747
gustavatmel 1:9c5af431a1f1 748 return err;
gustavatmel 1:9c5af431a1f1 749 }
gustavatmel 1:9c5af431a1f1 750 }
gustavatmel 1:9c5af431a1f1 751 }
gustavatmel 1:9c5af431a1f1 752
gustavatmel 1:9c5af431a1f1 753 // commit the devices into the whitelist
gustavatmel 1:9c5af431a1f1 754 for (size_t i = 0; i < whitelist.size; ++i) {
gustavatmel 1:9c5af431a1f1 755 _whitelist.addresses[i] = whitelist.addresses[i];
gustavatmel 1:9c5af431a1f1 756 }
gustavatmel 1:9c5af431a1f1 757
gustavatmel 1:9c5af431a1f1 758 _whitelist.size = whitelist.size;
gustavatmel 1:9c5af431a1f1 759
gustavatmel 1:9c5af431a1f1 760 return BLE_ERROR_NONE;
gustavatmel 1:9c5af431a1f1 761 }
gustavatmel 1:9c5af431a1f1 762
gustavatmel 1:9c5af431a1f1 763 ble_error_t GenericGap::setAdvertisingPolicyMode(AdvertisingPolicyMode_t mode)
gustavatmel 1:9c5af431a1f1 764 {
gustavatmel 1:9c5af431a1f1 765 if (mode > Gap::ADV_POLICY_FILTER_ALL_REQS) {
gustavatmel 1:9c5af431a1f1 766 return BLE_ERROR_INVALID_PARAM;
gustavatmel 1:9c5af431a1f1 767 }
gustavatmel 1:9c5af431a1f1 768
gustavatmel 1:9c5af431a1f1 769 _advertising_filter_policy = (pal::advertising_filter_policy_t::type) mode;
gustavatmel 1:9c5af431a1f1 770 return BLE_ERROR_NONE;
gustavatmel 1:9c5af431a1f1 771 }
gustavatmel 1:9c5af431a1f1 772
gustavatmel 1:9c5af431a1f1 773 ble_error_t GenericGap::setScanningPolicyMode(ScanningPolicyMode_t mode)
gustavatmel 1:9c5af431a1f1 774 {
gustavatmel 1:9c5af431a1f1 775 if (mode > Gap::SCAN_POLICY_FILTER_ALL_ADV) {
gustavatmel 1:9c5af431a1f1 776 return BLE_ERROR_INVALID_PARAM;
gustavatmel 1:9c5af431a1f1 777 }
gustavatmel 1:9c5af431a1f1 778
gustavatmel 1:9c5af431a1f1 779 _scanning_filter_policy = (pal::scanning_filter_policy_t::type) mode;
gustavatmel 1:9c5af431a1f1 780 return BLE_ERROR_NONE;
gustavatmel 1:9c5af431a1f1 781 }
gustavatmel 1:9c5af431a1f1 782
gustavatmel 1:9c5af431a1f1 783 ble_error_t GenericGap::setInitiatorPolicyMode(InitiatorPolicyMode_t mode)
gustavatmel 1:9c5af431a1f1 784 {
gustavatmel 1:9c5af431a1f1 785 if (mode > Gap::INIT_POLICY_FILTER_ALL_ADV) {
gustavatmel 1:9c5af431a1f1 786 return BLE_ERROR_INVALID_PARAM;
gustavatmel 1:9c5af431a1f1 787 }
gustavatmel 1:9c5af431a1f1 788
gustavatmel 1:9c5af431a1f1 789 _initiator_policy_mode = (pal::initiator_policy_t::type) mode;
gustavatmel 1:9c5af431a1f1 790 return BLE_ERROR_NONE;
gustavatmel 1:9c5af431a1f1 791 }
gustavatmel 1:9c5af431a1f1 792
gustavatmel 1:9c5af431a1f1 793 Gap::AdvertisingPolicyMode_t GenericGap::getAdvertisingPolicyMode(void) const
gustavatmel 1:9c5af431a1f1 794 {
gustavatmel 1:9c5af431a1f1 795 return (AdvertisingPolicyMode_t) _advertising_filter_policy.value();
gustavatmel 1:9c5af431a1f1 796 }
gustavatmel 1:9c5af431a1f1 797
gustavatmel 1:9c5af431a1f1 798 Gap::ScanningPolicyMode_t GenericGap::getScanningPolicyMode(void) const
gustavatmel 1:9c5af431a1f1 799 {
gustavatmel 1:9c5af431a1f1 800 return (ScanningPolicyMode_t) _scanning_filter_policy.value();
gustavatmel 1:9c5af431a1f1 801 }
gustavatmel 1:9c5af431a1f1 802
gustavatmel 1:9c5af431a1f1 803 Gap::InitiatorPolicyMode_t GenericGap::getInitiatorPolicyMode(void) const
gustavatmel 1:9c5af431a1f1 804 {
gustavatmel 1:9c5af431a1f1 805 return (InitiatorPolicyMode_t) _initiator_policy_mode.value();
gustavatmel 1:9c5af431a1f1 806 }
gustavatmel 1:9c5af431a1f1 807
gustavatmel 1:9c5af431a1f1 808 ble_error_t GenericGap::startRadioScan(const GapScanningParams &scanningParams)
gustavatmel 1:9c5af431a1f1 809 {
gustavatmel 1:9c5af431a1f1 810 if (is_scan_params_valid(&scanningParams) == false) {
gustavatmel 1:9c5af431a1f1 811 return BLE_ERROR_INVALID_PARAM;
gustavatmel 1:9c5af431a1f1 812 }
gustavatmel 1:9c5af431a1f1 813
gustavatmel 1:9c5af431a1f1 814 if (_scanning_filter_policy == pal::scanning_filter_policy_t::FILTER_ADVERTISING &&
gustavatmel 1:9c5af431a1f1 815 _whitelist.size == 0) {
gustavatmel 1:9c5af431a1f1 816 return BLE_ERROR_INVALID_STATE;
gustavatmel 1:9c5af431a1f1 817 }
gustavatmel 1:9c5af431a1f1 818
gustavatmel 1:9c5af431a1f1 819 ble_error_t err = _pal_gap.set_scan_parameters(
gustavatmel 1:9c5af431a1f1 820 scanningParams.getActiveScanning(),
gustavatmel 1:9c5af431a1f1 821 scanningParams.getInterval(),
gustavatmel 1:9c5af431a1f1 822 scanningParams.getWindow(),
gustavatmel 1:9c5af431a1f1 823 get_own_address_type(),
gustavatmel 1:9c5af431a1f1 824 _scanning_filter_policy
gustavatmel 1:9c5af431a1f1 825 );
gustavatmel 1:9c5af431a1f1 826
gustavatmel 1:9c5af431a1f1 827 if (err) {
gustavatmel 1:9c5af431a1f1 828 return err;
gustavatmel 1:9c5af431a1f1 829 }
gustavatmel 1:9c5af431a1f1 830
gustavatmel 1:9c5af431a1f1 831 err = _pal_gap.scan_enable(true, false);
gustavatmel 1:9c5af431a1f1 832
gustavatmel 1:9c5af431a1f1 833 if (err) {
gustavatmel 1:9c5af431a1f1 834 return err;
gustavatmel 1:9c5af431a1f1 835 }
gustavatmel 1:9c5af431a1f1 836
gustavatmel 1:9c5af431a1f1 837 _scan_timeout.detach();
gustavatmel 1:9c5af431a1f1 838 uint16_t timeout = scanningParams.getTimeout();
gustavatmel 1:9c5af431a1f1 839 if (timeout) {
gustavatmel 1:9c5af431a1f1 840 _scan_timeout.attach_us(
gustavatmel 1:9c5af431a1f1 841 mbed::callback(this, &GenericGap::on_scan_timeout),
gustavatmel 1:9c5af431a1f1 842 scanningParams.getTimeout() * 1000000U
gustavatmel 1:9c5af431a1f1 843 );
gustavatmel 1:9c5af431a1f1 844 }
gustavatmel 1:9c5af431a1f1 845
gustavatmel 1:9c5af431a1f1 846 return BLE_ERROR_NONE;
gustavatmel 1:9c5af431a1f1 847 }
gustavatmel 1:9c5af431a1f1 848
gustavatmel 1:9c5af431a1f1 849 ble_error_t GenericGap::initRadioNotification(void)
gustavatmel 1:9c5af431a1f1 850 {
gustavatmel 1:9c5af431a1f1 851 return BLE_ERROR_NOT_IMPLEMENTED;
gustavatmel 1:9c5af431a1f1 852 }
gustavatmel 1:9c5af431a1f1 853
gustavatmel 1:9c5af431a1f1 854 ble_error_t GenericGap::setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse)
gustavatmel 1:9c5af431a1f1 855 {
gustavatmel 1:9c5af431a1f1 856 ble_error_t err = _pal_gap.set_advertising_data(
gustavatmel 1:9c5af431a1f1 857 advData.getPayloadLen(),
gustavatmel 1:9c5af431a1f1 858 pal::advertising_data_t(advData.getPayload(), advData.getPayloadLen())
gustavatmel 1:9c5af431a1f1 859 );
gustavatmel 1:9c5af431a1f1 860 if (err) {
gustavatmel 1:9c5af431a1f1 861 return err;
gustavatmel 1:9c5af431a1f1 862 }
gustavatmel 1:9c5af431a1f1 863
gustavatmel 1:9c5af431a1f1 864 return _pal_gap.set_scan_response_data(
gustavatmel 1:9c5af431a1f1 865 scanResponse.getPayloadLen(),
gustavatmel 1:9c5af431a1f1 866 pal::advertising_data_t(scanResponse.getPayload(), scanResponse.getPayloadLen())
gustavatmel 1:9c5af431a1f1 867 );
gustavatmel 1:9c5af431a1f1 868 }
gustavatmel 1:9c5af431a1f1 869
gustavatmel 1:9c5af431a1f1 870 ble_error_t GenericGap::startAdvertising(const GapAdvertisingParams& params)
gustavatmel 1:9c5af431a1f1 871 {
gustavatmel 1:9c5af431a1f1 872 if (is_advertising_params_valid(params) == false) {
gustavatmel 1:9c5af431a1f1 873 return BLE_ERROR_INVALID_PARAM;
gustavatmel 1:9c5af431a1f1 874 }
gustavatmel 1:9c5af431a1f1 875
gustavatmel 1:9c5af431a1f1 876 // TODO: fix the high level API to have a min/max range
gustavatmel 1:9c5af431a1f1 877 // Going against recommendations (The Advertising_Interval_Min and
gustavatmel 1:9c5af431a1f1 878 // Advertising_Interval_Max should not be the same value to enable the
gustavatmel 1:9c5af431a1f1 879 // Controller to determine the best advertising interval given other activities.)
gustavatmel 1:9c5af431a1f1 880 // for now but not against specification: "The Advertising_Interval_Min
gustavatmel 1:9c5af431a1f1 881 // shall be less than or equal to the Advertising_Interval_Max"
gustavatmel 1:9c5af431a1f1 882 ble_error_t err = _pal_gap.set_advertising_parameters(
gustavatmel 1:9c5af431a1f1 883 /* advertising_interval_min */ params.getIntervalInADVUnits(),
gustavatmel 1:9c5af431a1f1 884 /* advertising_interval_max */ params.getIntervalInADVUnits(),
gustavatmel 1:9c5af431a1f1 885 (pal::advertising_type_t::type) params.getAdvertisingType(),
gustavatmel 1:9c5af431a1f1 886 get_own_address_type(),
gustavatmel 1:9c5af431a1f1 887 pal::advertising_peer_address_type_t::PUBLIC_ADDRESS,
gustavatmel 1:9c5af431a1f1 888 ble::address_t(),
gustavatmel 1:9c5af431a1f1 889 pal::advertising_channel_map_t::ALL_ADVERTISING_CHANNELS,
gustavatmel 1:9c5af431a1f1 890 _advertising_filter_policy
gustavatmel 1:9c5af431a1f1 891 );
gustavatmel 1:9c5af431a1f1 892
gustavatmel 1:9c5af431a1f1 893 if (err) {
gustavatmel 1:9c5af431a1f1 894 return err;
gustavatmel 1:9c5af431a1f1 895 }
gustavatmel 1:9c5af431a1f1 896
gustavatmel 1:9c5af431a1f1 897 err = _pal_gap.advertising_enable(true);
gustavatmel 1:9c5af431a1f1 898 if (err) {
gustavatmel 1:9c5af431a1f1 899 return err;
gustavatmel 1:9c5af431a1f1 900 }
gustavatmel 1:9c5af431a1f1 901
gustavatmel 1:9c5af431a1f1 902 state.advertising = true;
gustavatmel 1:9c5af431a1f1 903
gustavatmel 1:9c5af431a1f1 904 _advertising_timeout.detach();
gustavatmel 1:9c5af431a1f1 905 uint16_t timeout = params.getTimeout();
gustavatmel 1:9c5af431a1f1 906 if (timeout) {
gustavatmel 1:9c5af431a1f1 907 _advertising_timeout.attach_us(
gustavatmel 1:9c5af431a1f1 908 mbed::callback(this, &GenericGap::on_advertising_timeout),
gustavatmel 1:9c5af431a1f1 909 params.getTimeout() * 1000000U
gustavatmel 1:9c5af431a1f1 910 );
gustavatmel 1:9c5af431a1f1 911 }
gustavatmel 1:9c5af431a1f1 912
gustavatmel 1:9c5af431a1f1 913 return BLE_ERROR_NONE;
gustavatmel 1:9c5af431a1f1 914 }
gustavatmel 1:9c5af431a1f1 915
gustavatmel 1:9c5af431a1f1 916 ble_error_t GenericGap::reset(void)
gustavatmel 1:9c5af431a1f1 917 {
gustavatmel 1:9c5af431a1f1 918 Gap::reset();
gustavatmel 1:9c5af431a1f1 919 _advertising_timeout.detach();
gustavatmel 1:9c5af431a1f1 920 _scan_timeout.detach();
gustavatmel 1:9c5af431a1f1 921
gustavatmel 1:9c5af431a1f1 922 return BLE_ERROR_NONE;
gustavatmel 1:9c5af431a1f1 923 }
gustavatmel 1:9c5af431a1f1 924
gustavatmel 1:9c5af431a1f1 925 void GenericGap::processConnectionEvent(
gustavatmel 1:9c5af431a1f1 926 Handle_t handle,
gustavatmel 1:9c5af431a1f1 927 Role_t role,
gustavatmel 1:9c5af431a1f1 928 BLEProtocol::AddressType_t peerAddrType,
gustavatmel 1:9c5af431a1f1 929 const BLEProtocol::AddressBytes_t peerAddr,
gustavatmel 1:9c5af431a1f1 930 BLEProtocol::AddressType_t ownAddrType,
gustavatmel 1:9c5af431a1f1 931 const BLEProtocol::AddressBytes_t ownAddr,
gustavatmel 1:9c5af431a1f1 932 const ConnectionParams_t *connectionParams
gustavatmel 1:9c5af431a1f1 933 ) {
gustavatmel 1:9c5af431a1f1 934 if (_connection_event_handler) {
gustavatmel 1:9c5af431a1f1 935 _connection_event_handler->on_connected(
gustavatmel 1:9c5af431a1f1 936 handle,
gustavatmel 1:9c5af431a1f1 937 role,
gustavatmel 1:9c5af431a1f1 938 peerAddrType,
gustavatmel 1:9c5af431a1f1 939 peerAddr,
gustavatmel 1:9c5af431a1f1 940 ownAddrType,
gustavatmel 1:9c5af431a1f1 941 ownAddr,
gustavatmel 1:9c5af431a1f1 942 connectionParams
gustavatmel 1:9c5af431a1f1 943 );
gustavatmel 1:9c5af431a1f1 944 }
gustavatmel 1:9c5af431a1f1 945
gustavatmel 1:9c5af431a1f1 946 ::Gap::processConnectionEvent(
gustavatmel 1:9c5af431a1f1 947 handle,
gustavatmel 1:9c5af431a1f1 948 role,
gustavatmel 1:9c5af431a1f1 949 peerAddrType,
gustavatmel 1:9c5af431a1f1 950 peerAddr,
gustavatmel 1:9c5af431a1f1 951 ownAddrType,
gustavatmel 1:9c5af431a1f1 952 ownAddr,
gustavatmel 1:9c5af431a1f1 953 connectionParams
gustavatmel 1:9c5af431a1f1 954 );
gustavatmel 1:9c5af431a1f1 955 }
gustavatmel 1:9c5af431a1f1 956
gustavatmel 1:9c5af431a1f1 957 void GenericGap::processDisconnectionEvent(
gustavatmel 1:9c5af431a1f1 958 Handle_t handle,
gustavatmel 1:9c5af431a1f1 959 DisconnectionReason_t reason
gustavatmel 1:9c5af431a1f1 960 ) {
gustavatmel 1:9c5af431a1f1 961 if (_connection_event_handler) {
gustavatmel 1:9c5af431a1f1 962 _connection_event_handler->on_disconnected(
gustavatmel 1:9c5af431a1f1 963 handle,
gustavatmel 1:9c5af431a1f1 964 reason
gustavatmel 1:9c5af431a1f1 965 );
gustavatmel 1:9c5af431a1f1 966 }
gustavatmel 1:9c5af431a1f1 967
gustavatmel 1:9c5af431a1f1 968 ::Gap::processDisconnectionEvent(
gustavatmel 1:9c5af431a1f1 969 handle,
gustavatmel 1:9c5af431a1f1 970 reason
gustavatmel 1:9c5af431a1f1 971 );
gustavatmel 1:9c5af431a1f1 972 }
gustavatmel 1:9c5af431a1f1 973
gustavatmel 1:9c5af431a1f1 974 void GenericGap::on_scan_timeout()
gustavatmel 1:9c5af431a1f1 975 {
gustavatmel 1:9c5af431a1f1 976 _event_queue.post(mbed::callback(this, &GenericGap::process_scan_timeout));
gustavatmel 1:9c5af431a1f1 977 }
gustavatmel 1:9c5af431a1f1 978
gustavatmel 1:9c5af431a1f1 979 void GenericGap::process_scan_timeout()
gustavatmel 1:9c5af431a1f1 980 {
gustavatmel 1:9c5af431a1f1 981 ble_error_t err = _pal_gap.scan_enable(false, false);
gustavatmel 1:9c5af431a1f1 982 if (err) {
gustavatmel 1:9c5af431a1f1 983 // TODO: define the mechanism signaling the error
gustavatmel 1:9c5af431a1f1 984 }
gustavatmel 1:9c5af431a1f1 985 processTimeoutEvent(Gap::TIMEOUT_SRC_SCAN);
gustavatmel 1:9c5af431a1f1 986 }
gustavatmel 1:9c5af431a1f1 987
gustavatmel 1:9c5af431a1f1 988 void GenericGap::on_advertising_timeout()
gustavatmel 1:9c5af431a1f1 989 {
gustavatmel 1:9c5af431a1f1 990 _event_queue.post(mbed::callback(this, &GenericGap::process_advertising_timeout));
gustavatmel 1:9c5af431a1f1 991 }
gustavatmel 1:9c5af431a1f1 992
gustavatmel 1:9c5af431a1f1 993 void GenericGap::process_advertising_timeout()
gustavatmel 1:9c5af431a1f1 994 {
gustavatmel 1:9c5af431a1f1 995 ble_error_t err = _pal_gap.advertising_enable(false);
gustavatmel 1:9c5af431a1f1 996 if (err) {
gustavatmel 1:9c5af431a1f1 997 // TODO: define the mechanism signaling the error
gustavatmel 1:9c5af431a1f1 998 }
gustavatmel 1:9c5af431a1f1 999 processTimeoutEvent(Gap::TIMEOUT_SRC_ADVERTISING);
gustavatmel 1:9c5af431a1f1 1000 }
gustavatmel 1:9c5af431a1f1 1001
gustavatmel 1:9c5af431a1f1 1002 void GenericGap::on_gap_event_received(const pal::GapEvent& e)
gustavatmel 1:9c5af431a1f1 1003 {
gustavatmel 1:9c5af431a1f1 1004 switch (e.type.value()) {
gustavatmel 1:9c5af431a1f1 1005 case pal::GapEventType::ADVERTISING_REPORT:
gustavatmel 1:9c5af431a1f1 1006 on_advertising_report(static_cast<const pal::GapAdvertisingReportEvent&>(e));
gustavatmel 1:9c5af431a1f1 1007 break;
gustavatmel 1:9c5af431a1f1 1008
gustavatmel 1:9c5af431a1f1 1009 case pal::GapEventType::CONNECTION_COMPLETE:
gustavatmel 1:9c5af431a1f1 1010 on_connection_complete(static_cast<const pal::GapConnectionCompleteEvent&>(e));
gustavatmel 1:9c5af431a1f1 1011 break;
gustavatmel 1:9c5af431a1f1 1012
gustavatmel 1:9c5af431a1f1 1013 case pal::GapEventType::CONNECTION_UPDATE:
gustavatmel 1:9c5af431a1f1 1014 on_connection_update(static_cast<const pal::GapConnectionUpdateEvent&>(e));
gustavatmel 1:9c5af431a1f1 1015 break;
gustavatmel 1:9c5af431a1f1 1016
gustavatmel 1:9c5af431a1f1 1017 case pal::GapEventType::DISCONNECTION_COMPLETE:
gustavatmel 1:9c5af431a1f1 1018 on_disconnection_complete(static_cast<const pal::GapDisconnectionCompleteEvent&>(e));
gustavatmel 1:9c5af431a1f1 1019 break;
gustavatmel 1:9c5af431a1f1 1020
gustavatmel 1:9c5af431a1f1 1021 case pal::GapEventType::REMOTE_CONNECTION_PARAMETER_REQUEST:
gustavatmel 1:9c5af431a1f1 1022 on_connection_parameter_request(static_cast<const pal::GapRemoteConnectionParameterRequestEvent&>(e));
gustavatmel 1:9c5af431a1f1 1023 break;
gustavatmel 1:9c5af431a1f1 1024
gustavatmel 1:9c5af431a1f1 1025 case pal::GapEventType::UNEXPECTED_ERROR:
gustavatmel 1:9c5af431a1f1 1026 on_unexpected_error(static_cast<const pal::GapUnexpectedErrorEvent&>(e));
gustavatmel 1:9c5af431a1f1 1027 break;
gustavatmel 1:9c5af431a1f1 1028
gustavatmel 1:9c5af431a1f1 1029 default:
gustavatmel 1:9c5af431a1f1 1030 break;
gustavatmel 1:9c5af431a1f1 1031 }
gustavatmel 1:9c5af431a1f1 1032 }
gustavatmel 1:9c5af431a1f1 1033
gustavatmel 1:9c5af431a1f1 1034 void GenericGap::on_advertising_report(const pal::GapAdvertisingReportEvent& e)
gustavatmel 1:9c5af431a1f1 1035 {
gustavatmel 1:9c5af431a1f1 1036 for (size_t i = 0; i < e.size(); ++i) {
gustavatmel 1:9c5af431a1f1 1037 pal::GapAdvertisingReportEvent::advertising_t advertising = e[i];
gustavatmel 1:9c5af431a1f1 1038
gustavatmel 1:9c5af431a1f1 1039 processAdvertisementReport(
gustavatmel 1:9c5af431a1f1 1040 advertising.address.data(),
gustavatmel 1:9c5af431a1f1 1041 advertising.rssi,
gustavatmel 1:9c5af431a1f1 1042 advertising.type == pal::received_advertising_type_t::SCAN_RESPONSE,
gustavatmel 1:9c5af431a1f1 1043 (GapAdvertisingParams::AdvertisingType_t) advertising.type.value(),
gustavatmel 1:9c5af431a1f1 1044 advertising.data.size(),
gustavatmel 1:9c5af431a1f1 1045 advertising.data.data(),
gustavatmel 1:9c5af431a1f1 1046 (BLEProtocol::AddressType_t) advertising.address_type.value()
gustavatmel 1:9c5af431a1f1 1047 );
gustavatmel 1:9c5af431a1f1 1048 }
gustavatmel 1:9c5af431a1f1 1049 }
gustavatmel 1:9c5af431a1f1 1050
gustavatmel 1:9c5af431a1f1 1051 void GenericGap::on_connection_complete(const pal::GapConnectionCompleteEvent& e)
gustavatmel 1:9c5af431a1f1 1052 {
gustavatmel 1:9c5af431a1f1 1053 // TODO: deprecate ownAddrType and ownAddr, those are not specified
gustavatmel 1:9c5af431a1f1 1054 // from the Bluetooth perspective
gustavatmel 1:9c5af431a1f1 1055 if (e.status == pal::hci_error_code_t::SUCCESS) {
gustavatmel 1:9c5af431a1f1 1056 if (e.role.value() == e.role.SLAVE) {
gustavatmel 1:9c5af431a1f1 1057 _advertising_timeout.detach();
gustavatmel 1:9c5af431a1f1 1058 _pal_gap.advertising_enable(false);
gustavatmel 1:9c5af431a1f1 1059 }
gustavatmel 1:9c5af431a1f1 1060
gustavatmel 1:9c5af431a1f1 1061 // using these parameters if stupid, there is no range for the
gustavatmel 1:9c5af431a1f1 1062 // connection interval when the connection is established
gustavatmel 1:9c5af431a1f1 1063 ConnectionParams_t connection_params = {
gustavatmel 1:9c5af431a1f1 1064 /* minConnectionInterval */ e.connection_interval,
gustavatmel 1:9c5af431a1f1 1065 /* maxConnectionInterval */ e.connection_interval,
gustavatmel 1:9c5af431a1f1 1066 e.connection_latency,
gustavatmel 1:9c5af431a1f1 1067 e.supervision_timeout
gustavatmel 1:9c5af431a1f1 1068 };
gustavatmel 1:9c5af431a1f1 1069 ble::address_t address;
gustavatmel 1:9c5af431a1f1 1070 if (_address_type == BLEProtocol::AddressType::PUBLIC) {
gustavatmel 1:9c5af431a1f1 1071 address = _pal_gap.get_device_address();
gustavatmel 1:9c5af431a1f1 1072 } else {
gustavatmel 1:9c5af431a1f1 1073 address = _pal_gap.get_random_address();
gustavatmel 1:9c5af431a1f1 1074 }
gustavatmel 1:9c5af431a1f1 1075
gustavatmel 1:9c5af431a1f1 1076 processConnectionEvent(
gustavatmel 1:9c5af431a1f1 1077 e.connection_handle,
gustavatmel 1:9c5af431a1f1 1078 e.role.value() == e.role.MASTER ? ::Gap::CENTRAL : ::Gap::PERIPHERAL,
gustavatmel 1:9c5af431a1f1 1079 (BLEProtocol::AddressType_t) e.peer_address_type.value(),
gustavatmel 1:9c5af431a1f1 1080 e.peer_address.data(),
gustavatmel 1:9c5af431a1f1 1081 _address_type,
gustavatmel 1:9c5af431a1f1 1082 address.data(),
gustavatmel 1:9c5af431a1f1 1083 &connection_params
gustavatmel 1:9c5af431a1f1 1084 );
gustavatmel 1:9c5af431a1f1 1085 } else {
gustavatmel 1:9c5af431a1f1 1086 // for now notify user that the connection failled by issuing a timeout
gustavatmel 1:9c5af431a1f1 1087 // event
gustavatmel 1:9c5af431a1f1 1088
gustavatmel 1:9c5af431a1f1 1089 // TODO: Define events in case of connection faillure
gustavatmel 1:9c5af431a1f1 1090 processTimeoutEvent(Gap::TIMEOUT_SRC_CONN);
gustavatmel 1:9c5af431a1f1 1091 }
gustavatmel 1:9c5af431a1f1 1092 }
gustavatmel 1:9c5af431a1f1 1093
gustavatmel 1:9c5af431a1f1 1094 void GenericGap::on_disconnection_complete(const pal::GapDisconnectionCompleteEvent& e)
gustavatmel 1:9c5af431a1f1 1095 {
gustavatmel 1:9c5af431a1f1 1096 if (e.status == pal::hci_error_code_t::SUCCESS) {
gustavatmel 1:9c5af431a1f1 1097 processDisconnectionEvent(
gustavatmel 1:9c5af431a1f1 1098 e.connection_handle,
gustavatmel 1:9c5af431a1f1 1099 (Gap::DisconnectionReason_t) e.reason
gustavatmel 1:9c5af431a1f1 1100 );
gustavatmel 1:9c5af431a1f1 1101 } else {
gustavatmel 1:9c5af431a1f1 1102 // TODO: define what to do in case of faillure
gustavatmel 1:9c5af431a1f1 1103 }
gustavatmel 1:9c5af431a1f1 1104 }
gustavatmel 1:9c5af431a1f1 1105
gustavatmel 1:9c5af431a1f1 1106 void GenericGap::on_connection_parameter_request(const pal::GapRemoteConnectionParameterRequestEvent& e)
gustavatmel 1:9c5af431a1f1 1107 {
gustavatmel 1:9c5af431a1f1 1108 // intern behavior, accept all new parameter requests
gustavatmel 1:9c5af431a1f1 1109 // TODO: expose an API so user code can accept or reject such request
gustavatmel 1:9c5af431a1f1 1110 _pal_gap.accept_connection_parameter_request(
gustavatmel 1:9c5af431a1f1 1111 e.connection_handle,
gustavatmel 1:9c5af431a1f1 1112 e.min_connection_interval,
gustavatmel 1:9c5af431a1f1 1113 e.max_connection_interval,
gustavatmel 1:9c5af431a1f1 1114 e.connection_latency,
gustavatmel 1:9c5af431a1f1 1115 e.supervision_timeout,
gustavatmel 1:9c5af431a1f1 1116 /* minimum_connection_event_length */ 0,
gustavatmel 1:9c5af431a1f1 1117 /* maximum_connection_event_length */ 0
gustavatmel 1:9c5af431a1f1 1118 );
gustavatmel 1:9c5af431a1f1 1119 }
gustavatmel 1:9c5af431a1f1 1120
gustavatmel 1:9c5af431a1f1 1121 void GenericGap::on_connection_update(const pal::GapConnectionUpdateEvent& e)
gustavatmel 1:9c5af431a1f1 1122 {
gustavatmel 1:9c5af431a1f1 1123 // TODO: add feature in interface to notify the user that the connection
gustavatmel 1:9c5af431a1f1 1124 // has been updated.
gustavatmel 1:9c5af431a1f1 1125 }
gustavatmel 1:9c5af431a1f1 1126
gustavatmel 1:9c5af431a1f1 1127 void GenericGap::on_unexpected_error(const pal::GapUnexpectedErrorEvent& e)
gustavatmel 1:9c5af431a1f1 1128 {
gustavatmel 1:9c5af431a1f1 1129 // TODO: add feature in interface to notify the user that the connection
gustavatmel 1:9c5af431a1f1 1130 // has been updated.
gustavatmel 1:9c5af431a1f1 1131 }
gustavatmel 1:9c5af431a1f1 1132
gustavatmel 1:9c5af431a1f1 1133 pal::own_address_type_t GenericGap::get_own_address_type()
gustavatmel 1:9c5af431a1f1 1134 {
gustavatmel 1:9c5af431a1f1 1135 switch (_address_type) {
gustavatmel 1:9c5af431a1f1 1136 case BLEProtocol::AddressType::PUBLIC:
gustavatmel 1:9c5af431a1f1 1137 return pal::own_address_type_t::PUBLIC_ADDRESS;
gustavatmel 1:9c5af431a1f1 1138 case BLEProtocol::AddressType::RANDOM_STATIC:
gustavatmel 1:9c5af431a1f1 1139 case BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE:
gustavatmel 1:9c5af431a1f1 1140 return pal::own_address_type_t::RANDOM_ADDRESS;
gustavatmel 1:9c5af431a1f1 1141 case BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE:
gustavatmel 1:9c5af431a1f1 1142 return pal::own_address_type_t::RESOLVABLE_PRIVATE_ADDRESS_PUBLIC_FALLBACK;
gustavatmel 1:9c5af431a1f1 1143 default:
gustavatmel 1:9c5af431a1f1 1144 // not reachable
gustavatmel 1:9c5af431a1f1 1145 return pal::own_address_type_t::PUBLIC_ADDRESS;
gustavatmel 1:9c5af431a1f1 1146 }
gustavatmel 1:9c5af431a1f1 1147 }
gustavatmel 1:9c5af431a1f1 1148
gustavatmel 1:9c5af431a1f1 1149 bool GenericGap::initialize_whitelist() const
gustavatmel 1:9c5af431a1f1 1150 {
gustavatmel 1:9c5af431a1f1 1151 if (_whitelist.addresses != NULL) {
gustavatmel 1:9c5af431a1f1 1152 return true;
gustavatmel 1:9c5af431a1f1 1153 }
gustavatmel 1:9c5af431a1f1 1154
gustavatmel 1:9c5af431a1f1 1155 uint8_t whitelist_capacity = _pal_gap.read_white_list_capacity();
gustavatmel 1:9c5af431a1f1 1156
gustavatmel 1:9c5af431a1f1 1157 if (whitelist_capacity == 0) {
gustavatmel 1:9c5af431a1f1 1158 return false;
gustavatmel 1:9c5af431a1f1 1159 }
gustavatmel 1:9c5af431a1f1 1160
gustavatmel 1:9c5af431a1f1 1161 _whitelist.addresses = new (std::nothrow) BLEProtocol::Address_t[whitelist_capacity] ;
gustavatmel 1:9c5af431a1f1 1162 if (_whitelist.addresses == NULL) {
gustavatmel 1:9c5af431a1f1 1163 return false;
gustavatmel 1:9c5af431a1f1 1164 }
gustavatmel 1:9c5af431a1f1 1165
gustavatmel 1:9c5af431a1f1 1166 _whitelist.size = 0;
gustavatmel 1:9c5af431a1f1 1167 _whitelist.capacity = whitelist_capacity;
gustavatmel 1:9c5af431a1f1 1168
gustavatmel 1:9c5af431a1f1 1169 return true;
gustavatmel 1:9c5af431a1f1 1170 }
gustavatmel 1:9c5af431a1f1 1171
gustavatmel 1:9c5af431a1f1 1172 void GenericGap::set_connection_event_handler(pal::ConnectionEventMonitor::EventHandler *connection_event_handler)
gustavatmel 1:9c5af431a1f1 1173 {
gustavatmel 1:9c5af431a1f1 1174 _connection_event_handler = connection_event_handler;
gustavatmel 1:9c5af431a1f1 1175 }
gustavatmel 1:9c5af431a1f1 1176
gustavatmel 1:9c5af431a1f1 1177 } // namespace generic
gustavatmel 1:9c5af431a1f1 1178 } // namespace ble