Attempting to publish a tree

Dependencies:   nrf51-sdk

Dependents:   microbit-dal

Fork of nRF51822 by Lancaster University

Files at this revision

API Documentation at this revision

Comitter:
vcoubard
Date:
Mon Jan 11 10:19:24 2016 +0000
Parent:
574:7a531ae7a53c
Child:
576:b699791e1dbc
Commit message:
Synchronized with git rev 252ef3cf
Author: Andres Amaya Garcia
Make _gapInstance non-static in nRF5xn

Changed in this revision

module.json Show annotated file Show diff for this revision Revisions of this file
source/btle/btle.cpp Show annotated file Show diff for this revision Revisions of this file
source/btle/btle_discovery.cpp Show annotated file Show diff for this revision Revisions of this file
source/btle/btle_security.cpp Show annotated file Show diff for this revision Revisions of this file
source/nRF5xGap.cpp Show annotated file Show diff for this revision Revisions of this file
source/nRF5xGap.h Show annotated file Show diff for this revision Revisions of this file
source/nRF5xGattClient.cpp Show annotated file Show diff for this revision Revisions of this file
source/nRF5xGattClient.h Show annotated file Show diff for this revision Revisions of this file
source/nRF5xGattServer.cpp Show annotated file Show diff for this revision Revisions of this file
source/nRF5xGattServer.h Show annotated file Show diff for this revision Revisions of this file
source/nRF5xSecurityManager.cpp Show diff for this revision Revisions of this file
source/nRF5xSecurityManager.h Show annotated file Show diff for this revision Revisions of this file
source/nRF5xServiceDiscovery.h Show annotated file Show diff for this revision Revisions of this file
source/nRF5xn.cpp Show annotated file Show diff for this revision Revisions of this file
source/nRF5xn.h Show annotated file Show diff for this revision Revisions of this file
--- a/module.json	Mon Jan 11 10:19:23 2016 +0000
+++ b/module.json	Mon Jan 11 10:19:24 2016 +0000
@@ -1,6 +1,6 @@
 {
   "name": "ble-nrf51822",
-  "version": "2.2.6",
+  "version": "2.2.5",
   "description": "Nordic stack and drivers for the mbed BLE API.",
   "keywords": [
     "Bluetooth",
@@ -24,7 +24,7 @@
     }
   ],
   "dependencies": {
-    "ble": "^2.1.15",
+    "ble": "^2.1.11",
     "nrf51-sdk": "^1.0.0"
   },
   "extraIncludes": [
--- a/source/btle/btle.cpp	Mon Jan 11 10:19:23 2016 +0000
+++ b/source/btle/btle.cpp	Mon Jan 11 10:19:24 2016 +0000
@@ -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 @@
     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,14 +151,14 @@
 #else
             Gap::Role_t role = static_cast<Gap::Role_t>(p_ble_evt->evt.gap_evt.params.connected.role);
 #endif
-            nRF5xGap::getInstance().setConnectionHandle(handle);
+            gap.setConnectionHandle(handle);
             const Gap::ConnectionParams_t *params = reinterpret_cast<Gap::ConnectionParams_t *>(&(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<BLEProtocol::AddressType_t>(peer->addr_type), peer->addr,
-                                                           static_cast<BLEProtocol::AddressType_t>(own->addr_type),  own->addr,
+                                                           static_cast<Gap::AddressType_t>(peer->addr_type), peer->addr,
+                                                           static_cast<Gap::AddressType_t>(own->addr_type),  own->addr,
                                                            params);
             break;
         }
@@ -164,7 +167,7 @@
             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 @@
                     reason = static_cast<Gap::DisconnectionReason_t>(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<Gap::TimeoutSource_t>(p_ble_evt->evt.gap_evt.params.timeout.src));
+            gap.processTimeoutEvent(static_cast<Gap::TimeoutSource_t>(p_ble_evt->evt.gap_evt.params.timeout.src));
             break;
 
         case BLE_GATTC_EVT_TIMEOUT:
@@ -204,12 +207,12 @@
 
         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<GapAdvertisingParams::AdvertisingType_t>(advReport->type),
-                                                               advReport->dlen,
-                                                               advReport->data);
+            gap.processAdvertisementReport(advReport->peer_addr.addr,
+                                           advReport->rssi,
+                                           advReport->scan_rsp,
+                                           static_cast<GapAdvertisingParams::AdvertisingType_t>(advReport->type),
+                                           advReport->dlen,
+                                           advReport->data);
             break;
         }
 
