PBL mbed final

Fork of nRF51822 by Shuta Nakamae

Files at this revision

API Documentation at this revision

Comitter:
vcoubard
Date:
Mon Jan 11 10:19:21 2016 +0000
Parent:
569:9e72aa06ec32
Child:
571:bbf6410b6a89
Commit message:
Synchronized with git rev 786cd0b9
Author: Andres Amaya Garcia
Modify nRF5xn::shutdown to return actual error code

Changed in this revision

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/nRF5xCharacteristicDescriptorDiscoverer.cpp Show diff for this revision Revisions of this file
source/nRF5xCharacteristicDescriptorDiscoverer.h Show diff for this revision Revisions of this file
source/nRF5xDiscoveredCharacteristic.h 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.cpp 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/source/btle/btle.cpp	Mon Jan 11 10:19:20 2016 +0000
+++ b/source/btle/btle.cpp	Mon Jan 11 10:19:21 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"
@@ -41,10 +39,6 @@
 #include "ble_hci.h"
 #include "btle_discovery.h"
 
-#include "nRF5xGattClient.h"
-#include "nRF5xServiceDiscovery.h"
-#include "nRF5xCharacteristicDescriptorDiscoverer.h"
-
 extern "C" void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name);
 void            app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t *p_file_name);
 
@@ -142,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: {
@@ -152,11 +151,11 @@
 #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<Gap::AddressType_t>(peer->addr_type), peer->addr,
                                                            static_cast<Gap::AddressType_t>(own->addr_type),  own->addr,
@@ -168,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) {
@@ -187,22 +186,16 @@
                     reason = static_cast<Gap::DisconnectionReason_t>(p_ble_evt->evt.gap_evt.params.disconnected.reason);
                     break;
             }
-
-            // Close all pending discoveries for this connection
-            nRF5xGattClient& gattClient = nRF5xGattClient::getInstance();
-            gattClient.characteristicDescriptorDiscoverer().terminate(handle, BLE_ERROR_INVALID_STATE);
-            gattClient.discovery().terminate(handle);
-
-            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:
@@ -214,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;
         }
 
@@ -227,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:20 2016 +0000
+++ b/source/btle/btle_discovery.cpp	Mon Jan 11 10:19:21 2016 +0000
@@ -14,16 +14,15 @@
  * limitations under the License.
  */
 
-#include "nRF5xServiceDiscovery.h"
-#include "nRF5xCharacteristicDescriptorDiscoverer.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();
-    nRF5xCharacteristicDescriptorDiscoverer &characteristicDescriptorDiscoverer = 
-        nRF5xGattClient::getInstance().characteristicDescriptorDiscoverer();
+    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:
@@ -47,7 +46,7 @@
 
                 case BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND:
                 default:
-                    sdSingleton.terminateCharacteristicDiscovery(BLE_ERROR_NONE);
+                    sdSingleton.terminateCharacteristicDiscovery();
                     break;
             }
             break;
@@ -66,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;
 
@@ -79,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;
 
@@ -91,31 +90,9 @@
                 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;
-
-        case BLE_GATTC_EVT_DESC_DISC_RSP: {
-            uint16_t conn_handle = p_ble_evt->evt.gattc_evt.conn_handle;
-            uint16_t status = p_ble_evt->evt.gattc_evt.gatt_status;
-            const ble_gattc_evt_desc_disc_rsp_t& discovered_descriptors = p_ble_evt->evt.gattc_evt.params.desc_disc_rsp;
-
-            switch(status) { 
-                case BLE_GATT_STATUS_SUCCESS:
-                    characteristicDescriptorDiscoverer.process(
-                        conn_handle, 
-                        discovered_descriptors
-                    );                
-                    break;
-                case BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND:
-                    // end of discovery 
-                    characteristicDescriptorDiscoverer.terminate(conn_handle, BLE_ERROR_NONE);
-                    break;
-                default:
-                    characteristicDescriptorDiscoverer.terminate(conn_handle, BLE_ERROR_UNSPECIFIED);
-                    break;
-            }
-        }   break;
     }
 
     sdSingleton.progressCharacteristicDiscovery();
