diff --git a/ble/BLE.h b/ble/BLE.h index 00bce18..6a92ca1 100644 --- a/ble/BLE.h +++ b/ble/BLE.h @@ -22,6 +22,8 @@ #include "GattServer.h" #include "GattClient.h" +#include "ble/FunctionPointerWithContext.h" + #ifdef YOTTA_CFG_MBED_OS #include "mbed-drivers/mbed_error.h" #else @@ -41,16 +43,28 @@ public: typedef unsigned InstanceID_t; /** The type returned by BLE::getInstanceID(). */ /** - * The function signature for callbacks for initialization completion. + * The context provided to init-completion-callbacks (see init() below). + * * @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); + struct InitializationCompleteCallbackContext { + BLE& ble; /* Reference to the BLE object which has been initialized */ + ble_error_t error; /* Error status of the initialization. It is set to BLE_ERROR_NONE initialization completed successfully. */ + }; + + /** + * The signature for function-pointer like callbacks for initialization-completion. + * + * @note There are two versions of init(). In addition to the simple + * function-pointer, init() can also take a tuple as its + * callback target. In case of the latter, the following declaration doesn't apply. + */ + typedef void (*InitializationCompleteCallback_t)(InitializationCompleteCallbackContext *context); /** * Initialize the BLE controller. This should be called before using @@ -63,7 +77,7 @@ public: * context where ordering is compiler specific and can't be guaranteed--it * is safe to call BLE::init() from within main(). * - * @param callback + * @param initCompleteCallback * 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 @@ -72,17 +86,36 @@ public: * @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 If init() returns BLE_ERROR_NONE, the underlying stack must invoke + * the initialization completion callback at some point. + * + * @note 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. + * + * @note There are two versions of init(). In addition to the simple + * function-pointer, init() can also take an tuple as its + * callback target. */ - ble_error_t init(InitializationCompleteCallback_t callback = NULL); + ble_error_t init(InitializationCompleteCallback_t initCompleteCallback = NULL) { + FunctionPointerWithContext callback(initCompleteCallback); + initImplementation(callback); + } + + /** + * An alternate declaration for init(). This one takes an tuple as its + * callback target. + */ + template + ble_error_t init(T *object, void (T::*initCompleteCallback)(InitializationCompleteCallbackContext *context)) { + FunctionPointerWithContext callback(object, initCompleteCallback); + initImplementation(callback); + } /** * @return true if initialization has completed for the underlying BLE @@ -1387,6 +1420,15 @@ public: return securityManager().onPasskeyDisplay(callback); } +private: + /** + * Implementation of init() [internal to BLE_API]. + * + * The implementation is separated into a private method because it isn't + * suitable to be included in the header. + */ + ble_error_t initImplementation(FunctionPointerWithContext callback); + private: BLE(const BLE&); BLE &operator=(const BLE &); diff --git a/ble/BLEInstanceBase.h b/ble/BLEInstanceBase.h index e8cfc0d..7949ed4 100644 --- a/ble/BLEInstanceBase.h +++ b/ble/BLEInstanceBase.h @@ -32,7 +32,8 @@ class GattClient; class BLEInstanceBase { public: - virtual ble_error_t init(BLE::InstanceID_t instanceID, BLE::InitializationCompleteCallback_t) = 0; + virtual ble_error_t init(BLE::InstanceID_t instanceID, + FunctionPointerWithContext initCallback) = 0; virtual bool hasInitialized(void) const = 0; virtual ble_error_t shutdown(void) = 0; virtual const char * getVersion(void) = 0; diff --git a/ble/FunctionPointerWithContext.h b/ble/FunctionPointerWithContext.h index 41f8687..26447aa 100644 --- a/ble/FunctionPointerWithContext.h +++ b/ble/FunctionPointerWithContext.h @@ -19,8 +19,6 @@ #include - - /** A class for storing and calling a pointer to a static or member void function * which takes a context. */ @@ -107,10 +105,10 @@ private: template static void membercaller(pFunctionPointerWithContext_t self, ContextType context) { if (self->_memberFunctionAndPointer._object) { - T *o = static_cast(self->_memberFunctionAndPointer._object); + T *o = static_cast(self->_memberFunctionAndPointer._object); void (T::*m)(ContextType); memcpy((char*) &m, self->_memberFunctionAndPointer._memberFunction, sizeof(m)); - (o->*m)(context); + (o->*m)(context); } } @@ -122,9 +120,9 @@ private: struct MemberFunctionAndPtr { /* - * forward declaration of a class and a member function to this class. - * Because the compiler doesn't know anything about the forwarded member - * function, it will always use the biggest size and the biggest alignment + * forward declaration of a class and a member function to this class. + * Because the compiler doesn't know anything about the forwarded member + * function, it will always use the biggest size and the biggest alignment * that a member function can take for objects of type UndefinedMemberFunction. */ class UndefinedClass; @@ -133,17 +131,17 @@ private: void* _object; union { char _memberFunction[sizeof(UndefinedMemberFunction)]; - UndefinedMemberFunction _alignment; + UndefinedMemberFunction _alignment; }; }; union { pvoidfcontext_t _function; /**< static function pointer - NULL if none attached */ - /** - * object this pointer and pointer to member - - * _memberFunctionAndPointer._object will be NULL if none attached - */ - MemberFunctionAndPtr _memberFunctionAndPointer; + /** + * object this pointer and pointer to member - + * _memberFunctionAndPointer._object will be NULL if none attached + */ + MemberFunctionAndPtr _memberFunctionAndPointer; }; void (*_caller)(FunctionPointerWithContext*, ContextType); diff --git a/source/BLE.cpp b/source/BLE.cpp index 0328ef9..f2e537a 100644 --- a/source/BLE.cpp +++ b/source/BLE.cpp @@ -22,7 +22,7 @@ #endif ble_error_t -BLE::init(BLE::InitializationCompleteCallback_t callback) +BLE::initImplementation(FunctionPointerWithContext callback) { ble_error_t err = transport->init(instanceID, callback); if (err != BLE_ERROR_NONE) {