BLE
Fork of BLE_API by
ble/Gap.h
- Committer:
- rgrover1
- Date:
- 2015-11-26
- Revision:
- 924:ca1964e56ddf
- Parent:
- 923:e04837405cd5
- Child:
- 934:3ec277a0d780
File content as of revision 924:ca1964e56ddf:
/* mbed Microcontroller Library * Copyright (c) 2006-2013 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __GAP_H__ #define __GAP_H__ #include "GapAdvertisingData.h" #include "GapAdvertisingParams.h" #include "GapScanningParams.h" #include "GapEvents.h" #include "CallChainOfFunctionPointersWithContext.h" #include "FunctionPointerWithContext.h" /* Forward declarations for classes that will only be used for pointers or references in the following. */ class GapAdvertisingParams; class GapScanningParams; class GapAdvertisingData; class Gap { public: enum AddressType_t { ADDR_TYPE_PUBLIC = 0, ADDR_TYPE_RANDOM_STATIC, ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE, ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE }; typedef enum AddressType_t addr_type_t; /* @Note: Deprecated. Use AddressType_t instead. */ static const unsigned ADDR_LEN = 6; typedef uint8_t Address_t[ADDR_LEN]; /* 48-bit address, LSB format. */ typedef Address_t address_t; /* @Note: Deprecated. Use Address_t instead. */ enum TimeoutSource_t { TIMEOUT_SRC_ADVERTISING = 0x00, /**< Advertising timeout. */ TIMEOUT_SRC_SECURITY_REQUEST = 0x01, /**< Security request timeout. */ TIMEOUT_SRC_SCAN = 0x02, /**< Scanning timeout. */ TIMEOUT_SRC_CONN = 0x03, /**< Connection timeout. */ }; /** * Enumeration for disconnection reasons. The values for these reasons are * derived from Nordic's implementation, but the reasons are meant to be * independent of the transport. If you are returned a reason that is not * covered by this enumeration, please refer to the underlying * transport library. */ enum DisconnectionReason_t { CONNECTION_TIMEOUT = 0x08, REMOTE_USER_TERMINATED_CONNECTION = 0x13, REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES = 0x14, /**< Remote device terminated connection due to low resources.*/ REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF = 0x15, /**< Remote device terminated connection due to power off. */ LOCAL_HOST_TERMINATED_CONNECTION = 0x16, CONN_INTERVAL_UNACCEPTABLE = 0x3B, }; /* Describes the current state of the device (more than one bit can be set). */ struct GapState_t { unsigned advertising : 1; /**< Peripheral is currently advertising. */ unsigned connected : 1; /**< Peripheral is connected to a central. */ }; typedef uint16_t Handle_t; /* Type for connection handle. */ typedef struct { uint16_t minConnectionInterval; /**< Minimum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/ uint16_t maxConnectionInterval; /**< Maximum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/ uint16_t slaveLatency; /**< Slave Latency in number of connection events, see @ref BLE_GAP_CP_LIMITS.*/ uint16_t connectionSupervisionTimeout; /**< Connection Supervision Timeout in 10 ms units, see @ref BLE_GAP_CP_LIMITS.*/ } ConnectionParams_t; enum Role_t { PERIPHERAL = 0x1, /**< Peripheral Role. */ CENTRAL = 0x2, /**< Central Role. */ }; struct AdvertisementCallbackParams_t { Address_t peerAddr; int8_t rssi; bool isScanResponse; GapAdvertisingParams::AdvertisingType_t type; uint8_t advertisingDataLen; const uint8_t *advertisingData; }; typedef FunctionPointerWithContext<const AdvertisementCallbackParams_t *> AdvertisementReportCallback_t; struct ConnectionCallbackParams_t { Handle_t handle; Role_t role; AddressType_t peerAddrType; Address_t peerAddr; AddressType_t ownAddrType; Address_t ownAddr; const ConnectionParams_t *connectionParams; ConnectionCallbackParams_t(Handle_t handleIn, Role_t roleIn, AddressType_t peerAddrTypeIn, const uint8_t *peerAddrIn, AddressType_t ownAddrTypeIn, const uint8_t *ownAddrIn, const ConnectionParams_t *connectionParamsIn) : handle(handleIn), role(roleIn), peerAddrType(peerAddrTypeIn), peerAddr(), ownAddrType(ownAddrTypeIn), ownAddr(), connectionParams(connectionParamsIn) { memcpy(peerAddr, peerAddrIn, ADDR_LEN); memcpy(ownAddr, ownAddrIn, ADDR_LEN); } }; struct DisconnectionCallbackParams_t { Handle_t handle; DisconnectionReason_t reason; DisconnectionCallbackParams_t(Handle_t handleIn, DisconnectionReason_t reasonIn) : handle(handleIn), reason(reasonIn) {} }; static const uint16_t UNIT_1_25_MS = 1250; /**< Number of microseconds in 1.25 milliseconds. */ static uint16_t MSEC_TO_GAP_DURATION_UNITS(uint32_t durationInMillis) { return (durationInMillis * 1000) / UNIT_1_25_MS; } typedef FunctionPointerWithContext<TimeoutSource_t> TimeoutEventCallback_t; typedef CallChainOfFunctionPointersWithContext<TimeoutSource_t> TimeoutEventCallbackChain_t; typedef FunctionPointerWithContext<const ConnectionCallbackParams_t *> ConnectionEventCallback_t; typedef CallChainOfFunctionPointersWithContext<const ConnectionCallbackParams_t *> ConnectionEventCallbackChain_t; typedef FunctionPointerWithContext<const DisconnectionCallbackParams_t*> DisconnectionEventCallback_t; typedef CallChainOfFunctionPointersWithContext<const DisconnectionCallbackParams_t*> DisconnectionEventCallbackChain_t; typedef FunctionPointerWithContext<bool> RadioNotificationEventCallback_t; /* * The following functions are meant to be overridden in the platform-specific sub-class. */ public: /** * Set the BTLE MAC address and type. Please note that the address format is * least significant byte first (LSB). Please refer to Address_t. * * @return BLE_ERROR_NONE on success. */ virtual ble_error_t setAddress(AddressType_t type, const Address_t address) { /* avoid compiler warnings about unused variables */ (void)type; (void)address; return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */ } /** * Fetch the BTLE MAC address and type. * * @return BLE_ERROR_NONE on success. */ virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address) { /* Avoid compiler warnings about unused variables. */ (void)typeP; (void)address; return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */ } /** * @return Minimum Advertising interval in milliseconds. */ virtual uint16_t getMinAdvertisingInterval(void) const { return 0; /* Requesting action from porter(s): override this API if this capability is supported. */ } /** * @return Minimum Advertising interval in milliseconds for non-connectible mode. */ virtual uint16_t getMinNonConnectableAdvertisingInterval(void) const { return 0; /* Requesting action from porter(s): override this API if this capability is supported. */ } /** * @return Maximum Advertising interval in milliseconds. */ virtual uint16_t getMaxAdvertisingInterval(void) const { return 0xFFFF; /* Requesting action from porter(s): override this API if this capability is supported. */ } virtual ble_error_t stopAdvertising(void) { return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */ } /** * Stop scanning. The current scanning parameters remain in effect. * * @retval BLE_ERROR_NONE if successfully stopped scanning procedure. */ virtual ble_error_t stopScan() { return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */ } /** * Create a connection (GAP Link Establishment). * * @param peerAddr * 48-bit address, LSB format. * @param peerAddrType * Address type of the peer. * @param connectionParams * Connection parameters. * @param scanParams * Paramters to be used while scanning for the peer. * @return BLE_ERROR_NONE if connection establishment procedure is started * successfully. The connectionCallChain (if set) will be invoked upon * a connection event. */ virtual ble_error_t connect(const Address_t peerAddr, Gap::AddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams) { /* Avoid compiler warnings about unused variables. */ (void)peerAddr; (void)peerAddrType; (void)connectionParams; (void)scanParams; return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */ } /** * This call initiates the disconnection procedure, and its completion will * be communicated to the application with an invocation of the * disconnectionCallback. * * @param reason * The reason for disconnection; to be sent back to the peer. */ virtual ble_error_t disconnect(Handle_t connectionHandle, DisconnectionReason_t reason) { /* avoid compiler warnings about unused variables */ (void)connectionHandle; (void)reason; return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */ } /** * This call initiates the disconnection procedure, and its completion will * be communicated to the application with an invocation of the * disconnectionCallback. * * @param reason * The reason for disconnection; to be sent back to the peer. * * @note: This version of disconnect() doesn't take a connection handle. It * works reliably only for stacks that are limited to a single * connection. This API should be considered *deprecated* in favour of the * alternative, which takes a connection handle. It will be dropped in the future. */ virtual ble_error_t disconnect(DisconnectionReason_t reason) { /* Avoid compiler warnings about unused variables. */ (void)reason; return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */ } /** * Get the GAP peripheral preferred connection parameters. These are the * defaults that the peripheral would like to have in a connection. The * choice of the connection parameters is eventually up to the central. * * @param[out] params * The structure where the parameters will be stored. Memory * for this is owned by the caller. * * @return BLE_ERROR_NONE if the parameters were successfully filled into * the given structure pointed to by params. */ virtual ble_error_t getPreferredConnectionParams(ConnectionParams_t *params) { /* Avoid compiler warnings about unused variables. */ (void)params; return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */ } /** * Set the GAP peripheral preferred connection parameters. These are the * defaults that the peripheral would like to have in a connection. The * choice of the connection parameters is eventually up to the central. * * @param[in] params * The structure containing the desired parameters. */ virtual ble_error_t setPreferredConnectionParams(const ConnectionParams_t *params) { /* Avoid compiler warnings about unused variables. */ (void)params; return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */ } /** * Update connection parameters. * In the central role this will initiate a Link Layer connection parameter update procedure. * In the peripheral role, this will send the corresponding L2CAP request and wait for * the central to perform the procedure. * * @param[in] handle * Connection Handle. * @param[in] params * Pointer to desired connection parameters. If NULL is provided on a peripheral role, * the parameters in the PPCP characteristic of the GAP service will be used instead. */ virtual ble_error_t updateConnectionParams(Handle_t handle, const ConnectionParams_t *params) { /* avoid compiler warnings about unused variables */ (void)handle; (void)params; return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */ } /** * Set the device name characteristic in the GAP service. * @param[in] deviceName * The new value for the device-name. This is a UTF-8 encoded, <b>NULL-terminated</b> string. */ virtual ble_error_t setDeviceName(const uint8_t *deviceName) { /* Avoid compiler warnings about unused variables. */ (void)deviceName; return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */ } /** * Get the value of the device name characteristic in the GAP service. * @param[out] deviceName * Pointer to an empty buffer where the UTF-8 *non NULL- * terminated* string will be placed. Set this * value to NULL in order to obtain the deviceName-length * from the 'length' parameter. * * @param[in/out] lengthP * (on input) Length of the buffer pointed to by deviceName; * (on output) the complete device name length (without the * null terminator). * * @note If the device name is longer than the size of the supplied buffer, * length will return the complete device name length, and not the * number of bytes actually returned in deviceName. The application may * use this information to retry with a suitable buffer size. */ virtual ble_error_t getDeviceName(uint8_t *deviceName, unsigned *lengthP) { /* avoid compiler warnings about unused variables */ (void)deviceName; (void)lengthP; return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */ } /** * Set the appearance characteristic in the GAP service. * @param[in] appearance * The new value for the device-appearance. */ virtual ble_error_t setAppearance(GapAdvertisingData::Appearance appearance) { /* Avoid compiler warnings about unused variables. */ (void)appearance; return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */ } /** * Get the appearance characteristic in the GAP service. * @param[out] appearance * The new value for the device-appearance. */ virtual ble_error_t getAppearance(GapAdvertisingData::Appearance *appearanceP) { /* Avoid compiler warnings about unused variables. */ (void)appearanceP; return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */ } /** * Set the radio's transmit power. * @param[in] txPower Radio transmit power in dBm. */ virtual ble_error_t setTxPower(int8_t txPower) { /* Avoid compiler warnings about unused variables. */ (void)txPower; return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */ } /** * Query the underlying stack for permitted arguments for setTxPower(). * * @param[out] valueArrayPP * Out parameter to receive the immutable array of Tx values. * @param[out] countP * Out parameter to receive the array's size. */ virtual void getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP) { /* Avoid compiler warnings about unused variables. */ (void)valueArrayPP; (void)countP; *countP = 0; /* Requesting action from porter(s): override this API if this capability is supported. */ } protected: /* Override the following in the underlying adaptation layer to provide the functionality of scanning. */ virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams) { (void)scanningParams; return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */ } /* * APIs with non-virtual implementations. */ public: /** * Returns the current GAP state of the device using a bitmask that * describes whether the device is advertising or connected. */ GapState_t getState(void) const { return state; } /** * Set the GAP advertising mode to use for this device. */ void setAdvertisingType(GapAdvertisingParams::AdvertisingType_t advType) { _advParams.setAdvertisingType(advType); } /** * @param[in] interval * Advertising interval in units of milliseconds. Advertising * is disabled if interval is 0. If interval is smaller than * the minimum supported value, then the minimum supported * value is used instead. This minimum value can be discovered * using getMinAdvertisingInterval(). * * This field must be set to 0 if connectionMode is equal * to ADV_CONNECTABLE_DIRECTED. * * @note: Decreasing this value will allow central devices to detect a * peripheral faster, at the expense of more power being used by the radio * due to the higher data transmit rate. * * @note: This API is now *deprecated* and will be dropped in the future. * You should use the parallel API from Gap directly. A former call to * ble.setAdvertisingInterval(...) should now be achieved using * ble.gap().setAdvertisingInterval(...). * * @Note: [WARNING] This API previously used 0.625ms as the unit for its * 'interval' argument. That required an explicit conversion from * milliseconds using Gap::MSEC_TO_GAP_DURATION_UNITS(). This conversion is * no longer required as the new units are milliseconds. Any application * code depending on the old semantics needs to be updated accordingly. */ void setAdvertisingInterval(uint16_t interval) { if (interval == 0) { stopAdvertising(); } else if (interval < getMinAdvertisingInterval()) { interval = getMinAdvertisingInterval(); } _advParams.setInterval(interval); } /** * @param[in] timeout * Advertising timeout (in seconds) between 0x1 and 0x3FFF (1 * and 16383). Use 0 to disable the advertising timeout. */ void setAdvertisingTimeout(uint16_t timeout) { _advParams.setTimeout(timeout); } /** * Start advertising. */ ble_error_t startAdvertising(void) { setAdvertisingData(); /* Update the underlying stack. */ return startAdvertising(_advParams); } /** * Reset any advertising payload prepared from prior calls to * accumulateAdvertisingPayload(). This automatically propagates the re- * initialized advertising payload to the underlying stack. */ void clearAdvertisingPayload(void) { _advPayload.clear(); setAdvertisingData(); } /** * Accumulate an AD structure in the advertising payload. Please note that * the payload is limited to 31 bytes. The SCAN_RESPONSE message may be used * as an additional 31 bytes if the advertising payload is too * small. * * @param[in] flags * The flags to be added. Please refer to * GapAdvertisingData::Flags for valid flags. Multiple * flags may be specified in combination. */ ble_error_t accumulateAdvertisingPayload(uint8_t flags) { ble_error_t rc; if ((rc = _advPayload.addFlags(flags)) != BLE_ERROR_NONE) { return rc; } return setAdvertisingData(); } /** * Accumulate an AD structure in the advertising payload. Please note that * the payload is limited to 31 bytes. The SCAN_RESPONSE message may be used * as an additional 31 bytes if the advertising payload is too * small. * * @param app * The appearance of the peripheral. */ ble_error_t accumulateAdvertisingPayload(GapAdvertisingData::Appearance app) { setAppearance(app); ble_error_t rc; if ((rc = _advPayload.addAppearance(app)) != BLE_ERROR_NONE) { return rc; } return setAdvertisingData(); } /** * Accumulate an AD structure in the advertising payload. Please note that * the payload is limited to 31 bytes. The SCAN_RESPONSE message may be used * as an additional 31 bytes if the advertising payload is too * small. * * @param power * The max transmit power to be used by the controller (in dBm). */ ble_error_t accumulateAdvertisingPayloadTxPower(int8_t power) { ble_error_t rc; if ((rc = _advPayload.addTxPower(power)) != BLE_ERROR_NONE) { return rc; } return setAdvertisingData(); } /** * Accumulate a variable length byte-stream as an AD structure in the * advertising payload. Please note that the payload is limited to 31 bytes. * The SCAN_RESPONSE message may be used as an additional 31 bytes if the * advertising payload is too small. * * @param type The type describing the variable length data. * @param data Data bytes. * @param len Length of data. */ ble_error_t accumulateAdvertisingPayload(GapAdvertisingData::DataType type, const uint8_t *data, uint8_t len) { if (type == GapAdvertisingData::COMPLETE_LOCAL_NAME) { setDeviceName(data); } ble_error_t rc; if ((rc = _advPayload.addData(type, data, len)) != BLE_ERROR_NONE) { return rc; } return setAdvertisingData(); } /** * Update a particular ADV field in the advertising payload (based on * matching type and length). Note: the length of the new data must be the * same as the old one. * * @param[in] type The ADV type field describing the variable length data. * @param[in] data Data bytes. * @param[in] len Length of data. * * @note: If advertisements are enabled, then the update will take effect immediately. * * @return BLE_ERROR_NONE if the advertisement payload was updated based on * a <type, len> match; otherwise, an appropriate error. */ ble_error_t updateAdvertisingPayload(GapAdvertisingData::DataType type, const uint8_t *data, uint8_t len) { if (type == GapAdvertisingData::COMPLETE_LOCAL_NAME) { setDeviceName(data); } ble_error_t rc; if ((rc = _advPayload.updateData(type, data, len)) != BLE_ERROR_NONE) { return rc; } return setAdvertisingData(); } /** * Set up a particular, user-constructed advertisement payload for the * underlying stack. It would be uncommon for this API to be used directly; * there are other APIs to build an advertisement payload (see above). */ ble_error_t setAdvertisingPayload(const GapAdvertisingData &payload) { _advPayload = payload; return setAdvertisingData(); } /** * @return Read back advertising data. Useful for storing and * restoring payload. */ const GapAdvertisingData &getAdvertisingPayload(void) const { return _advPayload; } /** * Accumulate a variable length byte-stream as an AD structure in the * scanResponse payload. * * @param[in] type The type describing the variable length data. * @param[in] data Data bytes. * @param[in] len Length of data. */ ble_error_t accumulateScanResponse(GapAdvertisingData::DataType type, const uint8_t *data, uint8_t len) { ble_error_t rc; if ((rc = _scanResponse.addData(type, data, len)) != BLE_ERROR_NONE) { return rc; } return setAdvertisingData(); } /** * Reset any scan response prepared from prior calls to * accumulateScanResponse(). * * Note: This should be followed by a call to setAdvertisingPayload() or * startAdvertising() before the update takes effect. */ void clearScanResponse(void) { _scanResponse.clear(); setAdvertisingData(); } /** * Set up parameters for GAP scanning (observer mode). * @param[in] interval * Scan interval (in milliseconds) [valid values lie between 2.5ms and 10.24s]. * @param[in] window * Scan Window (in milliseconds) [valid values lie between 2.5ms and 10.24s]. * @param[in] timeout * Scan timeout (in seconds) between 0x0001 and 0xFFFF; 0x0000 disables the timeout. * @param[in] activeScanning * Set to True if active-scanning is required. This is used to fetch the * scan response from a peer if possible. * * The scanning window divided by the interval determines the duty cycle for * scanning. For example, if the interval is 100ms and the window is 10ms, * then the controller will scan for 10 percent of the time. It is possible * to have the interval and window set to the same value. In this case, * scanning is continuous, with a change of scanning frequency once every * interval. * * Once the scanning parameters have been configured, scanning can be * enabled by using startScan(). * * @Note: The scan interval and window are recommendations to the BLE stack. */ ble_error_t setScanParams(uint16_t interval = GapScanningParams::SCAN_INTERVAL_MAX, uint16_t window = GapScanningParams::SCAN_WINDOW_MAX, uint16_t timeout = 0, bool activeScanning = false) { ble_error_t rc; if (((rc = _scanningParams.setInterval(interval)) == BLE_ERROR_NONE) && ((rc = _scanningParams.setWindow(window)) == BLE_ERROR_NONE) && ((rc = _scanningParams.setTimeout(timeout)) == BLE_ERROR_NONE)) { _scanningParams.setActiveScanning(activeScanning); return BLE_ERROR_NONE; } return rc; } /** * Set up the scanInterval parameter for GAP scanning (observer mode). * @param[in] interval * Scan interval (in milliseconds) [valid values lie between 2.5ms and 10.24s]. * * The scanning window divided by the interval determines the duty cycle for * scanning. For example, if the interval is 100ms and the window is 10ms, * then the controller will scan for 10 percent of the time. It is possible * to have the interval and window set to the same value. In this case, * scanning is continuous, with a change of scanning frequency once every * interval. * * Once the scanning parameters have been configured, scanning can be * enabled by using startScan(). */ ble_error_t setScanInterval(uint16_t interval) { return _scanningParams.setInterval(interval); } /** * Set up the scanWindow parameter for GAP scanning (observer mode). * @param[in] window * Scan Window (in milliseconds) [valid values lie between 2.5ms and 10.24s]. * * The scanning window divided by the interval determines the duty cycle for * scanning. For example, if the interval is 100ms and the window is 10ms, * then the controller will scan for 10 percent of the time. It is possible * to have the interval and window set to the same value. In this case, * scanning is continuous, with a change of scanning frequency once every * interval. * * Once the scanning parameters have been configured, scanning can be * enabled by using startScan(). * * If scanning is already active, the updated value of scanWindow will be * propagated to the underlying BLE stack. */ ble_error_t setScanWindow(uint16_t window) { ble_error_t rc; if ((rc = _scanningParams.setWindow(window)) != BLE_ERROR_NONE) { return rc; } /* If scanning is already active, propagate the new setting to the stack. */ if (scanningActive) { return startRadioScan(_scanningParams); } return BLE_ERROR_NONE; } /** * Set up parameters for GAP scanning (observer mode). * @param[in] timeout * Scan timeout (in seconds) between 0x0001 and 0xFFFF; 0x0000 disables the timeout. * * Once the scanning parameters have been configured, scanning can be * enabled by using startScan(). * * If scanning is already active, the updated value of scanTimeout will be * propagated to the underlying BLE stack. */ ble_error_t setScanTimeout(uint16_t timeout) { ble_error_t rc; if ((rc = _scanningParams.setTimeout(timeout)) != BLE_ERROR_NONE) { return rc; } /* If scanning is already active, propagate the new settings to the stack. */ if (scanningActive) { return startRadioScan(_scanningParams); } return BLE_ERROR_NONE; } /** * Set up parameters for GAP scanning (observer mode). * @param[in] activeScanning * Set to True if active-scanning is required. This is used to fetch the * scan response from a peer if possible. * * Once the scanning parameters have been configured, scanning can be * enabled by using startScan(). * * If scanning is already in progress, then active-scanning will be enabled * for the underlying BLE stack. */ ble_error_t setActiveScanning(bool activeScanning) { _scanningParams.setActiveScanning(activeScanning); /* If scanning is already active, propagate the new settings to the stack. */ if (scanningActive) { return startRadioScan(_scanningParams); } return BLE_ERROR_NONE; } /** * Start scanning (Observer Procedure) based on the parameters currently in * effect. * * @param[in] callback * The application-specific callback to be invoked upon * receiving every advertisement report. This can be passed in * as NULL, in which case scanning may not be enabled at all. */ ble_error_t startScan(void (*callback)(const AdvertisementCallbackParams_t *params)) { ble_error_t err = BLE_ERROR_NONE; if (callback) { if ((err = startRadioScan(_scanningParams)) == BLE_ERROR_NONE) { scanningActive = true; onAdvertisementReport.attach(callback); } } return err; } /** * Same as above, but this takes an (object, method) pair for a callback. */ template<typename T> ble_error_t startScan(T *object, void (T::*callbackMember)(const AdvertisementCallbackParams_t *params)) { ble_error_t err = BLE_ERROR_NONE; if (object && callbackMember) { if ((err = startRadioScan(_scanningParams)) == BLE_ERROR_NONE) { scanningActive = true; onAdvertisementReport.attach(object, callbackMember); } } return err; } /** * Initialize radio-notification events to be generated from the stack. * This API doesn't need to be called directly. * * Radio Notification is a feature that enables ACTIVE and INACTIVE * (nACTIVE) signals from the stack that notify the application when the * radio is in use. * * The ACTIVE signal is sent before the radio event starts. The nACTIVE * signal is sent at the end of the radio event. These signals can be used * by the application programmer to synchronize application logic with radio * activity. For example, the ACTIVE signal can be used to shut off external * devices, to manage peak current drawn during periods when the radio is on, * or to trigger sensor data collection for transmission in the Radio Event. * * @return BLE_ERROR_NONE on successful initialization, otherwise an error code. */ virtual ble_error_t initRadioNotification(void) { return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */ } private: ble_error_t setAdvertisingData(void) { return setAdvertisingData(_advPayload, _scanResponse); } private: virtual ble_error_t setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) = 0; virtual ble_error_t startAdvertising(const GapAdvertisingParams &) = 0; public: /** * Accessors to read back currently active advertising params. */ GapAdvertisingParams &getAdvertisingParams(void) { return _advParams; } const GapAdvertisingParams &getAdvertisingParams(void) const { return _advParams; } /** * Set up a particular, user-constructed set of advertisement parameters for * the underlying stack. It would be uncommon for this API to be used * directly; there are other APIs to tweak advertisement parameters * individually. */ void setAdvertisingParams(const GapAdvertisingParams &newParams) { _advParams = newParams; } /* Event callback handlers. */ public: /** * Set up a callback for timeout events. Refer to TimeoutSource_t for * possible event types. */ void onTimeout(TimeoutEventCallback_t callback) { timeoutCallbackChain.add(callback); } TimeoutEventCallbackChain_t& onTimeout() { return timeoutCallbackChain; } /** * Append to a chain of callbacks to be invoked upon GAP connection. */ void onConnection(ConnectionEventCallback_t callback) {connectionCallChain.add(callback);} template<typename T> void onConnection(T *tptr, void (T::*mptr)(const ConnectionCallbackParams_t*)) {connectionCallChain.add(tptr, mptr);} ConnectionEventCallbackChain_t& onconnection() { return connectionCallChain; } /** * Append to a chain of callbacks to be invoked upon GAP disconnection. */ void onDisconnection(DisconnectionEventCallback_t callback) {disconnectionCallChain.add(callback);} template<typename T> void onDisconnection(T *tptr, void (T::*mptr)(const DisconnectionCallbackParams_t*)) {disconnectionCallChain.add(tptr, mptr);} DisconnectionEventCallbackChain_t& onDisconnection() { return disconnectionCallChain; } /** * Set the application callback for radio-notification events. * * Radio Notification is a feature that enables ACTIVE and INACTIVE * (nACTIVE) signals from the stack that notify the application when the * radio is in use. * * The ACTIVE signal is sent before the radio event starts. The nACTIVE * signal is sent at the end of the radio event. These signals can be used * by the application programmer to synchronize application logic with radio * activity. For example, the ACTIVE signal can be used to shut off external * devices, to manage peak current drawn during periods when the radio is on, * or to trigger sensor data collection for transmission in the Radio Event. * * @param callback * The application handler to be invoked in response to a radio * ACTIVE/INACTIVE event. * * Or in the other version: * * @param tptr * Pointer to the object of a class defining the member callback * function (mptr). * @param mptr * The member callback (within the context of an object) to be * invoked in response to a radio ACTIVE/INACTIVE event. */ void onRadioNotification(void (*callback)(bool param)) { radioNotificationCallback.attach(callback); // why does it start radio notification ? It is not even indicated in the // doc that it start the listening process initRadioNotification(); } template <typename T> void onRadioNotification(T *tptr, void (T::*mptr)(bool)) { radioNotificationCallback.attach(tptr, mptr); // why does it start radio notification ? initRadioNotification(); } protected: Gap() : _advParams(), _advPayload(), _scanningParams(), _scanResponse(), state(), scanningActive(false), timeoutCallbackChain(), radioNotificationCallback(), onAdvertisementReport(), connectionCallChain(), disconnectionCallChain() { _advPayload.clear(); _scanResponse.clear(); } /* Entry points for the underlying stack to report events back to the user. */ public: void processConnectionEvent(Handle_t handle, Role_t role, AddressType_t peerAddrType, const Address_t peerAddr, AddressType_t ownAddrType, const Address_t ownAddr, const ConnectionParams_t *connectionParams) { state.connected = 1; ConnectionCallbackParams_t callbackParams(handle, role, peerAddrType, peerAddr, ownAddrType, ownAddr, connectionParams); connectionCallChain.call(&callbackParams); } void processDisconnectionEvent(Handle_t handle, DisconnectionReason_t reason) { state.connected = 0; DisconnectionCallbackParams_t callbackParams(handle, reason); disconnectionCallChain.call(&callbackParams); } void processAdvertisementReport(const Address_t peerAddr, int8_t rssi, bool isScanResponse, GapAdvertisingParams::AdvertisingType_t type, uint8_t advertisingDataLen, const uint8_t *advertisingData) { AdvertisementCallbackParams_t params; memcpy(params.peerAddr, peerAddr, ADDR_LEN); params.rssi = rssi; params.isScanResponse = isScanResponse; params.type = type; params.advertisingDataLen = advertisingDataLen; params.advertisingData = advertisingData; onAdvertisementReport.call(¶ms); } void processTimeoutEvent(TimeoutSource_t source) { if (timeoutCallbackChain) { timeoutCallbackChain(source); } } protected: GapAdvertisingParams _advParams; GapAdvertisingData _advPayload; GapScanningParams _scanningParams; GapAdvertisingData _scanResponse; GapState_t state; bool scanningActive; protected: TimeoutEventCallbackChain_t timeoutCallbackChain; RadioNotificationEventCallback_t radioNotificationCallback; AdvertisementReportCallback_t onAdvertisementReport; ConnectionEventCallbackChain_t connectionCallChain; DisconnectionEventCallbackChain_t disconnectionCallChain; private: /* Disallow copy and assignment. */ Gap(const Gap &); Gap& operator=(const Gap &); }; #endif // ifndef __GAP_H__