--- a/source/btle/btle_security.cpp	Mon Jan 11 10:19:20 2016 +0000
+++ b/source/btle/btle_security.cpp	Mon Jan 11 10:19:21 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/nRF5xCharacteristicDescriptorDiscoverer.cpp	Mon Jan 11 10:19:20 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,236 +0,0 @@
-/* mbed Microcontroller Library
- * Copyright (c) 2006-2015 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 "nRF5xCharacteristicDescriptorDiscoverer.h"
-#include "ble_err.h"
-#include "mbed-drivers/mbed_error.h"
-#include "ble/DiscoveredCharacteristicDescriptor.h"
-
-nRF5xCharacteristicDescriptorDiscoverer::nRF5xCharacteristicDescriptorDiscoverer() :
-    discoveryRunning() {
-    // nothing to do
-}
-
-nRF5xCharacteristicDescriptorDiscoverer::~nRF5xCharacteristicDescriptorDiscoverer() {
-    // nothing to do
-}
-
-ble_error_t nRF5xCharacteristicDescriptorDiscoverer::launch(
-    const DiscoveredCharacteristic& characteristic,
-    const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
-    const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback
-) {
-    Gap::Handle_t connHandle = characteristic.getConnectionHandle();
-    // it is ok to deduce that the start handle for descriptors is after
-    // the characteristic declaration and the characteristic value declaration
-    // see BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part G] (3.3)
-    Gap::Handle_t descriptorStartHandle = characteristic.getDeclHandle() + 2;
-    Gap::Handle_t descriptorEndHandle = characteristic.getLastHandle();
-
-    // check if there is any descriptor to discover
-    if (descriptorEndHandle < descriptorStartHandle) {
-        CharacteristicDescriptorDiscovery::TerminationCallbackParams_t termParams = {
-            characteristic,
-            BLE_ERROR_NONE
-        };
-        terminationCallback.call(&termParams);
-        return BLE_ERROR_NONE;
-    }
-
-    // check if we can run this discovery
-    if (isConnectionInUse(connHandle)) {
-        return BLE_STACK_BUSY;
-    }
-
-    // get a new discovery slot, if none are available, just return
-    Discovery* discovery = getAvailableDiscoverySlot();
-    if(discovery == NULL) {
-        return BLE_STACK_BUSY;
-    }
-
-    // try to launch the discovery
-    ble_error_t err = gattc_descriptors_discover(connHandle, descriptorStartHandle, descriptorEndHandle);
-    if(!err) {
-        // commit the new discovery to its slot
-        *discovery = Discovery(characteristic, discoveryCallback, terminationCallback);
-    }
-
-    return err;
-}
-
-bool nRF5xCharacteristicDescriptorDiscoverer::isActive(const DiscoveredCharacteristic& characteristic) const {
-    for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
-        if(discoveryRunning[i].getCharacteristic() == characteristic) {
-            return true;
-        }
-    }
-    return false;
-}
-
-void nRF5xCharacteristicDescriptorDiscoverer::requestTerminate(const DiscoveredCharacteristic& characteristic) {
-    Discovery* discovery = findRunningDiscovery(characteristic);
-    if(discovery) {
-        // call terminate anyway
-        terminate(discovery, BLE_ERROR_NONE);
-    }
-}
-
-void nRF5xCharacteristicDescriptorDiscoverer::process(uint16_t connectionHandle, const ble_gattc_evt_desc_disc_rsp_t& descriptors) {
-    Discovery* discovery = findRunningDiscovery(connectionHandle);
-    // the discovery has been removed
-    if(!discovery) {
-        return;
-    }
-
-    for (uint16_t i = 0; i < descriptors.count; ++i) {
-        discovery->process(
-            descriptors.descs[i].handle, UUID(descriptors.descs[i].uuid.uuid)
-        );
-    }
-
-    // prepare the next discovery request (if needed)
-    uint16_t startHandle = descriptors.descs[descriptors.count - 1].handle + 1;
-    uint16_t endHandle = discovery->getCharacteristic().getLastHandle();
-
-    if(startHandle > endHandle) {
-        terminate(discovery, BLE_ERROR_NONE);
-        return;
-    }
-
-    ble_error_t err = gattc_descriptors_discover(connectionHandle, startHandle, endHandle);
-    if(err) {
-        terminate(discovery, err);
-        return;
-    }
-}
-
-void nRF5xCharacteristicDescriptorDiscoverer::terminate(uint16_t handle, ble_error_t err) {
-    Discovery* discovery = findRunningDiscovery(handle);
-    // the discovery has already been terminated
-    if(!discovery) {
-        return;
-    }
-
-    terminate(discovery, err);
-}
-
-void nRF5xCharacteristicDescriptorDiscoverer::terminate(Discovery* discovery, ble_error_t err) {
-    // temporary copy, user code can try to launch a new discovery in the onTerminate
-    // callback. So, this discovery should not appear in such case.
-    Discovery tmp = *discovery;
-    *discovery = Discovery();
-    tmp.terminate(err);
-}
-
-nRF5xCharacteristicDescriptorDiscoverer::Discovery*
-nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(const DiscoveredCharacteristic& characteristic) {
-    for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
-        if((discoveryRunning[i].getCharacteristic() == characteristic) &&
-           (discoveryRunning[i].isEmpty() == false)) {
-            return &discoveryRunning[i];
-        }
-    }
-    return NULL;
-}
-
-nRF5xCharacteristicDescriptorDiscoverer::Discovery*
-nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(uint16_t handle) {
-    for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
-        if((discoveryRunning[i].getCharacteristic().getConnectionHandle() == handle) &&
-           (discoveryRunning[i].isEmpty() == false)) {
-            return &discoveryRunning[i];
-        }
-    }
-    return NULL;
-}
-
-nRF5xCharacteristicDescriptorDiscoverer::Discovery*
-nRF5xCharacteristicDescriptorDiscoverer::getAvailableDiscoverySlot() {
-    for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
-        if(discoveryRunning[i].isEmpty()) {
-            return &discoveryRunning[i];
-        }
-    }
-    return NULL;
-}
-
-bool nRF5xCharacteristicDescriptorDiscoverer::isConnectionInUse(uint16_t connHandle) {
-     return findRunningDiscovery(connHandle) != NULL;
-}
-
-ble_error_t nRF5xCharacteristicDescriptorDiscoverer::gattc_descriptors_discover(
-    uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle) {
-
-    ble_gattc_handle_range_t discoveryRange = {
-        start_handle,
-        end_handle
-    };
-    uint32_t err = sd_ble_gattc_descriptors_discover(connection_handle, &discoveryRange);
-
-    switch(err) {
-        case NRF_SUCCESS:
-            return BLE_ERROR_NONE;
-        case BLE_ERROR_INVALID_CONN_HANDLE:
-            return BLE_ERROR_INVALID_PARAM;
-        case NRF_ERROR_INVALID_ADDR:
-            return BLE_ERROR_PARAM_OUT_OF_RANGE;
-        case NRF_ERROR_BUSY:
-            return BLE_STACK_BUSY;
-        default:
-            return BLE_ERROR_UNSPECIFIED;
-    }
-}
-
-// implementation of nRF5xCharacteristicDescriptorDiscoverer::Discovery
-
-nRF5xCharacteristicDescriptorDiscoverer::Discovery::Discovery() :
-    characteristic(), onDiscovery(), onTerminate() {
-}
-
-nRF5xCharacteristicDescriptorDiscoverer::Discovery::Discovery(
-    const DiscoveredCharacteristic& c, const DiscoveryCallback_t& dCb, const TerminationCallback_t& tCb) :
-    characteristic(c), onDiscovery(dCb), onTerminate(tCb) {
-}
-
-void nRF5xCharacteristicDescriptorDiscoverer::Discovery::process(
-    GattAttribute::Handle_t handle, const UUID& uuid) {
-    CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t params = {
-        characteristic,
-        DiscoveredCharacteristicDescriptor(
-            characteristic.getGattClient(),
-            characteristic.getConnectionHandle(),
-            handle,
-            uuid
-        )
-    };
-    onDiscovery.call(&params);
-}
-
-void nRF5xCharacteristicDescriptorDiscoverer::Discovery::terminate(ble_error_t err) {
-    CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = {
-        characteristic,
-        err
-    };
-
-    onTerminate.call(&params);
-}
-
-bool nRF5xCharacteristicDescriptorDiscoverer::Discovery::isEmpty() const {
-    return *this == Discovery();
-}
-
-const DiscoveredCharacteristic& nRF5xCharacteristicDescriptorDiscoverer::Discovery::getCharacteristic() const {
-    return characteristic;
-}
\ No newline at end of file
--- a/source/nRF5xCharacteristicDescriptorDiscoverer.h	Mon Jan 11 10:19:20 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,214 +0,0 @@
-/* mbed Microcontroller Library
- * Copyright (c) 2006-2015 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.
- */
-
-#ifndef __NRF_CHARACTERISTIC_DESCRIPTOR_DISCOVERY_H__
-#define __NRF_CHARACTERISTIC_DESCRIPTOR_DISCOVERY_H__
-
-#include "ble/Gap.h"
-#include "ble/DiscoveredCharacteristic.h"
-#include "ble/CharacteristicDescriptorDiscovery.h"
-#include "ble/GattClient.h"
-#include "ble_gattc.h"
-
-/**
- * @brief Manage the discovery of Characteristic descriptors
- * @details is a bridge between BLE API and Nordic stack regarding Characteristic
- * Descriptor discovery. The BLE API can launch, monitor and ask for termination
- * of a discovery. The Nordic stack will provide new descriptors and indicate when
- * the discovery is done.
- */
-class nRF5xCharacteristicDescriptorDiscoverer
-{
-    typedef CharacteristicDescriptorDiscovery::DiscoveryCallback_t DiscoveryCallback_t;
-    typedef CharacteristicDescriptorDiscovery::TerminationCallback_t TerminationCallback_t;
-
-public:
-    /**
-     * @brief Construct a new characteristic descriptor discoverer.
-     */
-    nRF5xCharacteristicDescriptorDiscoverer();
-
-    /**
-     * @brief Destroy a characteristic descriptor discoverer.
-     */
-    ~nRF5xCharacteristicDescriptorDiscoverer();
-
-    /**
-     * Launch a new characteristic descriptor discovery for a given DiscoveredCharacteristic.
-     * @param characteristic The characteristic owning the descriptors to discover.
-     * @param discoveryCallback The callback called when a descriptor is discovered.
-     * @param terminationCallback The callback called when the discovery process end.
-     * @return BLE_ERROR_NONE if characteristic descriptor discovery is launched successfully;
-     *         else an appropriate error.
-     * @note: this will be called by BLE API side.
-     */
-    ble_error_t launch(
-        const DiscoveredCharacteristic& characteristic,
-        const DiscoveryCallback_t& discoveryCallback,
-        const TerminationCallback_t& terminationCallback
-    );
-
-    /**
-     * @brief indicate if a characteristic descriptor discovery is active for a
-     * given DiscoveredCharacteristic.
-     * @param characteristic The characteristic for whom the descriptor might be
-     * currently discovered.
-     * @return true if descriptors of characteristic are discovered, false otherwise.
-     * @note: this will be called by BLE API side.
-     */
-    bool isActive(const DiscoveredCharacteristic& characteristic) const;
-
-    /**
-     * @brief request the termination of characteristic descriptor discovery
-     * for a give DiscoveredCharacteristic
-     * @param characteristic The characteristic for whom the descriptor discovery
-     * should be stopped.
-     * @note: this will be called by BLE API side.
-     */
-    void requestTerminate(const DiscoveredCharacteristic& characteristic);
-
-    /**
-     * @brief process descriptors discovered from the Nordic stack.
-     * @param connectionHandle The connection handle upon which descriptors has been
-     * discovered.
-     * @param descriptors Discovered descriptors.
-     * @note This will be called by the Nordic stack.
-     */
-    void process(uint16_t connectionHandle, const ble_gattc_evt_desc_disc_rsp_t& descriptors);
-
-    /**
-     * @brief Called by the Nordic stack when the discovery is over.
-     * @param The connection handle upon which the discovery process is done.
-     * @param err An error if the termination is due to an error.
-     */
-    void terminate(uint16_t connectionHandle, ble_error_t err);
-
-private:
-    // protection against copy construction and assignment
-    nRF5xCharacteristicDescriptorDiscoverer(const nRF5xCharacteristicDescriptorDiscoverer&);
-    nRF5xCharacteristicDescriptorDiscoverer& operator=(const nRF5xCharacteristicDescriptorDiscoverer&);
-
-    /**
-     * @brief Discovery process, it store the DiscoveredCharacteristic, the
-     * discovery callback and the termination callback.
-     */
-    class Discovery {
-    public:
-        /**
-         * @brief Construct an empty discovery, such can be considerate as a not running discovery.
-         * @note #isEmpty function will return true
-         */
-        Discovery();
-
-        /**
-         * @brief Construct a valid discovery process.
-         *
-         * @param c the characteristic from whom descriptors will be discovered.
-         * @param dCb The discovery callback called each time a descriptor is discovered.
-         * @param tCb The termination callback called when the discovery terminate.
-         *
-         * @note #isEmpty function will return false
-         */
-        Discovery(const DiscoveredCharacteristic& c, const DiscoveryCallback_t& dCb, const TerminationCallback_t& tCb);
-
-        /**
-         * @brief Process the discovery of a descriptor.
-         *
-         * @param handle The attribute handle of the descriptor found
-         * @param uuid The UUID of the descriptor found.
-         */
-        void process(GattAttribute::Handle_t handle, const UUID& uuid);
-
-        /**
-         * @brief Terminate the discovery process.
-         *
-         * @param err Error associate with the termination
-         * @note after this call #isEmpty function will return true.
-         */
-        void terminate(ble_error_t err);
-
-        /**
-         * @brief check if the discovery process is empty or not. Empty discovery are
-         * not running.
-         *
-         * @detail Discovery are empty after:
-         *     - a default construction
-         *     - a copy construction form a default constructed
-         *     - an assignment from a default constructed Discovery
-         * @return true if the Discovery is empty and false otherwise.
-         */
-        bool isEmpty() const;
-
-        /**
-         * @brief return the characteristic from whom descriptors are discovered.
-         * @return the characteristic from whom descriptors are discovered.
-         */
-        const DiscoveredCharacteristic& getCharacteristic() const;
-
-        /**
-         * @brief equal to operator, test if two discovery process are equal
-         *
-         * @param lhs left hand side of the expression
-         * @param rhs right hand side of the expression
-         * @return true if lhs == rhs
-         */
-        friend bool operator==(const Discovery& lhs, const Discovery& rhs) {
-            return lhs.characteristic == rhs.characteristic &&
-                   lhs.onDiscovery == rhs.onDiscovery &&
-                   lhs.onTerminate == rhs.onTerminate;
-        }
-
-        /**
-         * @brief not equal to operator, test if two discovery process are not equal
-         *
-         * @param lhs left hand side of the expression
-         * @param rhs right hand side of the expression
-         * @return true if lhs != rhs
-         */
-        friend bool operator!=(const Discovery& lhs, const Discovery& rhs) {
-            return !(lhs == rhs);
-        }
-
-    private:
-        DiscoveredCharacteristic characteristic;
-        DiscoveryCallback_t onDiscovery;
-        TerminationCallback_t onTerminate;
-    };
-
-    // find a running discovery process
-    Discovery* findRunningDiscovery(const DiscoveredCharacteristic& characteristic);
-    Discovery* findRunningDiscovery(uint16_t handle);
-
-    // Called to terminate a discovery is over.
-    void terminate(Discovery* discovery, ble_error_t err);
-
-    // get one slot for a discovery process
-    Discovery* getAvailableDiscoverySlot();
-
-    // indicate if a connection is already running a discovery
-    bool isConnectionInUse(uint16_t connHandle);
-
-    // low level start of a discovery
-    static ble_error_t gattc_descriptors_discover(uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle);
-
-    // count of concurrent connections which can run a descriptor discovery process
-    static const size_t MAXIMUM_CONCURRENT_CONNECTIONS_COUNT = 3;
-
-    // array of running discoveries
-    Discovery discoveryRunning[MAXIMUM_CONCURRENT_CONNECTIONS_COUNT];
-};
-
-#endif /*__NRF_CHARACTERISTIC_DESCRIPTOR_DISCOVERY_H__*/
\ No newline at end of file
--- a/source/nRF5xDiscoveredCharacteristic.h	Mon Jan 11 10:19:20 2016 +0000
+++ b/source/nRF5xDiscoveredCharacteristic.h	Mon Jan 11 10:19:21 2016 +0000
@@ -36,10 +36,6 @@
                ble_gatt_char_props_t    propsIn,
                GattAttribute::Handle_t  declHandleIn,
                GattAttribute::Handle_t  valueHandleIn);
