diff --git a/source/btle/btle.cpp b/source/btle/btle.cpp index f119d27..edd2a72 100644 --- a/source/btle/btle.cpp +++ b/source/btle/btle.cpp @@ -27,9 +27,7 @@ #include "custom/custom_helper.h" #include "ble/GapEvents.h" -#include "nRF5xGap.h" -#include "nRF5xGattServer.h" -#include "nRF5xSecurityManager.h" +#include "nRF5xn.h" extern "C" { #include "pstorage.h" @@ -138,6 +136,11 @@ static void btle_handler(ble_evt_t *p_ble_evt) bleGattcEventHandler(p_ble_evt); #endif + nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE); + nRF5xGap &gap = (nRF5xGap &) ble.getGap(); + nRF5xGattServer &gattServer = (nRF5xGattServer &) ble.getGattServer(); + nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager(); + /* Custom event handler */ switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: { @@ -148,11 +151,11 @@ static void btle_handler(ble_evt_t *p_ble_evt) #else Gap::Role_t role = static_cast(p_ble_evt->evt.gap_evt.params.connected.role); #endif - nRF5xGap::getInstance().setConnectionHandle(handle); + gap.setConnectionHandle(handle); const Gap::ConnectionParams_t *params = reinterpret_cast(&(p_ble_evt->evt.gap_evt.params.connected.conn_params)); const ble_gap_addr_t *peer = &p_ble_evt->evt.gap_evt.params.connected.peer_addr; const ble_gap_addr_t *own = &p_ble_evt->evt.gap_evt.params.connected.own_addr; - nRF5xGap::getInstance().processConnectionEvent(handle, + gap.processConnectionEvent(handle, role, static_cast(peer->addr_type), peer->addr, static_cast(own->addr_type), own->addr, @@ -164,7 +167,7 @@ static void btle_handler(ble_evt_t *p_ble_evt) Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle; // Since we are not in a connection and have not started advertising, // store bonds - nRF5xGap::getInstance().setConnectionHandle (BLE_CONN_HANDLE_INVALID); + gap.setConnectionHandle (BLE_CONN_HANDLE_INVALID); Gap::DisconnectionReason_t reason; switch (p_ble_evt->evt.gap_evt.params.disconnected.reason) { @@ -183,16 +186,16 @@ static void btle_handler(ble_evt_t *p_ble_evt) reason = static_cast(p_ble_evt->evt.gap_evt.params.disconnected.reason); break; } - nRF5xGap::getInstance().processDisconnectionEvent(handle, reason); + gap.processDisconnectionEvent(handle, reason); break; } case BLE_GAP_EVT_PASSKEY_DISPLAY: - nRF5xSecurityManager::getInstance().processPasskeyDisplayEvent(p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->evt.gap_evt.params.passkey_display.passkey); + securityManager.processPasskeyDisplayEvent(p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->evt.gap_evt.params.passkey_display.passkey); break; case BLE_GAP_EVT_TIMEOUT: - nRF5xGap::getInstance().processTimeoutEvent(static_cast(p_ble_evt->evt.gap_evt.params.timeout.src)); + gap.processTimeoutEvent(static_cast(p_ble_evt->evt.gap_evt.params.timeout.src)); break; case BLE_GATTC_EVT_TIMEOUT: @@ -204,12 +207,12 @@ static void btle_handler(ble_evt_t *p_ble_evt) case BLE_GAP_EVT_ADV_REPORT: { const ble_gap_evt_adv_report_t *advReport = &p_ble_evt->evt.gap_evt.params.adv_report; - nRF5xGap::getInstance().processAdvertisementReport(advReport->peer_addr.addr, - advReport->rssi, - advReport->scan_rsp, - static_cast(advReport->type), - advReport->dlen, - advReport->data); + gap.processAdvertisementReport(advReport->peer_addr.addr, + advReport->rssi, + advReport->scan_rsp, + static_cast(advReport->type), + advReport->dlen, + advReport->data); break; } @@ -217,7 +220,7 @@ static void btle_handler(ble_evt_t *p_ble_evt) break; } - nRF5xGattServer::getInstance().hwCallback(p_ble_evt); + gattServer.hwCallback(p_ble_evt); } /*! @brief Callback when an error occurs inside the SoftDevice */ diff --git a/source/btle/btle_discovery.cpp b/source/btle/btle_discovery.cpp index 2329c97..1e5b1d7 100644 --- a/source/btle/btle_discovery.cpp +++ b/source/btle/btle_discovery.cpp @@ -14,13 +14,15 @@ * limitations under the License. */ -#include "nRF5xServiceDiscovery.h" -#include "nRF5xGattClient.h" +#include "nRF5xn.h" #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) void bleGattcEventHandler(const ble_evt_t *p_ble_evt) { - nRF5xServiceDiscovery &sdSingleton = nRF5xGattClient::getInstance().discovery; + nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE); + nRF5xGap &gap = (nRF5xGap &) ble.getGap(); + nRF5xGattClient &gattClient = (nRF5xGattClient &) ble.getGattClient(); + nRF5xServiceDiscovery &sdSingleton = gattClient.discovery; switch (p_ble_evt->header.evt_id) { case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: @@ -63,7 +65,7 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) .len = p_ble_evt->evt.gattc_evt.params.read_rsp.len, .data = p_ble_evt->evt.gattc_evt.params.read_rsp.data, }; - nRF5xGattClient::getInstance().processReadResponse(&response); + gattClient.processReadResponse(&response); } break; @@ -76,7 +78,7 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) .len = p_ble_evt->evt.gattc_evt.params.write_rsp.len, .data = p_ble_evt->evt.gattc_evt.params.write_rsp.data, }; - nRF5xGattClient::getInstance().processWriteResponse(&response); + gattClient.processWriteResponse(&response); } break; @@ -88,7 +90,7 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) params.len = p_ble_evt->evt.gattc_evt.params.hvx.len; params.data = p_ble_evt->evt.gattc_evt.params.hvx.data; - nRF5xGattClient::getInstance().processHVXEvent(¶ms); + gattClient.processHVXEvent(¶ms); } break; } diff --git a/source/btle/btle_security.cpp b/source/btle/btle_security.cpp index 3f4ee02..ba92fe7 100644 --- a/source/btle/btle_security.cpp +++ b/source/btle/btle_security.cpp @@ -16,8 +16,7 @@ #include "btle.h" -#include "nRF5xGap.h" -#include "nRF5xSecurityManager.h" +#include "nRF5xn.h" extern "C" { #include "pstorage.h" @@ -204,17 +203,20 @@ btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMo ret_code_t dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result) { + nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE); + nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager(); + switch (p_event->event_id) { case DM_EVT_SECURITY_SETUP: /* started */ { const ble_gap_sec_params_t *peerParams = &p_event->event_param.p_gap_param->params.sec_params_request.peer_params; - nRF5xSecurityManager::getInstance().processSecuritySetupInitiatedEvent(p_event->event_param.p_gap_param->conn_handle, + securityManager.processSecuritySetupInitiatedEvent(p_event->event_param.p_gap_param->conn_handle, peerParams->bond, peerParams->mitm, (SecurityManager::SecurityIOCapabilities_t)peerParams->io_caps); break; } case DM_EVT_SECURITY_SETUP_COMPLETE: - nRF5xSecurityManager::getInstance(). + securityManager. processSecuritySetupCompletedEvent(p_event->event_param.p_gap_param->conn_handle, (SecurityManager::SecurityCompletionStatus_t)(p_event->event_param.p_gap_param->params.auth_status.auth_status)); break; @@ -248,11 +250,11 @@ dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t ev break; } - nRF5xSecurityManager::getInstance().processLinkSecuredEvent(p_event->event_param.p_gap_param->conn_handle, resolvedSecurityMode); + securityManager.processLinkSecuredEvent(p_event->event_param.p_gap_param->conn_handle, resolvedSecurityMode); break; } case DM_EVT_DEVICE_CONTEXT_STORED: - nRF5xSecurityManager::getInstance().processSecurityContextStoredEvent(p_event->event_param.p_gap_param->conn_handle); + securityManager.processSecurityContextStoredEvent(p_event->event_param.p_gap_param->conn_handle); break; default: break; diff --git a/source/nRF5xGap.cpp b/source/nRF5xGap.cpp index 912f536..a1c744f 100644 --- a/source/nRF5xGap.cpp +++ b/source/nRF5xGap.cpp @@ -14,20 +14,17 @@ * limitations under the License. */ -#include "nRF5xGap.h" +#include "nRF5xn.h" #include "mbed.h" +#include "ble/BLE.h" #include "common/common.h" #include "ble_advdata.h" #include "ble_hci.h" -nRF5xGap &nRF5xGap::getInstance() { - static nRF5xGap m_instance; - return m_instance; -} - void radioNotificationStaticCallback(bool param) { - nRF5xGap::getInstance().processRadioNotificationEvent(param); + nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap(); + gap.processRadioNotificationEvent(param); } /**************************************************************************/ @@ -336,6 +333,29 @@ ble_error_t nRF5xGap::updateConnectionParams(Handle_t handle, const ConnectionPa } } +/**************************************************************************/ +/*! + @brief Clear nRF5xGap's state. + + @returns ble_error_t + + @retval BLE_ERROR_NONE + Everything executed properly +*/ +/**************************************************************************/ +ble_error_t nRF5xGap::reset(void) +{ + /* Clear all state that is from the parent, including private members */ + if (Gap::reset() != BLE_ERROR_NONE) { + return BLE_ERROR_INVALID_STATE; + } + + /* Clear derived class members */ + m_connectionHandle = BLE_CONN_HANDLE_INVALID; + + return BLE_ERROR_NONE; +} + /**************************************************************************/ /*! @brief Sets the 16-bit connection handle diff --git a/source/nRF5xGap.h b/source/nRF5xGap.h index a7cb732..285cbeb 100644 --- a/source/nRF5xGap.h +++ b/source/nRF5xGap.h @@ -44,8 +44,6 @@ void radioNotificationStaticCallback(bool param); class nRF5xGap : public Gap { public: - static nRF5xGap &getInstance(); - /* Functions that must be implemented from Gap */ virtual ble_error_t setAddress(AddressType_t type, const Address_t address); virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address); @@ -76,6 +74,8 @@ class nRF5xGap : public Gap virtual ble_error_t setPreferredConnectionParams(const ConnectionParams_t *params); virtual ble_error_t updateConnectionParams(Handle_t handle, const ConnectionParams_t *params); + virtual ble_error_t reset(void); + virtual ble_error_t initRadioNotification(void) { if (ble_radio_notification_init(NRF_APP_PRIORITY_HIGH, NRF_RADIO_NOTIFICATION_DISTANCE_800US, radioNotificationStaticCallback) == NRF_SUCCESS) { return BLE_ERROR_NONE; @@ -196,6 +196,12 @@ class nRF5xGap : public Gap private: uint16_t m_connectionHandle; + + /* + * Allow instantiation from nRF5xn when required. + */ + friend class nRF5xn; + nRF5xGap() { m_connectionHandle = BLE_CONN_HANDLE_INVALID; } diff --git a/source/nRF5xGattClient.cpp b/source/nRF5xGattClient.cpp index 3a4b1e6..aae8fb6 100644 --- a/source/nRF5xGattClient.cpp +++ b/source/nRF5xGattClient.cpp @@ -16,15 +16,6 @@ #include "nRF5xGattClient.h" -nRF5xGattClient & -nRF5xGattClient::getInstance(void) { - static nRF5xGattClient* nRFGattClientSingleton = NULL; - if (nRFGattClientSingleton == NULL) { - nRFGattClientSingleton = new nRF5xGattClient(); - } - return *nRFGattClientSingleton; -} - #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) ble_error_t nRF5xGattClient::launchServiceDiscovery(Gap::Handle_t connectionHandle, diff --git a/source/nRF5xGattClient.h b/source/nRF5xGattClient.h index 5974f18..cb108de 100644 --- a/source/nRF5xGattClient.h +++ b/source/nRF5xGattClient.h @@ -23,8 +23,6 @@ class nRF5xGattClient : public GattClient { public: - static nRF5xGattClient &getInstance(); - /** * When using S110, all Gatt client features will return * BLE_ERROR_NOT_IMPLEMENTED @@ -147,7 +145,30 @@ class nRF5xGattClient : public GattClient } } + /** + * @brief Clear nRF5xGattClient's state. + * + * @return + * BLE_ERROR_NONE if successful. + */ + virtual ble_error_t reset(void) { + /* Clear all state that is from the parent, including private members */ + if (GattClient::reset() != BLE_ERROR_NONE) { + return BLE_ERROR_INVALID_STATE; + } + + /* Clear derived class members */ + discovery.reset(); + + return BLE_ERROR_NONE; + } + public: + /* + * Allow instantiation from nRF5xn when required. + */ + friend class nRF5xn; + nRF5xGattClient() : discovery(this) { /* empty */ } diff --git a/source/nRF5xGattServer.cpp b/source/nRF5xGattServer.cpp index 7af8576..fb6e0c7 100644 --- a/source/nRF5xGattServer.cpp +++ b/source/nRF5xGattServer.cpp @@ -20,12 +20,7 @@ #include "common/common.h" #include "btle/custom/custom_helper.h" -#include "nRF5xGap.h" - -nRF5xGattServer &nRF5xGattServer::getInstance(void) { - static nRF5xGattServer m_instance; - return m_instance; -} +#include "nRF5xn.h" /**************************************************************************/ /*! @@ -241,7 +236,8 @@ ble_error_t nRF5xGattServer::write(Gap::Handle_t connectionHandle, GattAttribute hvx_params.p_len = &len; if (connectionHandle == BLE_CONN_HANDLE_INVALID) { /* use the default connection handle if the caller hasn't specified a valid connectionHandle. */ - connectionHandle = nRF5xGap::getInstance().getConnectionHandle(); + nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap(); + connectionHandle = gap.getConnectionHandle(); } error_t error = (error_t) sd_ble_gatts_hvx(connectionHandle, &hvx_params); if (error != ERROR_NONE) { @@ -280,7 +276,8 @@ ble_error_t nRF5xGattServer::write(Gap::Handle_t connectionHandle, GattAttribute ble_error_t nRF5xGattServer::areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP) { /* Forward the call with the default connection handle. */ - return areUpdatesEnabled(nRF5xGap::getInstance().getConnectionHandle(), characteristic, enabledP); + nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap(); + return areUpdatesEnabled(gap.getConnectionHandle(), characteristic, enabledP); } ble_error_t nRF5xGattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP) @@ -310,6 +307,33 @@ ble_error_t nRF5xGattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, c return BLE_ERROR_NONE; } +/**************************************************************************/ +/*! + @brief Clear nRF5xGattServer's state. + + @returns ble_error_t + + @retval BLE_ERROR_NONE + Everything executed properly +*/ +/**************************************************************************/ +ble_error_t nRF5xGattServer::reset(void) +{ + /* Clear all state that is from the parent, including private members */ + if (GattServer::reset() != BLE_ERROR_NONE) { + return BLE_ERROR_INVALID_STATE; + } + + /* Clear derived class members */ + memset(p_characteristics, 0, sizeof(p_characteristics)); + memset(p_descriptors, 0, sizeof(p_descriptors)); + memset(nrfCharacteristicHandles, 0, sizeof(ble_gatts_char_handles_t)); + memset(nrfDescriptorHandles, 0, sizeof(nrfDescriptorHandles)); + descriptorCount = 0; + + return BLE_ERROR_NONE; +} + /**************************************************************************/ /*! @brief Callback handler for events getting pushed up from the SD diff --git a/source/nRF5xGattServer.h b/source/nRF5xGattServer.h index 9c9a14f..f929f8c 100644 --- a/source/nRF5xGattServer.h +++ b/source/nRF5xGattServer.h @@ -27,8 +27,6 @@ class nRF5xGattServer : public GattServer { public: - static nRF5xGattServer &getInstance(); - /* Functions that must be implemented from GattServer */ virtual ble_error_t addService(GattService &); virtual ble_error_t read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP); @@ -37,11 +35,13 @@ class nRF5xGattServer : public GattServer virtual ble_error_t write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t, const uint8_t[], uint16_t, bool localOnly = false); virtual ble_error_t areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP); virtual ble_error_t areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP); + virtual ble_error_t reset(void); /* nRF51 Functions */ void eventCallback(void); void hwCallback(ble_evt_t *p_ble_evt); + private: const static unsigned BLE_TOTAL_CHARACTERISTICS = 20; const static unsigned BLE_TOTAL_DESCRIPTORS = 8; @@ -86,6 +86,11 @@ class nRF5xGattServer : public GattServer uint8_t descriptorCount; uint16_t nrfDescriptorHandles[BLE_TOTAL_DESCRIPTORS]; + /* + * Allow instantiation from nRF5xn when required. + */ + friend class nRF5xn; + nRF5xGattServer() : GattServer(), p_characteristics(), nrfCharacteristicHandles(), p_descriptors(), descriptorCount(0), nrfDescriptorHandles() { /* empty */ } diff --git a/source/nRF5xSecurityManager.cpp b/source/nRF5xSecurityManager.cpp deleted file mode 100644 index a4ccd4f..0000000 --- a/source/nRF5xSecurityManager.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* 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. - */ - -#include "nRF5xSecurityManager.h" - -nRF5xSecurityManager &nRF5xSecurityManager::getInstance(void) { - static nRF5xSecurityManager* m_instance = NULL; - if (m_instance == NULL) { - m_instance = new nRF5xSecurityManager(); - } - return *m_instance; -} diff --git a/source/nRF5xSecurityManager.h b/source/nRF5xSecurityManager.h index fb723e6..4c30841 100644 --- a/source/nRF5xSecurityManager.h +++ b/source/nRF5xSecurityManager.h @@ -25,8 +25,6 @@ class nRF5xSecurityManager : public SecurityManager { public: - static nRF5xSecurityManager &getInstance(); - /* Functions that must be implemented from SecurityManager */ virtual ble_error_t init(bool enableBonding, bool requireMITM, @@ -47,7 +45,27 @@ class nRF5xSecurityManager : public SecurityManager return btle_purgeAllBondingState(); } + /** + * @brief Clear nRF5xSecurityManager's state. + * + * @return + * BLE_ERROR_NONE if successful. + */ + virtual ble_error_t reset(void) + { + if (SecurityManager::reset() != BLE_ERROR_NONE) { + return BLE_ERROR_INVALID_STATE; + } + + return BLE_ERROR_NONE; + } + public: + /* + * Allow instantiation from nRF5xn when required. + */ + friend class nRF5xn; + nRF5xSecurityManager() { /* empty */ } diff --git a/source/nRF5xServiceDiscovery.h b/source/nRF5xServiceDiscovery.h index 8c89f93..29d41c0 100644 --- a/source/nRF5xServiceDiscovery.h +++ b/source/nRF5xServiceDiscovery.h @@ -99,6 +99,34 @@ class nRF5xServiceDiscovery : public ServiceDiscovery onTerminationCallback = callback; } + /** + * @brief Clear nRF5xServiceDiscovery's state. + * + * @return + * BLE_ERROR_NONE if successful. + */ + virtual ble_error_t reset(void) { + /* Clear all state that is from the parent, including private members */ + if (ServiceDiscovery::reset() != BLE_ERROR_NONE) { + return BLE_ERROR_INVALID_STATE; + } + + /* Clear derived class members */ + serviceIndex = 0; + numServices = 0; + characteristicIndex = 0; + numCharacteristics = 0; + + state = INACTIVE; + + serviceUUIDDiscoveryQueue.reset(); + charUUIDDiscoveryQueue.reset(); + + onTerminationCallback = NULL; + + return BLE_ERROR_NONE; + } + private: ble_error_t launchCharacteristicDiscovery(Gap::Handle_t connectionHandle, Gap::Handle_t startHandle, Gap::Handle_t endHandle); diff --git a/source/nRF5xn.cpp b/source/nRF5xn.cpp index b706b33..f2e8882 100644 --- a/source/nRF5xn.cpp +++ b/source/nRF5xn.cpp @@ -38,10 +38,22 @@ static nRF5xn deviceInstance; BLEInstanceBase * createBLEInstance(void) { - return (&deviceInstance); + return &nRF5xn::Instance(BLE::DEFAULT_INSTANCE); } -nRF5xn::nRF5xn(void) : initialized(false), instanceID(BLE::DEFAULT_INSTANCE) +nRF5xn& nRF5xn::Instance(BLE::InstanceID_t instanceId) +{ + return deviceInstance; +} + +nRF5xn::nRF5xn(void) : + initialized(false), + instanceID(BLE::DEFAULT_INSTANCE), + _gapInstance(), + gapInstance(NULL), + gattServerInstance(NULL), + gattClientInstance(NULL), + securityManagerInstance(NULL) { } @@ -104,16 +116,69 @@ ble_error_t nRF5xn::init(BLE::InstanceID_t instanceID, FunctionPointerWithContex return BLE_ERROR_NONE; } +/**************************************************************************/ +/*! + @brief Purge the BLE stack of GATT and GAP state. + + @returns ble_error_t + + @retval BLE_ERROR_NONE + Everything executed properly + + @note When using S110, GattClient::shutdown() will not be called + since Gatt client features are not supported. +*/ +/**************************************************************************/ ble_error_t nRF5xn::shutdown(void) { if (!initialized) { return BLE_ERROR_INITIALIZATION_INCOMPLETE; } + /* + * Shutdown the SoftDevice first. This is because we need to disable all + * interrupts. Otherwise if we clear the BLE API and glue code first there + * will be many NULL references and no config information which could lead + * to errors if the shutdown process is interrupted. + */ if(softdevice_handler_sd_disable() != NRF_SUCCESS) { return BLE_STACK_BUSY; } + + /* Shutdown the BLE API and nRF51 glue code */ + ble_error_t error; + + if (gattServerInstance != NULL) { + error = gattServerInstance->reset(); + if (error != BLE_ERROR_NONE) { + return error; + } + } + + if (securityManagerInstance != NULL) { + error = securityManagerInstance->reset(); + if (error != BLE_ERROR_NONE) { + return error; + } + } + + /* S110 does not support BLE client features, nothing to reset. */ +#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) + if (gattClientInstance != NULL) { + error = gattClientInstance->reset(); + if (error != BLE_ERROR_NONE) { + return error; + } + } +#endif + + /* Gap instance is always present */ + error = gapInstance->reset(); + if (error != BLE_ERROR_NONE) { + return error; + } + initialized = false; return BLE_ERROR_NONE; } diff --git a/source/nRF5xn.h b/source/nRF5xn.h index 2dd13c9..c0a65f3 100644 --- a/source/nRF5xn.h +++ b/source/nRF5xn.h @@ -41,32 +41,152 @@ class nRF5xn : public BLEInstanceBase virtual ble_error_t shutdown(void); virtual const char *getVersion(void); + /** + * Accessors to GAP. This function checks whether gapInstance points to an + * object. If if does not, then the gapInstance is updated to + * &_getInstance before returning. + * + * @return A reference to GattServer. + * + * @note Unlike the GattClient, GattServer and SecurityManager, Gap is + * always needed in a BLE application. Therefore it is allocated + * statically. + */ virtual Gap &getGap() { - return nRF5xGap::getInstance(); - }; - virtual const Gap &getGap() const { - return nRF5xGap::getInstance(); + if (gapInstance == NULL) { + gapInstance = &_gapInstance; + } + return *gapInstance; }; + + /** + * Accessors to GATT Server. This function checks whether a GattServer + * object was previously instantiated. If such object does not exist, then + * it is created before returning. + * + * @return A reference to GattServer. + */ virtual GattServer &getGattServer() { - return nRF5xGattServer::getInstance(); - }; - virtual const GattServer &getGattServer() const { - return nRF5xGattServer::getInstance(); + if (gattServerInstance == NULL) { + gattServerInstance = new nRF5xGattServer(); + } + return *gattServerInstance; }; + + /** + * Accessors to GATT Client. This function checks whether a GattClient + * object was previously instantiated. If such object does not exist, then + * it is created before returning. + * + * @return A reference to GattClient. + */ virtual GattClient &getGattClient() { - return nRF5xGattClient::getInstance(); - } - virtual const SecurityManager &getSecurityManager() const { - return nRF5xSecurityManager::getInstance(); + if (gattClientInstance == NULL) { + gattClientInstance = new nRF5xGattClient(); + } + return *gattClientInstance; } + + /** + * Accessors to Security Manager. This function checks whether a SecurityManager + * object was previously instantiated. If such object does not exist, then + * it is created before returning. + * + * @return A reference to GattServer. + */ virtual SecurityManager &getSecurityManager() { - return nRF5xSecurityManager::getInstance(); + if (securityManagerInstance == NULL) { + securityManagerInstance = new nRF5xSecurityManager(); + } + return *securityManagerInstance; } + + /** + * Accessors to GAP. This function checks whether gapInstance points to an + * object. If if does not, then the gapInstance is updated to + * &_getInstance before returning. + * + * @return A const reference to GattServer. + * + * @note Unlike the GattClient, GattServer and SecurityManager, Gap is + * always needed in a BLE application. Therefore it is allocated + * statically. + * + * @note The accessor is able to modify the object's state because the + * internal pointer has been declared mutable. + */ + virtual const Gap &getGap() const { + if (gapInstance == NULL) { + gapInstance = &_gapInstance; + } + return *gapInstance; + }; + + /** + * Accessors to GATT Server. This function checks whether a GattServer + * object was previously instantiated. If such object does not exist, then + * it is created before returning. + * + * @return A const reference to GattServer. + * + * @note The accessor is able to modify the object's state because the + * internal pointer has been declared mutable. + */ + virtual const GattServer &getGattServer() const { + if (gattServerInstance == NULL) { + gattServerInstance = new nRF5xGattServer(); + } + return *gattServerInstance; + }; + + /** + * Accessors to Security Manager. This function checks whether a SecurityManager + * object was previously instantiated. If such object does not exist, then + * it is created before returning. + * + * @return A const reference to GattServer. + * + * @note The accessor is able to modify the object's state because the + * internal pointer has been declared mutable. + */ + virtual const SecurityManager &getSecurityManager() const { + if (securityManagerInstance == NULL) { + securityManagerInstance = new nRF5xSecurityManager(); + } + return *securityManagerInstance; + } + virtual void waitForEvent(void); +public: + static nRF5xn& Instance(BLE::InstanceID_t instanceId); + private: bool initialized; BLE::InstanceID_t instanceID; + +private: + mutable nRF5xGap _gapInstance; /**< Gap instance whose reference is returned from a call to + * getGap(). Unlike the GattClient, GattServer and + * SecurityManager, Gap is always needed in a BLE application. */ + +private: + mutable nRF5xGap *gapInstance; /**< Pointer to the Gap object instance. + * If NULL, then Gap has not been initialized. + * The pointer has been declared as 'mutable' so that + * it can be assigned inside a 'const' function. */ + mutable nRF5xGattServer *gattServerInstance; /**< Pointer to the GattServer object instance. + * If NULL, then GattServer has not been initialized. + * The pointer has been declared as 'mutable' so that + * it can be assigned inside a 'const' function. */ + mutable nRF5xGattClient *gattClientInstance; /**< Pointer to the GattClient object instance. + * If NULL, then GattClient has not been initialized. + * The pointer has been declared as 'mutable' so that + * it can be assigned inside a 'const' function. */ + mutable nRF5xSecurityManager *securityManagerInstance; /**< Pointer to the SecurityManager object instance. + * If NULL, then SecurityManager has not been initialized. + * The pointer has been declared as 'mutable' so that + * it can be assigned inside a 'const' function. */ }; #endif