From 918af4fbacec39d64f2752afa4e3008ef5154848 Mon Sep 17 00:00:00 2001 From: Rohit Grover Date: Wed, 28 Oct 2015 11:30:10 +0000 Subject: [PATCH] Major change: - There's a new type: BLE::InitializationCompleteCallback_t - init() now takes a completion callback. This is an optional parameter, if no callback is setup the application can still determine the status of initialization using BLE::hasInitialized() (see below). - There's a new API: BLEInstanceBase::hasInitialized() which transports need to implement. - BLEInstanceBase.h is no longer included from BLE.h. We use a forward declaration of BLEInstanceBase instead. This is required us to move implementations of BLE methods out of the header and into BLE.cpp. - There's a new API: BLE::getInstanceID(), which simply returns the ID of an instance. - There are new error types around initialization. --- ble/BLE.h | 118 +++++++++++++++++------------------------- ble/BLEInstanceBase.h | 22 ++++---- ble/blecommon.h | 22 ++++---- source/BLE.cpp | 116 +++++++++++++++++++++++++++++++++++++++-- 4 files changed, 185 insertions(+), 93 deletions(-) diff --git a/ble/BLE.h b/ble/BLE.h index 952318d..8654f7a 100644 --- a/ble/BLE.h +++ b/ble/BLE.h @@ -21,7 +21,6 @@ #include "Gap.h" #include "GattServer.h" #include "GattClient.h" -#include "BLEInstanceBase.h" #ifdef YOTTA_CFG_MBED_OS #include "mbed-drivers/mbed_error.h" @@ -29,6 +28,9 @@ #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, * to enable this BLE API to work with any radio transparently. @@ -36,6 +38,9 @@ class BLE { public: + typedef unsigned InstanceID_t; + typedef void (*InitializationCompleteCallback_t)(BLE &bleInstance); + /** * Initialize the BLE controller. This should be called before using * anything else in the BLE_API. @@ -46,21 +51,38 @@ public: * 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 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. @@ -68,81 +90,36 @@ public: * @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 @@ -151,15 +128,9 @@ public: * 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; @@ -194,6 +165,12 @@ public: */ 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! @@ -1398,6 +1375,7 @@ private: BLE &operator=(const BLE &); private: + InstanceID_t instanceID; BLEInstanceBase *transport; /* the device specific backend */ }; diff --git a/ble/BLEInstanceBase.h b/ble/BLEInstanceBase.h index ab7ba04..e8cfc0d 100644 --- a/ble/BLEInstanceBase.h +++ b/ble/BLEInstanceBase.h @@ -19,6 +19,7 @@ #include "Gap.h" #include "ble/SecurityManager.h" +#include "ble/BLE.h" /* forward declarations */ class GattServer; @@ -31,17 +32,18 @@ class GattClient; 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; }; /** diff --git a/ble/blecommon.h b/ble/blecommon.h index 07e5b63..c2c49db 100644 --- a/ble/blecommon.h +++ b/ble/blecommon.h @@ -114,16 +114,18 @@ enum { */ /**************************************************************************/ 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. */ diff --git a/source/BLE.cpp b/source/BLE.cpp index 28bfd0b..0328ef9 100644 --- a/source/BLE.cpp +++ b/source/BLE.cpp @@ -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 @@ BLE::Instance(InstanceID_t id) return badSingleton; } -BLE::BLE(InstanceID_t instanceID) : transport() +BLE::BLE(InstanceID_t instanceIDIn) : instanceID(instanceIDIn), transport() { static BLEInstanceBase *transportInstances[NUM_INSTANCES]; @@ -118,3 +119,112 @@ BLE::BLE(InstanceID_t instanceID) : transport() 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(); +}