-
-    void setLastHandle(GattAttribute::Handle_t last) {
-      lastHandle = last;
-    }
 };
 
 #endif /* __NRF_DISCOVERED_CHARACTERISTIC_H__ */
\ No newline at end of file
--- a/source/nRF5xGap.cpp	Mon Jan 11 10:19:20 2016 +0000
+++ b/source/nRF5xGap.cpp	Mon Jan 11 10:19:21 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
 */
 /**************************************************************************/
--- a/source/nRF5xGap.h	Mon Jan 11 10:19:20 2016 +0000
+++ b/source/nRF5xGap.h	Mon Jan 11 10:19:21 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:20 2016 +0000
+++ b/source/nRF5xGattClient.cpp	Mon Jan 11 10:19:21 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,
@@ -33,27 +24,6 @@
                                         const UUID                                 &matchingServiceUUIDIn,
                                         const UUID                                 &matchingCharacteristicUUIDIn)
 {
-    return _discovery.launch(connectionHandle, sc, cc, matchingServiceUUIDIn, matchingCharacteristicUUIDIn);
+    return discovery.launch(connectionHandle, sc, cc, matchingServiceUUIDIn, matchingCharacteristicUUIDIn);
 }
-
-ble_error_t nRF5xGattClient::discoverCharacteristicDescriptors(
-    const DiscoveredCharacteristic& characteristic,
-    const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
-    const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback)
-{
-    return _characteristicDescriptorDiscoverer.launch(
-        characteristic, 
-        discoveryCallback, 
-        terminationCallback
-    );
-}
-
-bool nRF5xGattClient::isCharacteristicDescriptorsDiscoveryActive(const DiscoveredCharacteristic& characteristic) const {
-    return _characteristicDescriptorDiscoverer.isActive(characteristic);   
-}
-
-void nRF5xGattClient::terminateCharacteristicDescriptorsDiscovery(const DiscoveredCharacteristic& characteristic) { 
-    return _characteristicDescriptorDiscoverer.requestTerminate(characteristic);
-}
-
 #endif
