diff --git a/ble/BLE.h b/ble/BLE.h index 0966b91..097e8a4 100644 --- a/ble/BLE.h +++ b/ble/BLE.h @@ -196,7 +196,7 @@ public: * directly, as it returns references to singletons. * * @param[in] id - * Instance-ID. This should be less than NUM_INSTANCES + * Instance-ID. This should be less than NUM_INSTANCES * for the returned BLE singleton to be useful. * * @return a reference to a single object. @@ -239,7 +239,7 @@ public: * ble.setAddress(...) should be replaced with * ble.gap().setAddress(...). */ - ble_error_t setAddress(Gap::AddressType_t type, const Gap::Address_t address) { + ble_error_t setAddress(BLEProtocol::AddressType_t type, const BLEProtocol::Address_t address) { return gap().setAddress(type, address); } @@ -252,7 +252,7 @@ public: * ble.getAddress(...) should be replaced with * ble.gap().getAddress(...). */ - ble_error_t getAddress(Gap::AddressType_t *typeP, Gap::Address_t address) { + ble_error_t getAddress(BLEProtocol::AddressType_t *typeP, BLEProtocol::Address_t address) { return gap().getAddress(typeP, address); } @@ -752,8 +752,8 @@ public: * ble.connect(...) should be replaced with * ble.gap().connect(...). */ - ble_error_t connect(const Gap::Address_t peerAddr, - Gap::AddressType_t peerAddrType = Gap::ADDR_TYPE_RANDOM_STATIC, + ble_error_t connect(const BLEProtocol::Address_t peerAddr, + BLEProtocol::AddressType_t peerAddrType = BLEProtocol::AddressType::RANDOM_STATIC, const Gap::ConnectionParams_t *connectionParams = NULL, const GapScanningParams *scanParams = NULL) { return gap().connect(peerAddr, peerAddrType, connectionParams, scanParams); @@ -773,7 +773,7 @@ public: } /** - * This call initiates the disconnection procedure, and its completion + * This call initiates the disconnection procedure, and its completion * is communicated to the application with an invocation of the * onDisconnection callback. * @@ -1407,7 +1407,7 @@ public: /** * Set up a callback for when the passkey needs to be displayed on a * peripheral with DISPLAY capability. This happens when security is - * configured to prevent Man-In-The-Middle attacks, and the peers need to exchange + * configured to prevent Man-In-The-Middle attacks, and the peers need to exchange * a passkey (or PIN) to authenticate the connection * attempt. * diff --git a/ble/BLEProtocol.h b/ble/BLEProtocol.h new file mode 100644 index 0000000..1454022 --- /dev/null +++ b/ble/BLEProtocol.h @@ -0,0 +1,49 @@ +/* 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 __BLE_PROTOCOL_H__ +#define __BLE_PROTOCOL_H__ + +#include +#include + +/** + * A common namespace for types and constants used everywhere in BLE API. + */ +namespace BLEProtocol { + /**< Address-type for Protocol addresses. */ + struct AddressType { /* Adding a struct to encapsulate the contained enumeration + * prevents polluting the BLEProtocol namespace with the + * enumerated values. It also allows type-aliases for the + * enumeration while retaining the enumerated values. i.e. + * + * doing: + * typedef AddressType_t AliasedType_t; + * would allow the use of AliasedType_t::PUBLIC in code. */ + enum Type { + PUBLIC = 0, + RANDOM_STATIC, + RANDOM_PRIVATE_RESOLVABLE, + RANDOM_PRIVATE_NON_RESOLVABLE + }; + }; + typedef AddressType::Type AddressType_t; /**< Alias for AddressType::Type */ + + static const size_t ADDR_LEN = 6; /**< Length (in octets) of the BLE MAC address. */ + typedef uint8_t Address_t[ADDR_LEN]; /**< 48-bit address, in LSB format. */ +}; + +#endif /* __BLE_PROTOCOL_H__ */ diff --git a/ble/Gap.h b/ble/Gap.h index dfa07c1..181a3c5 100644 --- a/ble/Gap.h +++ b/ble/Gap.h @@ -17,6 +17,7 @@ #ifndef __GAP_H__ #define __GAP_H__ +#include "ble/BLEProtocol.h" #include "GapAdvertisingData.h" #include "GapAdvertisingParams.h" #include "GapScanningParams.h" @@ -30,19 +31,44 @@ class GapScanningParams; class GapAdvertisingData; class Gap { + /* + * DEPRECATION ALERT: all of the APIs in this `public` block are deprecated. + * They have been relocated to the class BLEProtocol. + */ public: - enum AddressType_t { - ADDR_TYPE_PUBLIC = 0, - ADDR_TYPE_RANDOM_STATIC, - ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE, - ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE + /** + * Address-type for BLEProtocol addresses. + * + * @note: deprecated. Use BLEProtocol::AddressType_t instead. + */ + typedef BLEProtocol::AddressType_t AddressType_t; + + /** + * Address-type for BLEProtocol addresses. + * @note: deprecated. Use BLEProtocol::AddressType_t instead. + */ + typedef BLEProtocol::AddressType_t addr_type_t; + + /** + * Address-type for BLEProtocol addresses. + * @note: deprecated. Use BLEProtocol::AddressType_t instead. + * + * DEPRECATION ALERT: The following constants have been left in their + * deprecated state to transparenly support existing applications which may + * have used Gap::ADDR_TYPE_*. + */ + enum { + ADDR_TYPE_PUBLIC = BLEProtocol::AddressType::PUBLIC, + ADDR_TYPE_RANDOM_STATIC = BLEProtocol::AddressType::RANDOM_STATIC, + ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE = BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE, + ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE = BLEProtocol::AddressType::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. */ + static const unsigned ADDR_LEN = BLEProtocol::ADDR_LEN; /**< Length (in octets) of the BLE MAC address. */ + typedef BLEProtocol::Address_t Address_t; /**< 48-bit address, LSB format. @Note: Deprecated. Use BLEProtocol::Address_t instead. */ + typedef BLEProtocol::Address_t address_t; /**< 48-bit address, LSB format. @Note: Deprecated. Use BLEProtocol::Address_t instead. */ +public: enum TimeoutSource_t { TIMEOUT_SRC_ADVERTISING = 0x00, /**< Advertising timeout. */ TIMEOUT_SRC_SECURITY_REQUEST = 0x01, /**< Security request timeout. */ @@ -87,31 +113,31 @@ public: }; struct AdvertisementCallbackParams_t { - Address_t peerAddr; - int8_t rssi; - bool isScanResponse; - GapAdvertisingParams::AdvertisingType_t type; - uint8_t advertisingDataLen; - const uint8_t *advertisingData; + BLEProtocol::Address_t peerAddr; + int8_t rssi; + bool isScanResponse; + GapAdvertisingParams::AdvertisingType_t type; + uint8_t advertisingDataLen; + const uint8_t *advertisingData; }; typedef FunctionPointerWithContext 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; + Handle_t handle; + Role_t role; + BLEProtocol::AddressType_t peerAddrType; + BLEProtocol::Address_t peerAddr; + BLEProtocol::AddressType_t ownAddrType; + BLEProtocol::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) : + ConnectionCallbackParams_t(Handle_t handleIn, + Role_t roleIn, + BLEProtocol::AddressType_t peerAddrTypeIn, + const uint8_t *peerAddrIn, + BLEProtocol::AddressType_t ownAddrTypeIn, + const uint8_t *ownAddrIn, + const ConnectionParams_t *connectionParamsIn) : handle(handleIn), role(roleIn), peerAddrType(peerAddrTypeIn), @@ -151,17 +177,20 @@ public: typedef FunctionPointerWithContext RadioNotificationEventCallback_t; + typedef FunctionPointerWithContext GapShutdownCallback_t; + typedef CallChainOfFunctionPointersWithContext GapShutdownCallbackChain_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. + * least significant byte first (LSB). Please refer to BLEProtocol::Address_t. * * @return BLE_ERROR_NONE on success. */ - virtual ble_error_t setAddress(AddressType_t type, const Address_t address) { + virtual ble_error_t setAddress(BLEProtocol::AddressType_t type, const BLEProtocol::Address_t address) { /* avoid compiler warnings about unused variables */ (void)type; (void)address; @@ -174,7 +203,7 @@ public: * * @return BLE_ERROR_NONE on success. */ - virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address) { + virtual ble_error_t getAddress(BLEProtocol::AddressType_t *typeP, BLEProtocol::Address_t address) { /* Avoid compiler warnings about unused variables. */ (void)typeP; (void)address; @@ -233,10 +262,10 @@ public: * 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) { + virtual ble_error_t connect(const BLEProtocol::Address_t peerAddr, + BLEProtocol::AddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParams) { /* Avoid compiler warnings about unused variables. */ (void)peerAddr; (void)peerAddrType; @@ -575,6 +604,16 @@ public: * @param type The type describing the variable length data. * @param data Data bytes. * @param len Length of data. + * + * @return BLE_ERROR_NONE if the advertisement payload was updated based on + * matching AD type; otherwise, an appropriate error. + * + * @note When the specified AD type is INCOMPLETE_LIST_16BIT_SERVICE_IDS, + * COMPLETE_LIST_16BIT_SERVICE_IDS, INCOMPLETE_LIST_32BIT_SERVICE_IDS, + * COMPLETE_LIST_32BIT_SERVICE_IDS, INCOMPLETE_LIST_128BIT_SERVICE_IDS, + * COMPLETE_LIST_128BIT_SERVICE_IDS or LIST_128BIT_SOLICITATION_IDS the + * supplied value is appended to the values previously added to the + * payload. */ ble_error_t accumulateAdvertisingPayload(GapAdvertisingData::DataType type, const uint8_t *data, uint8_t len) { if (type == GapAdvertisingData::COMPLETE_LOCAL_NAME) { @@ -591,8 +630,7 @@ public: /** * 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. + * matching type). * * @param[in] type The ADV type field describing the variable length data. * @param[in] data Data bytes. @@ -601,7 +639,7 @@ public: * @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 match; otherwise, an appropriate error. + * matching AD type; otherwise, an appropriate error. */ ble_error_t updateAdvertisingPayload(GapAdvertisingData::DataType type, const uint8_t *data, uint8_t len) { if (type == GapAdvertisingData::COMPLETE_LOCAL_NAME) { @@ -983,6 +1021,80 @@ public: radioNotificationCallback.attach(tptr, mptr); } + /** + * Setup a callback to be invoked to notify the user application that the + * Gap instance is about to shutdown (possibly as a result of a call + * to BLE::shutdown()). + * + * @Note: It is possible to chain together multiple onShutdown callbacks + * (potentially from different modules of an application) to be notified + * before the Gap instance is shutdown. + * + * @Note: It is also possible to set up a callback into a member function of + * some object. + * + * @Note It is possible to unregister a callback using onShutdown().detach(callback) + */ + void onShutdown(const GapShutdownCallback_t& callback) { + shutdownCallChain.add(callback); + } + template + void onShutdown(T *objPtr, void (T::*memberPtr)(void)) { + shutdownCallChain.add(objPtr, memberPtr); + } + + /** + * @brief provide access to the callchain of shutdown event callbacks + * It is possible to register callbacks using onShutdown().add(callback); + * It is possible to unregister callbacks using onShutdown().detach(callback) + * @return The shutdown event callbacks chain + */ + GapShutdownCallbackChain_t& onShutdown() { + return shutdownCallChain; + } + +public: + /** + * Notify all registered onShutdown callbacks that the Gap instance is + * about to be shutdown and clear all Gap state of the + * associated object. + * + * This function is meant to be overridden in the platform-specific + * sub-class. Nevertheless, the sub-class is only expected to reset its + * state and not the data held in Gap members. This shall be achieved by a + * call to Gap::reset() from the sub-class' reset() implementation. + * + * @return BLE_ERROR_NONE on success. + * + * @note: Currently a call to reset() does not reset the advertising and + * scan parameters to default values. + */ + virtual ble_error_t reset(void) { + /* Notify that the instance is about to shutdown */ + shutdownCallChain.call(this); + shutdownCallChain.clear(); + + /* Clear Gap state */ + state.advertising = 0; + state.connected = 0; + + /* Clear scanning state */ + scanningActive = false; + + /* Clear advertising and scanning data */ + _advPayload.clear(); + _scanResponse.clear(); + + /* Clear callbacks */ + timeoutCallbackChain.clear(); + connectionCallChain.clear(); + disconnectionCallChain.clear(); + radioNotificationCallback = NULL; + onAdvertisementReport = NULL; + + return BLE_ERROR_NONE; + } + protected: Gap() : _advParams(), @@ -1002,13 +1114,13 @@ protected: /* 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) { + void processConnectionEvent(Handle_t handle, + Role_t role, + BLEProtocol::AddressType_t peerAddrType, + const BLEProtocol::Address_t peerAddr, + BLEProtocol::AddressType_t ownAddrType, + const BLEProtocol::Address_t ownAddr, + const ConnectionParams_t *connectionParams) { state.connected = 1; ConnectionCallbackParams_t callbackParams(handle, role, peerAddrType, peerAddr, ownAddrType, ownAddr, connectionParams); connectionCallChain.call(&callbackParams); @@ -1020,12 +1132,12 @@ public: disconnectionCallChain.call(&callbackParams); } - void processAdvertisementReport(const Address_t peerAddr, - int8_t rssi, - bool isScanResponse, + void processAdvertisementReport(const BLEProtocol::Address_t peerAddr, + int8_t rssi, + bool isScanResponse, GapAdvertisingParams::AdvertisingType_t type, - uint8_t advertisingDataLen, - const uint8_t *advertisingData) { + uint8_t advertisingDataLen, + const uint8_t *advertisingData) { AdvertisementCallbackParams_t params; memcpy(params.peerAddr, peerAddr, ADDR_LEN); params.rssi = rssi; @@ -1058,6 +1170,9 @@ protected: ConnectionEventCallbackChain_t connectionCallChain; DisconnectionEventCallbackChain_t disconnectionCallChain; +private: + GapShutdownCallbackChain_t shutdownCallChain; + private: /* Disallow copy and assignment. */ Gap(const Gap &); diff --git a/ble/GapAdvertisingData.h b/ble/GapAdvertisingData.h index 8d0ffb5..7032042 100644 --- a/ble/GapAdvertisingData.h +++ b/ble/GapAdvertisingData.h @@ -187,6 +187,7 @@ public: PULSE_OXIMETER_GENERIC = 3136, /**< Generic Pulse Oximeter. */ PULSE_OXIMETER_FINGERTIP = 3137, /**< Fingertip Pulse Oximeter. */ PULSE_OXIMETER_WRIST_WORN = 3138, /**< Wrist Worn Pulse Oximeter. */ + GENERIC_WEIGHT_SCALE = 3200, /**< Generic Weight Scale. */ OUTDOOR_GENERIC = 5184, /**< Generic Outdoor. */ OUTDOOR_LOCATION_DISPLAY_DEVICE = 5185, /**< Outdoor Location Display Device. */ OUTDOOR_LOCATION_AND_NAVIGATION_DISPLAY_DEVICE = 5186, /**< Outdoor Location and Navigation Display Device. */ @@ -201,149 +202,63 @@ public: /** * Adds advertising data based on the specified AD type (see DataType). - * - * @param advDataType The Advertising 'DataType' to add. - * @param payload Pointer to the payload contents. - * @param len Size of the payload in bytes. - * - * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the - * advertising buffer to overflow, else BLE_ERROR_NONE. - */ - ble_error_t addData(DataType advDataType, const uint8_t *payload, uint8_t len) - { - ble_error_t result = BLE_ERROR_BUFFER_OVERFLOW; - - // find field - uint8_t* field = findField(advDataType); - - // Field type already exist, either add to field or replace - if (field) { - switch(advDataType) { - // These fields will be overwritten with the new value - case FLAGS: - case SHORTENED_LOCAL_NAME: - case COMPLETE_LOCAL_NAME: - case TX_POWER_LEVEL: - case DEVICE_ID: - case SLAVE_CONNECTION_INTERVAL_RANGE: - case SERVICE_DATA: - case APPEARANCE: - case ADVERTISING_INTERVAL: - case MANUFACTURER_SPECIFIC_DATA: { - // current field length, with the type subtracted - uint8_t dataLength = field[0] - 1; - - // new data has same length, do in-order replacement - if (len == dataLength) { - for (uint8_t idx = 0; idx < dataLength; idx++) { - field[2 + idx] = payload[idx]; - } - } else { - // check if data fits - if ((_payloadLen - dataLength + len) <= GAP_ADVERTISING_DATA_MAX_PAYLOAD) { - - // remove old field - while ((field + dataLength + 2) < &_payload[_payloadLen]) { - *field = field[dataLength + 2]; - field++; - } - - // reduce length - _payloadLen -= dataLength + 2; - - // add new field - result = appendField(advDataType, payload, len); - } - } - - break; - } - // These fields will have the new data appended if there is sufficient space - case INCOMPLETE_LIST_16BIT_SERVICE_IDS: - case COMPLETE_LIST_16BIT_SERVICE_IDS: - case INCOMPLETE_LIST_32BIT_SERVICE_IDS: - case COMPLETE_LIST_32BIT_SERVICE_IDS: - case INCOMPLETE_LIST_128BIT_SERVICE_IDS: - case COMPLETE_LIST_128BIT_SERVICE_IDS: - case LIST_128BIT_SOLICITATION_IDS: { - // check if data fits - if ((_payloadLen + len) <= GAP_ADVERTISING_DATA_MAX_PAYLOAD) { - // make room for new field by moving the remainder of the - // advertisement payload "to the right" starting after the - // TYPE field. - uint8_t* end = &_payload[_payloadLen]; - - while (&field[1] < end) { - end[len] = *end; - end--; - } - - // insert new data - for (uint8_t idx = 0; idx < len; idx++) { - field[2 + idx] = payload[idx]; - } - - // increment lengths - field[0] += len; - _payloadLen += len; - - result = BLE_ERROR_NONE; - } - - break; - } - // Field exists but updating it is not supported. Abort operation. - default: - result = BLE_ERROR_NOT_IMPLEMENTED; - break; - } - } else { - // field doesn't exists, insert new - result = appendField(advDataType, payload, len); - } - - return result; - } - - /** - * 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. + * If the supplied AD type is already present in the advertising + * payload, then the value is updated. * * @param[in] advDataType The Advertising 'DataType' to add. * @param[in] payload Pointer to the payload contents. * @param[in] len Size of the payload in bytes. * - * @return BLE_ERROR_UNSPECIFIED if the specified field is not found, else - * BLE_ERROR_NONE. + * @return BLE_ERROR_BUFFER_OVERFLOW if the new value causes the + * advertising buffer to overflow. BLE_ERROR_NONE is returned + * on success. + * + * @note When the specified AD type is INCOMPLETE_LIST_16BIT_SERVICE_IDS, + * COMPLETE_LIST_16BIT_SERVICE_IDS, INCOMPLETE_LIST_32BIT_SERVICE_IDS, + * COMPLETE_LIST_32BIT_SERVICE_IDS, INCOMPLETE_LIST_128BIT_SERVICE_IDS, + * COMPLETE_LIST_128BIT_SERVICE_IDS or LIST_128BIT_SOLICITATION_IDS the + * supplied value is appended to the values previously added to the + * payload. + */ + ble_error_t addData(DataType_t advDataType, const uint8_t *payload, uint8_t len) + { + // find field + uint8_t* field = findField(advDataType); + + if (field) { + // Field type already exist, either add to field or replace + return addField(advDataType, payload, len, field); + } else { + // field doesn't exists, insert new + return appendField(advDataType, payload, len); + } + } + + /** + * Update a particular ADV field in the advertising payload (based on + * matching type). + * + * @param[in] advDataType The Advertising 'DataType' to add. + * @param[in] payload Pointer to the payload contents. + * @param[in] len Size of the payload in bytes. + * + * @return BLE_ERROR_UNSPECIFIED if the specified field is not found, + * BLE_ERROR_BUFFER_OVERFLOW if the new value causes the + * advertising buffer to overflow. BLE_ERROR_NONE is returned + * on success. */ ble_error_t updateData(DataType_t advDataType, const uint8_t *payload, uint8_t len) { - if ((payload == NULL) || (len == 0)) { - return BLE_ERROR_INVALID_PARAM; + // find field + uint8_t* field = findField(advDataType); + + if (field) { + // Field type already exist, replace field contents + return updateField(advDataType, payload, len, field); + } else { + // field doesn't exists, return an error + return BLE_ERROR_UNSPECIFIED; } - - /* A local struct to describe an ADV field. This definition comes from the Bluetooth Core Spec. (v4.2) Part C, Section 11. */ - struct ADVField_t { - uint8_t len; /* Describes the length (in bytes) of the following type and bytes. */ - uint8_t type; /* Should have the same representation of DataType_t (above). */ - uint8_t bytes[0]; /* A placeholder for variable length data. */ - }; - - /* Iterate over the adv fields looking for the first match. */ - uint8_t byteIndex = 0; - while (byteIndex < _payloadLen) { - ADVField_t *currentADV = (ADVField_t *)&_payload[byteIndex]; - if ((currentADV->len == (len + 1)) && /* Incoming len only describes the payload, whereas ADV->len describes [type + payload]. */ - (currentADV->type == advDataType)) { - memcpy(currentADV->bytes, payload, len); - return BLE_ERROR_NONE; - } - - byteIndex += (currentADV->len + 1); /* Advance by len+1; '+1' is needed to span the len field itself. */ - } - - return BLE_ERROR_UNSPECIFIED; } /** @@ -474,6 +389,107 @@ private: return NULL; } + /** + * Given the a pointer to a field in the advertising payload it replaces + * the existing data in the field with the supplied data. + * + * When the specified AD type is INCOMPLETE_LIST_16BIT_SERVICE_IDS, + * COMPLETE_LIST_16BIT_SERVICE_IDS, INCOMPLETE_LIST_32BIT_SERVICE_IDS, + * COMPLETE_LIST_32BIT_SERVICE_IDS, INCOMPLETE_LIST_128BIT_SERVICE_IDS, + * COMPLETE_LIST_128BIT_SERVICE_IDS or LIST_128BIT_SOLICITATION_IDS the + * supplied value is appended to the values previously added to the + * payload. + * + * Returns BLE_ERROR_NONE on success. + */ + ble_error_t addField(DataType_t advDataType, const uint8_t *payload, uint8_t len, uint8_t* field) + { + ble_error_t result = BLE_ERROR_BUFFER_OVERFLOW; + + switch(advDataType) { + // These fields will have the new data appended if there is sufficient space + case INCOMPLETE_LIST_16BIT_SERVICE_IDS: + case COMPLETE_LIST_16BIT_SERVICE_IDS: + case INCOMPLETE_LIST_32BIT_SERVICE_IDS: + case COMPLETE_LIST_32BIT_SERVICE_IDS: + case INCOMPLETE_LIST_128BIT_SERVICE_IDS: + case COMPLETE_LIST_128BIT_SERVICE_IDS: + case LIST_128BIT_SOLICITATION_IDS: { + // check if data fits + if ((_payloadLen + len) <= GAP_ADVERTISING_DATA_MAX_PAYLOAD) { + // make room for new field by moving the remainder of the + // advertisement payload "to the right" starting after the + // TYPE field. + uint8_t* end = &_payload[_payloadLen]; + + while (&field[1] < end) { + end[len] = *end; + end--; + } + + // insert new data + for (uint8_t idx = 0; idx < len; idx++) { + field[2 + idx] = payload[idx]; + } + + // increment lengths + field[0] += len; + _payloadLen += len; + + result = BLE_ERROR_NONE; + } + + break; + } + // These fields will be overwritten with the new value + default: { + result = updateField(advDataType, payload, len, field); + + break; + } + } + + return result; + } + + /** + * Given the a pointer to a field in the advertising payload it replaces + * the existing data in the field with the supplied data. + * Returns BLE_ERROR_NONE on success. + */ + ble_error_t updateField(DataType_t advDataType, const uint8_t *payload, uint8_t len, uint8_t* field) + { + ble_error_t result = BLE_ERROR_BUFFER_OVERFLOW; + uint8_t dataLength = field[0] - 1; + + // new data has same length, do in-order replacement + if (len == dataLength) { + for (uint8_t idx = 0; idx < dataLength; idx++) { + field[2 + idx] = payload[idx]; + } + + result = BLE_ERROR_NONE; + } else { + // check if data fits + if ((_payloadLen - dataLength + len) <= GAP_ADVERTISING_DATA_MAX_PAYLOAD) { + + // remove old field + while ((field + dataLength + 2) < &_payload[_payloadLen]) { + *field = field[dataLength + 2]; + field++; + } + + // reduce length + _payloadLen -= dataLength + 2; + + // add new field + result = appendField(advDataType, payload, len); + } + } + + return result; + } + uint8_t _payload[GAP_ADVERTISING_DATA_MAX_PAYLOAD]; uint8_t _payloadLen; uint16_t _appearance; diff --git a/ble/GattClient.h b/ble/GattClient.h index 9846071..5313388 100644 --- a/ble/GattClient.h +++ b/ble/GattClient.h @@ -42,6 +42,9 @@ public: typedef FunctionPointerWithContext HVXCallback_t; typedef CallChainOfFunctionPointersWithContext HVXCallbackChain_t; + typedef FunctionPointerWithContext GattClientShutdownCallback_t; + typedef CallChainOfFunctionPointersWithContext GattClientShutdownCallbackChain_t; + /* * The following functions are meant to be overridden in the platform-specific sub-class. */ @@ -368,6 +371,37 @@ public: onHVXCallbackChain.add(callback); } + /** + * Setup a callback to be invoked to notify the user application that the + * GattClient instance is about to shutdown (possibly as a result of a call + * to BLE::shutdown()). + * + * @Note: It is possible to chain together multiple onShutdown callbacks + * (potentially from different modules of an application) to be notified + * before the GattClient is shutdown. + * + * @Note: It is also possible to set up a callback into a member function of + * some object. + * + * @Note It is possible to unregister a callback using onShutdown().detach(callback) + */ + void onShutdown(const GattClientShutdownCallback_t& callback) { + shutdownCallChain.add(callback); + } + template + void onShutdown(T *objPtr, void (T::*memberPtr)(void)) { + shutdownCallChain.add(objPtr, memberPtr); + } + + /** + * @brief provide access to the callchain of shutdown event callbacks + * It is possible to register callbacks using onShutdown().add(callback); + * It is possible to unregister callbacks using onShutdown().detach(callback) + * @return The shutdown event callbacks chain + */ + GattClientShutdownCallbackChain_t& onShutdown() { + return shutdownCallChain; + } /** * @brief provide access to the callchain of HVX callbacks @@ -379,6 +413,32 @@ public: return onHVXCallbackChain; } +public: + /** + * Notify all registered onShutdown callbacks that the GattClient is + * about to be shutdown and clear all GattClient state of the + * associated object. + * + * This function is meant to be overridden in the platform-specific + * sub-class. Nevertheless, the sub-class is only expected to reset its + * state and not the data held in GattClient members. This shall be achieved + * by a call to GattClient::reset() from the sub-class' reset() + * implementation. + * + * @return BLE_ERROR_NONE on success. + */ + virtual ble_error_t reset(void) { + /* Notify that the instance is about to shutdown */ + shutdownCallChain.call(this); + shutdownCallChain.clear(); + + onDataReadCallbackChain.clear(); + onDataWriteCallbackChain.clear(); + onHVXCallbackChain.clear(); + + return BLE_ERROR_NONE; + } + protected: GattClient() { /* Empty */ @@ -401,9 +461,10 @@ public: } protected: - ReadCallbackChain_t onDataReadCallbackChain; - WriteCallbackChain_t onDataWriteCallbackChain; - HVXCallbackChain_t onHVXCallbackChain; + ReadCallbackChain_t onDataReadCallbackChain; + WriteCallbackChain_t onDataWriteCallbackChain; + HVXCallbackChain_t onHVXCallbackChain; + GattClientShutdownCallbackChain_t shutdownCallChain; private: /* Disallow copy and assignment. */ diff --git a/ble/GattServer.h b/ble/GattServer.h index 6a6324b..ea46a88 100644 --- a/ble/GattServer.h +++ b/ble/GattServer.h @@ -26,17 +26,19 @@ class GattServer { public: - /* Event callback handlers. */ typedef FunctionPointerWithContext DataSentCallback_t; typedef CallChainOfFunctionPointersWithContext DataSentCallbackChain_t; typedef FunctionPointerWithContext DataWrittenCallback_t; - typedef CallChainOfFunctionPointersWithContext DataWrittenCallbackChain_t; + typedef CallChainOfFunctionPointersWithContext DataWrittenCallbackChain_t; typedef FunctionPointerWithContext DataReadCallback_t; typedef CallChainOfFunctionPointersWithContext DataReadCallbackChain_t; + typedef FunctionPointerWithContext GattServerShutdownCallback_t; + typedef CallChainOfFunctionPointersWithContext GattServerShutdownCallbackChain_t; + typedef FunctionPointerWithContext EventCallback_t; protected: @@ -254,9 +256,9 @@ public: } /** - * @brief get the callback chain called when the event DATA_EVENT is triggered. + * @brief get the callback chain called when the event DATA_EVENT is triggered. */ - DataSentCallbackChain_t& onDataSent() { + DataSentCallbackChain_t& onDataSent() { return dataSentCallChain; } @@ -274,7 +276,7 @@ public: * * @Note: It is also possible to set up a callback into a member function of * some object. - * + * * @Note It is possible to unregister a callback using onDataWritten().detach(callback) */ void onDataWritten(const DataWrittenCallback_t& callback) {dataWrittenCallChain.add(callback);} @@ -286,9 +288,9 @@ public: /** * @brief provide access to the callchain of data written event callbacks * It is possible to register callbacks using onDataWritten().add(callback); - * It is possible to unregister callbacks using onDataWritten().detach(callback) + * It is possible to unregister callbacks using onDataWritten().detach(callback) * @return The data written event callbacks chain - */ + */ DataWrittenCallbackChain_t& onDataWritten() { return dataWrittenCallChain; } @@ -335,13 +337,45 @@ public: /** * @brief provide access to the callchain of data read event callbacks * It is possible to register callbacks using onDataRead().add(callback); - * It is possible to unregister callbacks using onDataRead().detach(callback) + * It is possible to unregister callbacks using onDataRead().detach(callback) * @return The data read event callbacks chain */ DataReadCallbackChain_t& onDataRead() { return dataReadCallChain; } + /** + * Setup a callback to be invoked to notify the user application that the + * GattServer instance is about to shutdown (possibly as a result of a call + * to BLE::shutdown()). + * + * @Note: It is possible to chain together multiple onShutdown callbacks + * (potentially from different modules of an application) to be notified + * before the GattServer is shutdown. + * + * @Note: It is also possible to set up a callback into a member function of + * some object. + * + * @Note It is possible to unregister a callback using onShutdown().detach(callback) + */ + void onShutdown(const GattServerShutdownCallback_t& callback) { + shutdownCallChain.add(callback); + } + template + void onShutdown(T *objPtr, void (T::*memberPtr)(void)) { + shutdownCallChain.add(objPtr, memberPtr); + } + + /** + * @brief provide access to the callchain of shutdown event callbacks + * It is possible to register callbacks using onShutdown().add(callback); + * It is possible to unregister callbacks using onShutdown().detach(callback) + * @return The shutdown event callbacks chain + */ + GattServerShutdownCallbackChain_t& onShutdown() { + return shutdownCallChain; + } + /** * Set up a callback for when notifications or indications are enabled for a * characteristic on the local GATT server. @@ -396,17 +430,50 @@ protected: dataSentCallChain.call(count); } +public: + /** + * Notify all registered onShutdown callbacks that the GattServer is + * about to be shutdown and clear all GattServer state of the + * associated object. + * + * This function is meant to be overridden in the platform-specific + * sub-class. Nevertheless, the sub-class is only expected to reset its + * state and not the data held in GattServer members. This shall be achieved + * by a call to GattServer::reset() from the sub-class' reset() + * implementation. + * + * @return BLE_ERROR_NONE on success. + */ + virtual ble_error_t reset(void) { + /* Notify that the instance is about to shutdown */ + shutdownCallChain.call(this); + shutdownCallChain.clear(); + + serviceCount = 0; + characteristicCount = 0; + + dataSentCallChain.clear(); + dataWrittenCallChain.clear(); + dataReadCallChain.clear(); + updatesEnabledCallback = NULL; + updatesDisabledCallback = NULL; + confirmationReceivedCallback = NULL; + + return BLE_ERROR_NONE; + } + protected: uint8_t serviceCount; uint8_t characteristicCount; private: - DataSentCallbackChain_t dataSentCallChain; - DataWrittenCallbackChain_t dataWrittenCallChain; - DataReadCallbackChain_t dataReadCallChain; - EventCallback_t updatesEnabledCallback; - EventCallback_t updatesDisabledCallback; - EventCallback_t confirmationReceivedCallback; + DataSentCallbackChain_t dataSentCallChain; + DataWrittenCallbackChain_t dataWrittenCallChain; + DataReadCallbackChain_t dataReadCallChain; + GattServerShutdownCallbackChain_t shutdownCallChain; + EventCallback_t updatesEnabledCallback; + EventCallback_t updatesDisabledCallback; + EventCallback_t confirmationReceivedCallback; private: /* Disallow copy and assignment. */ diff --git a/ble/SecurityManager.h b/ble/SecurityManager.h index 444e3aa..e508954 100644 --- a/ble/SecurityManager.h +++ b/ble/SecurityManager.h @@ -20,6 +20,7 @@ #include #include "Gap.h" +#include "CallChainOfFunctionPointersWithContext.h" class SecurityManager { public: @@ -82,6 +83,9 @@ public: typedef void (*LinkSecuredCallback_t)(Gap::Handle_t handle, SecurityMode_t securityMode); typedef void (*PasskeyDisplayCallback_t)(Gap::Handle_t handle, const Passkey_t passkey); + typedef FunctionPointerWithContext SecurityManagerShutdownCallback_t; + typedef CallChainOfFunctionPointersWithContext SecurityManagerShutdownCallbackChain_t; + /* * The following functions are meant to be overridden in the platform-specific sub-class. */ @@ -161,6 +165,38 @@ public: /* Event callback handlers. */ public: + /** + * Setup a callback to be invoked to notify the user application that the + * SecurityManager instance is about to shutdown (possibly as a result of a call + * to BLE::shutdown()). + * + * @Note: It is possible to chain together multiple onShutdown callbacks + * (potentially from different modules of an application) to be notified + * before the SecurityManager is shutdown. + * + * @Note: It is also possible to set up a callback into a member function of + * some object. + * + * @Note It is possible to unregister a callback using onShutdown().detach(callback) + */ + void onShutdown(const SecurityManagerShutdownCallback_t& callback) { + shutdownCallChain.add(callback); + } + template + void onShutdown(T *objPtr, void (T::*memberPtr)(void)) { + shutdownCallChain.add(objPtr, memberPtr); + } + + /** + * @brief provide access to the callchain of shutdown event callbacks + * It is possible to register callbacks using onShutdown().add(callback); + * It is possible to unregister callbacks using onShutdown().detach(callback) + * @return The shutdown event callbacks chain + */ + SecurityManagerShutdownCallbackChain_t& onShutdown() { + return shutdownCallChain; + } + /** * To indicate that a security procedure for the link has started. */ @@ -231,12 +267,43 @@ protected: /* empty */ } +public: + /** + * Notify all registered onShutdown callbacks that the SecurityManager is + * about to be shutdown and clear all SecurityManager state of the + * associated object. + * + * This function is meant to be overridden in the platform-specific + * sub-class. Nevertheless, the sub-class is only expected to reset its + * state and not the data held in SecurityManager members. This shall be + * achieved by a call to SecurityManager::reset() from the sub-class' + * reset() implementation. + * + * @return BLE_ERROR_NONE on success. + */ + virtual ble_error_t reset(void) { + /* Notify that the instance is about to shutdown */ + shutdownCallChain.call(this); + shutdownCallChain.clear(); + + securitySetupInitiatedCallback = NULL; + securitySetupCompletedCallback = NULL; + linkSecuredCallback = NULL; + securityContextStoredCallback = NULL; + passkeyDisplayCallback = NULL; + + return BLE_ERROR_NONE; + } + protected: SecuritySetupInitiatedCallback_t securitySetupInitiatedCallback; SecuritySetupCompletedCallback_t securitySetupCompletedCallback; LinkSecuredCallback_t linkSecuredCallback; HandleSpecificEvent_t securityContextStoredCallback; PasskeyDisplayCallback_t passkeyDisplayCallback; + +private: + SecurityManagerShutdownCallbackChain_t shutdownCallChain; }; #endif /*__SECURITY_MANAGER_H__*/ diff --git a/ble/ServiceDiscovery.h b/ble/ServiceDiscovery.h index 595bc20..c023aea 100644 --- a/ble/ServiceDiscovery.h +++ b/ble/ServiceDiscovery.h @@ -132,6 +132,27 @@ public: */ virtual void onTermination(TerminationCallback_t callback) = 0; + /** + * Clear all ServiceDiscovery state of the associated object. + * + * This function is meant to be overridden in the platform-specific + * sub-class. Nevertheless, the sub-class is only expected to reset its + * state and not the data held in ServiceDiscovery members. This shall be + * achieved by a call to ServiceDiscovery::reset() from the sub-class' + * reset() implementation. + * + * @return BLE_ERROR_NONE on success. + */ + virtual ble_error_t reset(void) { + connHandle = 0; + matchingServiceUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN); + serviceCallback = NULL; + matchingCharacteristicUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN); + characteristicCallback = NULL; + + return BLE_ERROR_NONE; + } + protected: Gap::Handle_t connHandle; /**< Connection handle as provided by the SoftDevice. */ UUID matchingServiceUUID; diff --git a/ble/blecommon.h b/ble/blecommon.h index ed71fff..16fdec0 100644 --- a/ble/blecommon.h +++ b/ble/blecommon.h @@ -49,62 +49,6 @@ enum { BLE_UUID_GAP_CHARACTERISTIC_PPCP = 0x2A04, /**< Peripheral Preferred Connection Parameters Characteristic. */ }; -/*! Bluetooth appearance values. - * @note Retrieved from http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml - */ -enum { - BLE_APPEARANCE_UNKNOWN = 0, /**< Unknown. */ - BLE_APPEARANCE_GENERIC_PHONE = 64, /**< Generic Phone. */ - BLE_APPEARANCE_GENERIC_COMPUTER = 128, /**< Generic Computer. */ - BLE_APPEARANCE_GENERIC_WATCH = 192, /**< Generic Watch. */ - BLE_APPEARANCE_WATCH_SPORTS_WATCH = 193, /**< Watch: Sports Watch. */ - BLE_APPEARANCE_GENERIC_CLOCK = 256, /**< Generic Clock. */ - BLE_APPEARANCE_GENERIC_DISPLAY = 320, /**< Generic Display. */ - BLE_APPEARANCE_GENERIC_REMOTE_CONTROL = 384, /**< Generic Remote Control. */ - BLE_APPEARANCE_GENERIC_EYE_GLASSES = 448, /**< Generic Eye-glasses. */ - BLE_APPEARANCE_GENERIC_TAG = 512, /**< Generic Tag. */ - BLE_APPEARANCE_GENERIC_KEYRING = 576, /**< Generic Keyring. */ - BLE_APPEARANCE_GENERIC_MEDIA_PLAYER = 640, /**< Generic Media Player. */ - BLE_APPEARANCE_GENERIC_BARCODE_SCANNER = 704, /**< Generic Barcode Scanner. */ - BLE_APPEARANCE_GENERIC_THERMOMETER = 768, /**< Generic Thermometer. */ - BLE_APPEARANCE_THERMOMETER_EAR = 769, /**< Thermometer: Ear. */ - BLE_APPEARANCE_GENERIC_HEART_RATE_SENSOR = 832, /**< Generic Heart Rate Sensor. */ - BLE_APPEARANCE_HEART_RATE_SENSOR_HEART_RATE_BELT = 833, /**< Heart Rate Sensor: Heart Rate Belt. */ - BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE = 896, /**< Generic Blood Pressure. */ - BLE_APPEARANCE_BLOOD_PRESSURE_ARM = 897, /**< Blood Pressure: Arm. */ - BLE_APPEARANCE_BLOOD_PRESSURE_WRIST = 898, /**< Blood Pressure: Wrist. */ - BLE_APPEARANCE_GENERIC_HID = 960, /**< Human Interface Device (HID). */ - BLE_APPEARANCE_HID_KEYBOARD = 961, /**< Keyboard (HID subtype). */ - BLE_APPEARANCE_HID_MOUSE = 962, /**< Mouse (HID subtype). */ - BLE_APPEARANCE_HID_JOYSTICK = 963, /**< Joystick (HID subtype). */ - BLE_APPEARANCE_HID_GAMEPAD = 964, /**< Gamepad (HID subtype). */ - BLE_APPEARANCE_HID_DIGITIZERSUBTYPE = 965, /**< Digitizer Tablet (HID subtype). */ - BLE_APPEARANCE_HID_CARD_READER = 966, /**< Card Reader (HID subtype). */ - BLE_APPEARANCE_HID_DIGITAL_PEN = 967, /**< Digital Pen (HID subtype). */ - BLE_APPEARANCE_HID_BARCODE = 968, /**< Barcode Scanner (HID subtype). */ - BLE_APPEARANCE_GENERIC_GLUCOSE_METER = 1024, /**< Generic Glucose Meter. */ - BLE_APPEARANCE_GENERIC_RUNNING_WALKING_SENSOR = 1088, /**< Generic Running Walking Sensor. */ - BLE_APPEARANCE_RUNNING_WALKING_SENSOR_IN_SHOE = 1089, /**< Running Walking Sensor: In-Shoe. */ - BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_SHOE = 1090, /**< Running Walking Sensor: On-Shoe. */ - BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_HIP = 1091, /**< Running Walking Sensor: On-Hip. */ - BLE_APPEARANCE_GENERIC_CYCLING = 1152, /**< Generic Cycling. */ - BLE_APPEARANCE_CYCLING_CYCLING_COMPUTER = 1153, /**< Cycling: Cycling Computer. */ - BLE_APPEARANCE_CYCLING_SPEED_SENSOR = 1154, /**< Cycling: Speed Sensor. */ - BLE_APPEARANCE_CYCLING_CADENCE_SENSOR = 1155, /**< Cycling: Cadence Sensor. */ - BLE_APPEARANCE_CYCLING_POWER_SENSOR = 1156, /**< Cycling: Power Sensor. */ - BLE_APPEARANCE_CYCLING_SPEED_CADENCE_SENSOR = 1157, /**< Cycling: Speed and Cadence Sensor. */ - BLE_APPEARANCE_GENERIC_PULSE_OXIMETER = 3136, /**< Generic Pulse Oximeter. */ - BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP = 3137, /**< Fingertip (Pulse Oximeter subtype). */ - BLE_APPEARANCE_PULSE_OXIMETER_WRIST_WORN = 3138, /**< Wrist Worn (Pulse Oximeter subtype). */ - BLE_APPEARANCE_GENERIC_WEIGHT_SCALE = 3200, /**< Generic Weight Scale. */ - BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS_ACT = 5184, /**< Generic Outdoor Sports Activity. */ - BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_DISP = 5185, /**< Location Display Device (Outdoor Sports Activity subtype). */ - BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_DISP = 5186, /**< Location and Navigation Display Device (Outdoor Sports Activity subtype). */ - BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_POD = 5187, /**< Location Pod (Outdoor Sports Activity subtype). */ - BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_POD = 5188, /**< Location and Navigation Pod (Outdoor Sports Activity subtype). */ -}; - - /*! @brief Error codes for the BLE API. */ enum ble_error_t { BLE_ERROR_NONE = 0, /**< No error. */ @@ -119,6 +63,7 @@ enum ble_error_t { BLE_ERROR_INITIALIZATION_INCOMPLETE = 9, BLE_ERROR_ALREADY_INITIALIZED = 10, BLE_ERROR_UNSPECIFIED = 11, /**< Unknown error. */ + BLE_ERROR_INTERNAL_STACK_FAILURE = 12, /**< The platform-specific stack failed */ }; /** @brief Default MTU size. */ diff --git a/module.json b/module.json index 7386e78..dd87d83 100644 --- a/module.json +++ b/module.json @@ -1,6 +1,6 @@ { "name": "ble", - "version": "2.1.14", + "version": "2.2.2", "description": "The BLE module offers a high level abstraction for using Bluetooth Low Energy on multiple platforms.", "keywords": [ "Bluetooth", @@ -26,7 +26,7 @@ "x-nucleo-idb0xa1": "^2.0.0" }, "nrf51822": { - "ble-nrf51822": "^2.1.3" + "ble-nrf51822": "^2.2.8" }, "cordio": { "ble-wicentric": "~0.0.4" diff --git a/source/BLE.cpp b/source/BLE.cpp index f2e537a..c1ac1b2 100644 --- a/source/BLE.cpp +++ b/source/BLE.cpp @@ -131,7 +131,6 @@ bool BLE::hasInitialized(void) const ble_error_t BLE::shutdown(void) { - clearAdvertisingPayload(); if (!transport) { error("bad handle to underlying transport"); } diff --git a/source/DiscoveredCharacteristic.cpp b/source/DiscoveredCharacteristic.cpp index 3e46ac7..e2a6849 100644 --- a/source/DiscoveredCharacteristic.cpp +++ b/source/DiscoveredCharacteristic.cpp @@ -31,29 +31,29 @@ DiscoveredCharacteristic::read(uint16_t offset) const return gattc->read(connHandle, valueHandle, offset); } -struct OneShotReadCallback { - static void launch(GattClient* client, Gap::Handle_t connHandle, - GattAttribute::Handle_t handle, const GattClient::ReadCallback_t& cb) { +struct OneShotReadCallback { + static void launch(GattClient* client, Gap::Handle_t connHandle, + GattAttribute::Handle_t handle, const GattClient::ReadCallback_t& cb) { OneShotReadCallback* oneShot = new OneShotReadCallback(client, connHandle, handle, cb); oneShot->attach(); // delete will be made when this callback is called } private: - OneShotReadCallback(GattClient* client, Gap::Handle_t connHandle, - GattAttribute::Handle_t handle, const GattClient::ReadCallback_t& cb) : + OneShotReadCallback(GattClient* client, Gap::Handle_t connHandle, + GattAttribute::Handle_t handle, const GattClient::ReadCallback_t& cb) : _client(client), _connHandle(connHandle), - _handle(handle), - _callback(cb) { } + _handle(handle), + _callback(cb) { } - void attach() { + void attach() { _client->onDataRead(makeFunctionPointer(this, &OneShotReadCallback::call)); } void call(const GattReadCallbackParams* params) { // verifiy that it is the right characteristic on the right connection - if (params->connHandle == _connHandle && params->handle == _handle) { + if (params->connHandle == _connHandle && params->handle == _handle) { _callback(params); _client->onDataRead().detach(makeFunctionPointer(this, &OneShotReadCallback::call)); delete this; @@ -68,7 +68,7 @@ private: ble_error_t DiscoveredCharacteristic::read(uint16_t offset, const GattClient::ReadCallback_t& onRead) const { ble_error_t error = read(offset); - if (error) { + if (error) { return error; } @@ -105,29 +105,29 @@ DiscoveredCharacteristic::writeWoResponse(uint16_t length, const uint8_t *value) return gattc->write(GattClient::GATT_OP_WRITE_CMD, connHandle, valueHandle, length, value); } -struct OneShotWriteCallback { - static void launch(GattClient* client, Gap::Handle_t connHandle, - GattAttribute::Handle_t handle, const GattClient::WriteCallback_t& cb) { +struct OneShotWriteCallback { + static void launch(GattClient* client, Gap::Handle_t connHandle, + GattAttribute::Handle_t handle, const GattClient::WriteCallback_t& cb) { OneShotWriteCallback* oneShot = new OneShotWriteCallback(client, connHandle, handle, cb); oneShot->attach(); // delete will be made when this callback is called } private: - OneShotWriteCallback(GattClient* client, Gap::Handle_t connHandle, - GattAttribute::Handle_t handle, const GattClient::WriteCallback_t& cb) : + OneShotWriteCallback(GattClient* client, Gap::Handle_t connHandle, + GattAttribute::Handle_t handle, const GattClient::WriteCallback_t& cb) : _client(client), _connHandle(connHandle), - _handle(handle), - _callback(cb) { } + _handle(handle), + _callback(cb) { } - void attach() { + void attach() { _client->onDataWritten(makeFunctionPointer(this, &OneShotWriteCallback::call)); } void call(const GattWriteCallbackParams* params) { // verifiy that it is the right characteristic on the right connection - if (params->connHandle == _connHandle && params->handle == _handle) { + if (params->connHandle == _connHandle && params->handle == _handle) { _callback(params); _client->onDataWritten().detach(makeFunctionPointer(this, &OneShotWriteCallback::call)); delete this; @@ -142,7 +142,7 @@ private: ble_error_t DiscoveredCharacteristic::write(uint16_t length, const uint8_t *value, const GattClient::WriteCallback_t& onRead) const { ble_error_t error = write(length, value); - if (error) { + if (error) { return error; }