@@ -217,7 +220,7 @@
             break;
     }
 
-    nRF5xGattServer::getInstance().hwCallback(p_ble_evt);
+    gattServer.hwCallback(p_ble_evt);
 }
 
 /*! @brief      Callback when an error occurs inside the SoftDevice */
--- a/source/btle/btle_discovery.cpp	Mon Jan 11 10:19:23 2016 +0000
+++ b/source/btle/btle_discovery.cpp	Mon Jan 11 10:19:24 2016 +0000
@@ -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 @@
                     .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 @@
                     .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 @@
                 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(&params);
+                gattClient.processHVXEvent(&params);
             }
             break;
     }
--- a/source/btle/btle_security.cpp	Mon Jan 11 10:19:23 2016 +0000
+++ b/source/btle/btle_security.cpp	Mon Jan 11 10:19:24 2016 +0000
@@ -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 @@
 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 @@
                     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;
--- a/source/nRF5xGap.cpp	Mon Jan 11 10:19:23 2016 +0000
+++ b/source/nRF5xGap.cpp	Mon Jan 11 10:19:24 2016 +0000
@@ -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);
 }
 
 /**************************************************************************/
@@ -338,6 +335,29 @@
 
 /**************************************************************************/
 /*!
+    @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
 */
 /**************************************************************************/
@@ -367,7 +387,7 @@
     @code
 
     uint8_t device_address[6] = { 0xca, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0 };
-    nrf.getGap().setAddress(Gap::BLEProtocol::AddressType::RANDOM_STATIC, device_address);
+    nrf.getGap().setAddress(Gap::ADDR_TYPE_RANDOM_STATIC, device_address);
 
     @endcode
 */
@@ -381,12 +401,12 @@
        When using Random Private addresses, the cycle mode must be Auto.
        In auto mode, the given address is ignored.
     */
-    if ((type == BLEProtocol::AddressType::PUBLIC) || (type == BLEProtocol::AddressType::RANDOM_STATIC))
+    if ((type == ADDR_TYPE_PUBLIC) || (type == ADDR_TYPE_RANDOM_STATIC))
     {
         cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_NONE;
         memcpy(dev_addr.addr, address, ADDR_LEN);
     }
-    else if ((type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) || (type == BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE))
+    else if ((type == ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) || (type == ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE))
     {
         cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_AUTO;
         // address is ignored when in auto mode
--- a/source/nRF5xGap.h	Mon Jan 11 10:19:23 2016 +0000
+++ b/source/nRF5xGap.h	Mon Jan 11 10:19:24 2016 +0000
@@ -44,8 +44,6 @@
 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 @@
     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 @@
 
 private:
     uint16_t m_connectionHandle;
+
+    /*
+     * Allow instantiation from nRF5xn when required.
+     */
+    friend class nRF5xn;
+
     nRF5xGap() {
         m_connectionHandle = BLE_CONN_HANDLE_INVALID;
     }
--- a/source/nRF5xGattClient.cpp	Mon Jan 11 10:19:23 2016 +0000
+++ b/source/nRF5xGattClient.cpp	Mon Jan 11 10:19:24 2016 +0000
@@ -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,
--- a/source/nRF5xGattClient.h	Mon Jan 11 10:19:23 2016 +0000
+++ b/source/nRF5xGattClient.h	Mon Jan 11 10:19:24 2016 +0000
@@ -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 @@
         }
     }
 