\ No newline at end of file
--- a/source/nRF5xGattClient.h	Mon Jan 11 10:19:20 2016 +0000
+++ b/source/nRF5xGattClient.h	Mon Jan 11 10:19:21 2016 +0000
@@ -19,13 +19,10 @@
 
 #include "ble/GattClient.h"
 #include "nRF5xServiceDiscovery.h"
-#include "nRF5xCharacteristicDescriptorDiscoverer.h"
 
 class nRF5xGattClient : public GattClient
 {
 public:
-    static nRF5xGattClient &getInstance();
-
     /**
      * When using S110, all Gatt client features will return
      * BLE_ERROR_NOT_IMPLEMENTED
@@ -88,14 +85,14 @@
                                                const UUID                                 &matchingCharacteristicUUIDIn = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN));
 
     virtual void onServiceDiscoveryTermination(ServiceDiscovery::TerminationCallback_t callback) {
-        _discovery.onTermination(callback);
+        discovery.onTermination(callback);
     }
 
     /**
      * Is service-discovery currently active?
      */
     virtual bool isServiceDiscoveryActive(void) const {
-        return _discovery.isActive();
+        return discovery.isActive();
     }
 
     /**
@@ -103,31 +100,9 @@
      * invocation of the TerminationCallback if service-discovery is active.
      */
     virtual void terminateServiceDiscovery(void) {
-        _discovery.terminate();
+        discovery.terminate();
     }
 
-    /**
-     * @brief Implementation of GattClient::discoverCharacteristicDescriptors 
-     * @see GattClient::discoverCharacteristicDescriptors 
-     */
-    virtual ble_error_t discoverCharacteristicDescriptors(
-        const DiscoveredCharacteristic& characteristic,
-        const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
-        const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback
-    );
-
-    /**
-     * @brief Implementation of GattClient::isCharacteristicDiscoveryActive 
-     * @see GattClient::isCharacteristicDiscoveryActive 
-     */
-    virtual bool isCharacteristicDescriptorsDiscoveryActive(const DiscoveredCharacteristic& characteristic) const;
-
-    /**
-     * @brief Implementation of GattClient::terminateCharacteristicDiscovery 
-     * @see GattClient::terminateCharacteristicDiscovery 
-     */
-    virtual void terminateCharacteristicDescriptorsDiscovery(const DiscoveredCharacteristic& characteristic);
-
     virtual ble_error_t read(Gap::Handle_t connHandle, GattAttribute::Handle_t attributeHandle, uint16_t offset) const {
         uint32_t rc = sd_ble_gattc_read(connHandle, attributeHandle, offset);
         if (rc == NRF_SUCCESS) {
@@ -170,26 +145,42 @@
         }
     }
 
+    /**
+     * @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:
-    nRF5xGattClient() : _discovery(this) {
+    /*
+     * Allow instantiation from nRF5xn when required.
+     */
+    friend class nRF5xn;
+
+    nRF5xGattClient() : discovery(this) {
         /* empty */
     }
 
-    nRF5xServiceDiscovery& discovery() { 
-        return _discovery;
-    }
-
-    nRF5xCharacteristicDescriptorDiscoverer& characteristicDescriptorDiscoverer() { 
-        return _characteristicDescriptorDiscoverer;
-    }
+    friend void bleGattcEventHandler(const ble_evt_t *p_ble_evt);
 
 private:
     nRF5xGattClient(const nRF5xGattClient &);
     const nRF5xGattClient& operator=(const nRF5xGattClient &);
 
 private:
-    nRF5xServiceDiscovery _discovery;
-    nRF5xCharacteristicDescriptorDiscoverer _characteristicDescriptorDiscoverer;
+    nRF5xServiceDiscovery discovery;
 
 #endif // if !S110
 };
