Software can read HMC5883L
Fork of BLE_API by
Revision 807:d119f9333581, committed 2015-09-29
- Comitter:
- rgrover1
- Date:
- Tue Sep 29 09:47:52 2015 +0100
- Parent:
- 806:50c121156a71
- Child:
- 808:f902b7ca06a6
- Commit message:
- Synchronized with git rev ad8e92ac
Author: Rohit Grover
adding an initial prototype for a yotta-config based initialization for BLE transports
Changed in this revision
ble/BLE.h | Show annotated file Show diff for this revision Revisions of this file |
source/BLE.cpp | Show annotated file Show diff for this revision Revisions of this file |
--- a/ble/BLE.h Tue Sep 29 09:47:51 2015 +0100 +++ b/ble/BLE.h Tue Sep 29 09:47:52 2015 +0100 @@ -23,6 +23,8 @@ #include "GattClient.h" #include "BLEInstanceBase.h" +#include "mbed_error.h" + /** * The base class used to abstract away BLE capable radio transceivers or SOCs, * to enable this BLE API to work with any radio transparently. @@ -50,6 +52,9 @@ */ ble_error_t shutdown(void) { clearAdvertisingPayload(); + if (!transport) { + error("bad handle to underlying transport"); + } return transport->shutdown(); } @@ -60,6 +65,9 @@ * Note: The string is owned by the BLE_API. */ const char *getVersion(void) { + if (!transport) { + error("bad handle to underlying transport"); + } return transport->getVersion(); } @@ -68,9 +76,15 @@ * 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(); } @@ -79,9 +93,15 @@ * 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(); } @@ -90,9 +110,15 @@ * 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(); } @@ -102,9 +128,15 @@ * 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(); } @@ -116,9 +148,49 @@ * WFE(). */ void waitForEvent(void) { + if (!transport) { + error("bad handle to underlying transport"); + } transport->waitForEvent(); } +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; +#else + static const InstanceID_t NUM_INSTANCES = YOTTA_CFG_BLE_INSTANCES_COUNT; +#endif + + /** + * Get a reference to the BLE singleton corresponding to a given interface. + * There is a static array of BLE singletons. + * + * @Note: Calling Instance() is preferred over constructing a BLE object + * directly, as it returns references to singletons. + * + * @param[in] id + * Instance-ID. This should be less than NUM_INSTANCES in order + * for the returned BLE singleton to be useful. + * + * @return a reference to a single object + */ + static BLE &Instance(InstanceID_t id = DEFAULT_INSTANCE); + + /** + * Constructor for a handle to a BLE instance (i.e. BLE stack). BLE handles + * are thin wrappers around a transport object (i.e. ptr. to + * BLEInstanceBase). + * + * BLE objects are are better created as singletons accessed through the + * Instance() method. If multiple BLE handles are constructed for the same + * interface (using this constructor), they will share the same underlying + * transport object. + */ + BLE(InstanceID_t instanceID = DEFAULT_INSTANCE); + + /* * Deprecation alert! * All of the following are deprecated and may be dropped in a future @@ -1327,17 +1399,12 @@ return securityManager().onPasskeyDisplay(callback); } -public: - BLE() : transport(createBLEInstance()) { - /* empty */ - } - private: BLE(const BLE&); BLE &operator=(const BLE &); private: - BLEInstanceBase *const transport; /* the device specific backend */ + BLEInstanceBase *transport; /* the device specific backend */ }; typedef BLE BLEDevice; /* DEPRECATED. This type alias is retained for the sake of compatibility with older
--- a/source/BLE.cpp Tue Sep 29 09:47:51 2015 +0100 +++ b/source/BLE.cpp Tue Sep 29 09:47:52 2015 +0100 @@ -35,4 +35,77 @@ #endif // TARGET_OTA_ENABLED return BLE_ERROR_NONE; +} + +/** + * BLE::Instance() and BLE constructor rely upon a static array of initializers + * to create actual BLE transport instances. A description of these instances + * and initializers is supposed to be put in some .json file contributing to + * yotta's configuration (typically the target.json). Here's a sample: + * + * "config": { + * ... + * "ble_instances": { + * "count": 1, + * "0" : { + * "initializer" : "createBLEInstance" + * } + * } + * } + * + * The following macros result in translating the above config into a static + * array: instanceConstructors. + */ +#ifdef YOTTA_CFG_BLE_INSTANCES_COUNT +#define CONCATENATE(A, B) A ## B +#define EXPAND(X) X /* this adds a level of indirection needed to allow macro-expansion following a token-paste operation (see use of CONCATENATE() below). */ + +#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_1 YOTTA_CFG_BLE_INSTANCES_0_INITIALIZER +#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_2 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_1, YOTTA_CFG_BLE_INSTANCES_1_INITIALIZER +#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_3 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_2, YOTTA_CFG_BLE_INSTANCES_2_INITIALIZER +#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_4 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_3, YOTTA_CFG_BLE_INSTANCES_3_INITIALIZER +#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_5 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_4, YOTTA_CFG_BLE_INSTANCES_4_INITIALIZER +/* ... add more of the above if ever needed */ + +#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS(N) EXPAND(CONCATENATE(INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_, N)) +#endif /* YOTTA_CFG_BLE_INSTANCES_COUNT */ + +typedef BLEInstanceBase *(*InstanceConstructor_t)(void); +static const InstanceConstructor_t instanceConstructors[BLE::NUM_INSTANCES] = { +#ifndef YOTTA_CFG_BLE_INSTANCES_COUNT + createBLEInstance +#else + INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS(YOTTA_CFG_BLE_INSTANCES_COUNT) +#endif +}; + +BLE::BLE & +BLE::Instance(InstanceID_t id) +{ + static BLE *singletons[NUM_INSTANCES]; + if (id < NUM_INSTANCES) { + if (singletons[id] == NULL) { + singletons[id] = new BLE(id); /* This object will never be freed. */ + } + + return *singletons[id]; + } + + /* we come here only in the case of a bad interfaceID. */ + static BLE badSingleton(NUM_INSTANCES /* this is a bad index; and will result in a NULL transport. */); + return badSingleton; +} + +BLE::BLE(InstanceID_t instanceID) : transport() +{ + static BLEInstanceBase *transportInstances[NUM_INSTANCES]; + + if (instanceID < NUM_INSTANCES) { + if (!transportInstances[instanceID]) { + transportInstances[instanceID] = instanceConstructors[instanceID](); /* Call the stack's initializer for the transport object. */ + } + transport = transportInstances[instanceID]; + } else { + transport = NULL; + } } \ No newline at end of file