+    /**
+     * @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 */
     }
--- a/source/nRF5xGattServer.cpp	Mon Jan 11 10:19:23 2016 +0000
+++ b/source/nRF5xGattServer.cpp	Mon Jan 11 10:19:24 2016 +0000
@@ -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 @@
         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::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)
@@ -312,6 +309,33 @@
 
 /**************************************************************************/
 /*!
+    @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
 */
 /**************************************************************************/
--- a/source/nRF5xGattServer.h	Mon Jan 11 10:19:23 2016 +0000
+++ b/source/nRF5xGattServer.h	Mon Jan 11 10:19:24 2016 +0000
@@ -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 @@
     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 @@
     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 */
     }
--- a/source/nRF5xSecurityManager.cpp	Mon Jan 11 10:19:23 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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;
-}
\ No newline at end of file
--- a/source/nRF5xSecurityManager.h	Mon Jan 11 10:19:23 2016 +0000
+++ b/source/nRF5xSecurityManager.h	Mon Jan 11 10:19:24 2016 +0000
@@ -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 @@
         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 */
     }
--- a/source/nRF5xServiceDiscovery.h	Mon Jan 11 10:19:23 2016 +0000
+++ b/source/nRF5xServiceDiscovery.h	Mon Jan 11 10:19:24 2016 +0000
@@ -99,6 +99,34 @@
         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);
 
--- a/source/nRF5xn.cpp	Mon Jan 11 10:19:23 2016 +0000
+++ b/source/nRF5xn.cpp	Mon Jan 11 10:19:24 2016 +0000
@@ -38,10 +38,22 @@
 BLEInstanceBase *
 createBLEInstance(void)
 {
-    return (&deviceInstance);
+    return &nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
+}
+
+nRF5xn& nRF5xn::Instance(BLE::InstanceID_t instanceId)
+{
+    return deviceInstance;
 }
 
-nRF5xn::nRF5xn(void) : initialized(false), instanceID(BLE::DEFAULT_INSTANCE)
+nRF5xn::nRF5xn(void) :
+    initialized(false),
+    instanceID(BLE::DEFAULT_INSTANCE),
+    _gapInstance(),
+    gapInstance(NULL),
+    gattServerInstance(NULL),
+    gattClientInstance(NULL),
+    securityManagerInstance(NULL)
 {
 }
 
@@ -104,16 +116,69 @@
     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;
 }
--- a/source/nRF5xn.h	Mon Jan 11 10:19:23 2016 +0000
+++ b/source/nRF5xn.h	Mon Jan 11 10:19:24 2016 +0000
@@ -41,32 +41,153 @@
     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();
+        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() {
+        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() {
+        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() {
+        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  {
-        return nRF5xGap::getInstance();
+        if (gapInstance == NULL) {
+            gapInstance = &_gapInstance;
+        }
+        return *gapInstance;
     };
-    virtual GattServer &getGattServer() {
-        return nRF5xGattServer::getInstance();
-    };
+
+    /**
+     * 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 {
-        return nRF5xGattServer::getInstance();
+        if (gattServerInstance == NULL) {
+            gattServerInstance = new nRF5xGattServer();
+        }
+        return *gattServerInstance;
     };
-    virtual GattClient &getGattClient() {
-        return nRF5xGattClient::getInstance();
-    }
+
+    /**
+     * 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 {
-        return nRF5xSecurityManager::getInstance();
+        if (securityManagerInstance == NULL) {
+            securityManagerInstance = new nRF5xSecurityManager();
+        }
+        return *securityManagerInstance;
     }
-    virtual SecurityManager &getSecurityManager() {
-        return nRF5xSecurityManager::getInstance();
-    }
+
     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.
+                                    * Therefore it is allocated statically. */
+
+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
\ No newline at end of file