--- a/source/nRF5xGattServer.cpp	Mon Jan 11 10:19:20 2016 +0000
+++ b/source/nRF5xGattServer.cpp	Mon Jan 11 10:19:21 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:20 2016 +0000
+++ b/source/nRF5xGattServer.h	Mon Jan 11 10:19:21 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:20 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:20 2016 +0000
+++ b/source/nRF5xSecurityManager.h	Mon Jan 11 10:19:21 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.cpp	Mon Jan 11 10:19:20 2016 +0000
+++ b/source/nRF5xServiceDiscovery.cpp	Mon Jan 11 10:19:21 2016 +0000
@@ -27,32 +27,22 @@
         .start_handle = startHandle,
         .end_handle   = endHandle
     };
-    uint32_t rc = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange);
-    ble_error_t err = BLE_ERROR_NONE;
-
-    switch (rc) {
-        case NRF_SUCCESS:
-            err = BLE_ERROR_NONE;
-            break;
-        case BLE_ERROR_INVALID_CONN_HANDLE:
-        case NRF_ERROR_INVALID_ADDR:
-            err = BLE_ERROR_INVALID_PARAM;
-            break;
-        case NRF_ERROR_BUSY:
-            err = BLE_STACK_BUSY;
-            break;
-        case NRF_ERROR_INVALID_STATE:
-            err = BLE_ERROR_INVALID_STATE;
-            break;
-        default:
-            err = BLE_ERROR_UNSPECIFIED;
-            break;
+    uint32_t rc;
+    if ((rc = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange)) != NRF_SUCCESS) {
+        terminateCharacteristicDiscovery();
+        switch (rc) {
+            case BLE_ERROR_INVALID_CONN_HANDLE:
+            case NRF_ERROR_INVALID_ADDR:
+                return BLE_ERROR_INVALID_PARAM;
+            case NRF_ERROR_BUSY:
+                return BLE_STACK_BUSY;
+            default:
+            case NRF_ERROR_INVALID_STATE:
+                return BLE_ERROR_INVALID_STATE;
+        }
     }
 
