sa

Fork of nRF51822 by Nordic Semiconductor

Files at this revision

API Documentation at this revision

Comitter:
vcoubard
Date:
Mon Jan 11 10:19:18 2016 +0000
Parent:
564:77d4fcde8f2a
Child:
566:e425ad9e5d6e
Commit message:
Synchronized with git rev 0bcc2e96
Author: Andres Amaya Garcia
Modify shutdown due to BLE API change

The module is updated to comply with the changes to BLE API regarding correct
shutdown functionality. The following changes are introduced to ble-nrf51822:

* Calls to the old static function shutdown in Gap, GattClient, GattServer and
SecurityManager are removed.
* The cleanup function in Gap, GattClient, GattServer and SecurityManager is
renamed to `reset()` and made public.
* The static references inside nRF5xGap, nRF5xGattClient, nRF5xGattServer and
nRF5xSecurityManager to objects of their own class are moved to nRF5xn.
* The static getInstance accessors in nRF5xGap, nRF5xGattClient,
nRF5xGattServer and nRF5xSecurityManager are removed and their functionality is
moved to the implemented virtual accessors in nRF5xn i.e. getGap(),
getGattClient, etc.
* A static function Instance is added to nRF5xn class to make the transport
object accessible across the module.

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:17 2016 +0000
+++ b/source/btle/btle.cpp	Mon Jan 11 10:19:18 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:17 2016 +0000
+++ b/source/btle/btle_discovery.cpp	Mon Jan 11 10:19:18 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:17 2016 +0000
+++ b/source/btle/btle_security.cpp	Mon Jan 11 10:19:18 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:17 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,208 +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"
-
-namespace { 
-    void emptyDiscoveryCallback(const CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t*) { }
-    void emptyTerminationCallback(const CharacteristicDescriptorDiscovery::TerminationCallbackParams_t*) { }
-}
-
-nRF5xCharacteristicDescriptorDiscoverer::nRF5xCharacteristicDescriptorDiscoverer(size_t concurrentConnectionsCount) : 
-    maximumConcurrentConnectionsCount(concurrentConnectionsCount), 
-    discoveryRunning(new Discovery[concurrentConnectionsCount]) {
-
-}
-
-nRF5xCharacteristicDescriptorDiscoverer::~nRF5xCharacteristicDescriptorDiscoverer() { 
-    delete [] discoveryRunning;
-}
-
-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 their 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 {
-    return findRunningDiscovery(characteristic) != NULL;
-}
-
-void nRF5xCharacteristicDescriptorDiscoverer::requestTerminate(const DiscoveredCharacteristic& characteristic) {
-    Discovery* discovery = findRunningDiscovery(characteristic);
-    if(discovery) { 
-        discovery->onDiscovery = emptyDiscoveryCallback;
-        // call terminate anyway
-        discovery->terminate(BLE_ERROR_NONE);
-        discovery->onTerminate = emptyTerminationCallback;
-    }
-}
-
-void nRF5xCharacteristicDescriptorDiscoverer::process(uint16_t connectionHandle, const ble_gattc_evt_desc_disc_rsp_t& descriptors) {
-    Discovery* discovery = findRunningDiscovery(connectionHandle);
-    if(!discovery) { 
-        error("logic error in nRF5xCharacteristicDescriptorDiscoverer::process !!!");
-    }
-
-    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->characteristic.getLastHandle();
-
-    if(startHandle > endHandle || 
-      (discovery->onDiscovery == emptyDiscoveryCallback && discovery->onTerminate == emptyTerminationCallback)) { 
-        terminate(connectionHandle, BLE_ERROR_NONE);
-        return;
-    }
-
-    ble_error_t err = gattc_descriptors_discover(connectionHandle, startHandle, endHandle);
-    if(err) { 
-        terminate(connectionHandle, err);
-        return;
-    }
-}
-
-void nRF5xCharacteristicDescriptorDiscoverer::terminate(uint16_t handle, ble_error_t err) {
-    Discovery* discovery = findRunningDiscovery(handle);
-    if(!discovery) { 
-        error("logic error in nRF5xCharacteristicDescriptorDiscoverer::process !!!");
-    }
-
-    Discovery tmp = *discovery;
-    *discovery = Discovery();
-    tmp.terminate(err);
-}
-
-nRF5xCharacteristicDescriptorDiscoverer::Discovery* 
-nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(const DiscoveredCharacteristic& characteristic) {
-    for(size_t i = 0; i < maximumConcurrentConnectionsCount; ++i) { 
-        if(discoveryRunning[i].characteristic == characteristic) { 
-            return &discoveryRunning[i];
-        }
-    }
-    return NULL;
-}
-
-nRF5xCharacteristicDescriptorDiscoverer::Discovery* 
-nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(const DiscoveredCharacteristic& characteristic) const {
-    for(size_t i = 0; i < maximumConcurrentConnectionsCount; ++i) { 
-        if(discoveryRunning[i].characteristic == characteristic) { 
-            return &discoveryRunning[i];
-        }
-    }
-    return NULL;
-}
-
-nRF5xCharacteristicDescriptorDiscoverer::Discovery* 
-nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(uint16_t handle) {
-    for(size_t i = 0; i < maximumConcurrentConnectionsCount; ++i) {
-        if(discoveryRunning[i].characteristic.getConnectionHandle() == handle && 
-           discoveryRunning[i] != Discovery()) {
-            return &discoveryRunning[i];
-        }
-    }
-    return NULL;
-}     
-
-void nRF5xCharacteristicDescriptorDiscoverer::removeDiscovery(Discovery* discovery) {
-    for(size_t i = 0; i < maximumConcurrentConnectionsCount; ++i) { 
-        if(&discoveryRunning[i] == discovery) { 
-            discoveryRunning[i] = Discovery();
-        }
-    }
-}
-
-nRF5xCharacteristicDescriptorDiscoverer::Discovery* 
-nRF5xCharacteristicDescriptorDiscoverer::getAvailableDiscoverySlot() {
-    for(size_t i = 0; i < maximumConcurrentConnectionsCount; ++i) { 
-        if(discoveryRunning[i] == Discovery()) {
-            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;
-    }
-}
\ No newline at end of file
--- a/source/nRF5xCharacteristicDescriptorDiscoverer.h	Mon Jan 11 10:19:17 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +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 beetween BLE API and nordic stack regarding Characteristic
- * Descriptor discovery. The BLE API can launch, monitorate 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:
-    nRF5xCharacteristicDescriptorDiscoverer(size_t concurrentConnectionsCount = 3);
-
-    ~nRF5xCharacteristicDescriptorDiscoverer();
-
-    /**
-     * Launch a new characteristic descriptor discovery for a given 
-     * DiscoveredCharacteristic.
-     * @note: this will be called by BLE API side
-     */
-    ble_error_t launch(
-        const DiscoveredCharacteristic& characteristic, 
-        const DiscoveryCallback_t& callback,
-        const TerminationCallback_t& terminationCallback
-    );
-
-    /**
-     * @brief indicate if a characteristic descriptor discovery is active for a 
-     * given DiscoveredCharacteristic
-     * @note: this will be called by BLE API side
-     */
-    bool isActive(const DiscoveredCharacteristic& characteristic) const;
-
-    /**
-     * @brief reauest the termination of characteristic descriptor discovery 
-     * for a give DiscoveredCharacteristic
-     * @note: this will be called by BLE API side
-     */
-    void requestTerminate(const DiscoveredCharacteristic& characteristic);
-
-    /**
-     * @brief process descriptors discovered from the nordic stack
-     */
-    void process(uint16_t handle, const ble_gattc_evt_desc_disc_rsp_t& descriptors);
-
-    /**
-     * @brief Called by the nordic stack when the discovery is over.
-     */
-    void terminate(uint16_t handle, ble_error_t err);
-
-private:
-    nRF5xCharacteristicDescriptorDiscoverer(const nRF5xCharacteristicDescriptorDiscoverer&);
-    nRF5xCharacteristicDescriptorDiscoverer& operator=(const nRF5xCharacteristicDescriptorDiscoverer&);
-
-    struct Discovery {
-        Discovery() : characteristic(), onDiscovery(), onTerminate() { }
-
-        Discovery(const DiscoveredCharacteristic& c, const DiscoveryCallback_t& dCb, const TerminationCallback_t& tCb) : 
-            characteristic(c), 
-            onDiscovery(dCb), 
-            onTerminate(tCb) { 
-        }
-
-        DiscoveredCharacteristic characteristic;
-        DiscoveryCallback_t onDiscovery;
-        TerminationCallback_t onTerminate;
-
-        void process(GattAttribute::Handle_t handle, const UUID& uuid) { 
-            CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t params = { 
-                characteristic,
-                DiscoveredCharacteristicDescriptor(
-                    characteristic.getGattClient(),
-                    characteristic.getConnectionHandle(),
-                    handle,
-                    uuid
-                )
-            };
-            onDiscovery.call(&params);
-        }
-
-        void terminate(ble_error_t err) { 
-            CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = {
-                characteristic,
-                err
-            };
-            onTerminate.call(&params);
-        }
-
-        friend bool operator==(const Discovery& lhs, const Discovery& rhs) {
-            return lhs.characteristic == rhs.characteristic &&
-                lhs.onDiscovery == rhs.onDiscovery &&
-                lhs.onTerminate == rhs.onTerminate;
-        }
-
-        friend bool operator!=(const Discovery& lhs, const Discovery& rhs) {
-            return !(lhs == rhs);
-        }
-    };
-
-    Discovery* findRunningDiscovery(const DiscoveredCharacteristic& characteristic);
-    Discovery* findRunningDiscovery(const DiscoveredCharacteristic& characteristic) const;
-    Discovery* findRunningDiscovery(uint16_t handle);
-    void removeDiscovery(Discovery* discovery);
-    Discovery* getAvailableDiscoverySlot(); 
-    bool isConnectionInUse(uint16_t connHandle);
-    static ble_error_t gattc_descriptors_discover(uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle); 
-
-
-    size_t maximumConcurrentConnectionsCount;
-    Discovery *discoveryRunning;
-};
-
-#endif /*__NRF_CHARACTERISTIC_DESCRIPTOR_DISCOVERY_H__*/
\ No newline at end of file
--- a/source/nRF5xDiscoveredCharacteristic.h	Mon Jan 11 10:19:17 2016 +0000
+++ b/source/nRF5xDiscoveredCharacteristic.h	Mon Jan 11 10:19:18 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:17 2016 +0000
+++ b/source/nRF5xGap.cpp	Mon Jan 11 10:19:18 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:17 2016 +0000
+++ b/source/nRF5xGap.h	Mon Jan 11 10:19:18 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:17 2016 +0000
+++ b/source/nRF5xGattClient.cpp	Mon Jan 11 10:19:18 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:17 2016 +0000
+++ b/source/nRF5xGattClient.h	Mon Jan 11 10:19:18 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:17 2016 +0000
+++ b/source/nRF5xGattServer.cpp	Mon Jan 11 10:19:18 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:17 2016 +0000
+++ b/source/nRF5xGattServer.h	Mon Jan 11 10:19:18 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:17 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:17 2016 +0000
+++ b/source/nRF5xSecurityManager.h	Mon Jan 11 10:19:18 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:17 2016 +0000
+++ b/source/nRF5xServiceDiscovery.cpp	Mon Jan 11 10:19:18 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,62 +114,37 @@
 void
 nRF5xServiceDiscovery::progressCharacteristicDiscovery(void)
 {
-    if(state != CHARACTERISTIC_DISCOVERY_ACTIVE) {
-        return;
-    }
-
-    if(remainingCharacteristic != nRF5xDiscoveredCharacteristic() && numCharacteristics > 0) { 
-        remainingCharacteristic.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 == remainingCharacteristic.getUUID()) &&
+            ((matchingCharacteristicUUID == characteristics[characteristicIndex].getUUID()) &&
              (matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) {
             if (characteristicCallback) {
-                characteristicCallback(&remainingCharacteristic);
+                characteristicCallback(&characteristics[characteristicIndex]);
             }
         }
-    }
-
-    for(uint8_t i = 0; i < numCharacteristics; ++i) {
-        if(state != CHARACTERISTIC_DISCOVERY_ACTIVE) {
-            return;
-        }
-
-        if(i == numCharacteristics - 1) { 
-            remainingCharacteristic = 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:17 2016 +0000
+++ b/source/nRF5xServiceDiscovery.h	Mon Jan 11 10:19:18 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) {
-        remainingCharacteristic = 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(remainingCharacteristic != nRF5xDiscoveredCharacteristic()) { 
-               if(err == BLE_ERROR_NONE) {
-                    // fullfill the last characteristic
-                    remainingCharacteristic.setLastHandle(services[serviceIndex].getEndHandle());
-
-                    if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
-                        ((matchingCharacteristicUUID == remainingCharacteristic.getUUID()) &&
-                         (matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) {
-                        if (characteristicCallback) {
-                            characteristicCallback(&remainingCharacteristic);
-                        }
-                    }
-               }
-               remainingCharacteristic = 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,8 +328,6 @@
     CharUUIDDiscoveryQueue      charUUIDDiscoveryQueue;
 
     TerminationCallback_t       onTerminationCallback;
-
-    nRF5xDiscoveredCharacteristic remainingCharacteristic;
 };
 
 #endif /*__NRF_SERVICE_DISCOVERY_H__*/
\ No newline at end of file
--- a/source/nRF5xn.cpp	Mon Jan 11 10:19:17 2016 +0000
+++ b/source/nRF5xn.cpp	Mon Jan 11 10:19:18 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,60 @@
     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 */
+    if (gattServerInstance != NULL &&
+        gattServerInstance->reset() != BLE_ERROR_NONE) {
+        return BLE_ERROR_INVALID_STATE;
+    }
+
+    if (securityManagerInstance != NULL &&
+        securityManagerInstance->reset() != BLE_ERROR_NONE) {
+        return BLE_ERROR_INVALID_STATE;
+    }
+
+    /* 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 &&
+        gattClientInstance->reset() != BLE_ERROR_NONE) {
+        return BLE_ERROR_INVALID_STATE;
+    }
+#endif
+
+    if (gapInstance != NULL &&
+        gapInstance->reset() != BLE_ERROR_NONE) {
+        return BLE_ERROR_INVALID_STATE;
+    }
+
     initialized = false;
     return BLE_ERROR_NONE;
 }
--- a/source/nRF5xn.h	Mon Jan 11 10:19:17 2016 +0000
+++ b/source/nRF5xn.h	Mon Jan 11 10:19:18 2016 +0000
@@ -1,72 +1,193 @@
-/* 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.
- */
-
-#ifndef __NRF51822_H__
-#define __NRF51822_H__
-
-#include "ble/BLE.h"
-#include "ble/blecommon.h"
-#include "ble/BLEInstanceBase.h"
-
-#include "nRF5xGap.h"
-#include "nRF5xGattServer.h"
-#include "nRF5xGattClient.h"
-#include "nRF5xSecurityManager.h"
-
-#include "btle.h"
-
-class nRF5xn : public BLEInstanceBase
-{
-public:
-    nRF5xn(void);
-    virtual ~nRF5xn(void);
-
-    virtual ble_error_t init(BLE::InstanceID_t instanceID, FunctionPointerWithContext<BLE::InitializationCompleteCallbackContext *> callback);
-    virtual bool        hasInitialized(void) const {
-        return initialized;
-    }
-    virtual ble_error_t shutdown(void);
-    virtual const char *getVersion(void);
-
-    virtual Gap &getGap() {
-        return nRF5xGap::getInstance();
-    };
-    virtual const Gap &getGap() const  {
-        return nRF5xGap::getInstance();
-    };
-    virtual GattServer &getGattServer() {
-        return nRF5xGattServer::getInstance();
-    };
-    virtual const GattServer &getGattServer() const {
-        return nRF5xGattServer::getInstance();
-    };
-    virtual GattClient &getGattClient() {
-        return nRF5xGattClient::getInstance();
-    }
-    virtual const SecurityManager &getSecurityManager() const {
-        return nRF5xSecurityManager::getInstance();
-    }
-    virtual SecurityManager &getSecurityManager() {
-        return nRF5xSecurityManager::getInstance();
-    }
-    virtual void waitForEvent(void);
-
-private:
-    bool              initialized;
-    BLE::InstanceID_t instanceID;
-};
-
+/* 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.
+ */
+
+#ifndef __NRF51822_H__
+#define __NRF51822_H__
+
+#include "ble/BLE.h"
+#include "ble/blecommon.h"
+#include "ble/BLEInstanceBase.h"
+
+#include "nRF5xGap.h"
+#include "nRF5xGattServer.h"
+#include "nRF5xGattClient.h"
+#include "nRF5xSecurityManager.h"
+
+#include "btle.h"
+
+class nRF5xn : public BLEInstanceBase
+{
+public:
+    nRF5xn(void);
+    virtual ~nRF5xn(void);
+
+    virtual ble_error_t init(BLE::InstanceID_t instanceID, FunctionPointerWithContext<BLE::InitializationCompleteCallbackContext *> callback);
+    virtual bool        hasInitialized(void) const {
+        return initialized;
+    }
+    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() {
+        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  {
+        if (gapInstance == NULL) {
+            gapInstance = &_gapInstance;
+        }
+        return *gapInstance;
+    };
+
+    /**
+     * Accessors to GATT Server. This function checks whether a GattServer
+     * object was previously instantiated. If such object does not exist, then
+     * it is created before returning.
+     *
+     * @return  A const reference to GattServer.
+     *
+     * @note  The accessor is able to modify the object's state because the
+     *        internal pointer has been declared mutable.
+     */
+    virtual const GattServer &getGattServer() const {
+        if (gattServerInstance == NULL) {
+            gattServerInstance = new nRF5xGattServer();
+        }
+        return *gattServerInstance;
+    };
+
+    /**
+     * Accessors to Security Manager. This function checks whether a SecurityManager
+     * object was previously instantiated. If such object does not exist, then
+     * it is created before returning.
+     *
+     * @return  A const reference to GattServer.
+     *
+     * @note  The accessor is able to modify the object's state because the
+     *        internal pointer has been declared mutable.
+     */
+    virtual const SecurityManager &getSecurityManager() const {
+        if (securityManagerInstance == NULL) {
+            securityManagerInstance = new nRF5xSecurityManager();
+        }
+        return *securityManagerInstance;
+    }
+
+    virtual void waitForEvent(void);
+
+public:
+    static nRF5xn& Instance(BLE::InstanceID_t instanceId);
+
+private:
+    bool              initialized;
+    BLE::InstanceID_t instanceID;
+
+private:
+    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