BLE_API

Committer:
vcoubard
Date:
Mon Jan 11 08:51:37 2016 +0000
Revision:
1062:a3fd424b73ca
Parent:
1056:ce2fb3d09929
Child:
1063:187f9929cb60
Synchronized with git rev b817cf3e
Author: Andres Amaya Garcia
Improve API to facilitate full shutdown procedure

The BLE API exposes a shutdown() function in BLE.h. This function is meant to
be overwridden by platform-specific sub-classes to clear all GAP and GATT
state. However, from the platform-specific implementation it is dificult to
achieve this because the Gap, GattClient, GattServer and SecurityManager
components of the API do not expose any functionality to shutdown.

This commit introduces the following changes:

* Add a static member pointer to Gap, GattClient, GattServer and
SecurityManager that is used to keep track of the initialized objects.
* Add a function member cleanup() to Gap, GattClient, GattServer and
SecurityManager to allow easy reset of the instance's state. This function
is meant to be overriden and called from the derived classes to fully clear the
state of the BLE API and the platform-specific implementation.
* Add a static member function shutdown() to Gap, GattClient, GattServer and
SecurityManager. This function shall be called from the shutdown()
overriding BLE::shutdown() for Gap, GattClient, GattServer and SecurityManager
that will in-turn clear the state of each of the components.