-    if (err) {
-        terminateCharacteristicDiscovery(err);
-    }
-    return err;
+    return BLE_ERROR_NONE;
 }
 
 void
@@ -88,6 +78,7 @@
 void
 nRF5xServiceDiscovery::setupDiscoveredCharacteristics(const ble_gattc_evt_char_disc_rsp_t *response)
 {
+    characteristicIndex = 0;
     numCharacteristics  = response->count;
 
     /* Account for the limitation on the number of discovered characteristics we can handle at a time. */
@@ -123,61 +114,37 @@
 void
 nRF5xServiceDiscovery::progressCharacteristicDiscovery(void)
 {
-    if (state != CHARACTERISTIC_DISCOVERY_ACTIVE) {
-        return;
-    }
-
-    if ((discoveredCharacteristic != nRF5xDiscoveredCharacteristic()) && (numCharacteristics > 0)) {
-        discoveredCharacteristic.setLastHandle(characteristics[0].getDeclHandle() - 1);
-
+    /* Iterate through the previously discovered characteristics cached in characteristics[]. */
+    while ((state == CHARACTERISTIC_DISCOVERY_ACTIVE) && (characteristicIndex < numCharacteristics)) {
         if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
-            ((matchingCharacteristicUUID == discoveredCharacteristic.getUUID()) &&
+            ((matchingCharacteristicUUID == characteristics[characteristicIndex].getUUID()) &&
              (matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) {
             if (characteristicCallback) {
-                characteristicCallback(&discoveredCharacteristic);
+                characteristicCallback(&characteristics[characteristicIndex]);
             }
         }
-    }
-
-    for (uint8_t i = 0; i < numCharacteristics; ++i) {
-        if (state != CHARACTERISTIC_DISCOVERY_ACTIVE) {
-            return;
-        }
-
-        if (i == (numCharacteristics - 1)) {
-            discoveredCharacteristic = characteristics[i];
-            break;
-        } else {
-            characteristics[i].setLastHandle(characteristics[i + 1].getDeclHandle() - 1);
-        }
 
-        if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
-            ((matchingCharacteristicUUID == characteristics[i].getUUID()) &&
-             (matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) {
-            if (characteristicCallback) {
-                characteristicCallback(&characteristics[i]);
-            }
-        }
-    }
-
-    if (state != CHARACTERISTIC_DISCOVERY_ACTIVE) {
-        return;
+        characteristicIndex++;
     }
 
-    Gap::Handle_t startHandle = (numCharacteristics > 0) ? characteristics[numCharacteristics - 1].getValueHandle() + 1 : SRV_DISC_END_HANDLE;
-    Gap::Handle_t endHandle   = services[serviceIndex].getEndHandle();
-    resetDiscoveredCharacteristics(); /* Note: resetDiscoveredCharacteristics() must come after fetching start and end Handles. */
+    /* Relaunch discovery of new characteristics beyond the last entry cached in characteristics[]. */
+    if (state == CHARACTERISTIC_DISCOVERY_ACTIVE) {
+        /* Determine the ending handle of the last cached characteristic. */
+        Gap::Handle_t startHandle = characteristics[characteristicIndex - 1].getValueHandle() + 1;
+        Gap::Handle_t endHandle   = services[serviceIndex].getEndHandle();
+        resetDiscoveredCharacteristics(); /* Note: resetDiscoveredCharacteristics() must come after fetching start and end Handles. */
 
-    if (startHandle < endHandle) {
-        ble_gattc_handle_range_t handleRange = {
-            .start_handle = startHandle,
-            .end_handle   = endHandle
-        };
-        if (sd_ble_gattc_characteristics_discover(connHandle, &handleRange) != NRF_SUCCESS) {
-            terminateCharacteristicDiscovery(BLE_ERROR_UNSPECIFIED);
+        if (startHandle < endHandle) {
+            ble_gattc_handle_range_t handleRange = {
+                .start_handle = startHandle,
+                .end_handle   = endHandle
+            };
+            if (sd_ble_gattc_characteristics_discover(connHandle, &handleRange) != NRF_SUCCESS) {
+                terminateCharacteristicDiscovery();
+            }
+        } else {
+            terminateCharacteristicDiscovery();
         }
-    } else {
-        terminateCharacteristicDiscovery(BLE_ERROR_NONE);
     }
 }
 
--- a/source/nRF5xServiceDiscovery.h	Mon Jan 11 10:19:20 2016 +0000
+++ b/source/nRF5xServiceDiscovery.h	Mon Jan 11 10:19:21 2016 +0000
@@ -41,6 +41,7 @@
         gattc(gattcIn),
         serviceIndex(0),
         numServices(0),
+        characteristicIndex(0),
         numCharacteristics(0),
         state(INACTIVE),
         services(),
@@ -94,14 +95,36 @@
         terminateServiceDiscovery();
     }
 
-    void terminate(Gap::Handle_t connectionHandle) {
-        if(connHandle == connectionHandle) {
-            terminate();
-        }
+    virtual void onTermination(ServiceDiscovery::TerminationCallback_t callback) {
+        onTerminationCallback = callback;
     }
 
-    virtual void onTermination(ServiceDiscovery::TerminationCallback_t callback) {
-        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:
@@ -116,8 +139,6 @@
     void removeFirstServiceNeedingUUIDDiscovery(void);
 
     void terminateServiceDiscovery(void) {
-        discoveredCharacteristic = nRF5xDiscoveredCharacteristic();
-
         bool wasActive = isActive();
         state = INACTIVE;
 
@@ -126,24 +147,8 @@
         }
     }
 
-    void terminateCharacteristicDiscovery(ble_error_t err) {
+    void terminateCharacteristicDiscovery(void) {
         if (state == CHARACTERISTIC_DISCOVERY_ACTIVE) {
-            if(discoveredCharacteristic != nRF5xDiscoveredCharacteristic()) {
-               if(err == BLE_ERROR_NONE) {
-                    // fullfill the last characteristic
-                    discoveredCharacteristic.setLastHandle(services[serviceIndex].getEndHandle());
-
-                    if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
-                        ((matchingCharacteristicUUID == discoveredCharacteristic.getUUID()) &&
-                         (matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) {
-                        if (characteristicCallback) {
-                            characteristicCallback(&discoveredCharacteristic);
-                        }
-                    }
-               }
-               discoveredCharacteristic = nRF5xDiscoveredCharacteristic();
-            }
-
             state = SERVICE_DISCOVERY_ACTIVE;
         }
         serviceIndex++; /* Progress service index to keep discovery alive. */
@@ -157,6 +162,7 @@
 
     void resetDiscoveredCharacteristics(void) {
         numCharacteristics  = 0;
+        characteristicIndex = 0;
     }
 
 private:
@@ -303,6 +309,7 @@
 private:
     uint8_t  serviceIndex;        /**< Index of the current service being discovered. This is intended for internal use during service discovery.*/
     uint8_t  numServices;         /**< Number of services at the peers GATT database.*/
+    uint8_t  characteristicIndex; /**< Index of the current characteristic being discovered. This is intended for internal use during service discovery.*/
     uint8_t  numCharacteristics;  /**< Number of characteristics within the service.*/
 
     enum State_t {
@@ -321,19 +328,6 @@
     CharUUIDDiscoveryQueue      charUUIDDiscoveryQueue;
 
     TerminationCallback_t       onTerminationCallback;
-
-    /*
-     * The currently discovered characteristic. Discovery of a characteristic
-     * is a two phase process.
-     * First, declaration handle is fetched, it provide the UUID, the value handle and
-     * the properties of a characteristic.
-     * Second, the next declaration handle is fetched, with its declaration handle, it is
-     * possible to compute the last handle of the discovered characteristic and fill the
-     * missing part of the object.
-     * If there is no remaining characteristic to discover, the last handle of the
-     * discovered characteristic will be set to the last handle of its enclosing service.
-     */
-    nRF5xDiscoveredCharacteristic discoveredCharacteristic;
 };
 
 #endif /*__NRF_SERVICE_DISCOVERY_H__*/
\ No newline at end of file
--- a/source/nRF5xn.cpp	Mon Jan 11 10:19:20 2016 +0000
+++ b/source/nRF5xn.cpp	Mon Jan 11 10:19:21 2016 +0000
@@ -32,16 +32,33 @@
 static nRF5xn deviceInstance;
 
 /**
+ * The singleton for nRF5xGap. This has been kept static because it is
+ * always needed for any application that uses BLE.
+ */
+nRF5xGap nRF5xn::_gapInstance;
+
+/**
  * BLE-API requires an implementation of the following function in order to
  * obtain its transport handle.
  */
 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(NULL),
+    gattServerInstance(NULL),
+    gattClientInstance(NULL),
+    securityManagerInstance(NULL)
 {
 }
 
@@ -104,16 +121,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:20 2016 +0000
+++ b/source/nRF5xn.h	Mon Jan 11 10:19:21 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:
+    static 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