High level Bluetooth Low Energy API and radio abstraction layer
Fork of BLE_API by
Revision 861:2afa79e3ed0a, committed 2015-11-02
- Comitter:
- rgrover1
- Date:
- Mon Nov 02 09:09:07 2015 +0000
- Parent:
- 860:0d41e4eb3d0a
- Child:
- 862:d4be8c0b9ab3
- Commit message:
- Synchronized with git rev e0ef88f4
Author: Rohit Grover
Merge branch 'master' into develop.
Changed in this revision
--- a/ble/BLE.h Mon Nov 02 09:09:07 2015 +0000 +++ b/ble/BLE.h Mon Nov 02 09:09:07 2015 +0000 @@ -21,9 +21,15 @@ #include "Gap.h" #include "GattServer.h" #include "GattClient.h" -#include "BLEInstanceBase.h" +#ifdef YOTTA_CFG_MBED_OS +#include "mbed-drivers/mbed_error.h" +#else #include "mbed_error.h" +#endif + +/* forward declaration for the implementation class */ +class BLEInstanceBase; /** * The base class used to abstract away BLE capable radio transceivers or SOCs, @@ -32,6 +38,20 @@ class BLE { public: + typedef unsigned InstanceID_t; /** The type returned by BLE::getInstanceID(). */ + + /** + * The function signature for callbacks for initialization completion. + * @param ble + * A reference to the BLE instance being initialized. + * @param error + * This captures the result of initialization. It is set to + * BLE_ERROR_NONE if initialization completed successfully. Else + * the error value is implementation specific. + * + */ + typedef void (*InitializationCompleteCallback_t)(BLE &ble, ble_error_t error); + /** * Initialize the BLE controller. This should be called before using * anything else in the BLE_API. @@ -42,21 +62,44 @@ * system startup. It may not be safe to call init() from global static * context where ordering is compiler specific and can't be guaranteed--it * is safe to call BLE::init() from within main(). + * + * @param callback + * A callback for when initialization completes for a BLE + * instance. This is an optional parameter, if no callback is + * setup the application can still determine the status of + * initialization using BLE::hasInitialized() (see below). + * + * @return BLE_ERROR_NONE if the initialization procedure was started + * successfully. + * + * @note The underlying stack must invoke the initialization completion + * callback in response to init(). In some cases, initialization is + * instantaneous (or blocking); if so, it is acceptable for the stack- + * specific implementation of init() to invoke the completion callback + * directly--i.e. within its own context. + * + * @note Nearly all BLE APIs would return + * BLE_ERROR_INITIALIZATION_INCOMPLETE if used on an instance before the + * corresponding transport is initialized. */ - ble_error_t init(); + ble_error_t init(InitializationCompleteCallback_t callback = NULL); + + /** + * @return true if initialization has completed for the underlying BLE + * transport. + * + * The application can setup a callback to signal completion of + * initialization when using init(). Otherwise, this method can be used to + * poll the state of initialization. + */ + bool hasInitialized(void) const; /** * Purge the BLE stack of GATT and GAP state. init() must be called * afterwards to re-instate services and GAP state. This API offers a way to * repopulate the GATT database with new services and characteristics. */ - ble_error_t shutdown(void) { - clearAdvertisingPayload(); - if (!transport) { - error("bad handle to underlying transport"); - } - return transport->shutdown(); - } + ble_error_t shutdown(void); /** * This call allows the application to get the BLE stack version information. @@ -64,81 +107,36 @@ * @return A pointer to a const string representing the version. * Note: The string is owned by the BLE_API. */ - const char *getVersion(void) { - if (!transport) { - error("bad handle to underlying transport"); - } - return transport->getVersion(); - } + const char *getVersion(void); /* * Accessors to GAP. Please refer to Gap.h. All GAP related functionality requires * going through this accessor. */ - const Gap &gap() const { - if (!transport) { - error("bad handle to underlying transport"); - } - return transport->getGap(); - } - Gap &gap() { - if (!transport) { - error("bad handle to underlying transport"); - } - return transport->getGap(); - } + const Gap &gap() const; + Gap &gap(); /* * Accessors to GATT Server. Please refer to GattServer.h. All GATTServer related * functionality requires going through this accessor. */ - const GattServer& gattServer() const { - if (!transport) { - error("bad handle to underlying transport"); - } - return transport->getGattServer(); - } - GattServer& gattServer() { - if (!transport) { - error("bad handle to underlying transport"); - } - return transport->getGattServer(); - } + const GattServer& gattServer() const; + GattServer& gattServer(); /* * Accessors to GATT Client. Please refer to GattClient.h. All GATTClient related * functionality requires going through this accessor. */ - const GattClient& gattClient() const { - if (!transport) { - error("bad handle to underlying transport"); - } - return transport->getGattClient(); - } - GattClient& gattClient() { - if (!transport) { - error("bad handle to underlying transport"); - } - return transport->getGattClient(); - } + const GattClient& gattClient() const; + GattClient& gattClient(); /* * Accessors to Security Manager. Please refer to SecurityManager.h. All * SecurityManager related functionality requires going through this * accessor. */ - const SecurityManager& securityManager() const { - if (!transport) { - error("bad handle to underlying transport"); - } - return transport->getSecurityManager(); - } - SecurityManager& securityManager() { - if (!transport) { - error("bad handle to underlying transport"); - } - return transport->getSecurityManager(); - } + const SecurityManager& securityManager() const; + SecurityManager& securityManager(); /** * Yield control to the BLE stack or to other tasks waiting for events. This @@ -147,15 +145,9 @@ * returning (to service the stack). This is not always interchangeable with * WFE(). */ - void waitForEvent(void) { - if (!transport) { - error("bad handle to underlying transport"); - } - transport->waitForEvent(); - } + void waitForEvent(void); public: - typedef unsigned InstanceID_t; static const InstanceID_t DEFAULT_INSTANCE = 0; #ifndef YOTTA_CFG_BLE_INSTANCES_COUNT static const InstanceID_t NUM_INSTANCES = 1; @@ -190,6 +182,12 @@ */ BLE(InstanceID_t instanceID = DEFAULT_INSTANCE); + /** + * Fetch the ID of a BLE instance. Typically there would only be the DEFAULT_INSTANCE. + */ + InstanceID_t getInstanceID(void) const { + return instanceID; + } /* * Deprecation alert! @@ -1394,6 +1392,7 @@ BLE &operator=(const BLE &); private: + InstanceID_t instanceID; BLEInstanceBase *transport; /* the device specific backend */ };
--- a/ble/BLEInstanceBase.h Mon Nov 02 09:09:07 2015 +0000 +++ b/ble/BLEInstanceBase.h Mon Nov 02 09:09:07 2015 +0000 @@ -18,6 +18,8 @@ #define __BLE_DEVICE_INSTANCE_BASE__ #include "Gap.h" +#include "ble/SecurityManager.h" +#include "ble/BLE.h" /* forward declarations */ class GattServer; @@ -30,17 +32,18 @@ class BLEInstanceBase { public: - virtual ble_error_t init(void) = 0; - virtual ble_error_t shutdown(void) = 0; - virtual const char *getVersion(void) = 0; - virtual Gap& getGap() = 0; - virtual const Gap& getGap() const = 0; - virtual GattServer& getGattServer() = 0; - virtual const GattServer& getGattServer() const = 0; - virtual GattClient& getGattClient() = 0; - virtual SecurityManager& getSecurityManager() = 0; + virtual ble_error_t init(BLE::InstanceID_t instanceID, BLE::InitializationCompleteCallback_t) = 0; + virtual bool hasInitialized(void) const = 0; + virtual ble_error_t shutdown(void) = 0; + virtual const char * getVersion(void) = 0; + virtual Gap& getGap() = 0; + virtual const Gap& getGap() const = 0; + virtual GattServer& getGattServer() = 0; + virtual const GattServer& getGattServer() const = 0; + virtual GattClient& getGattClient() = 0; + virtual SecurityManager& getSecurityManager() = 0; virtual const SecurityManager& getSecurityManager() const = 0; - virtual void waitForEvent(void) = 0; + virtual void waitForEvent(void) = 0; }; /**
--- a/ble/Gap.h Mon Nov 02 09:09:07 2015 +0000 +++ b/ble/Gap.h Mon Nov 02 09:09:07 2015 +0000 @@ -867,8 +867,8 @@ } private: - virtual ble_error_t setAdvertisingData(const GapAdvertisingData &, const GapAdvertisingData &) = 0; - virtual ble_error_t startAdvertising(const GapAdvertisingParams &) = 0; + virtual ble_error_t setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) = 0; + virtual ble_error_t startAdvertising(const GapAdvertisingParams &) = 0; public: /**
--- a/ble/UUID.h Mon Nov 02 09:09:07 2015 +0000 +++ b/ble/UUID.h Mon Nov 02 09:09:07 2015 +0000 @@ -74,7 +74,7 @@ * * @note we don't yet support 32-bit shortened UUIDs. */ - UUID(ShortUUIDBytes_t shortUUID) : type(UUID_TYPE_SHORT), baseUUID(), shortUUID(shortUUID) { + UUID(ShortUUIDBytes_t _shortUUID) : type(UUID_TYPE_SHORT), baseUUID(), shortUUID(_shortUUID) { /* empty */ }
--- a/ble/blecommon.h Mon Nov 02 09:09:07 2015 +0000 +++ b/ble/blecommon.h Mon Nov 02 09:09:07 2015 +0000 @@ -114,16 +114,18 @@ */ /**************************************************************************/ enum ble_error_t { - BLE_ERROR_NONE = 0, /**< No error */ - BLE_ERROR_BUFFER_OVERFLOW = 1, /**< The requested action would cause a buffer overflow and has been aborted */ - BLE_ERROR_NOT_IMPLEMENTED = 2, /**< Requested a feature that isn't yet implement or isn't supported by the target HW */ - BLE_ERROR_PARAM_OUT_OF_RANGE = 3, /**< One of the supplied parameters is outside the valid range */ - BLE_ERROR_INVALID_PARAM = 4, /**< One of the supplied parameters is invalid */ - BLE_STACK_BUSY = 5, /**< The stack is busy */ - BLE_ERROR_INVALID_STATE = 6, /**< Invalid state. */ - BLE_ERROR_NO_MEM = 7, /**< Out of Memory */ - BLE_ERROR_OPERATION_NOT_PERMITTED = 8, - BLE_ERROR_UNSPECIFIED = 9, /**< Unknown error. */ + BLE_ERROR_NONE = 0, /**< No error */ + BLE_ERROR_BUFFER_OVERFLOW = 1, /**< The requested action would cause a buffer overflow and has been aborted */ + BLE_ERROR_NOT_IMPLEMENTED = 2, /**< Requested a feature that isn't yet implement or isn't supported by the target HW */ + BLE_ERROR_PARAM_OUT_OF_RANGE = 3, /**< One of the supplied parameters is outside the valid range */ + BLE_ERROR_INVALID_PARAM = 4, /**< One of the supplied parameters is invalid */ + BLE_STACK_BUSY = 5, /**< The stack is busy */ + BLE_ERROR_INVALID_STATE = 6, /**< Invalid state. */ + BLE_ERROR_NO_MEM = 7, /**< Out of Memory */ + BLE_ERROR_OPERATION_NOT_PERMITTED = 8, + BLE_ERROR_INITIALIZATION_INCOMPLETE = 9, + BLE_ERROR_ALREADY_INITIALIZED = 10, + BLE_ERROR_UNSPECIFIED = 11, /**< Unknown error. */ }; /** @brief Default MTU size. */
--- a/ble/services/EddystoneConfigService.h Mon Nov 02 09:09:07 2015 +0000 +++ b/ble/services/EddystoneConfigService.h Mon Nov 02 09:09:07 2015 +0000 @@ -285,7 +285,7 @@ ble.setTxPower(radioPowerLevels[params.txPowerMode]); ble.setDeviceName(reinterpret_cast<const uint8_t *>(&DEVICE_NAME)); ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); - ble.setAdvertisingInterval(GapAdvertisingParams::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(ADVERTISING_INTERVAL_MSEC)); + ble.setAdvertisingInterval(ADVERTISING_INTERVAL_MSEC); } /* @@ -306,7 +306,7 @@ eddyServ.setTLMFrameData(params.tlmVersion, params.tlmBeaconPeriod); } if (params.uriEnabled) { - eddyServ.setURLFrameData(params.advPowerLevels[params.txPowerMode], (const char *) params.uriData, params.uriBeaconPeriod); + eddyServ.setURLFrameEncodedData(params.advPowerLevels[params.txPowerMode], (const char *) params.uriData, params.uriDataLength, params.uriBeaconPeriod); } if (params.uidEnabled) { eddyServ.setUIDFrameData(params.advPowerLevels[params.txPowerMode], @@ -340,7 +340,7 @@ } else if (handle == uriDataChar.getValueHandle()) { params.uriDataLength = writeParams->len; memset(params.uriData, 0x00, URI_DATA_MAX); // clear URI string - memcpy(params.uriData, writeParams->data, params.uriDataLength); // set URI string + memcpy(params.uriData, writeParams->data, writeParams->len); // set URI string params.uriEnabled = true; INFO("URI = %s, URILen = %d", writeParams->data, writeParams->len); } else if (handle == flagsChar.getValueHandle()) {
--- a/ble/services/EddystoneService.h Mon Nov 02 09:09:07 2015 +0000 +++ b/ble/services/EddystoneService.h Mon Nov 02 09:09:07 2015 +0000 @@ -175,16 +175,40 @@ urlIsSet = false; return false; } - defaultUrlPower = power; encodeURL(urlIn, defaultUriData, defaultUriDataLength); // encode URL to URL Formatting if (defaultUriDataLength > URI_DATA_MAX) { return true; // error, URL is too big } + defaultUrlPower = power; urlAdvPeriod = urlAdvPeriodIn; urlIsSet = true; return false; } + /** + * Set Eddystone URL Frame information. + * @param[in] power TX Power in dB measured at 0 meters from the device. + * @param[in] encodedUrlIn Encoded URL + * @param[in] encodedUrlInLength Length of the encoded URL + * @param[in] urlAdvPeriodIn How long to advertise the URL frame (measured in # of adv periods) + * @return false on success, true on failure. + */ + bool setURLFrameEncodedData(int8_t power, const char *encodedUrlIn, uint8_t encodedUrlInLength, uint32_t urlAdvPeriodIn) { + if (0 == urlAdvPeriodIn) { + urlIsSet = false; + return false; + } + memcpy(defaultUriData, encodedUrlIn, encodedUrlInLength); + if (defaultUriDataLength > URI_DATA_MAX) { + return true; // error, URL is too big + } + defaultUrlPower = power; + defaultUriDataLength = encodedUrlInLength; + urlAdvPeriod = urlAdvPeriodIn; + urlIsSet = true; + return false; + } + /* * Construct URL frame from private variables * @param[in/out] Data pointer to array to store constructed frame in @@ -236,6 +260,10 @@ * @return number of bytes used. negative number indicates error message. */ int constructTLMFrame(uint8_t *Data, uint8_t maxSize) { + uint32_t now = timeSinceBootTimer.read_ms(); + TlmTimeSinceBoot += (now - lastBootTimerRead) / 100; + lastBootTimerRead = now; + int index = 0; Data[index++] = FRAME_TYPE_TLM; // Eddystone frame type = Telemetry Data[index++] = TlmVersion; // TLM Version Number @@ -292,14 +320,6 @@ } /* - * callback function, called every 0.1s, incriments the TimeSinceBoot field in the TLM frame - * @return nothing - */ - void tsbCallback(void) { - TlmTimeSinceBoot++; - } - - /* * Update advertising data * @return true on success, false on failure */ @@ -500,7 +520,8 @@ // Make double sure the PDUCount and TimeSinceBoot fields are set to zero at reset updateTlmPduCount(0); updateTlmTimeSinceBoot(0); - timeSinceBootTick.attach(this, &EddystoneService::tsbCallback, 0.1); // incriment the TimeSinceBoot ticker every 0.1s + lastBootTimerRead = 0; + timeSinceBootTimer.start(); tlmTicker.attach(this, &EddystoneService::tlmCallback, TlmAdvPeriod); DBG("attached tlmCallback every %d seconds", TlmAdvPeriod); } @@ -519,7 +540,8 @@ BLEDevice &ble; uint16_t advPeriodus; uint8_t txPower; - Ticker timeSinceBootTick; // counter that counts time since boot + Timer timeSinceBootTimer; + volatile uint32_t lastBootTimerRead; volatile bool advLock; volatile FrameTypes frameIndex; Timeout stopAdv;
--- a/ble/services/HealthThermometerService.h Mon Nov 02 09:09:07 2015 +0000 +++ b/ble/services/HealthThermometerService.h Mon Nov 02 09:09:07 2015 +0000 @@ -17,7 +17,7 @@ #ifndef __BLE_HEALTH_THERMOMETER_SERVICE_H__ #define __BLE_HEALTH_THERMOMETER_SERVICE_H__ -#include "BLE.h" +#include "ble/BLE.h" /** * @class HealthThermometerService
--- a/ble/services/LinkLossService.h Mon Nov 02 09:09:07 2015 +0000 +++ b/ble/services/LinkLossService.h Mon Nov 02 09:09:07 2015 +0000 @@ -17,7 +17,7 @@ #ifndef __BLE_LINK_LOSS_SERVICE_H__ #define __BLE_LINK_LOSS_SERVICE_H__ -#include "Gap.h" +#include "ble/Gap.h" /** * @class LinkLossService @@ -55,7 +55,7 @@ ble.addService(linkLossService); serviceAdded = true; - ble.addToDisconnectionCallChain(this, &LinkLossService::onDisconnectionFilter); + ble.onDisconnection(this, &LinkLossService::onDisconnectionFilter); ble.onDataWritten(this, &LinkLossService::onDataWritten); } @@ -86,7 +86,7 @@ } } - void onDisconnectionFilter(void) { + void onDisconnectionFilter(const Gap::DisconnectionCallbackParams_t *params) { if (alertLevel != NO_ALERT) { callback(alertLevel); }
--- a/ble/services/UARTService.h Mon Nov 02 09:09:07 2015 +0000 +++ b/ble/services/UARTService.h Mon Nov 02 09:09:07 2015 +0000 @@ -17,8 +17,13 @@ #ifndef __BLE_UART_SERVICE_H__ #define __BLE_UART_SERVICE_H__ +#ifdef YOTTA_CFG_MBED_OS +#include "mbed-drivers/mbed.h" +#include "mbed-drivers/Stream.h" +#else #include "mbed.h" #include "Stream.h" +#endif #include "ble/UUID.h" #include "ble/BLE.h"
--- a/ble/services/URIBeaconConfigService.h Mon Nov 02 09:09:07 2015 +0000 +++ b/ble/services/URIBeaconConfigService.h Mon Nov 02 09:09:07 2015 +0000 @@ -18,7 +18,12 @@ #define SERVICES_URIBEACONCONFIGSERVICE_H_ #include "ble/BLE.h" + +#ifdef YOTTA_CFG_MBED_OS +#include "mbed-drivers/mbed.h" +#else #include "mbed.h" +#endif extern const uint8_t UUID_URI_BEACON_SERVICE[UUID::LENGTH_OF_LONG_UUID]; extern const uint8_t UUID_LOCK_STATE_CHAR[UUID::LENGTH_OF_LONG_UUID];
--- a/module.json Mon Nov 02 09:09:07 2015 +0000 +++ b/module.json Mon Nov 02 09:09:07 2015 +0000 @@ -1,6 +1,6 @@ { "name": "ble", - "version": "1.0.0", + "version": "1.1.0", "description": "The BLE module offers a high level abstraction for using Bluetooth Low Energy on multiple platforms.", "keywords": [ "Bluetooth", @@ -28,6 +28,9 @@ "nrf51822": { "ble-nrf51822": "^1.0.0" }, + "cordio": { + "ble-wicentric": "~0.0.0" + }, "mbed-classic": { "mbed-classic": "~0.0.1" },
--- a/source/BLE.cpp Mon Nov 02 09:09:07 2015 +0000 +++ b/source/BLE.cpp Mon Nov 02 09:09:07 2015 +0000 @@ -15,15 +15,16 @@ */ #include "ble/BLE.h" +#include "ble/BLEInstanceBase.h" #if defined(TARGET_OTA_ENABLED) #include "ble/services/DFUService.h" #endif ble_error_t -BLE::init() +BLE::init(BLE::InitializationCompleteCallback_t callback) { - ble_error_t err = transport->init(); + ble_error_t err = transport->init(instanceID, callback); if (err != BLE_ERROR_NONE) { return err; } @@ -105,7 +106,7 @@ return badSingleton; } -BLE::BLE(InstanceID_t instanceID) : transport() +BLE::BLE(InstanceID_t instanceIDIn) : instanceID(instanceIDIn), transport() { static BLEInstanceBase *transportInstances[NUM_INSTANCES]; @@ -117,4 +118,113 @@ } else { transport = NULL; } +} + +bool BLE::hasInitialized(void) const +{ + if (!transport) { + error("bad handle to underlying transport"); + } + + return transport->hasInitialized(); +} + +ble_error_t BLE::shutdown(void) +{ + clearAdvertisingPayload(); + if (!transport) { + error("bad handle to underlying transport"); + } + + return transport->shutdown(); +} + +const char *BLE::getVersion(void) +{ + if (!transport) { + error("bad handle to underlying transport"); + } + + return transport->getVersion(); +} + +const Gap &BLE::gap() const +{ + if (!transport) { + error("bad handle to underlying transport"); + } + + return transport->getGap(); +} + +Gap &BLE::gap() +{ + if (!transport) { + error("bad handle to underlying transport"); + } + + return transport->getGap(); +} + +const GattServer& BLE::gattServer() const +{ + if (!transport) { + error("bad handle to underlying transport"); + } + + return transport->getGattServer(); +} + +GattServer& BLE::gattServer() +{ + if (!transport) { + error("bad handle to underlying transport"); + } + + return transport->getGattServer(); +} + +const GattClient& BLE::gattClient() const +{ + if (!transport) { + error("bad handle to underlying transport"); + } + + return transport->getGattClient(); +} + +GattClient& BLE::gattClient() +{ + if (!transport) { + error("bad handle to underlying transport"); + } + + return transport->getGattClient(); +} + +const SecurityManager& BLE::securityManager() const +{ + if (!transport) { + error("bad handle to underlying transport"); + } + + return transport->getSecurityManager(); +} + +SecurityManager& BLE::securityManager() +{ + if (!transport) { + error("bad handle to underlying transport"); + } + + return transport->getSecurityManager(); +} + +void BLE::waitForEvent(void) +{ + if (!transport) { + error("bad handle to underlying transport"); + } + + transport->waitForEvent(); } \ No newline at end of file