**NOTE:** Platform-specific implementations of this API must be modified to
this changes into account.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 710:b2e1a2660ec2 1 /* mbed Microcontroller Library
rgrover1 710:b2e1a2660ec2 2 * Copyright (c) 2006-2013 ARM Limited
rgrover1 710:b2e1a2660ec2 3 *
rgrover1 710:b2e1a2660ec2 4 * Licensed under the Apache License, Version 2.0 (the "License");
rgrover1 710:b2e1a2660ec2 5 * you may not use this file except in compliance with the License.
rgrover1 710:b2e1a2660ec2 6 * You may obtain a copy of the License at
rgrover1 710:b2e1a2660ec2 7 *
rgrover1 710:b2e1a2660ec2 8 * http://www.apache.org/licenses/LICENSE-2.0
rgrover1 710:b2e1a2660ec2 9 *
rgrover1 710:b2e1a2660ec2 10 * Unless required by applicable law or agreed to in writing, software
rgrover1 710:b2e1a2660ec2 11 * distributed under the License is distributed on an "AS IS" BASIS,
rgrover1 710:b2e1a2660ec2 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rgrover1 710:b2e1a2660ec2 13 * See the License for the specific language governing permissions and
rgrover1 710:b2e1a2660ec2 14 * limitations under the License.
rgrover1 710:b2e1a2660ec2 15 */
rgrover1 710:b2e1a2660ec2 16
rgrover1 710:b2e1a2660ec2 17 #ifndef __GAP_H__
rgrover1 710:b2e1a2660ec2 18 #define __GAP_H__
rgrover1 710:b2e1a2660ec2 19
rgrover1 710:b2e1a2660ec2 20 #include "GapAdvertisingData.h"
rgrover1 710:b2e1a2660ec2 21 #include "GapAdvertisingParams.h"
rgrover1 710:b2e1a2660ec2 22 #include "GapScanningParams.h"
rgrover1 710:b2e1a2660ec2 23 #include "GapEvents.h"
rgrover1 829:9072de50087b 24 #include "CallChainOfFunctionPointersWithContext.h"
rgrover1 710:b2e1a2660ec2 25 #include "FunctionPointerWithContext.h"
rgrover1 710:b2e1a2660ec2 26
vcoubard 1048:efb29faf12fc 27 /* Forward declarations for classes that will only be used for pointers or references in the following. */
rgrover1 710:b2e1a2660ec2 28 class GapAdvertisingParams;
rgrover1 710:b2e1a2660ec2 29 class GapScanningParams;
rgrover1 710:b2e1a2660ec2 30 class GapAdvertisingData;
rgrover1 710:b2e1a2660ec2 31
rgrover1 710:b2e1a2660ec2 32 class Gap {
rgrover1 710:b2e1a2660ec2 33 public:
rgrover1 710:b2e1a2660ec2 34 enum AddressType_t {
rgrover1 710:b2e1a2660ec2 35 ADDR_TYPE_PUBLIC = 0,
rgrover1 710:b2e1a2660ec2 36 ADDR_TYPE_RANDOM_STATIC,
rgrover1 710:b2e1a2660ec2 37 ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE,
rgrover1 710:b2e1a2660ec2 38 ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE
rgrover1 710:b2e1a2660ec2 39 };
vcoubard 1048:efb29faf12fc 40 typedef enum AddressType_t addr_type_t; /* @Note: Deprecated. Use AddressType_t instead. */
rgrover1 710:b2e1a2660ec2 41
rgrover1 710:b2e1a2660ec2 42 static const unsigned ADDR_LEN = 6;
rgrover1 710:b2e1a2660ec2 43 typedef uint8_t Address_t[ADDR_LEN]; /* 48-bit address, LSB format. */
vcoubard 1048:efb29faf12fc 44 typedef Address_t address_t; /* @Note: Deprecated. Use Address_t instead. */
rgrover1 710:b2e1a2660ec2 45
rgrover1 710:b2e1a2660ec2 46 enum TimeoutSource_t {
rgrover1 710:b2e1a2660ec2 47 TIMEOUT_SRC_ADVERTISING = 0x00, /**< Advertising timeout. */
rgrover1 710:b2e1a2660ec2 48 TIMEOUT_SRC_SECURITY_REQUEST = 0x01, /**< Security request timeout. */
rgrover1 710:b2e1a2660ec2 49 TIMEOUT_SRC_SCAN = 0x02, /**< Scanning timeout. */
rgrover1 710:b2e1a2660ec2 50 TIMEOUT_SRC_CONN = 0x03, /**< Connection timeout. */
rgrover1 710:b2e1a2660ec2 51 };
rgrover1 710:b2e1a2660ec2 52
rgrover1 710:b2e1a2660ec2 53 /**
rgrover1 710:b2e1a2660ec2 54 * Enumeration for disconnection reasons. The values for these reasons are
vcoubard 1048:efb29faf12fc 55 * derived from Nordic's implementation, but the reasons are meant to be
vcoubard 1048:efb29faf12fc 56 * independent of the transport. If you are returned a reason that is not
vcoubard 1048:efb29faf12fc 57 * covered by this enumeration, please refer to the underlying
rgrover1 710:b2e1a2660ec2 58 * transport library.
rgrover1 710:b2e1a2660ec2 59 */
rgrover1 710:b2e1a2660ec2 60 enum DisconnectionReason_t {
rgrover1 710:b2e1a2660ec2 61 CONNECTION_TIMEOUT = 0x08,
rgrover1 710:b2e1a2660ec2 62 REMOTE_USER_TERMINATED_CONNECTION = 0x13,
vcoubard 1048:efb29faf12fc 63 REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES = 0x14, /**< Remote device terminated connection due to low resources.*/
vcoubard 1048:efb29faf12fc 64 REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF = 0x15, /**< Remote device terminated connection due to power off. */
rgrover1 710:b2e1a2660ec2 65 LOCAL_HOST_TERMINATED_CONNECTION = 0x16,
rgrover1 710:b2e1a2660ec2 66 CONN_INTERVAL_UNACCEPTABLE = 0x3B,
rgrover1 710:b2e1a2660ec2 67 };
rgrover1 710:b2e1a2660ec2 68
vcoubard 1048:efb29faf12fc 69 /* Describes the current state of the device (more than one bit can be set). */
rgrover1 710:b2e1a2660ec2 70 struct GapState_t {
vcoubard 1048:efb29faf12fc 71 unsigned advertising : 1; /**< Peripheral is currently advertising. */
vcoubard 1048:efb29faf12fc 72 unsigned connected : 1; /**< Peripheral is connected to a central. */
rgrover1 710:b2e1a2660ec2 73 };
rgrover1 710:b2e1a2660ec2 74
rgrover1 710:b2e1a2660ec2 75 typedef uint16_t Handle_t; /* Type for connection handle. */
rgrover1 710:b2e1a2660ec2 76
rgrover1 710:b2e1a2660ec2 77 typedef struct {
rgrover1 710:b2e1a2660ec2 78 uint16_t minConnectionInterval; /**< Minimum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/
rgrover1 710:b2e1a2660ec2 79 uint16_t maxConnectionInterval; /**< Maximum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/
rgrover1 710:b2e1a2660ec2 80 uint16_t slaveLatency; /**< Slave Latency in number of connection events, see @ref BLE_GAP_CP_LIMITS.*/
rgrover1 710:b2e1a2660ec2 81 uint16_t connectionSupervisionTimeout; /**< Connection Supervision Timeout in 10 ms units, see @ref BLE_GAP_CP_LIMITS.*/
rgrover1 710:b2e1a2660ec2 82 } ConnectionParams_t;
rgrover1 710:b2e1a2660ec2 83
rgrover1 710:b2e1a2660ec2 84 enum Role_t {
rgrover1 710:b2e1a2660ec2 85 PERIPHERAL = 0x1, /**< Peripheral Role. */
rgrover1 710:b2e1a2660ec2 86 CENTRAL = 0x2, /**< Central Role. */
rgrover1 710:b2e1a2660ec2 87 };
rgrover1 710:b2e1a2660ec2 88
rgrover1 710:b2e1a2660ec2 89 struct AdvertisementCallbackParams_t {
rgrover1 710:b2e1a2660ec2 90 Address_t peerAddr;
rgrover1 710:b2e1a2660ec2 91 int8_t rssi;
rgrover1 710:b2e1a2660ec2 92 bool isScanResponse;
rgrover1 710:b2e1a2660ec2 93 GapAdvertisingParams::AdvertisingType_t type;
rgrover1 710:b2e1a2660ec2 94 uint8_t advertisingDataLen;
rgrover1 710:b2e1a2660ec2 95 const uint8_t *advertisingData;
rgrover1 710:b2e1a2660ec2 96 };
rgrover1 710:b2e1a2660ec2 97 typedef FunctionPointerWithContext<const AdvertisementCallbackParams_t *> AdvertisementReportCallback_t;
rgrover1 710:b2e1a2660ec2 98
rgrover1 710:b2e1a2660ec2 99 struct ConnectionCallbackParams_t {
rgrover1 710:b2e1a2660ec2 100 Handle_t handle;
rgrover1 710:b2e1a2660ec2 101 Role_t role;
rgrover1 710:b2e1a2660ec2 102 AddressType_t peerAddrType;
rgrover1 710:b2e1a2660ec2 103 Address_t peerAddr;
rgrover1 710:b2e1a2660ec2 104 AddressType_t ownAddrType;
rgrover1 710:b2e1a2660ec2 105 Address_t ownAddr;
rgrover1 710:b2e1a2660ec2 106 const ConnectionParams_t *connectionParams;
rgrover1 710:b2e1a2660ec2 107
rgrover1 710:b2e1a2660ec2 108 ConnectionCallbackParams_t(Handle_t handleIn,
rgrover1 710:b2e1a2660ec2 109 Role_t roleIn,
rgrover1 710:b2e1a2660ec2 110 AddressType_t peerAddrTypeIn,
rgrover1 710:b2e1a2660ec2 111 const uint8_t *peerAddrIn,
rgrover1 710:b2e1a2660ec2 112 AddressType_t ownAddrTypeIn,
rgrover1 710:b2e1a2660ec2 113 const uint8_t *ownAddrIn,
rgrover1 710:b2e1a2660ec2 114 const ConnectionParams_t *connectionParamsIn) :
rgrover1 710:b2e1a2660ec2 115 handle(handleIn),
rgrover1 710:b2e1a2660ec2 116 role(roleIn),
rgrover1 710:b2e1a2660ec2 117 peerAddrType(peerAddrTypeIn),
rgrover1 710:b2e1a2660ec2 118 peerAddr(),
rgrover1 710:b2e1a2660ec2 119 ownAddrType(ownAddrTypeIn),
rgrover1 710:b2e1a2660ec2 120 ownAddr(),
rgrover1 710:b2e1a2660ec2 121 connectionParams(connectionParamsIn) {
rgrover1 710:b2e1a2660ec2 122 memcpy(peerAddr, peerAddrIn, ADDR_LEN);
rgrover1 710:b2e1a2660ec2 123 memcpy(ownAddr, ownAddrIn, ADDR_LEN);
rgrover1 710:b2e1a2660ec2 124 }
rgrover1 710:b2e1a2660ec2 125 };
rgrover1 710:b2e1a2660ec2 126
rgrover1 829:9072de50087b 127 struct DisconnectionCallbackParams_t {
rgrover1 829:9072de50087b 128 Handle_t handle;
rgrover1 829:9072de50087b 129 DisconnectionReason_t reason;
rgrover1 829:9072de50087b 130
rgrover1 829:9072de50087b 131 DisconnectionCallbackParams_t(Handle_t handleIn,
rgrover1 829:9072de50087b 132 DisconnectionReason_t reasonIn) :
rgrover1 829:9072de50087b 133 handle(handleIn),
rgrover1 829:9072de50087b 134 reason(reasonIn)
rgrover1 829:9072de50087b 135 {}
rgrover1 829:9072de50087b 136 };
rgrover1 829:9072de50087b 137
rgrover1 710:b2e1a2660ec2 138 static const uint16_t UNIT_1_25_MS = 1250; /**< Number of microseconds in 1.25 milliseconds. */
rgrover1 710:b2e1a2660ec2 139 static uint16_t MSEC_TO_GAP_DURATION_UNITS(uint32_t durationInMillis) {
rgrover1 710:b2e1a2660ec2 140 return (durationInMillis * 1000) / UNIT_1_25_MS;
rgrover1 710:b2e1a2660ec2 141 }
rgrover1 766:03f1a26f132f 142
vcoubard 1052:b55e1ad3e1b3 143 typedef FunctionPointerWithContext<TimeoutSource_t> TimeoutEventCallback_t;
vcoubard 1052:b55e1ad3e1b3 144 typedef CallChainOfFunctionPointersWithContext<TimeoutSource_t> TimeoutEventCallbackChain_t;
rgrover1 710:b2e1a2660ec2 145
vcoubard 1052:b55e1ad3e1b3 146 typedef FunctionPointerWithContext<const ConnectionCallbackParams_t *> ConnectionEventCallback_t;
vcoubard 1052:b55e1ad3e1b3 147 typedef CallChainOfFunctionPointersWithContext<const ConnectionCallbackParams_t *> ConnectionEventCallbackChain_t;
vcoubard 1052:b55e1ad3e1b3 148
vcoubard 1052:b55e1ad3e1b3 149 typedef FunctionPointerWithContext<const DisconnectionCallbackParams_t*> DisconnectionEventCallback_t;
vcoubard 1054:f59e5d9a992a 150 typedef CallChainOfFunctionPointersWithContext<const DisconnectionCallbackParams_t*> DisconnectionEventCallbackChain_t;
vcoubard 1052:b55e1ad3e1b3 151
rgrover1 753:0f60274cd3ad 152 typedef FunctionPointerWithContext<bool> RadioNotificationEventCallback_t;
rgrover1 710:b2e1a2660ec2 153
rgrover1 710:b2e1a2660ec2 154 /*
rgrover1 710:b2e1a2660ec2 155 * The following functions are meant to be overridden in the platform-specific sub-class.
rgrover1 710:b2e1a2660ec2 156 */
rgrover1 710:b2e1a2660ec2 157 public:
rgrover1 710:b2e1a2660ec2 158 /**
rgrover1 710:b2e1a2660ec2 159 * Set the BTLE MAC address and type. Please note that the address format is
vcoubard 1048:efb29faf12fc 160 * least significant byte first (LSB). Please refer to Address_t.
rgrover1 710:b2e1a2660ec2 161 *
rgrover1 710:b2e1a2660ec2 162 * @return BLE_ERROR_NONE on success.
rgrover1 710:b2e1a2660ec2 163 */
rgrover1 710:b2e1a2660ec2 164 virtual ble_error_t setAddress(AddressType_t type, const Address_t address) {
rgrover1 734:4872b70437ce 165 /* avoid compiler warnings about unused variables */
rgrover1 734:4872b70437ce 166 (void)type;
rgrover1 734:4872b70437ce 167 (void)address;
rgrover1 734:4872b70437ce 168
rgrover1 728:997ba5e7b3b6 169 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 170 }
rgrover1 710:b2e1a2660ec2 171
rgrover1 710:b2e1a2660ec2 172 /**
rgrover1 710:b2e1a2660ec2 173 * Fetch the BTLE MAC address and type.
rgrover1 710:b2e1a2660ec2 174 *
rgrover1 710:b2e1a2660ec2 175 * @return BLE_ERROR_NONE on success.
rgrover1 710:b2e1a2660ec2 176 */
rgrover1 710:b2e1a2660ec2 177 virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address) {
vcoubard 1048:efb29faf12fc 178 /* Avoid compiler warnings about unused variables. */
rgrover1 734:4872b70437ce 179 (void)typeP;
rgrover1 734:4872b70437ce 180 (void)address;
rgrover1 734:4872b70437ce 181
rgrover1 728:997ba5e7b3b6 182 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 183 }
rgrover1 710:b2e1a2660ec2 184
rgrover1 710:b2e1a2660ec2 185 /**
vcoubard 1056:ce2fb3d09929 186 * @return Minimum Advertising interval in milliseconds for connectable
vcoubard 1056:ce2fb3d09929 187 * undirected and connectable directed event types.
rgrover1 710:b2e1a2660ec2 188 */
rgrover1 710:b2e1a2660ec2 189 virtual uint16_t getMinAdvertisingInterval(void) const {
rgrover1 742:861ed7eb186d 190 return 0; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 191 }
rgrover1 710:b2e1a2660ec2 192
rgrover1 710:b2e1a2660ec2 193 /**
vcoubard 1056:ce2fb3d09929 194 * @return Minimum Advertising interval in milliseconds for scannable
vcoubard 1056:ce2fb3d09929 195 * undirected and non-connectable undirected event types.
rgrover1 710:b2e1a2660ec2 196 */
rgrover1 710:b2e1a2660ec2 197 virtual uint16_t getMinNonConnectableAdvertisingInterval(void) const {
rgrover1 742:861ed7eb186d 198 return 0; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 199 }
rgrover1 710:b2e1a2660ec2 200
rgrover1 710:b2e1a2660ec2 201 /**
rgrover1 710:b2e1a2660ec2 202 * @return Maximum Advertising interval in milliseconds.
rgrover1 710:b2e1a2660ec2 203 */
rgrover1 710:b2e1a2660ec2 204 virtual uint16_t getMaxAdvertisingInterval(void) const {
rgrover1 742:861ed7eb186d 205 return 0xFFFF; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 206 }
rgrover1 710:b2e1a2660ec2 207
rgrover1 710:b2e1a2660ec2 208 virtual ble_error_t stopAdvertising(void) {
rgrover1 728:997ba5e7b3b6 209 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 210 }
rgrover1 710:b2e1a2660ec2 211
rgrover1 710:b2e1a2660ec2 212 /**
rgrover1 710:b2e1a2660ec2 213 * Stop scanning. The current scanning parameters remain in effect.
rgrover1 710:b2e1a2660ec2 214 *
rgrover1 710:b2e1a2660ec2 215 * @retval BLE_ERROR_NONE if successfully stopped scanning procedure.
rgrover1 710:b2e1a2660ec2 216 */
rgrover1 710:b2e1a2660ec2 217 virtual ble_error_t stopScan() {
rgrover1 728:997ba5e7b3b6 218 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 219 }
rgrover1 710:b2e1a2660ec2 220
rgrover1 710:b2e1a2660ec2 221 /**
rgrover1 710:b2e1a2660ec2 222 * Create a connection (GAP Link Establishment).
rgrover1 710:b2e1a2660ec2 223 *
rgrover1 710:b2e1a2660ec2 224 * @param peerAddr
rgrover1 710:b2e1a2660ec2 225 * 48-bit address, LSB format.
rgrover1 710:b2e1a2660ec2 226 * @param peerAddrType
rgrover1 710:b2e1a2660ec2 227 * Address type of the peer.
rgrover1 710:b2e1a2660ec2 228 * @param connectionParams
rgrover1 710:b2e1a2660ec2 229 * Connection parameters.
rgrover1 710:b2e1a2660ec2 230 * @param scanParams
rgrover1 710:b2e1a2660ec2 231 * Paramters to be used while scanning for the peer.
rgrover1 710:b2e1a2660ec2 232 * @return BLE_ERROR_NONE if connection establishment procedure is started
rgrover1 829:9072de50087b 233 * successfully. The connectionCallChain (if set) will be invoked upon
rgrover1 710:b2e1a2660ec2 234 * a connection event.
rgrover1 710:b2e1a2660ec2 235 */
rgrover1 710:b2e1a2660ec2 236 virtual ble_error_t connect(const Address_t peerAddr,
rgrover1 710:b2e1a2660ec2 237 Gap::AddressType_t peerAddrType,
rgrover1 710:b2e1a2660ec2 238 const ConnectionParams_t *connectionParams,
rgrover1 710:b2e1a2660ec2 239 const GapScanningParams *scanParams) {
vcoubard 1048:efb29faf12fc 240 /* Avoid compiler warnings about unused variables. */
rgrover1 734:4872b70437ce 241 (void)peerAddr;
rgrover1 734:4872b70437ce 242 (void)peerAddrType;
rgrover1 734:4872b70437ce 243 (void)connectionParams;
rgrover1 734:4872b70437ce 244 (void)scanParams;
rgrover1 734:4872b70437ce 245
rgrover1 728:997ba5e7b3b6 246 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 247 }
rgrover1 710:b2e1a2660ec2 248
rgrover1 710:b2e1a2660ec2 249 /**
rgrover1 710:b2e1a2660ec2 250 * This call initiates the disconnection procedure, and its completion will
rgrover1 710:b2e1a2660ec2 251 * be communicated to the application with an invocation of the
rgrover1 710:b2e1a2660ec2 252 * disconnectionCallback.
rgrover1 710:b2e1a2660ec2 253 *
rgrover1 710:b2e1a2660ec2 254 * @param reason
vcoubard 1048:efb29faf12fc 255 * The reason for disconnection; to be sent back to the peer.
rgrover1 710:b2e1a2660ec2 256 */
rgrover1 710:b2e1a2660ec2 257 virtual ble_error_t disconnect(Handle_t connectionHandle, DisconnectionReason_t reason) {
rgrover1 734:4872b70437ce 258 /* avoid compiler warnings about unused variables */
rgrover1 734:4872b70437ce 259 (void)connectionHandle;
rgrover1 734:4872b70437ce 260 (void)reason;
rgrover1 734:4872b70437ce 261
rgrover1 728:997ba5e7b3b6 262 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 263 }
rgrover1 710:b2e1a2660ec2 264
rgrover1 710:b2e1a2660ec2 265 /**
rgrover1 710:b2e1a2660ec2 266 * This call initiates the disconnection procedure, and its completion will
rgrover1 710:b2e1a2660ec2 267 * be communicated to the application with an invocation of the
rgrover1 710:b2e1a2660ec2 268 * disconnectionCallback.
rgrover1 710:b2e1a2660ec2 269 *
rgrover1 710:b2e1a2660ec2 270 * @param reason
vcoubard 1048:efb29faf12fc 271 * The reason for disconnection; to be sent back to the peer.
rgrover1 710:b2e1a2660ec2 272 *
vcoubard 1048:efb29faf12fc 273 * @note: This version of disconnect() doesn't take a connection handle. It
vcoubard 1048:efb29faf12fc 274 * works reliably only for stacks that are limited to a single
rgrover1 710:b2e1a2660ec2 275 * connection. This API should be considered *deprecated* in favour of the
vcoubard 1048:efb29faf12fc 276 * alternative, which takes a connection handle. It will be dropped in the future.
rgrover1 710:b2e1a2660ec2 277 */
rgrover1 710:b2e1a2660ec2 278 virtual ble_error_t disconnect(DisconnectionReason_t reason) {
vcoubard 1048:efb29faf12fc 279 /* Avoid compiler warnings about unused variables. */
rgrover1 734:4872b70437ce 280 (void)reason;
rgrover1 734:4872b70437ce 281
rgrover1 728:997ba5e7b3b6 282 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 283 }
rgrover1 710:b2e1a2660ec2 284
rgrover1 710:b2e1a2660ec2 285 /**
rgrover1 710:b2e1a2660ec2 286 * Get the GAP peripheral preferred connection parameters. These are the
rgrover1 710:b2e1a2660ec2 287 * defaults that the peripheral would like to have in a connection. The
rgrover1 710:b2e1a2660ec2 288 * choice of the connection parameters is eventually up to the central.
rgrover1 710:b2e1a2660ec2 289 *
rgrover1 710:b2e1a2660ec2 290 * @param[out] params
rgrover1 710:b2e1a2660ec2 291 * The structure where the parameters will be stored. Memory
rgrover1 710:b2e1a2660ec2 292 * for this is owned by the caller.
rgrover1 710:b2e1a2660ec2 293 *
rgrover1 710:b2e1a2660ec2 294 * @return BLE_ERROR_NONE if the parameters were successfully filled into
rgrover1 710:b2e1a2660ec2 295 * the given structure pointed to by params.
rgrover1 710:b2e1a2660ec2 296 */
rgrover1 710:b2e1a2660ec2 297 virtual ble_error_t getPreferredConnectionParams(ConnectionParams_t *params) {
vcoubard 1048:efb29faf12fc 298 /* Avoid compiler warnings about unused variables. */
rgrover1 734:4872b70437ce 299 (void)params;
rgrover1 734:4872b70437ce 300
rgrover1 728:997ba5e7b3b6 301 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 302 }
rgrover1 710:b2e1a2660ec2 303
rgrover1 710:b2e1a2660ec2 304 /**
rgrover1 710:b2e1a2660ec2 305 * Set the GAP peripheral preferred connection parameters. These are the
rgrover1 710:b2e1a2660ec2 306 * defaults that the peripheral would like to have in a connection. The
rgrover1 710:b2e1a2660ec2 307 * choice of the connection parameters is eventually up to the central.
rgrover1 710:b2e1a2660ec2 308 *
rgrover1 710:b2e1a2660ec2 309 * @param[in] params
rgrover1 710:b2e1a2660ec2 310 * The structure containing the desired parameters.
rgrover1 710:b2e1a2660ec2 311 */
rgrover1 710:b2e1a2660ec2 312 virtual ble_error_t setPreferredConnectionParams(const ConnectionParams_t *params) {
vcoubard 1048:efb29faf12fc 313 /* Avoid compiler warnings about unused variables. */
rgrover1 734:4872b70437ce 314 (void)params;
rgrover1 734:4872b70437ce 315
rgrover1 728:997ba5e7b3b6 316 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 317 }
rgrover1 710:b2e1a2660ec2 318
rgrover1 710:b2e1a2660ec2 319 /**
rgrover1 816:2b4f0ef8c06e 320 * Update connection parameters.
vcoubard 1048:efb29faf12fc 321 * In the central role this will initiate a Link Layer connection parameter update procedure.
vcoubard 1048:efb29faf12fc 322 * In the peripheral role, this will send the corresponding L2CAP request and wait for
rgrover1 816:2b4f0ef8c06e 323 * the central to perform the procedure.
rgrover1 816:2b4f0ef8c06e 324 *
rgrover1 710:b2e1a2660ec2 325 * @param[in] handle
vcoubard 1048:efb29faf12fc 326 * Connection Handle.
rgrover1 710:b2e1a2660ec2 327 * @param[in] params
rgrover1 710:b2e1a2660ec2 328 * Pointer to desired connection parameters. If NULL is provided on a peripheral role,
rgrover1 710:b2e1a2660ec2 329 * the parameters in the PPCP characteristic of the GAP service will be used instead.
rgrover1 710:b2e1a2660ec2 330 */
rgrover1 710:b2e1a2660ec2 331 virtual ble_error_t updateConnectionParams(Handle_t handle, const ConnectionParams_t *params) {
rgrover1 734:4872b70437ce 332 /* avoid compiler warnings about unused variables */
rgrover1 734:4872b70437ce 333 (void)handle;
rgrover1 734:4872b70437ce 334 (void)params;
rgrover1 734:4872b70437ce 335
rgrover1 728:997ba5e7b3b6 336 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 337 }
rgrover1 710:b2e1a2660ec2 338
rgrover1 710:b2e1a2660ec2 339 /**
rgrover1 710:b2e1a2660ec2 340 * Set the device name characteristic in the GAP service.
rgrover1 710:b2e1a2660ec2 341 * @param[in] deviceName
rgrover1 710:b2e1a2660ec2 342 * The new value for the device-name. This is a UTF-8 encoded, <b>NULL-terminated</b> string.
rgrover1 710:b2e1a2660ec2 343 */
rgrover1 710:b2e1a2660ec2 344 virtual ble_error_t setDeviceName(const uint8_t *deviceName) {
vcoubard 1048:efb29faf12fc 345 /* Avoid compiler warnings about unused variables. */
rgrover1 734:4872b70437ce 346 (void)deviceName;
rgrover1 734:4872b70437ce 347
rgrover1 728:997ba5e7b3b6 348 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 349 }
rgrover1 710:b2e1a2660ec2 350
rgrover1 710:b2e1a2660ec2 351 /**
rgrover1 710:b2e1a2660ec2 352 * Get the value of the device name characteristic in the GAP service.
rgrover1 710:b2e1a2660ec2 353 * @param[out] deviceName
rgrover1 710:b2e1a2660ec2 354 * Pointer to an empty buffer where the UTF-8 *non NULL-
rgrover1 710:b2e1a2660ec2 355 * terminated* string will be placed. Set this
rgrover1 710:b2e1a2660ec2 356 * value to NULL in order to obtain the deviceName-length
rgrover1 710:b2e1a2660ec2 357 * from the 'length' parameter.
rgrover1 710:b2e1a2660ec2 358 *
rgrover1 710:b2e1a2660ec2 359 * @param[in/out] lengthP
rgrover1 710:b2e1a2660ec2 360 * (on input) Length of the buffer pointed to by deviceName;
rgrover1 710:b2e1a2660ec2 361 * (on output) the complete device name length (without the
rgrover1 710:b2e1a2660ec2 362 * null terminator).
rgrover1 710:b2e1a2660ec2 363 *
rgrover1 710:b2e1a2660ec2 364 * @note If the device name is longer than the size of the supplied buffer,
rgrover1 710:b2e1a2660ec2 365 * length will return the complete device name length, and not the
rgrover1 710:b2e1a2660ec2 366 * number of bytes actually returned in deviceName. The application may
rgrover1 710:b2e1a2660ec2 367 * use this information to retry with a suitable buffer size.
rgrover1 710:b2e1a2660ec2 368 */
rgrover1 710:b2e1a2660ec2 369 virtual ble_error_t getDeviceName(uint8_t *deviceName, unsigned *lengthP) {
rgrover1 734:4872b70437ce 370 /* avoid compiler warnings about unused variables */
rgrover1 734:4872b70437ce 371 (void)deviceName;
rgrover1 734:4872b70437ce 372 (void)lengthP;
rgrover1 734:4872b70437ce 373
rgrover1 728:997ba5e7b3b6 374 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 375 }
rgrover1 710:b2e1a2660ec2 376
rgrover1 710:b2e1a2660ec2 377 /**
rgrover1 710:b2e1a2660ec2 378 * Set the appearance characteristic in the GAP service.
rgrover1 710:b2e1a2660ec2 379 * @param[in] appearance
rgrover1 710:b2e1a2660ec2 380 * The new value for the device-appearance.
rgrover1 710:b2e1a2660ec2 381 */
rgrover1 710:b2e1a2660ec2 382 virtual ble_error_t setAppearance(GapAdvertisingData::Appearance appearance) {
vcoubard 1048:efb29faf12fc 383 /* Avoid compiler warnings about unused variables. */
rgrover1 734:4872b70437ce 384 (void)appearance;
rgrover1 734:4872b70437ce 385
rgrover1 728:997ba5e7b3b6 386 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 387 }
rgrover1 710:b2e1a2660ec2 388
rgrover1 710:b2e1a2660ec2 389 /**
rgrover1 710:b2e1a2660ec2 390 * Get the appearance characteristic in the GAP service.
rgrover1 710:b2e1a2660ec2 391 * @param[out] appearance
rgrover1 710:b2e1a2660ec2 392 * The new value for the device-appearance.
rgrover1 710:b2e1a2660ec2 393 */
rgrover1 710:b2e1a2660ec2 394 virtual ble_error_t getAppearance(GapAdvertisingData::Appearance *appearanceP) {
vcoubard 1048:efb29faf12fc 395 /* Avoid compiler warnings about unused variables. */
rgrover1 734:4872b70437ce 396 (void)appearanceP;
rgrover1 734:4872b70437ce 397
rgrover1 728:997ba5e7b3b6 398 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 399 }
rgrover1 710:b2e1a2660ec2 400
rgrover1 710:b2e1a2660ec2 401 /**
rgrover1 710:b2e1a2660ec2 402 * Set the radio's transmit power.
rgrover1 710:b2e1a2660ec2 403 * @param[in] txPower Radio transmit power in dBm.
rgrover1 710:b2e1a2660ec2 404 */
rgrover1 710:b2e1a2660ec2 405 virtual ble_error_t setTxPower(int8_t txPower) {
vcoubard 1048:efb29faf12fc 406 /* Avoid compiler warnings about unused variables. */
rgrover1 734:4872b70437ce 407 (void)txPower;
rgrover1 734:4872b70437ce 408
rgrover1 728:997ba5e7b3b6 409 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 410 }
rgrover1 710:b2e1a2660ec2 411
rgrover1 710:b2e1a2660ec2 412 /**
rgrover1 710:b2e1a2660ec2 413 * Query the underlying stack for permitted arguments for setTxPower().
rgrover1 710:b2e1a2660ec2 414 *
rgrover1 710:b2e1a2660ec2 415 * @param[out] valueArrayPP
rgrover1 710:b2e1a2660ec2 416 * Out parameter to receive the immutable array of Tx values.
rgrover1 710:b2e1a2660ec2 417 * @param[out] countP
rgrover1 710:b2e1a2660ec2 418 * Out parameter to receive the array's size.
rgrover1 710:b2e1a2660ec2 419 */
rgrover1 710:b2e1a2660ec2 420 virtual void getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP) {
vcoubard 1048:efb29faf12fc 421 /* Avoid compiler warnings about unused variables. */
rgrover1 734:4872b70437ce 422 (void)valueArrayPP;
rgrover1 734:4872b70437ce 423 (void)countP;
rgrover1 734:4872b70437ce 424
rgrover1 742:861ed7eb186d 425 *countP = 0; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 426 }
rgrover1 710:b2e1a2660ec2 427
rgrover1 710:b2e1a2660ec2 428 protected:
rgrover1 710:b2e1a2660ec2 429 /* Override the following in the underlying adaptation layer to provide the functionality of scanning. */
rgrover1 710:b2e1a2660ec2 430 virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams) {
rgrover1 772:b6d27ab66c94 431 (void)scanningParams;
rgrover1 728:997ba5e7b3b6 432 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 710:b2e1a2660ec2 433 }
rgrover1 710:b2e1a2660ec2 434
rgrover1 710:b2e1a2660ec2 435 /*
rgrover1 710:b2e1a2660ec2 436 * APIs with non-virtual implementations.
rgrover1 710:b2e1a2660ec2 437 */
rgrover1 710:b2e1a2660ec2 438 public:
rgrover1 710:b2e1a2660ec2 439 /**
vcoubard 1048:efb29faf12fc 440 * Returns the current GAP state of the device using a bitmask that
vcoubard 1048:efb29faf12fc 441 * describes whether the device is advertising or connected.
rgrover1 710:b2e1a2660ec2 442 */
rgrover1 710:b2e1a2660ec2 443 GapState_t getState(void) const {
rgrover1 710:b2e1a2660ec2 444 return state;
rgrover1 710:b2e1a2660ec2 445 }
rgrover1 710:b2e1a2660ec2 446
rgrover1 710:b2e1a2660ec2 447 /**
rgrover1 710:b2e1a2660ec2 448 * Set the GAP advertising mode to use for this device.
rgrover1 710:b2e1a2660ec2 449 */
rgrover1 710:b2e1a2660ec2 450 void setAdvertisingType(GapAdvertisingParams::AdvertisingType_t advType) {
rgrover1 710:b2e1a2660ec2 451 _advParams.setAdvertisingType(advType);
rgrover1 710:b2e1a2660ec2 452 }
rgrover1 710:b2e1a2660ec2 453
rgrover1 710:b2e1a2660ec2 454 /**
rgrover1 710:b2e1a2660ec2 455 * @param[in] interval
rgrover1 710:b2e1a2660ec2 456 * Advertising interval in units of milliseconds. Advertising
rgrover1 710:b2e1a2660ec2 457 * is disabled if interval is 0. If interval is smaller than
rgrover1 710:b2e1a2660ec2 458 * the minimum supported value, then the minimum supported
rgrover1 710:b2e1a2660ec2 459 * value is used instead. This minimum value can be discovered
rgrover1 710:b2e1a2660ec2 460 * using getMinAdvertisingInterval().
rgrover1 710:b2e1a2660ec2 461 *
rgrover1 710:b2e1a2660ec2 462 * This field must be set to 0 if connectionMode is equal
rgrover1 710:b2e1a2660ec2 463 * to ADV_CONNECTABLE_DIRECTED.
rgrover1 710:b2e1a2660ec2 464 *
rgrover1 710:b2e1a2660ec2 465 * @note: Decreasing this value will allow central devices to detect a
vcoubard 1048:efb29faf12fc 466 * peripheral faster, at the expense of more power being used by the radio
rgrover1 710:b2e1a2660ec2 467 * due to the higher data transmit rate.
rgrover1 710:b2e1a2660ec2 468 *
rgrover1 710:b2e1a2660ec2 469 * @Note: [WARNING] This API previously used 0.625ms as the unit for its
rgrover1 710:b2e1a2660ec2 470 * 'interval' argument. That required an explicit conversion from
rgrover1 710:b2e1a2660ec2 471 * milliseconds using Gap::MSEC_TO_GAP_DURATION_UNITS(). This conversion is
rgrover1 710:b2e1a2660ec2 472 * no longer required as the new units are milliseconds. Any application
vcoubard 1048:efb29faf12fc 473 * code depending on the old semantics needs to be updated accordingly.
rgrover1 710:b2e1a2660ec2 474 */
rgrover1 710:b2e1a2660ec2 475 void setAdvertisingInterval(uint16_t interval) {
rgrover1 710:b2e1a2660ec2 476 if (interval == 0) {
rgrover1 710:b2e1a2660ec2 477 stopAdvertising();
rgrover1 710:b2e1a2660ec2 478 } else if (interval < getMinAdvertisingInterval()) {
rgrover1 710:b2e1a2660ec2 479 interval = getMinAdvertisingInterval();
rgrover1 710:b2e1a2660ec2 480 }
rgrover1 786:d6d7087d8377 481 _advParams.setInterval(interval);
rgrover1 710:b2e1a2660ec2 482 }
rgrover1 710:b2e1a2660ec2 483
rgrover1 710:b2e1a2660ec2 484 /**
rgrover1 710:b2e1a2660ec2 485 * @param[in] timeout
rgrover1 710:b2e1a2660ec2 486 * Advertising timeout (in seconds) between 0x1 and 0x3FFF (1
rgrover1 710:b2e1a2660ec2 487 * and 16383). Use 0 to disable the advertising timeout.
rgrover1 710:b2e1a2660ec2 488 */
rgrover1 710:b2e1a2660ec2 489 void setAdvertisingTimeout(uint16_t timeout) {
rgrover1 710:b2e1a2660ec2 490 _advParams.setTimeout(timeout);
rgrover1 710:b2e1a2660ec2 491 }
rgrover1 710:b2e1a2660ec2 492
rgrover1 710:b2e1a2660ec2 493 /**
rgrover1 710:b2e1a2660ec2 494 * Start advertising.
rgrover1 710:b2e1a2660ec2 495 */
rgrover1 710:b2e1a2660ec2 496 ble_error_t startAdvertising(void) {
vcoubard 1048:efb29faf12fc 497 setAdvertisingData(); /* Update the underlying stack. */
rgrover1 710:b2e1a2660ec2 498 return startAdvertising(_advParams);
rgrover1 710:b2e1a2660ec2 499 }
rgrover1 710:b2e1a2660ec2 500
rgrover1 710:b2e1a2660ec2 501 /**
rgrover1 710:b2e1a2660ec2 502 * Reset any advertising payload prepared from prior calls to
rgrover1 710:b2e1a2660ec2 503 * accumulateAdvertisingPayload(). This automatically propagates the re-
vcoubard 1048:efb29faf12fc 504 * initialized advertising payload to the underlying stack.
rgrover1 710:b2e1a2660ec2 505 */
rgrover1 710:b2e1a2660ec2 506 void clearAdvertisingPayload(void) {
rgrover1 710:b2e1a2660ec2 507 _advPayload.clear();
rgrover1 710:b2e1a2660ec2 508 setAdvertisingData();
rgrover1 710:b2e1a2660ec2 509 }
rgrover1 710:b2e1a2660ec2 510
rgrover1 710:b2e1a2660ec2 511 /**
rgrover1 710:b2e1a2660ec2 512 * Accumulate an AD structure in the advertising payload. Please note that
rgrover1 710:b2e1a2660ec2 513 * the payload is limited to 31 bytes. The SCAN_RESPONSE message may be used
vcoubard 1048:efb29faf12fc 514 * as an additional 31 bytes if the advertising payload is too
rgrover1 710:b2e1a2660ec2 515 * small.
rgrover1 710:b2e1a2660ec2 516 *
rgrover1 710:b2e1a2660ec2 517 * @param[in] flags
rgrover1 710:b2e1a2660ec2 518 * The flags to be added. Please refer to
rgrover1 710:b2e1a2660ec2 519 * GapAdvertisingData::Flags for valid flags. Multiple
rgrover1 710:b2e1a2660ec2 520 * flags may be specified in combination.
rgrover1 710:b2e1a2660ec2 521 */
rgrover1 710:b2e1a2660ec2 522 ble_error_t accumulateAdvertisingPayload(uint8_t flags) {
rgrover1 710:b2e1a2660ec2 523 ble_error_t rc;
rgrover1 710:b2e1a2660ec2 524 if ((rc = _advPayload.addFlags(flags)) != BLE_ERROR_NONE) {
rgrover1 710:b2e1a2660ec2 525 return rc;
rgrover1 710:b2e1a2660ec2 526 }
rgrover1 710:b2e1a2660ec2 527
rgrover1 710:b2e1a2660ec2 528 return setAdvertisingData();
rgrover1 710:b2e1a2660ec2 529 }
rgrover1 710:b2e1a2660ec2 530
rgrover1 710:b2e1a2660ec2 531 /**
rgrover1 710:b2e1a2660ec2 532 * Accumulate an AD structure in the advertising payload. Please note that
rgrover1 710:b2e1a2660ec2 533 * the payload is limited to 31 bytes. The SCAN_RESPONSE message may be used
vcoubard 1048:efb29faf12fc 534 * as an additional 31 bytes if the advertising payload is too
rgrover1 710:b2e1a2660ec2 535 * small.
rgrover1 710:b2e1a2660ec2 536 *
rgrover1 710:b2e1a2660ec2 537 * @param app
rgrover1 710:b2e1a2660ec2 538 * The appearance of the peripheral.
rgrover1 710:b2e1a2660ec2 539 */
rgrover1 710:b2e1a2660ec2 540 ble_error_t accumulateAdvertisingPayload(GapAdvertisingData::Appearance app) {
rgrover1 710:b2e1a2660ec2 541 setAppearance(app);
rgrover1 710:b2e1a2660ec2 542
rgrover1 710:b2e1a2660ec2 543 ble_error_t rc;
rgrover1 710:b2e1a2660ec2 544 if ((rc = _advPayload.addAppearance(app)) != BLE_ERROR_NONE) {
rgrover1 710:b2e1a2660ec2 545 return rc;
rgrover1 710:b2e1a2660ec2 546 }
rgrover1 710:b2e1a2660ec2 547
rgrover1 710:b2e1a2660ec2 548 return setAdvertisingData();
rgrover1 710:b2e1a2660ec2 549 }
rgrover1 710:b2e1a2660ec2 550
rgrover1 710:b2e1a2660ec2 551 /**
rgrover1 710:b2e1a2660ec2 552 * Accumulate an AD structure in the advertising payload. Please note that
rgrover1 710:b2e1a2660ec2 553 * the payload is limited to 31 bytes. The SCAN_RESPONSE message may be used
vcoubard 1048:efb29faf12fc 554 * as an additional 31 bytes if the advertising payload is too
rgrover1 710:b2e1a2660ec2 555 * small.
rgrover1 710:b2e1a2660ec2 556 *
vcoubard 1048:efb29faf12fc 557 * @param power
rgrover1 764:1e560f0d45e1 558 * The max transmit power to be used by the controller (in dBm).
rgrover1 710:b2e1a2660ec2 559 */
rgrover1 710:b2e1a2660ec2 560 ble_error_t accumulateAdvertisingPayloadTxPower(int8_t power) {
rgrover1 710:b2e1a2660ec2 561 ble_error_t rc;
rgrover1 710:b2e1a2660ec2 562 if ((rc = _advPayload.addTxPower(power)) != BLE_ERROR_NONE) {
rgrover1 710:b2e1a2660ec2 563 return rc;
rgrover1 710:b2e1a2660ec2 564 }
rgrover1 710:b2e1a2660ec2 565
rgrover1 710:b2e1a2660ec2 566 return setAdvertisingData();
rgrover1 710:b2e1a2660ec2 567 }
rgrover1 710:b2e1a2660ec2 568
rgrover1 710:b2e1a2660ec2 569 /**
rgrover1 710:b2e1a2660ec2 570 * Accumulate a variable length byte-stream as an AD structure in the
rgrover1 710:b2e1a2660ec2 571 * advertising payload. Please note that the payload is limited to 31 bytes.
rgrover1 710:b2e1a2660ec2 572 * The SCAN_RESPONSE message may be used as an additional 31 bytes if the
vcoubard 1048:efb29faf12fc 573 * advertising payload is too small.
rgrover1 710:b2e1a2660ec2 574 *
vcoubard 1048:efb29faf12fc 575 * @param type The type describing the variable length data.
vcoubard 1048:efb29faf12fc 576 * @param data Data bytes.
vcoubard 1048:efb29faf12fc 577 * @param len Length of data.
rgrover1 710:b2e1a2660ec2 578 */
rgrover1 710:b2e1a2660ec2 579 ble_error_t accumulateAdvertisingPayload(GapAdvertisingData::DataType type, const uint8_t *data, uint8_t len) {
rgrover1 710:b2e1a2660ec2 580 if (type == GapAdvertisingData::COMPLETE_LOCAL_NAME) {
rgrover1 710:b2e1a2660ec2 581 setDeviceName(data);
rgrover1 710:b2e1a2660ec2 582 }
rgrover1 710:b2e1a2660ec2 583
rgrover1 710:b2e1a2660ec2 584 ble_error_t rc;
rgrover1 710:b2e1a2660ec2 585 if ((rc = _advPayload.addData(type, data, len)) != BLE_ERROR_NONE) {
rgrover1 710:b2e1a2660ec2 586 return rc;
rgrover1 710:b2e1a2660ec2 587 }
rgrover1 710:b2e1a2660ec2 588
rgrover1 710:b2e1a2660ec2 589 return setAdvertisingData();
rgrover1 710:b2e1a2660ec2 590 }
rgrover1 710:b2e1a2660ec2 591
rgrover1 710:b2e1a2660ec2 592 /**
rgrover1 765:4cd91998cd48 593 * Update a particular ADV field in the advertising payload (based on
rgrover1 765:4cd91998cd48 594 * matching type and length). Note: the length of the new data must be the
rgrover1 765:4cd91998cd48 595 * same as the old one.
rgrover1 763:36c3e2b1f1ae 596 *
vcoubard 1048:efb29faf12fc 597 * @param[in] type The ADV type field describing the variable length data.
vcoubard 1048:efb29faf12fc 598 * @param[in] data Data bytes.
vcoubard 1048:efb29faf12fc 599 * @param[in] len Length of data.
rgrover1 765:4cd91998cd48 600 *
rgrover1 765:4cd91998cd48 601 * @note: If advertisements are enabled, then the update will take effect immediately.
rgrover1 765:4cd91998cd48 602 *
rgrover1 765:4cd91998cd48 603 * @return BLE_ERROR_NONE if the advertisement payload was updated based on
vcoubard 1048:efb29faf12fc 604 * a <type, len> match; otherwise, an appropriate error.
rgrover1 763:36c3e2b1f1ae 605 */
rgrover1 763:36c3e2b1f1ae 606 ble_error_t updateAdvertisingPayload(GapAdvertisingData::DataType type, const uint8_t *data, uint8_t len) {
rgrover1 763:36c3e2b1f1ae 607 if (type == GapAdvertisingData::COMPLETE_LOCAL_NAME) {
rgrover1 763:36c3e2b1f1ae 608 setDeviceName(data);
rgrover1 763:36c3e2b1f1ae 609 }
rgrover1 763:36c3e2b1f1ae 610
rgrover1 763:36c3e2b1f1ae 611 ble_error_t rc;
rgrover1 763:36c3e2b1f1ae 612 if ((rc = _advPayload.updateData(type, data, len)) != BLE_ERROR_NONE) {
rgrover1 763:36c3e2b1f1ae 613 return rc;
rgrover1 763:36c3e2b1f1ae 614 }
rgrover1 763:36c3e2b1f1ae 615
rgrover1 763:36c3e2b1f1ae 616 return setAdvertisingData();
rgrover1 763:36c3e2b1f1ae 617 }
rgrover1 763:36c3e2b1f1ae 618
rgrover1 763:36c3e2b1f1ae 619 /**
vcoubard 1048:efb29faf12fc 620 * Set up a particular, user-constructed advertisement payload for the
rgrover1 710:b2e1a2660ec2 621 * underlying stack. It would be uncommon for this API to be used directly;
rgrover1 710:b2e1a2660ec2 622 * there are other APIs to build an advertisement payload (see above).
rgrover1 710:b2e1a2660ec2 623 */
rgrover1 710:b2e1a2660ec2 624 ble_error_t setAdvertisingPayload(const GapAdvertisingData &payload) {
rgrover1 710:b2e1a2660ec2 625 _advPayload = payload;
rgrover1 710:b2e1a2660ec2 626 return setAdvertisingData();
rgrover1 710:b2e1a2660ec2 627 }
rgrover1 710:b2e1a2660ec2 628
rgrover1 710:b2e1a2660ec2 629 /**
rgrover1 710:b2e1a2660ec2 630 * @return Read back advertising data. Useful for storing and
rgrover1 710:b2e1a2660ec2 631 * restoring payload.
rgrover1 710:b2e1a2660ec2 632 */
rgrover1 710:b2e1a2660ec2 633 const GapAdvertisingData &getAdvertisingPayload(void) const {
rgrover1 710:b2e1a2660ec2 634 return _advPayload;
rgrover1 710:b2e1a2660ec2 635 }
rgrover1 710:b2e1a2660ec2 636
rgrover1 710:b2e1a2660ec2 637 /**
rgrover1 710:b2e1a2660ec2 638 * Accumulate a variable length byte-stream as an AD structure in the
rgrover1 710:b2e1a2660ec2 639 * scanResponse payload.
rgrover1 710:b2e1a2660ec2 640 *
vcoubard 1048:efb29faf12fc 641 * @param[in] type The type describing the variable length data.
vcoubard 1048:efb29faf12fc 642 * @param[in] data Data bytes.
vcoubard 1048:efb29faf12fc 643 * @param[in] len Length of data.
rgrover1 710:b2e1a2660ec2 644 */
rgrover1 710:b2e1a2660ec2 645 ble_error_t accumulateScanResponse(GapAdvertisingData::DataType type, const uint8_t *data, uint8_t len) {
rgrover1 710:b2e1a2660ec2 646 ble_error_t rc;
rgrover1 710:b2e1a2660ec2 647 if ((rc = _scanResponse.addData(type, data, len)) != BLE_ERROR_NONE) {
rgrover1 710:b2e1a2660ec2 648 return rc;
rgrover1 710:b2e1a2660ec2 649 }
rgrover1 710:b2e1a2660ec2 650
rgrover1 710:b2e1a2660ec2 651 return setAdvertisingData();
rgrover1 710:b2e1a2660ec2 652 }
rgrover1 710:b2e1a2660ec2 653
rgrover1 710:b2e1a2660ec2 654 /**
rgrover1 710:b2e1a2660ec2 655 * Reset any scan response prepared from prior calls to
rgrover1 710:b2e1a2660ec2 656 * accumulateScanResponse().
rgrover1 710:b2e1a2660ec2 657 *
rgrover1 710:b2e1a2660ec2 658 * Note: This should be followed by a call to setAdvertisingPayload() or
rgrover1 710:b2e1a2660ec2 659 * startAdvertising() before the update takes effect.
rgrover1 710:b2e1a2660ec2 660 */
rgrover1 710:b2e1a2660ec2 661 void clearScanResponse(void) {
rgrover1 710:b2e1a2660ec2 662 _scanResponse.clear();
rgrover1 710:b2e1a2660ec2 663 setAdvertisingData();
rgrover1 710:b2e1a2660ec2 664 }
rgrover1 710:b2e1a2660ec2 665
rgrover1 710:b2e1a2660ec2 666 /**
vcoubard 1048:efb29faf12fc 667 * Set up parameters for GAP scanning (observer mode).
rgrover1 710:b2e1a2660ec2 668 * @param[in] interval
rgrover1 710:b2e1a2660ec2 669 * Scan interval (in milliseconds) [valid values lie between 2.5ms and 10.24s].
rgrover1 710:b2e1a2660ec2 670 * @param[in] window
rgrover1 710:b2e1a2660ec2 671 * Scan Window (in milliseconds) [valid values lie between 2.5ms and 10.24s].
rgrover1 710:b2e1a2660ec2 672 * @param[in] timeout
vcoubard 1048:efb29faf12fc 673 * Scan timeout (in seconds) between 0x0001 and 0xFFFF; 0x0000 disables the timeout.
rgrover1 710:b2e1a2660ec2 674 * @param[in] activeScanning
rgrover1 710:b2e1a2660ec2 675 * Set to True if active-scanning is required. This is used to fetch the
rgrover1 710:b2e1a2660ec2 676 * scan response from a peer if possible.
rgrover1 710:b2e1a2660ec2 677 *
rgrover1 710:b2e1a2660ec2 678 * The scanning window divided by the interval determines the duty cycle for
rgrover1 710:b2e1a2660ec2 679 * scanning. For example, if the interval is 100ms and the window is 10ms,
rgrover1 710:b2e1a2660ec2 680 * then the controller will scan for 10 percent of the time. It is possible
rgrover1 710:b2e1a2660ec2 681 * to have the interval and window set to the same value. In this case,
rgrover1 710:b2e1a2660ec2 682 * scanning is continuous, with a change of scanning frequency once every
rgrover1 710:b2e1a2660ec2 683 * interval.
rgrover1 710:b2e1a2660ec2 684 *
rgrover1 710:b2e1a2660ec2 685 * Once the scanning parameters have been configured, scanning can be
rgrover1 710:b2e1a2660ec2 686 * enabled by using startScan().
rgrover1 710:b2e1a2660ec2 687 *
rgrover1 710:b2e1a2660ec2 688 * @Note: The scan interval and window are recommendations to the BLE stack.
rgrover1 710:b2e1a2660ec2 689 */
rgrover1 710:b2e1a2660ec2 690 ble_error_t setScanParams(uint16_t interval = GapScanningParams::SCAN_INTERVAL_MAX,
rgrover1 710:b2e1a2660ec2 691 uint16_t window = GapScanningParams::SCAN_WINDOW_MAX,
rgrover1 710:b2e1a2660ec2 692 uint16_t timeout = 0,
rgrover1 710:b2e1a2660ec2 693 bool activeScanning = false) {
rgrover1 710:b2e1a2660ec2 694 ble_error_t rc;
rgrover1 710:b2e1a2660ec2 695 if (((rc = _scanningParams.setInterval(interval)) == BLE_ERROR_NONE) &&
rgrover1 710:b2e1a2660ec2 696 ((rc = _scanningParams.setWindow(window)) == BLE_ERROR_NONE) &&
rgrover1 710:b2e1a2660ec2 697 ((rc = _scanningParams.setTimeout(timeout)) == BLE_ERROR_NONE)) {
rgrover1 710:b2e1a2660ec2 698 _scanningParams.setActiveScanning(activeScanning);
rgrover1 710:b2e1a2660ec2 699 return BLE_ERROR_NONE;
rgrover1 710:b2e1a2660ec2 700 }
rgrover1 710:b2e1a2660ec2 701
rgrover1 710:b2e1a2660ec2 702 return rc;
rgrover1 710:b2e1a2660ec2 703 }
rgrover1 710:b2e1a2660ec2 704
rgrover1 710:b2e1a2660ec2 705 /**
vcoubard 1048:efb29faf12fc 706 * Set up the scanInterval parameter for GAP scanning (observer mode).
rgrover1 710:b2e1a2660ec2 707 * @param[in] interval
rgrover1 710:b2e1a2660ec2 708 * Scan interval (in milliseconds) [valid values lie between 2.5ms and 10.24s].
rgrover1 710:b2e1a2660ec2 709 *
rgrover1 710:b2e1a2660ec2 710 * The scanning window divided by the interval determines the duty cycle for
rgrover1 710:b2e1a2660ec2 711 * scanning. For example, if the interval is 100ms and the window is 10ms,
rgrover1 710:b2e1a2660ec2 712 * then the controller will scan for 10 percent of the time. It is possible
rgrover1 710:b2e1a2660ec2 713 * to have the interval and window set to the same value. In this case,
rgrover1 710:b2e1a2660ec2 714 * scanning is continuous, with a change of scanning frequency once every
rgrover1 710:b2e1a2660ec2 715 * interval.
rgrover1 710:b2e1a2660ec2 716 *
rgrover1 710:b2e1a2660ec2 717 * Once the scanning parameters have been configured, scanning can be
rgrover1 710:b2e1a2660ec2 718 * enabled by using startScan().
rgrover1 710:b2e1a2660ec2 719 */
rgrover1 710:b2e1a2660ec2 720 ble_error_t setScanInterval(uint16_t interval) {
rgrover1 710:b2e1a2660ec2 721 return _scanningParams.setInterval(interval);
rgrover1 710:b2e1a2660ec2 722 }
rgrover1 710:b2e1a2660ec2 723
rgrover1 710:b2e1a2660ec2 724 /**
vcoubard 1048:efb29faf12fc 725 * Set up the scanWindow parameter for GAP scanning (observer mode).
rgrover1 710:b2e1a2660ec2 726 * @param[in] window
rgrover1 710:b2e1a2660ec2 727 * Scan Window (in milliseconds) [valid values lie between 2.5ms and 10.24s].
rgrover1 710:b2e1a2660ec2 728 *
rgrover1 710:b2e1a2660ec2 729 * The scanning window divided by the interval determines the duty cycle for
rgrover1 710:b2e1a2660ec2 730 * scanning. For example, if the interval is 100ms and the window is 10ms,
rgrover1 710:b2e1a2660ec2 731 * then the controller will scan for 10 percent of the time. It is possible
rgrover1 710:b2e1a2660ec2 732 * to have the interval and window set to the same value. In this case,
rgrover1 710:b2e1a2660ec2 733 * scanning is continuous, with a change of scanning frequency once every
rgrover1 710:b2e1a2660ec2 734 * interval.
rgrover1 710:b2e1a2660ec2 735 *
rgrover1 710:b2e1a2660ec2 736 * Once the scanning parameters have been configured, scanning can be
rgrover1 710:b2e1a2660ec2 737 * enabled by using startScan().
rgrover1 770:079b714e9c1a 738 *
rgrover1 770:079b714e9c1a 739 * If scanning is already active, the updated value of scanWindow will be
rgrover1 770:079b714e9c1a 740 * propagated to the underlying BLE stack.
rgrover1 710:b2e1a2660ec2 741 */
rgrover1 710:b2e1a2660ec2 742 ble_error_t setScanWindow(uint16_t window) {
rgrover1 770:079b714e9c1a 743 ble_error_t rc;
rgrover1 770:079b714e9c1a 744 if ((rc = _scanningParams.setWindow(window)) != BLE_ERROR_NONE) {
rgrover1 770:079b714e9c1a 745 return rc;
rgrover1 770:079b714e9c1a 746 }
rgrover1 770:079b714e9c1a 747
rgrover1 770:079b714e9c1a 748 /* If scanning is already active, propagate the new setting to the stack. */
rgrover1 770:079b714e9c1a 749 if (scanningActive) {
rgrover1 770:079b714e9c1a 750 return startRadioScan(_scanningParams);
rgrover1 770:079b714e9c1a 751 }
rgrover1 770:079b714e9c1a 752
rgrover1 770:079b714e9c1a 753 return BLE_ERROR_NONE;
rgrover1 710:b2e1a2660ec2 754 }
rgrover1 710:b2e1a2660ec2 755
rgrover1 710:b2e1a2660ec2 756 /**
vcoubard 1048:efb29faf12fc 757 * Set up parameters for GAP scanning (observer mode).
rgrover1 710:b2e1a2660ec2 758 * @param[in] timeout
vcoubard 1048:efb29faf12fc 759 * Scan timeout (in seconds) between 0x0001 and 0xFFFF; 0x0000 disables the timeout.
rgrover1 710:b2e1a2660ec2 760 *
rgrover1 710:b2e1a2660ec2 761 * Once the scanning parameters have been configured, scanning can be
rgrover1 710:b2e1a2660ec2 762 * enabled by using startScan().
rgrover1 770:079b714e9c1a 763 *
rgrover1 770:079b714e9c1a 764 * If scanning is already active, the updated value of scanTimeout will be
rgrover1 770:079b714e9c1a 765 * propagated to the underlying BLE stack.
rgrover1 710:b2e1a2660ec2 766 */
rgrover1 710:b2e1a2660ec2 767 ble_error_t setScanTimeout(uint16_t timeout) {
rgrover1 770:079b714e9c1a 768 ble_error_t rc;
rgrover1 770:079b714e9c1a 769 if ((rc = _scanningParams.setTimeout(timeout)) != BLE_ERROR_NONE) {
rgrover1 770:079b714e9c1a 770 return rc;
rgrover1 770:079b714e9c1a 771 }
rgrover1 770:079b714e9c1a 772
rgrover1 770:079b714e9c1a 773 /* If scanning is already active, propagate the new settings to the stack. */
rgrover1 770:079b714e9c1a 774 if (scanningActive) {
rgrover1 770:079b714e9c1a 775 return startRadioScan(_scanningParams);
rgrover1 770:079b714e9c1a 776 }
rgrover1 770:079b714e9c1a 777
rgrover1 770:079b714e9c1a 778 return BLE_ERROR_NONE;
rgrover1 710:b2e1a2660ec2 779 }
rgrover1 710:b2e1a2660ec2 780
rgrover1 710:b2e1a2660ec2 781 /**
vcoubard 1048:efb29faf12fc 782 * Set up parameters for GAP scanning (observer mode).
rgrover1 710:b2e1a2660ec2 783 * @param[in] activeScanning
rgrover1 710:b2e1a2660ec2 784 * Set to True if active-scanning is required. This is used to fetch the
rgrover1 710:b2e1a2660ec2 785 * scan response from a peer if possible.
rgrover1 710:b2e1a2660ec2 786 *
rgrover1 710:b2e1a2660ec2 787 * Once the scanning parameters have been configured, scanning can be
rgrover1 710:b2e1a2660ec2 788 * enabled by using startScan().
rgrover1 770:079b714e9c1a 789 *
rgrover1 770:079b714e9c1a 790 * If scanning is already in progress, then active-scanning will be enabled
rgrover1 770:079b714e9c1a 791 * for the underlying BLE stack.
rgrover1 710:b2e1a2660ec2 792 */
rgrover1 770:079b714e9c1a 793 ble_error_t setActiveScanning(bool activeScanning) {
rgrover1 710:b2e1a2660ec2 794 _scanningParams.setActiveScanning(activeScanning);
rgrover1 770:079b714e9c1a 795
rgrover1 770:079b714e9c1a 796 /* If scanning is already active, propagate the new settings to the stack. */
rgrover1 770:079b714e9c1a 797 if (scanningActive) {
rgrover1 770:079b714e9c1a 798 return startRadioScan(_scanningParams);
rgrover1 770:079b714e9c1a 799 }
rgrover1 770:079b714e9c1a 800
rgrover1 770:079b714e9c1a 801 return BLE_ERROR_NONE;
rgrover1 710:b2e1a2660ec2 802 }
rgrover1 710:b2e1a2660ec2 803
rgrover1 710:b2e1a2660ec2 804 /**
rgrover1 710:b2e1a2660ec2 805 * Start scanning (Observer Procedure) based on the parameters currently in
rgrover1 710:b2e1a2660ec2 806 * effect.
rgrover1 710:b2e1a2660ec2 807 *
rgrover1 710:b2e1a2660ec2 808 * @param[in] callback
vcoubard 1048:efb29faf12fc 809 * The application-specific callback to be invoked upon
rgrover1 710:b2e1a2660ec2 810 * receiving every advertisement report. This can be passed in
rgrover1 710:b2e1a2660ec2 811 * as NULL, in which case scanning may not be enabled at all.
rgrover1 710:b2e1a2660ec2 812 */
rgrover1 710:b2e1a2660ec2 813 ble_error_t startScan(void (*callback)(const AdvertisementCallbackParams_t *params)) {
rgrover1 710:b2e1a2660ec2 814 ble_error_t err = BLE_ERROR_NONE;
rgrover1 710:b2e1a2660ec2 815 if (callback) {
rgrover1 710:b2e1a2660ec2 816 if ((err = startRadioScan(_scanningParams)) == BLE_ERROR_NONE) {
rgrover1 770:079b714e9c1a 817 scanningActive = true;
rgrover1 710:b2e1a2660ec2 818 onAdvertisementReport.attach(callback);
rgrover1 710:b2e1a2660ec2 819 }
rgrover1 710:b2e1a2660ec2 820 }
rgrover1 710:b2e1a2660ec2 821
rgrover1 710:b2e1a2660ec2 822 return err;
rgrover1 710:b2e1a2660ec2 823 }
rgrover1 710:b2e1a2660ec2 824
rgrover1 710:b2e1a2660ec2 825 /**
rgrover1 710:b2e1a2660ec2 826 * Same as above, but this takes an (object, method) pair for a callback.
rgrover1 710:b2e1a2660ec2 827 */
rgrover1 710:b2e1a2660ec2 828 template<typename T>
rgrover1 710:b2e1a2660ec2 829 ble_error_t startScan(T *object, void (T::*callbackMember)(const AdvertisementCallbackParams_t *params)) {
rgrover1 710:b2e1a2660ec2 830 ble_error_t err = BLE_ERROR_NONE;
rgrover1 710:b2e1a2660ec2 831 if (object && callbackMember) {
rgrover1 710:b2e1a2660ec2 832 if ((err = startRadioScan(_scanningParams)) == BLE_ERROR_NONE) {
rgrover1 770:079b714e9c1a 833 scanningActive = true;
rgrover1 710:b2e1a2660ec2 834 onAdvertisementReport.attach(object, callbackMember);
rgrover1 710:b2e1a2660ec2 835 }
rgrover1 710:b2e1a2660ec2 836 }
rgrover1 710:b2e1a2660ec2 837
rgrover1 710:b2e1a2660ec2 838 return err;
rgrover1 710:b2e1a2660ec2 839 }
rgrover1 710:b2e1a2660ec2 840
rgrover1 753:0f60274cd3ad 841 /**
rgrover1 753:0f60274cd3ad 842 * Initialize radio-notification events to be generated from the stack.
vcoubard 1048:efb29faf12fc 843 * This API doesn't need to be called directly.
rgrover1 753:0f60274cd3ad 844 *
rgrover1 753:0f60274cd3ad 845 * Radio Notification is a feature that enables ACTIVE and INACTIVE
rgrover1 753:0f60274cd3ad 846 * (nACTIVE) signals from the stack that notify the application when the
rgrover1 753:0f60274cd3ad 847 * radio is in use.
rgrover1 753:0f60274cd3ad 848 *
vcoubard 1048:efb29faf12fc 849 * The ACTIVE signal is sent before the radio event starts. The nACTIVE
vcoubard 1048:efb29faf12fc 850 * signal is sent at the end of the radio event. These signals can be used
rgrover1 753:0f60274cd3ad 851 * by the application programmer to synchronize application logic with radio
rgrover1 753:0f60274cd3ad 852 * activity. For example, the ACTIVE signal can be used to shut off external
vcoubard 1048:efb29faf12fc 853 * devices, to manage peak current drawn during periods when the radio is on,
rgrover1 753:0f60274cd3ad 854 * or to trigger sensor data collection for transmission in the Radio Event.
rgrover1 753:0f60274cd3ad 855 *
rgrover1 753:0f60274cd3ad 856 * @return BLE_ERROR_NONE on successful initialization, otherwise an error code.
rgrover1 753:0f60274cd3ad 857 */
rgrover1 753:0f60274cd3ad 858 virtual ble_error_t initRadioNotification(void) {
rgrover1 753:0f60274cd3ad 859 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */
rgrover1 753:0f60274cd3ad 860 }
rgrover1 753:0f60274cd3ad 861
rgrover1 710:b2e1a2660ec2 862 private:
rgrover1 710:b2e1a2660ec2 863 ble_error_t setAdvertisingData(void) {
rgrover1 710:b2e1a2660ec2 864 return setAdvertisingData(_advPayload, _scanResponse);
rgrover1 710:b2e1a2660ec2 865 }
rgrover1 710:b2e1a2660ec2 866
rgrover1 710:b2e1a2660ec2 867 private:
rgrover1 896:791741895cd8 868 virtual ble_error_t setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) = 0;
rgrover1 896:791741895cd8 869 virtual ble_error_t startAdvertising(const GapAdvertisingParams &) = 0;
rgrover1 710:b2e1a2660ec2 870
rgrover1 710:b2e1a2660ec2 871 public:
rgrover1 710:b2e1a2660ec2 872 /**
rgrover1 710:b2e1a2660ec2 873 * Accessors to read back currently active advertising params.
rgrover1 710:b2e1a2660ec2 874 */
rgrover1 710:b2e1a2660ec2 875 GapAdvertisingParams &getAdvertisingParams(void) {
rgrover1 710:b2e1a2660ec2 876 return _advParams;
rgrover1 710:b2e1a2660ec2 877 }
rgrover1 710:b2e1a2660ec2 878 const GapAdvertisingParams &getAdvertisingParams(void) const {
rgrover1 710:b2e1a2660ec2 879 return _advParams;
rgrover1 710:b2e1a2660ec2 880 }
rgrover1 710:b2e1a2660ec2 881
rgrover1 710:b2e1a2660ec2 882 /**
vcoubard 1048:efb29faf12fc 883 * Set up a particular, user-constructed set of advertisement parameters for
rgrover1 710:b2e1a2660ec2 884 * the underlying stack. It would be uncommon for this API to be used
rgrover1 710:b2e1a2660ec2 885 * directly; there are other APIs to tweak advertisement parameters
rgrover1 710:b2e1a2660ec2 886 * individually.
rgrover1 710:b2e1a2660ec2 887 */
rgrover1 710:b2e1a2660ec2 888 void setAdvertisingParams(const GapAdvertisingParams &newParams) {
rgrover1 710:b2e1a2660ec2 889 _advParams = newParams;
rgrover1 710:b2e1a2660ec2 890 }
rgrover1 710:b2e1a2660ec2 891
rgrover1 710:b2e1a2660ec2 892 /* Event callback handlers. */
rgrover1 710:b2e1a2660ec2 893 public:
rgrover1 710:b2e1a2660ec2 894 /**
vcoubard 1048:efb29faf12fc 895 * Set up a callback for timeout events. Refer to TimeoutSource_t for
rgrover1 710:b2e1a2660ec2 896 * possible event types.
vcoubard 1052:b55e1ad3e1b3 897 * @note It is possible to unregister callbacks using onTimeout().detach(callback)
rgrover1 710:b2e1a2660ec2 898 */
vcoubard 1052:b55e1ad3e1b3 899 void onTimeout(TimeoutEventCallback_t callback) {
vcoubard 1052:b55e1ad3e1b3 900 timeoutCallbackChain.add(callback);
vcoubard 1052:b55e1ad3e1b3 901 }
vcoubard 1052:b55e1ad3e1b3 902
vcoubard 1052:b55e1ad3e1b3 903 /**
vcoubard 1052:b55e1ad3e1b3 904 * @brief provide access to the callchain of timeout event callbacks
vcoubard 1052:b55e1ad3e1b3 905 * It is possible to register callbacks using onTimeout().add(callback);
vcoubard 1054:f59e5d9a992a 906 * It is possible to unregister callbacks using onTimeout().detach(callback)
vcoubard 1052:b55e1ad3e1b3 907 * @return The timeout event callbacks chain
vcoubard 1052:b55e1ad3e1b3 908 */
vcoubard 1052:b55e1ad3e1b3 909 TimeoutEventCallbackChain_t& onTimeout() {
vcoubard 1052:b55e1ad3e1b3 910 return timeoutCallbackChain;
vcoubard 1052:b55e1ad3e1b3 911 }
rgrover1 710:b2e1a2660ec2 912
rgrover1 710:b2e1a2660ec2 913 /**
rgrover1 829:9072de50087b 914 * Append to a chain of callbacks to be invoked upon GAP connection.
vcoubard 1052:b55e1ad3e1b3 915 * @note It is possible to unregister callbacks using onConnection().detach(callback)
rgrover1 710:b2e1a2660ec2 916 */
rgrover1 829:9072de50087b 917 void onConnection(ConnectionEventCallback_t callback) {connectionCallChain.add(callback);}
rgrover1 710:b2e1a2660ec2 918
rgrover1 829:9072de50087b 919 template<typename T>
rgrover1 829:9072de50087b 920 void onConnection(T *tptr, void (T::*mptr)(const ConnectionCallbackParams_t*)) {connectionCallChain.add(tptr, mptr);}
rgrover1 710:b2e1a2660ec2 921
rgrover1 710:b2e1a2660ec2 922 /**
vcoubard 1052:b55e1ad3e1b3 923 * @brief provide access to the callchain of connection event callbacks
vcoubard 1052:b55e1ad3e1b3 924 * It is possible to register callbacks using onConnection().add(callback);
vcoubard 1054:f59e5d9a992a 925 * It is possible to unregister callbacks using onConnection().detach(callback)
vcoubard 1052:b55e1ad3e1b3 926 * @return The connection event callbacks chain
vcoubard 1052:b55e1ad3e1b3 927 */
vcoubard 1054:f59e5d9a992a 928 ConnectionEventCallbackChain_t& onConnection() {
vcoubard 1052:b55e1ad3e1b3 929 return connectionCallChain;
vcoubard 1052:b55e1ad3e1b3 930 }
vcoubard 1052:b55e1ad3e1b3 931
vcoubard 1052:b55e1ad3e1b3 932 /**
rgrover1 829:9072de50087b 933 * Append to a chain of callbacks to be invoked upon GAP disconnection.
vcoubard 1052:b55e1ad3e1b3 934 * @note It is possible to unregister callbacks using onDisconnection().detach(callback)
rgrover1 816:2b4f0ef8c06e 935 */
rgrover1 829:9072de50087b 936 void onDisconnection(DisconnectionEventCallback_t callback) {disconnectionCallChain.add(callback);}
rgrover1 816:2b4f0ef8c06e 937
rgrover1 710:b2e1a2660ec2 938 template<typename T>
rgrover1 829:9072de50087b 939 void onDisconnection(T *tptr, void (T::*mptr)(const DisconnectionCallbackParams_t*)) {disconnectionCallChain.add(tptr, mptr);}
rgrover1 710:b2e1a2660ec2 940
rgrover1 710:b2e1a2660ec2 941 /**
vcoubard 1052:b55e1ad3e1b3 942 * @brief provide access to the callchain of disconnection event callbacks
vcoubard 1052:b55e1ad3e1b3 943 * It is possible to register callbacks using onDisconnection().add(callback);
vcoubard 1054:f59e5d9a992a 944 * It is possible to unregister callbacks using onDisconnection().detach(callback)
vcoubard 1052:b55e1ad3e1b3 945 * @return The disconnection event callbacks chain
vcoubard 1052:b55e1ad3e1b3 946 */
vcoubard 1052:b55e1ad3e1b3 947 DisconnectionEventCallbackChain_t& onDisconnection() {
vcoubard 1052:b55e1ad3e1b3 948 return disconnectionCallChain;
vcoubard 1052:b55e1ad3e1b3 949 }
vcoubard 1052:b55e1ad3e1b3 950
vcoubard 1052:b55e1ad3e1b3 951 /**
rgrover1 710:b2e1a2660ec2 952 * Set the application callback for radio-notification events.
rgrover1 710:b2e1a2660ec2 953 *
rgrover1 710:b2e1a2660ec2 954 * Radio Notification is a feature that enables ACTIVE and INACTIVE
rgrover1 710:b2e1a2660ec2 955 * (nACTIVE) signals from the stack that notify the application when the
rgrover1 753:0f60274cd3ad 956 * radio is in use.
rgrover1 710:b2e1a2660ec2 957 *
vcoubard 1048:efb29faf12fc 958 * The ACTIVE signal is sent before the radio event starts. The nACTIVE
vcoubard 1048:efb29faf12fc 959 * signal is sent at the end of the radio event. These signals can be used
rgrover1 710:b2e1a2660ec2 960 * by the application programmer to synchronize application logic with radio
rgrover1 710:b2e1a2660ec2 961 * activity. For example, the ACTIVE signal can be used to shut off external
vcoubard 1048:efb29faf12fc 962 * devices, to manage peak current drawn during periods when the radio is on,
rgrover1 710:b2e1a2660ec2 963 * or to trigger sensor data collection for transmission in the Radio Event.
rgrover1 710:b2e1a2660ec2 964 *
rgrover1 710:b2e1a2660ec2 965 * @param callback
rgrover1 710:b2e1a2660ec2 966 * The application handler to be invoked in response to a radio
rgrover1 710:b2e1a2660ec2 967 * ACTIVE/INACTIVE event.
rgrover1 754:9b391fb5c5d7 968 *
vcoubard 1048:efb29faf12fc 969 * Or in the other version:
rgrover1 754:9b391fb5c5d7 970 *
rgrover1 754:9b391fb5c5d7 971 * @param tptr
rgrover1 754:9b391fb5c5d7 972 * Pointer to the object of a class defining the member callback
rgrover1 754:9b391fb5c5d7 973 * function (mptr).
rgrover1 754:9b391fb5c5d7 974 * @param mptr
rgrover1 754:9b391fb5c5d7 975 * The member callback (within the context of an object) to be
rgrover1 754:9b391fb5c5d7 976 * invoked in response to a radio ACTIVE/INACTIVE event.
rgrover1 710:b2e1a2660ec2 977 */
rgrover1 753:0f60274cd3ad 978 void onRadioNotification(void (*callback)(bool param)) {
rgrover1 753:0f60274cd3ad 979 radioNotificationCallback.attach(callback);
rgrover1 753:0f60274cd3ad 980 }
rgrover1 753:0f60274cd3ad 981 template <typename T>
rgrover1 753:0f60274cd3ad 982 void onRadioNotification(T *tptr, void (T::*mptr)(bool)) {
rgrover1 753:0f60274cd3ad 983 radioNotificationCallback.attach(tptr, mptr);
rgrover1 753:0f60274cd3ad 984 }
rgrover1 710:b2e1a2660ec2 985
rgrover1 710:b2e1a2660ec2 986 protected:
vcoubard 1062:a3fd424b73ca 987 /**
vcoubard 1062:a3fd424b73ca 988 * Clear all Gap state of the associated object.
vcoubard 1062:a3fd424b73ca 989 *
vcoubard 1062:a3fd424b73ca 990 * This function is meant to be overridden in the platform-specific
vcoubard 1062:a3fd424b73ca 991 * sub-class. Nevertheless, the sub-class is only expected to clean up its
vcoubard 1062:a3fd424b73ca 992 * state and not the data held in Gap members. This shall be achieved by a
vcoubard 1062:a3fd424b73ca 993 * call to Gap::cleanup() from the sub-class' cleanup() implementation.
vcoubard 1062:a3fd424b73ca 994 *
vcoubard 1062:a3fd424b73ca 995 * @return BLE_ERROR_NONE on success.
vcoubard 1062:a3fd424b73ca 996 *
vcoubard 1062:a3fd424b73ca 997 * @note: Currently a call to cleanup() does not reset the advertising and
vcoubard 1062:a3fd424b73ca 998 * scan parameters to default values.
vcoubard 1062:a3fd424b73ca 999 */
vcoubard 1062:a3fd424b73ca 1000 virtual ble_error_t cleanup(void) {
vcoubard 1062:a3fd424b73ca 1001 /* Clear Gap state */
vcoubard 1062:a3fd424b73ca 1002 state.advertising = 0;
vcoubard 1062:a3fd424b73ca 1003 state.connected = 0;
vcoubard 1062:a3fd424b73ca 1004
vcoubard 1062:a3fd424b73ca 1005 /* Clear scanning state */
vcoubard 1062:a3fd424b73ca 1006 scanningActive = false;
vcoubard 1062:a3fd424b73ca 1007
vcoubard 1062:a3fd424b73ca 1008 /* Clear advertising and scanning data */
vcoubard 1062:a3fd424b73ca 1009 _advPayload.clear();
vcoubard 1062:a3fd424b73ca 1010 _scanResponse.clear();
vcoubard 1062:a3fd424b73ca 1011
vcoubard 1062:a3fd424b73ca 1012 return BLE_ERROR_NONE;
vcoubard 1062:a3fd424b73ca 1013 }
vcoubard 1062:a3fd424b73ca 1014
vcoubard 1062:a3fd424b73ca 1015 public:
vcoubard 1062:a3fd424b73ca 1016 /**
vcoubard 1062:a3fd424b73ca 1017 * Clear all Gap state of the object pointed to by gapInstance.
vcoubard 1062:a3fd424b73ca 1018 *
vcoubard 1062:a3fd424b73ca 1019 * This function is meant to be called by the overridden BLE::shutdown()
vcoubard 1062:a3fd424b73ca 1020 * in the platform-specific sub-class.
vcoubard 1062:a3fd424b73ca 1021 *
vcoubard 1062:a3fd424b73ca 1022 * @return BLE_ERROR_NONE on success.
vcoubard 1062:a3fd424b73ca 1023 *
vcoubard 1062:a3fd424b73ca 1024 * @note: If gapInstance is NULL then it is assumed that Gap has not been
vcoubard 1062:a3fd424b73ca 1025 * instantiated and a call to Gap::shutdown() will succeed.
vcoubard 1062:a3fd424b73ca 1026 */
vcoubard 1062:a3fd424b73ca 1027 static ble_error_t shutdown(void) {
vcoubard 1062:a3fd424b73ca 1028 if (gapInstance) {
vcoubard 1062:a3fd424b73ca 1029 return gapInstance->cleanup();
vcoubard 1062:a3fd424b73ca 1030 }
vcoubard 1062:a3fd424b73ca 1031 return BLE_ERROR_NONE;
vcoubard 1062:a3fd424b73ca 1032 }
vcoubard 1062:a3fd424b73ca 1033
vcoubard 1062:a3fd424b73ca 1034 protected:
rgrover1 710:b2e1a2660ec2 1035 Gap() :
rgrover1 710:b2e1a2660ec2 1036 _advParams(),
rgrover1 710:b2e1a2660ec2 1037 _advPayload(),
rgrover1 710:b2e1a2660ec2 1038 _scanningParams(),
rgrover1 710:b2e1a2660ec2 1039 _scanResponse(),
rgrover1 710:b2e1a2660ec2 1040 state(),
rgrover1 770:079b714e9c1a 1041 scanningActive(false),
vcoubard 1052:b55e1ad3e1b3 1042 timeoutCallbackChain(),
rgrover1 710:b2e1a2660ec2 1043 radioNotificationCallback(),
rgrover1 710:b2e1a2660ec2 1044 onAdvertisementReport(),
rgrover1 816:2b4f0ef8c06e 1045 connectionCallChain(),
rgrover1 710:b2e1a2660ec2 1046 disconnectionCallChain() {
rgrover1 710:b2e1a2660ec2 1047 _advPayload.clear();
rgrover1 710:b2e1a2660ec2 1048 _scanResponse.clear();
rgrover1 710:b2e1a2660ec2 1049 }
rgrover1 710:b2e1a2660ec2 1050
rgrover1 710:b2e1a2660ec2 1051 /* Entry points for the underlying stack to report events back to the user. */
rgrover1 710:b2e1a2660ec2 1052 public:
rgrover1 710:b2e1a2660ec2 1053 void processConnectionEvent(Handle_t handle,
rgrover1 710:b2e1a2660ec2 1054 Role_t role,
rgrover1 710:b2e1a2660ec2 1055 AddressType_t peerAddrType,
rgrover1 710:b2e1a2660ec2 1056 const Address_t peerAddr,
rgrover1 710:b2e1a2660ec2 1057 AddressType_t ownAddrType,
rgrover1 710:b2e1a2660ec2 1058 const Address_t ownAddr,
rgrover1 710:b2e1a2660ec2 1059 const ConnectionParams_t *connectionParams) {
rgrover1 710:b2e1a2660ec2 1060 state.connected = 1;
rgrover1 829:9072de50087b 1061 ConnectionCallbackParams_t callbackParams(handle, role, peerAddrType, peerAddr, ownAddrType, ownAddr, connectionParams);
rgrover1 829:9072de50087b 1062 connectionCallChain.call(&callbackParams);
rgrover1 710:b2e1a2660ec2 1063 }
rgrover1 710:b2e1a2660ec2 1064
rgrover1 710:b2e1a2660ec2 1065 void processDisconnectionEvent(Handle_t handle, DisconnectionReason_t reason) {
rgrover1 710:b2e1a2660ec2 1066 state.connected = 0;
rgrover1 829:9072de50087b 1067 DisconnectionCallbackParams_t callbackParams(handle, reason);
rgrover1 829:9072de50087b 1068 disconnectionCallChain.call(&callbackParams);
rgrover1 710:b2e1a2660ec2 1069 }
rgrover1 710:b2e1a2660ec2 1070
rgrover1 710:b2e1a2660ec2 1071 void processAdvertisementReport(const Address_t peerAddr,
rgrover1 710:b2e1a2660ec2 1072 int8_t rssi,
rgrover1 710:b2e1a2660ec2 1073 bool isScanResponse,
rgrover1 710:b2e1a2660ec2 1074 GapAdvertisingParams::AdvertisingType_t type,
rgrover1 710:b2e1a2660ec2 1075 uint8_t advertisingDataLen,
rgrover1 710:b2e1a2660ec2 1076 const uint8_t *advertisingData) {
rgrover1 710:b2e1a2660ec2 1077 AdvertisementCallbackParams_t params;
rgrover1 710:b2e1a2660ec2 1078 memcpy(params.peerAddr, peerAddr, ADDR_LEN);
rgrover1 710:b2e1a2660ec2 1079 params.rssi = rssi;
rgrover1 710:b2e1a2660ec2 1080 params.isScanResponse = isScanResponse;
rgrover1 710:b2e1a2660ec2 1081 params.type = type;
rgrover1 710:b2e1a2660ec2 1082 params.advertisingDataLen = advertisingDataLen;
rgrover1 710:b2e1a2660ec2 1083 params.advertisingData = advertisingData;
rgrover1 710:b2e1a2660ec2 1084 onAdvertisementReport.call(&params);
rgrover1 710:b2e1a2660ec2 1085 }
rgrover1 710:b2e1a2660ec2 1086
rgrover1 710:b2e1a2660ec2 1087 void processTimeoutEvent(TimeoutSource_t source) {
vcoubard 1052:b55e1ad3e1b3 1088 if (timeoutCallbackChain) {
vcoubard 1052:b55e1ad3e1b3 1089 timeoutCallbackChain(source);
rgrover1 710:b2e1a2660ec2 1090 }
rgrover1 710:b2e1a2660ec2 1091 }
rgrover1 710:b2e1a2660ec2 1092
rgrover1 710:b2e1a2660ec2 1093 protected:
rgrover1 710:b2e1a2660ec2 1094 GapAdvertisingParams _advParams;
rgrover1 710:b2e1a2660ec2 1095 GapAdvertisingData _advPayload;
rgrover1 710:b2e1a2660ec2 1096 GapScanningParams _scanningParams;
rgrover1 710:b2e1a2660ec2 1097 GapAdvertisingData _scanResponse;
rgrover1 710:b2e1a2660ec2 1098
rgrover1 710:b2e1a2660ec2 1099 GapState_t state;
rgrover1 770:079b714e9c1a 1100 bool scanningActive;
rgrover1 710:b2e1a2660ec2 1101
rgrover1 710:b2e1a2660ec2 1102 protected:
vcoubard 1062:a3fd424b73ca 1103 static Gap *gapInstance; /**< Pointer to the Gap object instance.
vcoubard 1062:a3fd424b73ca 1104 * If NULL, then Gap has not been initialized. */
vcoubard 1062:a3fd424b73ca 1105
vcoubard 1062:a3fd424b73ca 1106 protected:
vcoubard 1052:b55e1ad3e1b3 1107 TimeoutEventCallbackChain_t timeoutCallbackChain;
vcoubard 1052:b55e1ad3e1b3 1108 RadioNotificationEventCallback_t radioNotificationCallback;
vcoubard 1052:b55e1ad3e1b3 1109 AdvertisementReportCallback_t onAdvertisementReport;
vcoubard 1052:b55e1ad3e1b3 1110 ConnectionEventCallbackChain_t connectionCallChain;
vcoubard 1052:b55e1ad3e1b3 1111 DisconnectionEventCallbackChain_t disconnectionCallChain;
rgrover1 710:b2e1a2660ec2 1112
rgrover1 710:b2e1a2660ec2 1113 private:
vcoubard 1048:efb29faf12fc 1114 /* Disallow copy and assignment. */
rgrover1 710:b2e1a2660ec2 1115 Gap(const Gap &);
rgrover1 710:b2e1a2660ec2 1116 Gap& operator=(const Gap &);
rgrover1 710:b2e1a2660ec2 1117 };
rgrover1 710:b2e1a2660ec2 1118
rgrover1 710:b2e1a2660ec2 1119 #endif // ifndef __GAP_H__