Glimworm Beacons / nRF51822

Fork of nRF51822 by Nordic Semiconductor

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers device_manager_peripheral.c Source File

device_manager_peripheral.c

00001 /*
00002  * Copyright (c) Nordic Semiconductor ASA
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without modification,
00006  * are permitted provided that the following conditions are met:
00007  *
00008  *   1. Redistributions of source code must retain the above copyright notice, this
00009  *   list of conditions and the following disclaimer.
00010  *
00011  *   2. Redistributions in binary form must reproduce the above copyright notice, this
00012  *   list of conditions and the following disclaimer in the documentation and/or
00013  *   other materials provided with the distribution.
00014  *
00015  *   3. Neither the name of Nordic Semiconductor ASA nor the names of other
00016  *   contributors to this software may be used to endorse or promote products
00017  *   derived from this software without specific prior written permission.
00018  *
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00021  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00022  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00023  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00024  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00025  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00026  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00027  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00028  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00029  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030  *
00031  */
00032 
00033 #include "device_manager.h "
00034 // #include "app_trace.h"
00035 #include "pstorage.h "
00036 #include "ble_hci.h"
00037 #include "app_error.h"
00038 
00039 #if defined ( __CC_ARM )
00040     #ifndef __ALIGN
00041         #define __ALIGN(x)      __align(x)                  /**< Forced aligment keyword for ARM Compiler */
00042     #endif
00043 #elif defined ( __ICCARM__ )
00044     #ifndef __ALIGN
00045         #define __ALIGN(x)                                  /**< Forced aligment keyword for IAR Compiler */
00046     #endif
00047 #elif defined   ( __GNUC__ )
00048     #ifndef __ALIGN
00049         #define __ALIGN(x)      __attribute__((aligned(x))) /**< Forced aligment keyword for GNU Compiler */
00050     #endif
00051 #endif
00052 
00053 #define INVALID_ADDR_TYPE 0xFF   /**< Identifier for an invalid address type. */
00054 #define EDIV_INIT_VAL     0xFFFF /**< Initial value for diversifier. */
00055 
00056 /**
00057  * @defgroup device_manager_app_states Connection Manager Application States
00058  * @{
00059  */
00060 #define STATE_CONTROL_PROCEDURE_IN_PROGRESS 0x01 /**< State where a security procedure is ongoing. */
00061 #define STATE_QUEUED_CONTROL_REQUEST        0x02 /**< State where it is known if there is any queued security request or not. */
00062 /** @} */
00063 
00064 /**
00065  * @defgroup device_manager_conn_inst_states Connection Manager Connection Instances States.
00066  * @{
00067  */
00068 #define STATE_IDLE             0x01 /**< State where connection instance is free. */
00069 #define STATE_CONNECTED        0x02 /**< State where connection is successfully established. */
00070 #define STATE_PAIRING          0x04 /**< State where pairing procedure is in progress. This state is used for pairing and bonding, as pairing is needed for both. */
00071 #define STATE_BONDED           0x08 /**< State where device is bonded. */
00072 #define STATE_DISCONNECTING    0x10 /**< State where disconnection is in progress, application will be notified first, but no further active procedures on the link. */
00073 #define STATE_PAIRING_PENDING  0x20 /**< State where pairing request is pending on the link. */
00074 #define STATE_BOND_INFO_UPDATE 0x40 /**< State where information has been updated, update the flash. */
00075 #define STATE_LINK_ENCRYPTED   0x80 /**< State where link is encrypted. */
00076 /** @} */
00077 
00078 /**
00079  * @defgroup device_manager_peer_id_defines Peer Identification Information Defines.
00080  *
00081  * @brief These defines are used to know which of the peer identification is applicable for a peer.
00082  *
00083  * @details These defines are used for peer identification. Here, bit map is used because it is
00084  *          possible that the application has both IRK and address for identification.
00085  * @{
00086  */
00087 #define UNASSIGNED            0xFF /**< Peer instance is unassigned/unused. */
00088 #define IRK_ENTRY             0x01 /**< Peer instance has IRK as identification information. */
00089 #define ADDR_ENTRY            0x02 /**< Peer instance has address as identification information. */
00090 #define SERVICE_CONTEXT_ENTRY 0x04 /**< Peer instance has service context set. */
00091 #define APP_CONTEXT_ENTRY     0x08 /**< Peer instance has an application context set. */
00092 /** @} */
00093 
00094 /**@brief Device store state identifiers. */
00095 typedef enum
00096 {
00097     STORE_ALL_CONTEXT, /**< Store all context. */
00098     FIRST_BOND_STORE,  /**< Store bond. */
00099     UPDATE_PEER_ADDR   /**< Update peer address. */
00100 } device_store_state_t;
00101 
00102 /**
00103  * @defgroup device_manager_context_offsets Context Offsets
00104  * @{
00105  *
00106  * @brief Context offsets each of the context information in persistent memory.
00107  *
00108  * @details Below is a layout showing how each how the context information is stored in persistent
00109  *          memory.
00110  *
00111  * All Device context is stored in the flash as follows:
00112  * +---------+---------+---------+------------------+----------------+--------------------+
00113  * | Block / Device ID + Layout of stored information in storage block                    |
00114  * +---------+---------+---------+------------------+----------------+--------------------+
00115  * | Block 0 | Device 0| Peer Id | Bond Information | Service Context| Application Context|
00116  * +---------+---------+---------+------------------+----------------+--------------------+
00117  * | Block 1 | Device 1| Peer Id | Bond Information | Service Context| Application Context|
00118  * +---------+---------+---------+------------------+----------------+--------------------+
00119  * |  ...              | ....                                                             |
00120  * +---------+---------+---------+------------------+----------------+--------------------+
00121  * | Block N | Device N| Peer Id | Bond Information | Service Context| Application Context|
00122  * +---------+---------+---------+------------------+----------------+--------------------+
00123  *
00124  * The following defines are used to get offset of each of the components within a block.
00125  */
00126 
00127 #define PEER_ID_STORAGE_OFFSET     0                                               /**< Offset at which peer id is stored in the block. */
00128 #define BOND_STORAGE_OFFSET        PEER_ID_SIZE                                    /**< Offset at which bond information is stored in the block. */
00129 #define SERVICE_STORAGE_OFFSET     (BOND_STORAGE_OFFSET + BOND_SIZE)               /**< Offset at which service context is stored in the block. */
00130 #define APP_CONTEXT_STORAGE_OFFSET (SERVICE_STORAGE_OFFSET + SERVICE_CONTEXT_SIZE) /**< Offset at which application context is stored in the block. */
00131 /** @} */
00132 
00133 /**
00134  * @defgroup device_manager_context_size Context size.
00135  * @{
00136  *
00137  * @brief This group defines the size of each of the context information.
00138  */
00139 #define PEER_ID_SIZE               (sizeof(peer_id_t))                                             /**< Size of peer identification information. */
00140 #define BOND_SIZE                  (sizeof(bond_context_t))                                        /**< Size of bond information. */
00141 #define DEVICE_CONTEXT_SIZE        (PEER_ID_SIZE + BOND_SIZE)                                      /**< Size of Device context, include peer identification and bond information. */
00142 #define GATTS_SERVICE_CONTEXT_SIZE (sizeof(dm_gatts_context_t))                                    /**< Size of GATTS service context. */
00143 #define GATTC_SERVICE_CONTEXT_SIZE (sizeof(dm_gatt_client_context_t))                              /**< Size of GATTC service context. */
00144 #define SERVICE_CONTEXT_SIZE       (GATTS_SERVICE_CONTEXT_SIZE + GATTC_SERVICE_CONTEXT_SIZE)       /**< Combined size of GATTS and GATTC service contexts. */
00145 #define APP_CONTEXT_MIN_SIZE       4                                                               /**< Minimum size for application context data. */
00146 #if (DEVICE_MANAGER_APP_CONTEXT_SIZE != 0)
00147 #define APP_CONTEXT_SIZE           (sizeof(uint32_t) + DEVICE_MANAGER_APP_CONTEXT_SIZE)            /**< Size of application context including length field. */
00148 #else //DEVICE_MANAGER_APP_CONTEXT_SIZE
00149 #define APP_CONTEXT_SIZE           0                                                               /**< Size of application context. */
00150 #endif // DEVICE_MANAGER_APP_CONTEXT_SIZE
00151 #define ALL_CONTEXT_SIZE           (DEVICE_CONTEXT_SIZE + SERVICE_CONTEXT_SIZE + APP_CONTEXT_SIZE) /**< Size of all contexts. */
00152 /** @} */
00153 
00154 
00155 /**
00156  * @defgroup device_manager_log Module's Log Macros
00157  *
00158  * @details Macros used for creating module logs which can be useful in understanding handling
00159  *          of events or actions on API requests. These are intended for debugging purposes and
00160  *          can be disabled by defining the DM_DISABLE_LOGS.
00161  *
00162  * @note That if ENABLE_DEBUG_LOG_SUPPORT is disabled, having DM_DISABLE_LOGS has no effect.
00163  * @{
00164  */
00165 #define DM_DISABLE_LOGS        /**< Enable this macro to disable any logs from this module. */
00166 
00167 #ifndef DM_DISABLE_LOGS
00168 #define DM_LOG  app_trace_log  /**< Used for logging details. */
00169 #define DM_ERR  app_trace_log  /**< Used for logging errors in the module. */
00170 #define DM_TRC  app_trace_log  /**< Used for getting trace of execution in the module. */
00171 #define DM_DUMP app_trace_dump /**< Used for dumping octet information to get details of bond information etc. */
00172 #else //DM_DISABLE_LOGS
00173 #define DM_DUMP(...)           /**< Disables dumping of octet streams. */
00174 #define DM_LOG(...)            /**< Disables detailed logs. */
00175 #define DM_ERR(...)            /**< Disables error logs. */
00176 #define DM_TRC(...)            /**< Disables traces. */
00177 #endif //DM_DISABLE_LOGS
00178 /** @} */
00179 
00180 /**
00181  * @defgroup device_manager_mutex_lock_unlock Module's Mutex Lock/Unlock Macros.
00182  *
00183  * @details Macros used to lock and unlock modules. Currently the SDK does not use mutexes but
00184  *          framework is provided in case need arises to use an alternative architecture.
00185  * @{
00186  */
00187 #define DM_MUTEX_LOCK()   SDK_MUTEX_LOCK(m_dm_mutex)   /**< Lock module using mutex. */
00188 #define DM_MUTEX_UNLOCK() SDK_MUTEX_UNLOCK(m_dm_mutex) /**< Unlock module using mutex. */
00189 /** @} */
00190 
00191 
00192 /**
00193  * @defgroup device_manager_misc_defines Miscellaneous defines used across the module.
00194  * @{
00195  */
00196 #define DM_GATT_ATTR_SIZE            6                                                   /**< Size of each GATT attribute to be stored persistently. */
00197 #define DM_GATT_SERVER_ATTR_MAX_SIZE ((DM_GATT_ATTR_SIZE * DM_GATT_CCCD_COUNT) + 2) /**< Maximum size of GATT attributes to be stored.*/
00198 #define DM_SERVICE_CONTEXT_COUNT     (DM_PROTOCOL_CNTXT_ALL + 1)                         /**< Maximum number of service contexts. */
00199 #define DM_EVT_DEVICE_CONTEXT_BASE   0x20                                                /**< Base for device context base. */
00200 #define DM_EVT_SERVICE_CONTEXT_BASE  0x30                                                /**< Base for service context base. */
00201 #define DM_EVT_APP_CONTEXT_BASE      0x40                                                /**< Base for application context base. */
00202 #define DM_LOAD_OPERATION_ID         0x01                                                /**< Load operation identifier. */
00203 #define DM_STORE_OPERATION_ID        0x02                                                /**< Store operation identifier. */
00204 #define DM_CLEAR_OPERATION_ID        0x03                                                /**< Clear operation identifier. */
00205 /** @} */
00206 
00207 #define DM_GATTS_INVALID_SIZE        0xFFFFFFFF                                     /**< Identifer for GATTS invalid size. */
00208 
00209 /**
00210  * @defgroup api_param_check API Parameters check macros.
00211  *
00212  * @details Macros for verifying parameters passed to the module in the APIs. These macros
00213  *          could be mapped to nothing in the final version of the code in order to save execution 
00214  *          time and program size.
00215  * @{
00216  */
00217 
00218 //#define DM_DISABLE_API_PARAM_CHECK /**< Macro to disable API parameters check. */
00219 
00220 #ifndef DM_DISABLE_API_PARAM_CHECK
00221 
00222 /**@brief Macro for verifying NULL parameters are not passed to API.
00223  *
00224  * @param[in] PARAM Parameter checked for NULL.
00225  *
00226  * @retval (NRF_ERROR_NULL | DEVICE_MANAGER_ERR_BASE) when @ref PARAM is NULL.
00227  */
00228 #define NULL_PARAM_CHECK(PARAM)                            \
00229     if ((PARAM) == NULL)                                   \
00230     {                                                      \
00231         return (NRF_ERROR_NULL | DEVICE_MANAGER_ERR_BASE); \
00232     }
00233 /**@} */
00234 
00235 
00236 /**@brief Macro for verifying module's initialization status.
00237  *
00238  * @retval (NRF_ERROR_INVALID_STATE | DEVICE_MANAGER_ERR_BASE) when module is not initialized.
00239  */
00240 #define VERIFY_MODULE_INITIALIZED()                                     \
00241     do                                                                  \
00242     {                                                                   \
00243         if (!m_module_initialized)                                      \
00244         {                                                               \
00245             return (NRF_ERROR_INVALID_STATE | DEVICE_MANAGER_ERR_BASE); \
00246         }                                                               \
00247     } while (0)
00248 
00249 
00250 /**@brief Macro for verifying module's initialization status. Returns in case it is not initialized.
00251  */
00252 #define VERIFY_MODULE_INITIALIZED_VOID() \
00253     do                                   \
00254     {                                    \
00255         if (!m_module_initialized)       \
00256         {                                \
00257             return;                      \
00258         }                                \
00259     } while (0)
00260 
00261 
00262 /**@brief Macro for verifying that the application is registered.
00263  *
00264  * @param[in] X Application instance identifier.
00265  *
00266  * @retval (NRF_ERROR_INVALID_STATE | DEVICE_MANAGER_ERR_BASE) when module API is called without
00267  *         registering an application with the module.
00268  */
00269 #define VERIFY_APP_REGISTERED(X)                                        \
00270     do                                                                  \
00271     {                                                                   \
00272         if (((X) >= DEVICE_MANAGER_MAX_APPLICATIONS) ||                 \
00273             (m_application_table[(X)].ntf_cb == NULL))                  \
00274         {                                                               \
00275             return (NRF_ERROR_INVALID_STATE | DEVICE_MANAGER_ERR_BASE); \
00276         }                                                               \
00277     } while (0)
00278 
00279 
00280 /**@brief Macro for verifying that the application is registered. Returns in case it is not
00281  *        registered.
00282  *
00283  * @param[in] X Application instance identifier.
00284  */
00285 #define VERIFY_APP_REGISTERED_VOID(X)                   \
00286     do                                                  \
00287     {                                                   \
00288         if (((X) >= DEVICE_MANAGER_MAX_APPLICATIONS) || \
00289             (m_application_table[(X)].ntf_cb == NULL))  \
00290         {                                               \
00291             return;                                     \
00292         }                                               \
00293     } while (0)
00294 
00295 
00296 /**@brief Macro for verifying connection instance is allocated.
00297  *
00298  * @param[in] X Connection instance identifier.
00299  *
00300  * @retval (NRF_ERROR_INVALID_ADDR | DEVICE_MANAGER_ERR_BASE) when connection instance is not
00301  *         allocated.
00302  */
00303 #define VERIFY_CONNECTION_INSTANCE(X)                                  \
00304     do                                                                 \
00305     {                                                                  \
00306         if (((X) >= DEVICE_MANAGER_MAX_CONNECTIONS) ||                 \
00307             (m_connection_table[(X)].state == STATE_IDLE))             \
00308         {                                                              \
00309             return (NRF_ERROR_INVALID_ADDR | DEVICE_MANAGER_ERR_BASE); \
00310         }                                                              \
00311     } while (0)
00312 
00313 
00314 /**@brief Macro for verifying if device instance is allocated.
00315  *
00316  * @param[in] X Device instance identifier.
00317  *
00318  * @retval (NRF_ERROR_INVALID_ADDR | DEVICE_MANAGER_ERR_BASE) when device instance is not allocated.
00319  */
00320 #define VERIFY_DEVICE_INSTANCE(X)                                      \
00321     do                                                                 \
00322     {                                                                  \
00323         if (((X) >= DEVICE_MANAGER_MAX_BONDS) ||                       \
00324             (m_peer_table[(X)].id_bitmap == UNASSIGNED))               \
00325         {                                                              \
00326             return (NRF_ERROR_INVALID_ADDR | DEVICE_MANAGER_ERR_BASE); \
00327         }                                                              \
00328     } while (0)
00329 
00330 /**@brief Macro for verifying if device is bonded and thus can store data persistantly.
00331  *
00332  * @param[in] X Connection instance identifier.
00333  *
00334  * @retval (NRF_ERROR_INVALID_STATE | DEVICE_MANAGER_ERR_BASE) when device is not bonded.
00335  */
00336 #define VERIFY_DEVICE_BOND(X)                                              \
00337     do                                                                     \
00338     {                                                                      \
00339         if ((m_connection_table[(X)].state & STATE_BONDED) != STATE_BONDED)\
00340         {                                                                  \
00341             return (NRF_ERROR_INVALID_STATE | DEVICE_MANAGER_ERR_BASE);    \
00342         }                                                                  \
00343     } while (0)
00344 #else
00345 #define NULL_PARAM_CHECK(X)
00346 #define VERIFY_MODULE_INITIALIZED()
00347 #define VERIFY_MODULE_INITIALIZED_VOID()
00348 #define VERIFY_APP_REGISTERED(X)
00349 #define VERIFY_APP_REGISTERED_VOID(X)
00350 #define VERIFY_CONNECTION_INSTANCE(X)
00351 #define VERIFY_DEVICE_INSTANCE(X)
00352 #endif //DM_DISABLE_API_PARAM_CHECK
00353 /** @} */
00354 
00355 #define INVALID_CONTEXT_LEN 0xFFFFFFFF /**< Identifier for invalid context length. */
00356 /**@brief Macro for checking that application context size is greater that minimal size.
00357  *
00358  * @param[in] X Size of application context.
00359  *
00360  * @retval (NRF_ERROR_INVALID_PARAM) when size is smaller than minimun required size.
00361  */
00362 #define SIZE_CHECK_APP_CONTEXT(X)                                      \
00363     if ((X) < (APP_CONTEXT_MIN_SIZE))                                  \
00364     {                                                                  \
00365         return NRF_ERROR_INVALID_PARAM;                                \
00366     }
00367 
00368 
00369 /**
00370  * @defgroup dm_data_types Module's internal data types.
00371  *
00372  * @brief This section describes a module's internal data structures.
00373  * @{
00374  */
00375 /**@brief Peer identification information.
00376  */
00377 typedef struct
00378 { 
00379     ble_gap_id_key_t peer_id;   /**< IRK and/or address of peer. */
00380     uint16_t         ediv;      /**< Peer's encrypted diversifier. */
00381     uint8_t          id_bitmap; /**< Contains information if above field is valid. */
00382 } peer_id_t;
00383 
00384 STATIC_ASSERT(sizeof(peer_id_t) % 4 == 0); /**< Check to ensure Peer identification information is a multiple of 4. */
00385 
00386 /**@brief Portion of bonding information exchanged by a device during bond creation that needs to
00387  *        be stored persistently.
00388  *
00389  * @note  An entry is not made in this table unless device is bonded.
00390  */
00391 typedef struct
00392 {
00393     ble_gap_enc_key_t peer_enc_key; /**< Local LTK info, central IRK and address */
00394 } bond_context_t;
00395 
00396 STATIC_ASSERT(sizeof(bond_context_t) % 4 == 0); /**< Check to ensure bond information is a multiple of 4. */
00397 
00398 /**@brief GATT Server Attributes size and data.
00399  */
00400 typedef struct
00401 {
00402     uint32_t flags;                                    /**< Flags identifying the stored attributes. */
00403     uint32_t size;                                     /**< Size of stored attributes. */
00404     uint8_t  attributes[DM_GATT_SERVER_ATTR_MAX_SIZE]; /**< Array to hold the server attributes. */
00405 } dm_gatts_context_t;
00406 
00407 STATIC_ASSERT(sizeof(dm_gatts_context_t) % 4 == 0); /**< Check to ensure GATT Server Attributes size and data information is a multiple of 4. */
00408 
00409 /**@brief GATT Client context information. Placeholder for now.
00410  */
00411 typedef struct
00412 {
00413     void * p_dummy; /**< Placeholder, currently unused. */
00414 } dm_gatt_client_context_t;
00415 
00416 STATIC_ASSERT(sizeof(dm_gatt_client_context_t) % 4 == 0);  /**< Check to ensure GATT Client context information is a multiple of 4. */
00417 STATIC_ASSERT((DEVICE_MANAGER_APP_CONTEXT_SIZE % 4) == 0); /**< Check to ensure device manager application context information is a multiple of 4. */
00418 
00419 /**@brief Connection instance definition. Maintains information with respect to an active peer.
00420  */
00421 typedef struct
00422 {
00423     ble_gap_addr_t peer_addr;     /**< Peer identification information. This information is retained as long as the connection session exists, once disconnected, for non-bonded devices this information is not stored persistently. */
00424     uint16_t       conn_handle;   /**< Connection handle for the device. */
00425     uint8_t        state;         /**< Link state. */
00426     uint8_t        bonded_dev_id; /**< In case the device is bonded, this points to the corresponding bonded device. This index can be used to index service and bond context as well. */
00427 } connection_instance_t;
00428 
00429 /**@brief Application instance definition. Maintains information with respect to a registered
00430  *        application.
00431  */
00432 typedef struct
00433 {
00434     dm_event_cb_t        ntf_cb;    /**< Callback registered with the application. */
00435     ble_gap_sec_params_t sec_param; /**< Local security parameters registered by the application. */
00436     uint8_t              state;     /**< Application state. Currently this is used only for knowing if any security procedure is in progress and/or a security procedure is pending to be requested. */
00437     uint8_t              service;   /**< Service registered by the application. */
00438 } application_instance_t;
00439 
00440 /**@brief Function for performing necessary action of storing each of the service context as
00441  *        registered by the application.
00442  *
00443  * @param[in] p_block_handle Storage block identifier.
00444  * @param[in] p_handle       Device handle identifying device that is stored.
00445  *
00446  * @retval Operation result code.
00447  */
00448 typedef ret_code_t (* service_context_access_t)(pstorage_handle_t const * p_block_handle,
00449                                                 dm_handle_t const       * p_handle);
00450 
00451 /**@brief Function for performing necessary action of applying the context information.
00452  *
00453  * @param[in] p_handle Device handle identifying device that is stored.
00454  *
00455  * @retval Operation result code.
00456  */
00457 typedef ret_code_t (* service_context_apply_t)(dm_handle_t * p_handle);
00458 
00459 /**@brief Function for performing necessary functions of storing or updating.
00460  *
00461  * @param[in] p_dest Destination address where data is stored persistently.
00462  * @param[in] p_src  Source address containing data to be stored.
00463  * @param[in] size   Size of data to be stored expressed in bytes. Must be word aligned.
00464  * @param[in] offset Offset in bytes to be applied when writing to the block.
00465  *
00466  * @retval Operation result code.
00467  */
00468 typedef uint32_t (* storage_operation)(pstorage_handle_t * p_dest,
00469                                        uint8_t           * p_src,
00470                                        pstorage_size_t     size,
00471                                        pstorage_size_t     offset);
00472 /** @} */
00473 
00474 /**
00475  * @defgroup dm_tables Module's internal tables.
00476  *
00477  * @brief This section describes the module's internal tables and the static global variables
00478  *        needed for its functionality.
00479  * @{
00480  */
00481 #if (DEVICE_MANAGER_APP_CONTEXT_SIZE != 0)
00482 static uint8_t * m_app_context_table[DEVICE_MANAGER_MAX_BONDS];                     /**< Table to remember application contexts of bonded devices. */
00483 #endif //DEVICE_MANAGER_APP_CONTEXT_SIZE
00484 __ALIGN(sizeof(uint32_t))
00485 static peer_id_t              m_peer_table[DEVICE_MANAGER_MAX_BONDS] ;              /**< Table to maintain bonded devices' identification information, an instance is allocated in the table when a device is bonded and freed when bond information is deleted. */
00486 __ALIGN(sizeof(uint32_t))
00487 static bond_context_t         m_bond_table[DEVICE_MANAGER_MAX_CONNECTIONS];         /**< Table to maintain bond information for active peers. */
00488 static dm_gatts_context_t     m_gatts_table[DEVICE_MANAGER_MAX_CONNECTIONS];        /**< Table for service information for active connection instances. */
00489 static connection_instance_t  m_connection_table[DEVICE_MANAGER_MAX_CONNECTIONS];   /**< Table to maintain active peer information. An instance is allocated in the table when a new connection is established and freed on disconnection. */
00490 static application_instance_t m_application_table[DEVICE_MANAGER_MAX_APPLICATIONS]; /**< Table to maintain application instances. */
00491 static pstorage_handle_t      m_storage_handle;                                     /**< Persistent storage handle for blocks requested by the module. */
00492 static uint32_t               m_peer_addr_update;                                   /**< 32-bit bitmap to remember peer device address update. */
00493 static ble_gap_id_key_t       m_local_id_info;                                      /**< ID information of central in case resolvable address is used. */
00494 static bool                   m_module_initialized = false;                         /**< State indicating if module is initialized or not. */
00495 static uint8_t                m_irk_index_table[DEVICE_MANAGER_MAX_BONDS];          /**< List maintaining IRK index list. */
00496 
00497 SDK_MUTEX_DEFINE(m_dm_mutex) /**< Mutex variable. Currently unused, this declaration does not occupy any space in RAM. */
00498 /** @} */
00499 
00500 static __INLINE ret_code_t no_service_context_store(pstorage_handle_t const * p_block_handle,
00501                                                     dm_handle_t const       * p_handle);
00502 
00503 static __INLINE ret_code_t gatts_context_store(pstorage_handle_t const * p_block_handle,
00504                                                dm_handle_t const       * p_handle);
00505 
00506 static __INLINE ret_code_t gattc_context_store(pstorage_handle_t const * p_block_handle,
00507                                                dm_handle_t const       * p_handle);
00508 
00509 static __INLINE ret_code_t gattsc_context_store(pstorage_handle_t const * p_block_handle,
00510                                                 dm_handle_t const       * p_handle);
00511 
00512 static __INLINE ret_code_t no_service_context_load(pstorage_handle_t const * p_block_handle,
00513                                                    dm_handle_t const       * p_handle);
00514 
00515 static __INLINE ret_code_t gatts_context_load(pstorage_handle_t const * p_block_handle,
00516                                               dm_handle_t const       * p_handle);
00517 
00518 static __INLINE ret_code_t gattc_context_load(pstorage_handle_t const * p_block_handle,
00519                                               dm_handle_t const       * p_handle);
00520 
00521 static __INLINE ret_code_t gattsc_context_load(pstorage_handle_t const * p_block_handle,
00522                                                dm_handle_t const       * p_handle);
00523 
00524 static __INLINE ret_code_t no_service_context_apply(dm_handle_t * p_handle);
00525 
00526 static __INLINE ret_code_t gatts_context_apply(dm_handle_t * p_handle);
00527 
00528 static __INLINE ret_code_t gattc_context_apply(dm_handle_t * p_handle);
00529 
00530 static __INLINE ret_code_t gattsc_context_apply(dm_handle_t * p_handle);
00531 
00532 
00533 /**< Array of function pointers based on the types of service registered. */
00534 const service_context_access_t m_service_context_store[DM_SERVICE_CONTEXT_COUNT] =
00535 {
00536     no_service_context_store, /**< Dummy function, when there is no service context registered. */
00537     gatts_context_store,      /**< GATT Server context store function. */
00538     gattc_context_store,      /**< GATT Client context store function. */
00539     gattsc_context_store      /**< GATT Server & Client context store function. */
00540 };
00541 
00542 
00543 /**< Array of function pointers based on the types of service registered. */
00544 const service_context_access_t m_service_context_load[DM_SERVICE_CONTEXT_COUNT] =
00545 {
00546     no_service_context_load,  /**< Dummy function, when there is no service context registered. */
00547     gatts_context_load,       /**< GATT Server context load function. */
00548     gattc_context_load,       /**< GATT Client context load function. */
00549     gattsc_context_load       /**< GATT Server & Client context load function. */
00550 };
00551 
00552 
00553 /**< Array of function pointers based on the types of service registered. */
00554 const service_context_apply_t m_service_context_apply[DM_SERVICE_CONTEXT_COUNT] =
00555 {
00556     no_service_context_apply, /**< Dummy function, when there is no service context registered. */
00557     gatts_context_apply,      /**< GATT Server context apply function. */
00558     gattc_context_apply,      /**< GATT Client context apply function. */
00559     gattsc_context_apply      /**< GATT Server & Client context apply function. */
00560 };
00561 
00562 
00563 const uint32_t m_context_init_len = 0xFFFFFFFF; /**< Constant used to update the initial value for context in the flash. */
00564 
00565 /**@brief Function for setting update status for the device identified by 'index'.
00566  *
00567  * @param[in] index Device identifier.
00568  */
00569 static __INLINE void update_status_bit_set(uint32_t index)
00570 {
00571     m_peer_addr_update |= (BIT_0 << index);
00572 }
00573 
00574 
00575 /**@brief Function for resetting update status for device identified by 'index'.
00576  *
00577  * @param[in] index Device identifier.
00578  */
00579 static __INLINE void update_status_bit_reset(uint32_t index)
00580 {
00581     m_peer_addr_update &= (~((uint32_t)BIT_0 << index));
00582 }
00583 
00584 
00585 /**@brief Function for providing update status for the device identified by 'index'.
00586  *
00587  * @param[in] index Device identifier.
00588  *
00589  * @retval true if the bit is set, false otherwise.
00590  */
00591 static __INLINE bool update_status_bit_is_set(uint32_t index)
00592 {
00593     return ((m_peer_addr_update & (BIT_0 << index)) ? true : false);
00594 }
00595 
00596 
00597 /**@brief Function for initialiasing the application instance identified by 'index'.
00598  *
00599  * @param[in] index Device identifier.
00600  */
00601 static __INLINE void application_instance_init(uint32_t index)
00602 {
00603     DM_TRC("[DM]: Initializing Application Instance 0x%08X.\r\n", index);
00604 
00605     m_application_table[index].ntf_cb  = NULL;
00606     m_application_table[index].state   = 0x00;
00607     m_application_table[index].service = 0x00;
00608 }
00609 
00610 
00611 /**@brief Function for initialiasing the connection instance identified by 'index'.
00612  *
00613  * @param[in] index Device identifier.
00614  */
00615 static __INLINE void connection_instance_init(uint32_t index)
00616 {
00617     DM_TRC("[DM]: Initializing Connection Instance 0x%08X.\r\n", index);
00618     
00619     m_connection_table[index].state         = STATE_IDLE;
00620     m_connection_table[index].conn_handle   = BLE_CONN_HANDLE_INVALID;
00621     m_connection_table[index].bonded_dev_id = DM_INVALID_ID;
00622     
00623     memset(&m_connection_table[index].peer_addr, 0, sizeof (ble_gap_addr_t));
00624 }
00625 
00626 
00627 /**@brief Function for initialiasing the peer device instance identified by 'index'.
00628  *
00629  * @param[in] index Device identifier.
00630  */
00631 static __INLINE void peer_instance_init(uint32_t index)
00632 {
00633     DM_TRC("[DM]: Initializing Peer Instance 0x%08X.\r\n", index);
00634     
00635     memset(m_peer_table[index].peer_id.id_addr_info.addr, 0, BLE_GAP_ADDR_LEN);
00636     memset(m_peer_table[index].peer_id.id_info.irk, 0, BLE_GAP_SEC_KEY_LEN);
00637 
00638     //Initialize the address type to invalid.
00639     m_peer_table[index].peer_id.id_addr_info.addr_type = INVALID_ADDR_TYPE;
00640 
00641     //Initialize the identification bit map to unassigned.
00642     m_peer_table[index].id_bitmap = UNASSIGNED;
00643 
00644     // Initialize diversifier.
00645     m_peer_table[index].ediv      = EDIV_INIT_VAL;
00646 
00647 
00648     //Reset the status bit.
00649     update_status_bit_reset(index);
00650 
00651 #if (DEVICE_MANAGER_APP_CONTEXT_SIZE != 0)
00652     //Initialize the application context for bond device.
00653     m_app_context_table[index] = NULL;
00654 #endif //DEVICE_MANAGER_APP_CONTEXT_SIZE
00655 }
00656 
00657 
00658 /**@brief Function for searching connection instance matching the connection handle and the state
00659  *        requested.
00660  *
00661  * @details Connection handle and state information is used to get a connection instance, it
00662  *          is possible to ignore the connection handle by using BLE_CONN_HANDLE_INVALID.
00663  *
00664  * @param[in]  conn_handle Connection handle.
00665  * @param[in]  state       Connection instance state.
00666  * @param[out] p_instance  Connection instance.
00667  *
00668  * @retval NRF_SUCCESS             Operation success.
00669  * @retval NRF_ERROR_INVALID_STATE Operation failure. Invalid state
00670  * @retval NRF_ERROR_NOT_FOUND     Operation failure. Not found
00671  */
00672 static ret_code_t connection_instance_find(uint16_t   conn_handle,
00673                                            uint8_t    state,
00674                                            uint32_t * p_instance)
00675 {
00676     ret_code_t err_code;
00677     uint32_t   index;
00678 
00679     err_code = NRF_ERROR_INVALID_STATE;
00680 
00681     for (index = 0; index < DEVICE_MANAGER_MAX_CONNECTIONS; index++)
00682     {
00683         //Search only based on the state.
00684         if (state & m_connection_table[index].state)
00685         {
00686             //Ignore the connection handle.
00687             if ((conn_handle == BLE_CONN_HANDLE_INVALID) ||
00688                 (conn_handle == m_connection_table[index].conn_handle))
00689             {
00690                 //Search for matching connection handle.
00691                 (*p_instance) = index;
00692                 err_code      = NRF_SUCCESS;
00693 
00694                 break;
00695             }
00696             else
00697             {
00698                 err_code = NRF_ERROR_NOT_FOUND;
00699             }
00700         }
00701     }
00702 
00703     return err_code;
00704 }
00705 
00706 
00707 /**@brief Function for allocating device instance for a bonded device.
00708  *
00709  * @param[out] p_device_index Device index.
00710  * @param[in]  p_addr         Peer identification information.
00711  *
00712  * @retval NRF_SUCCESS            Operation success.
00713  * @retval DM_DEVICE_CONTEXT_FULL Operation failure.
00714  */
00715 static __INLINE ret_code_t device_instance_allocate(uint8_t *              p_device_index,
00716                                                     ble_gap_addr_t const * p_addr)
00717 {
00718     ret_code_t err_code;
00719     uint32_t   index;
00720 
00721     err_code = DM_DEVICE_CONTEXT_FULL;
00722 
00723     for (index = 0; index < DEVICE_MANAGER_MAX_BONDS; index++)
00724     {
00725         DM_TRC("[DM]:[DI 0x%02X]: Device type 0x%02X.\r\n",
00726                index, m_peer_table[index].peer_id.id_addr_info.addr_type);
00727         DM_TRC("[DM]: Device Addr 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X.\r\n",
00728                m_peer_table[index].peer_id.id_addr_info.addr[0],
00729                m_peer_table[index].peer_id.id_addr_info.addr[1],
00730                m_peer_table[index].peer_id.id_addr_info.addr[2],
00731                m_peer_table[index].peer_id.id_addr_info.addr[3],
00732                m_peer_table[index].peer_id.id_addr_info.addr[4],
00733                m_peer_table[index].peer_id.id_addr_info.addr[5]);
00734 
00735         if (m_peer_table[index].id_bitmap == UNASSIGNED)
00736         {
00737             if (p_addr->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE)
00738             {
00739                 m_peer_table[index].id_bitmap            &= (~ADDR_ENTRY);
00740                 m_peer_table[index].peer_id.id_addr_info  = (*p_addr);
00741             }
00742             else
00743             {
00744                 m_peer_table[index].id_bitmap &= (~IRK_ENTRY);
00745             }
00746 
00747             (*p_device_index) = index;
00748             err_code          = NRF_SUCCESS;
00749 
00750             DM_LOG("[DM]: Allocated device instance 0x%02X\r\n", index);
00751             
00752             break;
00753         }
00754     }
00755 
00756     return err_code;
00757 }
00758 
00759 
00760 /**@brief Function for freeing a device instance allocated for bonded device.
00761  *
00762  * @param[in] device_index Device index.
00763  *
00764  * @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
00765  */
00766 static __INLINE ret_code_t device_instance_free(uint32_t device_index)
00767 {
00768     ret_code_t        err_code;
00769     pstorage_handle_t block_handle;
00770 
00771     //Get the block handle.
00772     err_code = pstorage_block_identifier_get(&m_storage_handle, device_index, &block_handle);
00773 
00774     if (err_code == NRF_SUCCESS)
00775     {
00776         DM_TRC("[DM]:[DI 0x%02X]: Freeing Instance.\r\n", device_index);
00777 
00778         //Request clearing of the block.
00779         err_code = pstorage_clear(&block_handle, ALL_CONTEXT_SIZE);
00780 
00781         if (err_code == NRF_SUCCESS)
00782         {
00783             peer_instance_init(device_index);
00784         }
00785     }
00786 
00787     return err_code;
00788 }
00789 
00790 
00791 /**@brief Function for searching for the device in the bonded device list.
00792  *
00793  * @param[in]  p_addr         Peer identification information.
00794  * @param[out] p_device_index Device index.
00795  *
00796  * @retval NRF_SUCCESS         Operation success.
00797  * @retval NRF_ERROR_NOT_FOUND Operation failure.
00798  */
00799 static ret_code_t device_instance_find(ble_gap_addr_t const * p_addr, uint32_t * p_device_index, uint16_t ediv)
00800 {
00801     ret_code_t err_code;
00802     uint32_t   index;
00803 
00804     err_code = NRF_ERROR_NOT_FOUND;
00805     
00806     DM_TRC("[DM]: Searching for device 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X.\r\n",
00807            p_addr->addr[0], 
00808            p_addr->addr[1], 
00809            p_addr->addr[2], 
00810            p_addr->addr[3],
00811            p_addr->addr[4], 
00812            p_addr->addr[5]);
00813 
00814     for (index = 0; index < DEVICE_MANAGER_MAX_BONDS; index++)
00815     {
00816         DM_TRC("[DM]:[DI 0x%02X]: Device type 0x%02X.\r\n",
00817                index, m_peer_table[index].peer_id.id_addr_info.addr_type);
00818         DM_TRC("[DM]: Device Addr 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X.\r\n",
00819                m_peer_table[index].peer_id.id_addr_info.addr[0],
00820                m_peer_table[index].peer_id.id_addr_info.addr[1],
00821                m_peer_table[index].peer_id.id_addr_info.addr[2],
00822                m_peer_table[index].peer_id.id_addr_info.addr[3],
00823                m_peer_table[index].peer_id.id_addr_info.addr[4],
00824                m_peer_table[index].peer_id.id_addr_info.addr[5]);
00825 
00826         if (((NULL == p_addr) && (ediv == m_peer_table[index].ediv)) ||
00827             ((NULL != p_addr) && (memcmp(&m_peer_table[index].peer_id.id_addr_info, p_addr, sizeof(ble_gap_addr_t)) == 0)))
00828         {
00829             DM_LOG("[DM]: Found device at instance 0x%02X\r\n", index);
00830 
00831             (*p_device_index) = index;
00832             err_code          = NRF_SUCCESS;
00833 
00834             break;
00835         }
00836     }
00837 
00838     return err_code;
00839 }
00840 
00841 
00842 /**@brief Function for notifying connection manager event to the application.
00843  *
00844  * @param[in] p_handle     Device handle identifying device.
00845  * @param[in] p_event      Connection manager event details.
00846  * @param[in] event_result Event result code.
00847  */
00848 static __INLINE void app_evt_notify(dm_handle_t const * const p_handle,
00849                                     dm_event_t const * const  p_event,
00850                                     uint32_t                  event_result)
00851 {
00852     dm_event_cb_t app_cb = m_application_table[0].ntf_cb;
00853 
00854     DM_MUTEX_UNLOCK();
00855 
00856     DM_TRC("[DM]: Notifying application of event 0x%02X\r\n", p_event->event_id);
00857 
00858     //No need to do any kind of return value processing thus can be supressed.
00859     UNUSED_VARIABLE(app_cb(p_handle, p_event, event_result));
00860 
00861     DM_MUTEX_LOCK();
00862 }
00863 
00864 
00865 /**@brief Function for allocating instance.
00866  *
00867  * @details The instance identifier is provided in the 'p_instance' parameter if the routine
00868  *          succeeds.
00869  *
00870  * @param[out] p_instance Connection instance.
00871  *
00872  * @retval NRF_SUCCESS      Operation success.
00873  * @retval NRF_ERROR_NO_MEM Operation failure. No memory.
00874  */
00875 static __INLINE uint32_t connection_instance_allocate(uint32_t * p_instance)
00876 {
00877     uint32_t err_code;
00878 
00879     DM_TRC("[DM]: Request to allocation connection instance\r\n");
00880 
00881     err_code = connection_instance_find(BLE_CONN_HANDLE_INVALID, STATE_IDLE, p_instance);
00882 
00883     if (err_code == NRF_SUCCESS)
00884     {
00885         DM_LOG("[DM]:[%02X]: Connection Instance Allocated.\r\n", (*p_instance));        
00886         m_connection_table[*p_instance].state = STATE_CONNECTED;
00887     }
00888     else
00889     {
00890         DM_LOG("[DM]: No free connection instances available\r\n");        
00891         err_code = NRF_ERROR_NO_MEM;
00892     }
00893 
00894     return err_code;
00895 }
00896 
00897 
00898 /**@brief Function for freeing instance. Instance identifier is provided in the parameter
00899  *        'p_instance' in case the routine succeeds.
00900  *
00901  * @param[in] p_instance Connection instance.
00902  */
00903 static __INLINE void connection_instance_free(uint32_t const * p_instance)
00904 {
00905     DM_TRC("[DM]:[CI 0x%02X]: Freeing connection instance\r\n", (*p_instance));
00906 
00907     if (m_connection_table[*p_instance].state != STATE_IDLE)
00908     {
00909         DM_LOG("[DM]:[%02X]: Freed connection instance.\r\n", (*p_instance));
00910         connection_instance_init(*p_instance);
00911     }
00912 }
00913 
00914 
00915 /**@brief Function for storage operation dummy handler.
00916  *
00917  * @param[in] p_dest Destination address where data is to be stored persistently.
00918  * @param[in] p_src  Source address containing data to be stored. API assumes this to be resident
00919  *                   memory and no intermediate copy of data is made by the API.
00920  * @param[in] size   Size of data to be stored expressed in bytes. Should be word aligned.
00921  * @param[in] offset Offset in bytes to be applied when writing to the block.
00922  *                   For example, if within a block of 100 bytes, application wishes to
00923  *                   write 20 bytes at offset of 12, then this field should be set to 12.
00924  *                   Should be word aligned.
00925  *
00926  * @retval NRF_SUCCESS Operation success.
00927  */
00928 static uint32_t storage_operation_dummy_handler(pstorage_handle_t * p_dest,
00929                                                 uint8_t           * p_src,
00930                                                 pstorage_size_t     size,
00931                                                 pstorage_size_t     offset)
00932 {
00933     return NRF_SUCCESS;
00934 }
00935 
00936 
00937 /**@brief Function for saving the device context persistently.
00938  *
00939  * @param[in] p_handle Device handle identifying device.
00940  * @param[in] state    Device store state.
00941  */
00942 static __INLINE void device_context_store(dm_handle_t const * p_handle, device_store_state_t state)
00943 {
00944     pstorage_handle_t block_handle;
00945     storage_operation store_fn;
00946     ret_code_t        err_code;
00947 
00948     DM_LOG("[DM]: --> device_context_store\r\n");
00949 
00950     err_code = pstorage_block_identifier_get(&m_storage_handle,
00951                                              p_handle->device_id,
00952                                              &block_handle);
00953 
00954     if (err_code == NRF_SUCCESS)
00955     {
00956         if ((STATE_BOND_INFO_UPDATE ==
00957              (m_connection_table[p_handle->connection_id].state & STATE_BOND_INFO_UPDATE)) ||
00958             (state == UPDATE_PEER_ADDR))
00959         {
00960             DM_LOG("[DM]:[DI %02X]:[CI %02X]: -> Updating bonding information.\r\n",
00961                    p_handle->device_id, p_handle->connection_id);
00962 
00963             store_fn = pstorage_update;
00964         }
00965         else if (state == FIRST_BOND_STORE)
00966         {
00967             DM_LOG("[DM]:[DI %02X]:[CI %02X]: -> Storing bonding information.\r\n",
00968                    p_handle->device_id, p_handle->connection_id);
00969 
00970             store_fn = pstorage_store;
00971         }
00972         else
00973         {
00974             DM_LOG("[DM]:[DI %02X]:[CI %02X]: -> No update in bonding information.\r\n",
00975                    p_handle->device_id, p_handle->connection_id);
00976 
00977             //No operation needed.
00978             store_fn = storage_operation_dummy_handler;
00979         }
00980 
00981         //Store the peer id.
00982         err_code = store_fn(&block_handle,
00983                             (uint8_t *)&m_peer_table[p_handle->device_id],
00984                             PEER_ID_SIZE,
00985                             PEER_ID_STORAGE_OFFSET);
00986 
00987         if ((err_code == NRF_SUCCESS) && (state != UPDATE_PEER_ADDR))
00988         {
00989             m_connection_table[p_handle->connection_id].state &= (~STATE_BOND_INFO_UPDATE);
00990 
00991             //Store the bond information.
00992             err_code = store_fn(&block_handle,
00993                                 (uint8_t *)&m_bond_table[p_handle->connection_id],
00994                                 BOND_SIZE,
00995                                 BOND_STORAGE_OFFSET);
00996 
00997             if (err_code != NRF_SUCCESS)
00998             {
00999                 DM_ERR("[DM]:[0x%02X]:Failed to store bond information, reason 0x%08X\r\n",
01000                        p_handle->device_id, err_code);
01001             }
01002         }
01003 
01004         if (state != UPDATE_PEER_ADDR)
01005         {
01006             //Store the service information
01007             err_code = m_service_context_store[m_application_table[p_handle->appl_id].service]
01008                     (
01009                         &block_handle,
01010                         p_handle
01011                     );
01012 
01013             if (err_code != NRF_SUCCESS)
01014             {
01015                 //Notify application of an error event.
01016                 DM_ERR("[DM]: Failed to store service context, reason %08X\r\n", err_code);
01017             }
01018         }
01019     }
01020 
01021     if (err_code != NRF_SUCCESS)
01022     {
01023         //Notify application of an error event.
01024         DM_ERR("[DM]: Failed to store device context, reason %08X\r\n", err_code);
01025     }
01026 }
01027 
01028 
01029 /**@brief Function for storing when there is no service registered.
01030  *
01031  * @param[in] p_block_handle Storage block identifier.
01032  * @param[in] p_handle       Device handle identifying device that is loaded.
01033  *
01034  * @retval NRF_SUCCESS
01035  */
01036 static __INLINE ret_code_t no_service_context_store(pstorage_handle_t const * p_block_handle,
01037                                                     dm_handle_t const       * p_handle)
01038 {
01039     DM_LOG("[DM]: --> no_service_context_store\r\n");
01040 
01041     return NRF_SUCCESS;
01042 }
01043 
01044 
01045 /**@brief Function for storing GATT Server context.
01046  *
01047  * @param[in] p_block_handle Storage block identifier.
01048  * @param[in] p_handle       Device handle identifying device that is stored.
01049  *
01050  * @retval NRF_SUCCESS Operation success.
01051  */
01052 static __INLINE ret_code_t gatts_context_store(pstorage_handle_t const * p_block_handle,
01053                                                dm_handle_t const       * p_handle)
01054 {
01055     storage_operation store_fn;
01056     uint32_t          attr_flags = BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS | BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS;
01057     uint16_t          attr_len   = DM_GATT_SERVER_ATTR_MAX_SIZE;
01058     uint8_t           sys_data[DM_GATT_SERVER_ATTR_MAX_SIZE];
01059 
01060     DM_LOG("[DM]: --> gatts_context_store\r\n");
01061 
01062     uint32_t err_code = sd_ble_gatts_sys_attr_get(
01063         m_connection_table[p_handle->connection_id].conn_handle,
01064         sys_data,
01065         &attr_len,
01066         attr_flags);
01067 
01068     if (err_code == NRF_SUCCESS)
01069     {
01070         if (memcmp(m_gatts_table[p_handle->connection_id].attributes, sys_data, attr_len) == 0)
01071         {
01072             //No store operation is needed.
01073             DM_LOG("[DM]:[0x%02X]: No change in GATTS Context information.\r\n",
01074                    p_handle->device_id);
01075 
01076             if ((m_connection_table[p_handle->connection_id].state & STATE_CONNECTED) !=
01077                 STATE_CONNECTED)
01078             {
01079                 DM_LOG("[DM]:[0x%02X]: Resetting GATTS for active instance.\r\n",
01080                        p_handle->connection_id);
01081 
01082                 //Reset GATTS information for the current context.
01083                 memset(&m_gatts_table[p_handle->connection_id], 0, sizeof(dm_gatts_context_t));
01084             }
01085         }
01086         else
01087         {
01088             if (m_gatts_table[p_handle->connection_id].size != 0)
01089             {
01090                 //There is data already stored in persistent memory, therefore an update is needed.
01091                 DM_LOG("[DM]:[0x%02X]: Updating stored service context\r\n", p_handle->device_id);
01092 
01093                 store_fn = pstorage_update;
01094             }
01095             else
01096             {
01097                 //Fresh write, a store is needed.
01098                 DM_LOG("[DM]:[0x%02X]: Storing service context\r\n", p_handle->device_id);
01099 
01100                 store_fn = pstorage_store;
01101             }
01102 
01103             m_gatts_table[p_handle->connection_id].flags = attr_flags;
01104             m_gatts_table[p_handle->connection_id].size  = attr_len;
01105             memcpy(m_gatts_table[p_handle->connection_id].attributes, sys_data, attr_len);
01106 
01107             DM_DUMP((uint8_t *)&m_gatts_table[p_handle->connection_id], sizeof(dm_gatts_context_t));
01108 
01109             DM_LOG("[DM]:[0x%02X]: GATTS Data size 0x%08X\r\n",
01110                    p_handle->device_id,
01111                    m_gatts_table[p_handle->connection_id].size);
01112 
01113             //Store GATTS information.
01114             err_code = store_fn((pstorage_handle_t *)p_block_handle,
01115                                 (uint8_t *)&m_gatts_table[p_handle->connection_id],
01116                                 GATTS_SERVICE_CONTEXT_SIZE,
01117                                 SERVICE_STORAGE_OFFSET);
01118 
01119             if (err_code != NRF_SUCCESS)
01120             {
01121                 DM_ERR("[DM]:[0x%02X]:Failed to store service context, reason 0x%08X\r\n",
01122                        p_handle->device_id,
01123                        err_code);
01124             }
01125             else
01126             {
01127                 DM_LOG("[DM]: Service context successfully stored.\r\n");
01128             }
01129         }
01130     }
01131 
01132     return NRF_SUCCESS;
01133 }
01134 
01135 
01136 /**@brief Function for storing GATT Client context.
01137  *
01138  * @param[in] p_block_handle Storage block identifier.
01139  * @param[in] p_handle       Device handle identifying device that is stored.
01140  *
01141  * @retval NRF_SUCCESS Operation success.
01142  */
01143 static __INLINE ret_code_t gattc_context_store(pstorage_handle_t const * p_block_handle,
01144                                                dm_handle_t const       * p_handle)
01145 {
01146     DM_LOG("[DM]: --> gattc_context_store\r\n");
01147 
01148     return NRF_SUCCESS;
01149 }
01150 
01151 
01152 /**@brief Function for storing GATT Server & Client context.
01153  *
01154  * @param[in] p_block_handle Storage block identifier.
01155  * @param[in] p_handle       Device handle identifying device that is stored.
01156  *
01157  * @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
01158  */
01159 static __INLINE ret_code_t gattsc_context_store(pstorage_handle_t const * p_block_handle,
01160                                                 dm_handle_t const       * p_handle)
01161 {
01162     DM_LOG("[DM]: --> gattsc_context_store\r\n");
01163 
01164     ret_code_t err_code = gatts_context_store(p_block_handle, p_handle);
01165 
01166     if (NRF_SUCCESS == err_code)
01167     {
01168         err_code = gattc_context_store(p_block_handle, p_handle);
01169     }
01170 
01171     return err_code;
01172 }
01173 
01174 
01175 /**@brief Function for loading when there is no service registered.
01176  *
01177  * @param[in] p_block_handle Storage block identifier.
01178  * @param[in] p_handle       Device handle identifying device that is loaded.
01179  *
01180  * @retval NRF_SUCCESS
01181  */
01182 static __INLINE ret_code_t no_service_context_load(pstorage_handle_t const * p_block_handle,
01183                                                    dm_handle_t const       * p_handle)
01184 {
01185     DM_LOG("[DM]: --> no_service_context_load\r\n");
01186 
01187     return NRF_SUCCESS;
01188 }
01189 
01190 
01191 /**@brief Function for loading GATT Server context.
01192  *
01193  * @param[in] p_block_handle Storage block identifier.
01194  * @param[in] p_handle       Device handle identifying device that is loaded.
01195  *
01196  * @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
01197  */
01198 static __INLINE ret_code_t gatts_context_load(pstorage_handle_t const * p_block_handle,
01199                                               dm_handle_t const       * p_handle)
01200 {
01201     DM_LOG("[DM]:[CI 0x%02X]:[DI 0x%02X]: --> gatts_context_load\r\n",
01202            p_handle->connection_id,
01203            p_handle->device_id);
01204 
01205     ret_code_t err_code = pstorage_load((uint8_t *)&m_gatts_table[p_handle->connection_id],
01206                                         (pstorage_handle_t *)p_block_handle,
01207                                         GATTS_SERVICE_CONTEXT_SIZE,
01208                                         SERVICE_STORAGE_OFFSET);
01209 
01210     if (err_code == NRF_SUCCESS)
01211     {
01212         DM_LOG("[DM]:[%02X]:[Block ID 0x%08X]: Service context loaded, size 0x%08X\r\n",
01213                p_handle->connection_id,
01214                p_block_handle->block_id,
01215                m_gatts_table[p_handle->connection_id].size);
01216         DM_DUMP((uint8_t *)&m_gatts_table[p_handle->connection_id], sizeof(dm_gatts_context_t));
01217 
01218         if (m_gatts_table[p_handle->connection_id].size == DM_GATTS_INVALID_SIZE)
01219         {
01220             m_gatts_table[p_handle->connection_id].size = 0;
01221         }
01222     }
01223     else
01224     {
01225         DM_ERR("[DM]:[%02X]: Failed to load Service context, reason %08X\r\n",
01226                p_handle->connection_id,
01227                err_code);
01228     }
01229 
01230     return err_code;
01231 }
01232 
01233 
01234 /**@brief Function for loading GATT Client context.
01235  *
01236  * @param[in] p_block_handle Storage block identifier.
01237  * @param[in] p_handle       Device handle identifying device that is loaded.
01238  *
01239  * @retval NRF_SUCCESS
01240  */
01241 static __INLINE ret_code_t gattc_context_load(pstorage_handle_t const * p_block_handle,
01242                                               dm_handle_t const       * p_handle)
01243 {
01244     DM_LOG("[DM]: --> gattc_context_load\r\n");
01245 
01246     return NRF_SUCCESS;
01247 }
01248 
01249 
01250 /**@brief Function for loading GATT Server & Client context.
01251  *
01252  * @param[in] p_block_handle Storage block identifier.
01253  * @param[in] p_handle       Device handle identifying device that is loaded.
01254  *
01255  * @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
01256  */
01257 static __INLINE ret_code_t gattsc_context_load(pstorage_handle_t const * p_block_handle,
01258                                                dm_handle_t const       * p_handle)
01259 {
01260     DM_LOG("[DM]: --> gattsc_context_load\r\n");
01261 
01262     ret_code_t err_code = gatts_context_load(p_block_handle, p_handle);
01263 
01264     if (NRF_SUCCESS == err_code)
01265     {
01266         err_code = gattc_context_load(p_block_handle, p_handle);
01267     }
01268 
01269     return err_code;
01270 }
01271 
01272 
01273 /**@brief Function for applying when there is no service registered.
01274  *
01275  * @param[in] p_handle Device handle identifying device that is applied.
01276  *
01277  * @retval NRF_SUCCESS
01278  */
01279 static __INLINE ret_code_t no_service_context_apply(dm_handle_t * p_handle)
01280 {
01281     DM_LOG("[DM]: --> no_service_context_apply\r\n");
01282     DM_LOG("[DM]:[CI 0x%02X]: No Service context\r\n", p_handle->connection_id);
01283 
01284     return NRF_SUCCESS;
01285 }
01286 
01287 
01288 /**@brief Function for applying GATT Server context.
01289  *
01290  * @param[in] p_handle Device handle identifying device that is applied.
01291  *
01292  * @retval NRF_SUCCESS                    On success.
01293  * @retval DM_SERVICE_CONTEXT_NOT_APPLIED On failure.
01294  */
01295 static __INLINE ret_code_t gatts_context_apply(dm_handle_t * p_handle)
01296 {
01297     uint32_t err_code;
01298 
01299     uint8_t * p_gatts_context = NULL;
01300     uint16_t  context_len     = 0;
01301     uint32_t  context_flags   = 0;
01302 
01303     DM_LOG("[DM]: --> gatts_context_apply\r\n");
01304     DM_LOG("[DM]:[CI 0x%02X]: State 0x%02X, Size 0x%08X\r\n",
01305            p_handle->connection_id,
01306            m_connection_table[p_handle->connection_id].state,
01307            m_gatts_table[p_handle->connection_id].size);
01308 
01309     if ((m_gatts_table[p_handle->connection_id].size != 0) &&
01310         (
01311             ((m_connection_table[p_handle->connection_id].state & STATE_LINK_ENCRYPTED) == STATE_LINK_ENCRYPTED) &&
01312             ((m_connection_table[p_handle->connection_id].state & STATE_BOND_INFO_UPDATE)
01313              != STATE_BOND_INFO_UPDATE)
01314         )
01315        )
01316     {
01317         DM_LOG("[DM]: Setting stored context.\r\n");
01318 
01319         p_gatts_context = &m_gatts_table[p_handle->connection_id].attributes[0];
01320         context_len     = m_gatts_table[p_handle->connection_id].size;
01321         context_flags   = m_gatts_table[p_handle->connection_id].flags;
01322     }
01323 
01324     err_code = sd_ble_gatts_sys_attr_set(m_connection_table[p_handle->connection_id].conn_handle,
01325                                          p_gatts_context,
01326                                          context_len,
01327                                          context_flags);
01328 
01329     if (err_code == NRF_ERROR_INVALID_DATA)
01330     {
01331         // Indication that the ATT table has changed. Restore the system attributes to system
01332         // services only and send a service changed indication if possible.
01333         context_flags = BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS;
01334         err_code      = sd_ble_gatts_sys_attr_set(m_connection_table[p_handle->connection_id].conn_handle,
01335                                                   p_gatts_context,
01336                                                   context_len,
01337                                                   context_flags);
01338     }
01339 
01340     if (err_code != NRF_SUCCESS)
01341     {
01342         DM_LOG("[DM]: Failed to set system attributes, reason 0x%08X.\r\n", err_code);
01343 
01344         err_code = DM_SERVICE_CONTEXT_NOT_APPLIED;
01345     }
01346 
01347     if (context_flags == BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS)
01348     {
01349         err_code = sd_ble_gatts_service_changed(m_connection_table[p_handle->connection_id].conn_handle,
01350                                                 0x000C,
01351                                                 0xFFFF);
01352         if (err_code != NRF_SUCCESS)
01353         {
01354             DM_LOG("[DM]: Failed to send Service Changed indication, reason 0x%08X.\r\n", err_code);
01355             if ((err_code != BLE_ERROR_INVALID_CONN_HANDLE) &&
01356                 (err_code != NRF_ERROR_INVALID_STATE) &&
01357                 (err_code != BLE_ERROR_NO_TX_BUFFERS) &&
01358                 (err_code != NRF_ERROR_BUSY))
01359             {
01360                 // Those errors can be expected when sending trying to send Service Changed
01361                 // Indication if the CCCD is not set to indicate. Thus set the returning error
01362                 //  code to success.
01363                 err_code = NRF_SUCCESS;
01364             }
01365             else
01366             {
01367                 err_code = DM_SERVICE_CONTEXT_NOT_APPLIED;
01368             }
01369         }
01370     }
01371 
01372     return err_code;
01373 }
01374 
01375 
01376 /**@brief Function for applying GATT Client context.
01377  *
01378  * @param[in] p_handle Device handle identifying device that is applied.
01379  *
01380  * @retval NRF_SUCCESS On success.
01381  */
01382 static __INLINE ret_code_t gattc_context_apply(dm_handle_t * p_handle)
01383 {
01384     DM_LOG("[DM]: --> gattc_context_apply\r\n");
01385 
01386     return NRF_SUCCESS;
01387 }
01388 
01389 
01390 /**@brief Function for applying GATT Server & Client context.
01391  *
01392  * @param[in] p_handle Device handle identifying device that is applied.
01393  *
01394  * @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
01395  */
01396 static __INLINE ret_code_t gattsc_context_apply(dm_handle_t * p_handle)
01397 {
01398     uint32_t err_code;
01399 
01400     DM_LOG("[DM]: --> gattsc_context_apply\r\n");
01401 
01402     err_code = gatts_context_apply(p_handle);
01403 
01404     if (err_code == NRF_SUCCESS)
01405     {
01406         err_code = gattc_context_apply(p_handle);
01407     }
01408 
01409     return err_code;
01410 }
01411 
01412 
01413 /**@brief Function for pstorage module callback.
01414  *
01415  * @param[in] p_handle Identifies module and block for which callback is received.
01416  * @param[in] op_code  Identifies the operation for which the event is notified.
01417  * @param[in] result   Identifies the result of flash access operation.
01418  *                     NRF_SUCCESS implies, operation succeeded.
01419  * @param[in] p_data   Identifies the application data pointer. In case of store operation, this
01420  *                     points to the resident source of application memory that application can now
01421  *                     free or reuse. In case of clear, this is NULL as no application pointer is
01422  *                     needed for this operation.
01423  * @param[in] data_len Length of data provided by the application for the operation.
01424  */
01425 static void dm_pstorage_cb_handler(pstorage_handle_t * p_handle,
01426                                    uint8_t             op_code,
01427                                    uint32_t            result,
01428                                    uint8_t           * p_data,
01429                                    uint32_t            data_len)
01430 {
01431     VERIFY_APP_REGISTERED_VOID(0);
01432 
01433     if (data_len > ALL_CONTEXT_SIZE)
01434     {
01435         //Clearing of all bonds at initialization, no event is generated.
01436         return;
01437     }
01438 
01439     DM_MUTEX_LOCK();
01440 
01441     dm_event_t        dm_event;
01442     dm_handle_t       dm_handle;
01443     dm_context_t      context_data;
01444     pstorage_handle_t block_handle;
01445     uint32_t          index_count;
01446     uint32_t          err_code;
01447 
01448     bool app_notify = true;
01449 
01450     err_code = dm_handle_initialize(&dm_handle);
01451     APP_ERROR_CHECK(err_code);
01452 
01453     dm_handle.appl_id = 0;
01454     dm_event.event_id = 0x00;
01455 
01456     //Construct the event which it is related to.
01457 
01458     //Initialize context data information and length.
01459     context_data.p_data = p_data;
01460     context_data.len    = data_len;
01461 
01462     for (uint32_t index = 0; index < DEVICE_MANAGER_MAX_BONDS; index++)
01463     {
01464         err_code = pstorage_block_identifier_get(&m_storage_handle, index, &block_handle);
01465         if ((err_code == NRF_SUCCESS) &&
01466             (
01467                 (memcmp(p_handle, &block_handle, sizeof(pstorage_handle_t)) == 0)
01468             )
01469            )
01470         {
01471             dm_handle.device_id = index;
01472             break;
01473         }
01474     }
01475 
01476     if (dm_handle.device_id != DM_INVALID_ID)
01477     {
01478         if (op_code == PSTORAGE_CLEAR_OP_CODE)
01479         {
01480             if (data_len == ALL_CONTEXT_SIZE)
01481             {
01482                 dm_event.event_id = DM_EVT_DEVICE_CONTEXT_BASE;
01483             }
01484             else
01485             {
01486                 dm_event.event_id = DM_EVT_APP_CONTEXT_BASE;
01487             }
01488         }
01489         else
01490         {
01491             //Update or store operation.
01492             //Context is identified based on the pointer value. Device context, application context
01493             //and service context all have their own value range.
01494             index_count = ((uint32_t)(p_data - (uint8_t *)m_peer_table)) / PEER_ID_SIZE;
01495 
01496             if (index_count < DEVICE_MANAGER_MAX_BONDS)
01497             {
01498                 dm_event.event_param.p_device_context = &context_data;
01499 
01500                 //Only the peer identification is stored, not bond information. Hence do not notify
01501                 //the application yet, unless the store operation resulted in a failure.
01502                 if ((result == NRF_SUCCESS) &&
01503                     (
01504                         (update_status_bit_is_set(dm_handle.device_id) == false)
01505                     )
01506                    )
01507                 {
01508                     app_notify = false;
01509                 }
01510                 else
01511                 {
01512                     //Reset update status since update is complete.
01513                     update_status_bit_reset(dm_handle.device_id);
01514 
01515                     //Notify application of error in storing the context.
01516                     dm_event.event_id = DM_EVT_DEVICE_CONTEXT_BASE;
01517                 }
01518             }
01519             else
01520             {
01521                 index_count = ((uint32_t)(p_data - (uint8_t *)m_bond_table)) / BOND_SIZE;
01522 
01523                 if (index_count < DEVICE_MANAGER_MAX_CONNECTIONS)
01524                 {
01525                     DM_LOG("[DM]:[0x%02X]:[0x%02X]: Bond context Event\r\n",
01526                            dm_handle.device_id,
01527                            dm_handle.connection_id);
01528 
01529                     dm_event.event_param.p_device_context = &context_data;
01530                     dm_event.event_id                     = DM_EVT_DEVICE_CONTEXT_BASE;
01531                     dm_handle.connection_id               = index_count;
01532 
01533                     ble_gap_sec_keyset_t keys_exchanged;
01534                     keys_exchanged.keys_central.p_enc_key = NULL;
01535                     keys_exchanged.keys_central.p_id_key  = &m_local_id_info;
01536                     keys_exchanged.keys_periph.p_enc_key  = &m_bond_table[index_count].peer_enc_key;
01537                     keys_exchanged.keys_periph.p_id_key   =
01538                         &m_peer_table[dm_handle.device_id].peer_id;
01539 
01540                     //Context information updated to provide the keys.
01541                     context_data.p_data = (uint8_t *)&keys_exchanged;
01542                     context_data.len    = sizeof(ble_gap_sec_keyset_t);
01543                 }
01544                 else
01545                 {
01546                     index_count = ((uint32_t)(p_data - (uint8_t *)m_gatts_table)) /
01547                                   GATTS_SERVICE_CONTEXT_SIZE;
01548 
01549                     if (index_count < DEVICE_MANAGER_MAX_CONNECTIONS)
01550                     {
01551                         DM_LOG("[DM]:[0x%02X]:[0x%02X]: Service context Event\r\n",
01552                                dm_handle.device_id,
01553                                dm_handle.connection_id);
01554 
01555                         //Notify application.
01556                         dm_event.event_id       = DM_EVT_SERVICE_CONTEXT_BASE;
01557                         dm_handle.connection_id = index_count;
01558                         dm_handle.service_id    = DM_PROTOCOL_CNTXT_GATT_SRVR_ID;
01559 
01560                         //Reset the service context now that it was successfully written to the
01561                         //application and the link is disconnected.
01562                         if ((m_connection_table[index_count].state & STATE_CONNECTED) !=
01563                             STATE_CONNECTED)
01564                         {
01565                             DM_LOG("[DM]:[0x%02X]:[0x%02X]: Resetting bond information for "
01566                                    "active instance.\r\n",
01567                                    dm_handle.device_id,
01568                                    dm_handle.connection_id);
01569 
01570                             memset(&m_gatts_table[dm_handle.connection_id],
01571                                    0,
01572                                    sizeof(dm_gatts_context_t));
01573                         }
01574                     }
01575                     else
01576                     {
01577                         DM_LOG("[DM]:[0x%02X]:[0x%02X]: App context Event\r\n",
01578                                dm_handle.device_id,
01579                                dm_handle.connection_id);
01580 
01581                         app_notify        = false;
01582                         dm_event.event_id = DM_EVT_APP_CONTEXT_BASE;
01583 #if (DEVICE_MANAGER_APP_CONTEXT_SIZE != 0)
01584 
01585                         if (p_data == (uint8_t *)(&m_context_init_len))
01586                         {
01587                             //Context data is deleted.
01588                             //This is a workaround to get the right event as on delete operation
01589                             //update operation is used instead of clear.
01590                             op_code    = PSTORAGE_CLEAR_OP_CODE;
01591                             app_notify = true;
01592                         }
01593                         else if (m_app_context_table[dm_handle.device_id] == p_data)
01594                         {
01595                             app_notify                         = true;
01596                             dm_event.event_param.p_app_context = &context_data;
01597 
01598                             //Verify if the device is connected, if yes set connection instance.
01599                             for (uint32_t index = 0;
01600                                  index < DEVICE_MANAGER_MAX_CONNECTIONS;
01601                                  index++)
01602                             {
01603                                 if (dm_handle.device_id == m_connection_table[index].bonded_dev_id)
01604                                 {
01605                                     dm_handle.connection_id = index;
01606                                     break;
01607                                 }
01608                             }
01609                         }
01610                         else
01611                         {
01612                             //No implementation needed.
01613                         }
01614 #endif //DEVICE_MANAGER_APP_CONTEXT_SIZE
01615                     }
01616                 }
01617             }
01618         }
01619 
01620         if (app_notify == true)
01621         {
01622             if (op_code == PSTORAGE_CLEAR_OP_CODE)
01623             {
01624                 dm_event.event_id |= DM_CLEAR_OPERATION_ID;
01625             }
01626             else if (op_code == PSTORAGE_LOAD_OP_CODE)
01627             {
01628                 dm_event.event_id |= DM_LOAD_OPERATION_ID;
01629             }
01630             else
01631             {
01632                 dm_event.event_id |= DM_STORE_OPERATION_ID;
01633             }
01634 
01635             dm_event.event_param.p_app_context = &context_data;
01636             app_evt_notify(&dm_handle, &dm_event, result);
01637         }
01638     }
01639 
01640     DM_MUTEX_UNLOCK();
01641 }
01642 
01643 
01644 ret_code_t dm_init(dm_init_param_t const * const p_init_param)
01645 {
01646     pstorage_module_param_t param;
01647     pstorage_handle_t       block_handle;
01648     ret_code_t              err_code;
01649     uint32_t                index;
01650 
01651     DM_LOG("[DM]: >> dm_init.\r\n");
01652 
01653     NULL_PARAM_CHECK(p_init_param);
01654 
01655     SDK_MUTEX_INIT(m_dm_mutex);
01656 
01657     DM_MUTEX_LOCK();
01658 
01659     for (index = 0; index < DEVICE_MANAGER_MAX_APPLICATIONS; index++)
01660     {
01661         application_instance_init(index);
01662     }
01663 
01664     for (index = 0; index < DEVICE_MANAGER_MAX_CONNECTIONS; index++)
01665     {
01666         connection_instance_init(index);
01667     }
01668 
01669     memset(m_gatts_table, 0, sizeof(m_gatts_table));
01670 
01671     //Initialization of all device instances.
01672     for (index = 0; index < DEVICE_MANAGER_MAX_BONDS; index++)
01673     {
01674         peer_instance_init(index);
01675         m_irk_index_table[index] = DM_INVALID_ID;
01676     }
01677 
01678     //All context with respect to a particular device is stored contiguously.
01679     param.block_size  = ALL_CONTEXT_SIZE;
01680     param.block_count = DEVICE_MANAGER_MAX_BONDS;
01681     param.cb          = dm_pstorage_cb_handler;
01682 
01683     err_code = pstorage_register(&param, &m_storage_handle);
01684 
01685     if (err_code == NRF_SUCCESS)
01686     {
01687         m_module_initialized = true;
01688 
01689         if (p_init_param->clear_persistent_data == false)
01690         {
01691             DM_LOG("[DM]: Storage handle 0x%08X.\r\n", m_storage_handle.block_id);
01692 
01693             //Copy bonded peer device address and IRK to RAM table.
01694 
01695             //Bonded devices are stored in range (0,DEVICE_MANAGER_MAX_BONDS-1). The remaining
01696             //range is for active connections that may or may not be bonded.
01697             for (index = 0; index < DEVICE_MANAGER_MAX_BONDS; index++)
01698             {
01699                 err_code = pstorage_block_identifier_get(&m_storage_handle, index, &block_handle);
01700 
01701                 //Issue read request if you successfully get the block identifier.
01702                 if (err_code == NRF_SUCCESS)
01703                 {
01704                     DM_TRC("[DM]:[0x%02X]: Block handle 0x%08X.\r\n", index, block_handle.block_id);
01705 
01706                     err_code = pstorage_load((uint8_t *)&m_peer_table[index],
01707                                              &block_handle,
01708                                              sizeof(peer_id_t),
01709                                              0);
01710 
01711                     if (err_code != NRF_SUCCESS)
01712                     {
01713                         // In case a peer device could not be loaded successfully, rest of the
01714                         // initialization procedure are skipped and an error is sent to the
01715                         // application.
01716                         DM_ERR(
01717                             "[DM]: Failed to load peer device %08X from storage, reason %08X.\r\n",
01718                             index,
01719                             err_code);
01720 
01721                         m_module_initialized = false;
01722                         break;
01723                     }
01724                     else
01725                     {
01726                         DM_TRC("[DM]:[DI 0x%02X]: Device type 0x%02X.\r\n",
01727                                index,
01728                                m_peer_table[index].peer_id.id_addr_info.addr_type);
01729                         DM_TRC("[DM]: Device Addr 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X.\r\n",
01730                                m_peer_table[index].peer_id.id_addr_info.addr[0],
01731                                m_peer_table[index].peer_id.id_addr_info.addr[1],
01732                                m_peer_table[index].peer_id.id_addr_info.addr[2],
01733                                m_peer_table[index].peer_id.id_addr_info.addr[3],
01734                                m_peer_table[index].peer_id.id_addr_info.addr[4],
01735                                m_peer_table[index].peer_id.id_addr_info.addr[5]);
01736                     }
01737                 }
01738                 else
01739                 {
01740                     //In case a peer device could not be loaded successfully, rest of the
01741                     //initialization procedure are skipped and an error is sent to the application.
01742                     DM_LOG("[DM]: Failed to get block handle for instance %08X, reason %08X.\r\n",
01743                            index,
01744                            err_code);
01745 
01746                     m_module_initialized = false;
01747                     break;
01748                 }
01749             }
01750         }
01751         else
01752         {
01753             err_code = pstorage_clear(&m_storage_handle, (param.block_size * param.block_count));
01754             DM_ERR("[DM]: Successfully requested clear of persistent data.\r\n");
01755         }
01756     }
01757     else
01758     {
01759         DM_ERR("[DM]: Failed to register with storage module, reason 0x%08X.\r\n", err_code);
01760     }
01761 
01762     DM_MUTEX_UNLOCK();
01763 
01764     DM_TRC("[DM]: << dm_init.\r\n");
01765 
01766     return err_code;
01767 }
01768 
01769 
01770 ret_code_t dm_register(dm_application_instance_t    * p_appl_instance,
01771                        dm_application_param_t const * p_appl_param)
01772 {
01773     VERIFY_MODULE_INITIALIZED();
01774     NULL_PARAM_CHECK(p_appl_instance);
01775     NULL_PARAM_CHECK(p_appl_param);
01776     NULL_PARAM_CHECK(p_appl_param->evt_handler);
01777 
01778     DM_MUTEX_LOCK();
01779 
01780     DM_LOG("[DM]: >> dm_register.\r\n");
01781 
01782     uint32_t err_code;
01783 
01784     //Verify if an application instance is available. Currently only one instance is supported.
01785     if (m_application_table[0].ntf_cb == NULL)
01786     {
01787         DM_LOG("[DM]: Application Instance allocated.\r\n");
01788 
01789         //Mark instance as allocated.
01790         m_application_table[0].ntf_cb    = p_appl_param->evt_handler;
01791         m_application_table[0].sec_param = p_appl_param->sec_param;
01792         m_application_table[0].service   = p_appl_param->service_type;
01793 
01794         m_application_table[0].sec_param.kdist_central.enc  = 0;
01795         m_application_table[0].sec_param.kdist_central.id   = 1;
01796         m_application_table[0].sec_param.kdist_central.sign = 0;
01797         m_application_table[0].sec_param.kdist_periph.enc   = 1;
01798         m_application_table[0].sec_param.kdist_periph.id    = 1;
01799         m_application_table[0].sec_param.kdist_periph.sign  = 0;
01800         //Populate application's instance variable with the assigned allocation instance.
01801         *p_appl_instance = 0;
01802         err_code         = NRF_SUCCESS;
01803     }
01804     else
01805     {
01806         err_code = (NRF_ERROR_NO_MEM | DEVICE_MANAGER_ERR_BASE);
01807     }
01808 
01809     DM_MUTEX_UNLOCK();
01810 
01811     DM_TRC("[DM]: << dm_register.\r\n");
01812 
01813     return err_code;
01814 }
01815 
01816 
01817 ret_code_t dm_security_setup_req(dm_handle_t * p_handle)
01818 {
01819     VERIFY_MODULE_INITIALIZED();
01820     NULL_PARAM_CHECK(p_handle);
01821     VERIFY_APP_REGISTERED(p_handle->appl_id);
01822     VERIFY_CONNECTION_INSTANCE(p_handle->connection_id);
01823 
01824     DM_MUTEX_LOCK();
01825 
01826     DM_LOG("[DM]: >> dm_security_setup_req\r\n");
01827 
01828     uint32_t err_code = (NRF_ERROR_INVALID_STATE | DEVICE_MANAGER_ERR_BASE);
01829 
01830     if ((m_connection_table[p_handle->connection_id].state & STATE_CONNECTED) == STATE_CONNECTED)
01831     {
01832         err_code = sd_ble_gap_authenticate(m_connection_table[p_handle->connection_id].conn_handle,
01833                                            &m_application_table[0].sec_param);
01834     }
01835 
01836     DM_TRC("[DM]: << dm_security_setup_req, 0x%08X\r\n", err_code);
01837 
01838     DM_MUTEX_UNLOCK();
01839 
01840     return err_code;
01841 }
01842 
01843 
01844 ret_code_t dm_security_status_req(dm_handle_t const    * p_handle,
01845                                   dm_security_status_t * p_status)
01846 {
01847     VERIFY_MODULE_INITIALIZED();
01848     NULL_PARAM_CHECK(p_handle);
01849     NULL_PARAM_CHECK(p_status);
01850     VERIFY_APP_REGISTERED(p_handle->appl_id);
01851     VERIFY_CONNECTION_INSTANCE(p_handle->connection_id);
01852 
01853     DM_MUTEX_LOCK();
01854 
01855     DM_LOG("[DM]: >> dm_security_status_req\r\n");
01856 
01857     if ((m_connection_table[p_handle->connection_id].state & STATE_PAIRING) ||
01858         (m_connection_table[p_handle->connection_id].state & STATE_PAIRING_PENDING))
01859     {
01860         (*p_status) = ENCRYPTION_IN_PROGRESS;
01861     }
01862     else if (m_connection_table[p_handle->connection_id].state & STATE_LINK_ENCRYPTED)
01863     {
01864         (*p_status) = ENCRYPTED;
01865     }
01866     else
01867     {
01868         (*p_status) = NOT_ENCRYPTED;
01869     }
01870 
01871     DM_TRC("[DM]: << dm_security_status_req\r\n");
01872 
01873     DM_MUTEX_UNLOCK();
01874 
01875     return NRF_SUCCESS;
01876 }
01877 
01878 
01879 ret_code_t dm_whitelist_create(dm_application_instance_t const * p_handle,
01880                                ble_gap_whitelist_t             * p_whitelist)
01881 {
01882     VERIFY_MODULE_INITIALIZED();
01883     NULL_PARAM_CHECK(p_handle);
01884     NULL_PARAM_CHECK(p_whitelist);
01885     NULL_PARAM_CHECK(p_whitelist->pp_addrs);
01886     NULL_PARAM_CHECK(p_whitelist->pp_irks);
01887     VERIFY_APP_REGISTERED(*p_handle);
01888 
01889     DM_MUTEX_LOCK();
01890 
01891     DM_LOG("[DM]: >> dm_whitelist_create\r\n");
01892 
01893     uint32_t addr_count = 0;
01894     uint32_t irk_count  = 0;
01895     bool     connected  = false;
01896 
01897     for (uint32_t index = 0; index < DEVICE_MANAGER_MAX_BONDS; index++)
01898     {
01899         connected = false;
01900 
01901         for (uint32_t c_index = 0; c_index < DEVICE_MANAGER_MAX_CONNECTIONS; c_index++)
01902         {
01903             if ((index == m_connection_table[c_index].bonded_dev_id) &&
01904                 ((m_connection_table[c_index].state & STATE_CONNECTED) == STATE_CONNECTED))
01905             {
01906                 connected = true;
01907                 break;
01908             }
01909         }
01910 
01911         if (connected == false)
01912         {
01913             if ((irk_count < p_whitelist->irk_count) &&
01914                 ((m_peer_table[index].id_bitmap & IRK_ENTRY) == 0))
01915             {
01916                 p_whitelist->pp_irks[irk_count] = &m_peer_table[index].peer_id.id_info;
01917                 m_irk_index_table[irk_count]    = index;
01918                 irk_count++;
01919             }
01920 
01921             if ((addr_count < p_whitelist->addr_count) &&
01922                 (m_peer_table[index].id_bitmap & ADDR_ENTRY) == 0)
01923             {
01924                 p_whitelist->pp_addrs[addr_count] = &m_peer_table[index].peer_id.id_addr_info;
01925                 addr_count++;
01926             }
01927         }
01928     }
01929 
01930     p_whitelist->addr_count = addr_count;
01931     p_whitelist->irk_count  = irk_count;
01932 
01933     DM_LOG("[DM]: Created whitelist, number of IRK = 0x%02X, number of addr = 0x%02X\r\n",
01934            irk_count,
01935            addr_count);
01936 
01937     DM_TRC("[DM]: << dm_whitelist_create\r\n");
01938 
01939     DM_MUTEX_UNLOCK();
01940 
01941     return NRF_SUCCESS;
01942 }
01943 
01944 
01945 ret_code_t dm_device_add(dm_handle_t               * p_handle,
01946                          dm_device_context_t const * p_context)
01947 {
01948     return (API_NOT_IMPLEMENTED | DEVICE_MANAGER_ERR_BASE);
01949 }
01950 
01951 
01952 ret_code_t dm_device_delete(dm_handle_t const * p_handle)
01953 {
01954     VERIFY_MODULE_INITIALIZED();
01955     NULL_PARAM_CHECK(p_handle);
01956     VERIFY_APP_REGISTERED(p_handle->appl_id);
01957     VERIFY_DEVICE_INSTANCE(p_handle->device_id);
01958 
01959     DM_MUTEX_LOCK();
01960 
01961     DM_TRC("[DM]: >> dm_device_delete\r\n");
01962 
01963     uint32_t err_code = device_instance_free(p_handle->device_id);
01964 
01965     DM_TRC("[DM]: << dm_device_delete\r\n");
01966 
01967     DM_MUTEX_UNLOCK();
01968 
01969     return err_code;
01970 }
01971 
01972 
01973 ret_code_t dm_device_delete_all(dm_application_instance_t const * p_handle)
01974 {
01975     VERIFY_MODULE_INITIALIZED();
01976     NULL_PARAM_CHECK(p_handle);
01977     VERIFY_APP_REGISTERED((*p_handle));
01978 
01979     DM_MUTEX_LOCK();
01980 
01981     uint32_t err_code = NRF_SUCCESS;
01982 
01983     DM_TRC("[DM]: >> dm_device_delete_all\r\n");
01984 
01985     for (uint32_t index = 0; index < DEVICE_MANAGER_MAX_BONDS; index++)
01986     {
01987         if (m_peer_table[index].id_bitmap != UNASSIGNED)
01988         {
01989             err_code = device_instance_free(index);
01990         }
01991     }
01992 
01993     DM_TRC("[DM]: << dm_device_delete_all\r\n");
01994 
01995     DM_MUTEX_UNLOCK();
01996 
01997     return err_code;
01998 }
01999 
02000 
02001 ret_code_t dm_service_context_set(dm_handle_t const          * p_handle,
02002                                   dm_service_context_t const * p_context)
02003 {
02004     VERIFY_MODULE_INITIALIZED();
02005     NULL_PARAM_CHECK(p_handle);
02006     NULL_PARAM_CHECK(p_context);
02007     VERIFY_APP_REGISTERED(p_handle->appl_id);
02008     VERIFY_CONNECTION_INSTANCE(p_handle->connection_id);
02009     VERIFY_DEVICE_INSTANCE(p_handle->device_id);
02010 
02011     DM_MUTEX_LOCK();
02012 
02013     DM_TRC("[DM]: >> dm_service_context_set\r\n");
02014 
02015     if ((p_context->context_data.p_data != NULL) &&
02016         (
02017             (p_context->context_data.len != 0) &&
02018             (p_context->context_data.len < DM_GATT_SERVER_ATTR_MAX_SIZE)
02019         )
02020        )
02021     {
02022         if (p_context->service_type == DM_PROTOCOL_CNTXT_GATT_SRVR_ID)
02023         {
02024             memcpy(m_gatts_table[p_handle->connection_id].attributes,
02025                    p_context->context_data.p_data,
02026                    p_context->context_data.len);
02027         }
02028     }
02029 
02030     pstorage_handle_t block_handle;
02031     uint32_t          err_code = pstorage_block_identifier_get(&m_storage_handle,
02032                                                                p_handle->device_id,
02033                                                                &block_handle);
02034 
02035     err_code = m_service_context_store[p_context->service_type](&block_handle, p_handle);
02036 
02037     DM_TRC("[DM]: << dm_service_context_set\r\n");
02038 
02039     DM_MUTEX_UNLOCK();
02040 
02041     return err_code;
02042 }
02043 
02044 
02045 ret_code_t dm_service_context_get(dm_handle_t const    * p_handle,
02046                                   dm_service_context_t * p_context)
02047 {
02048     VERIFY_MODULE_INITIALIZED();
02049     NULL_PARAM_CHECK(p_handle);
02050     NULL_PARAM_CHECK(p_context);
02051     VERIFY_APP_REGISTERED(p_handle->appl_id);
02052     VERIFY_DEVICE_INSTANCE(p_handle->device_id);
02053 
02054     if ((m_connection_table[p_handle->connection_id].state & STATE_CONNECTED) != STATE_CONNECTED)
02055     {
02056         DM_TRC("[DM]: Device must be connected to get context. \r\n");
02057 
02058         return (FEATURE_NOT_ENABLED | DEVICE_MANAGER_ERR_BASE);
02059     }
02060 
02061     DM_MUTEX_LOCK();
02062 
02063     DM_TRC("[DM]: >> dm_service_context_get\r\n");
02064 
02065     if ((p_context->context_data.p_data == NULL) &&
02066         (p_context->context_data.len < DM_GATT_SERVER_ATTR_MAX_SIZE))
02067     {
02068         if (p_context->service_type == DM_PROTOCOL_CNTXT_GATT_SRVR_ID)
02069         {
02070             p_context->context_data.p_data = m_gatts_table[p_handle->connection_id].attributes;
02071             p_context->context_data.len    = m_gatts_table[p_handle->connection_id].size;
02072         }
02073     }
02074 
02075     pstorage_handle_t block_handle;
02076     uint32_t          err_code = pstorage_block_identifier_get(&m_storage_handle,
02077                                                                p_handle->device_id,
02078                                                                &block_handle);
02079 
02080     err_code = m_service_context_load[p_context->service_type](&block_handle, p_handle);
02081 
02082     DM_TRC("[DM]: << dm_service_context_get\r\n");
02083 
02084     DM_MUTEX_UNLOCK();
02085 
02086     return err_code;
02087 }
02088 
02089 
02090 ret_code_t dm_service_context_delete(dm_handle_t const * p_handle)
02091 {
02092     VERIFY_MODULE_INITIALIZED();
02093     NULL_PARAM_CHECK(p_handle);
02094     VERIFY_APP_REGISTERED(p_handle->appl_id);
02095     VERIFY_DEVICE_INSTANCE(p_handle->device_id);
02096 
02097     DM_LOG("[DM]: Context delete is not supported yet.\r\n");
02098 
02099     return (API_NOT_IMPLEMENTED | DEVICE_MANAGER_ERR_BASE);
02100 }
02101 
02102 
02103 ret_code_t dm_application_context_set(dm_handle_t const              * p_handle,
02104                                       dm_application_context_t const * p_context)
02105 {
02106 #if (DEVICE_MANAGER_APP_CONTEXT_SIZE != 0)
02107     VERIFY_MODULE_INITIALIZED();
02108     NULL_PARAM_CHECK(p_handle);
02109     NULL_PARAM_CHECK(p_context);
02110     NULL_PARAM_CHECK(p_context->p_data);
02111     VERIFY_APP_REGISTERED(p_handle->appl_id);
02112     VERIFY_DEVICE_INSTANCE(p_handle->device_id);
02113     VERIFY_DEVICE_BOND(p_handle->connection_id);
02114     SIZE_CHECK_APP_CONTEXT(p_context->len);
02115 
02116     DM_MUTEX_LOCK();
02117 
02118     DM_TRC("[DM]: >> dm_application_context_set\r\n");
02119 
02120     uint32_t          err_code;
02121     uint32_t          context_len;
02122     pstorage_handle_t block_handle;
02123 
02124     storage_operation store_fn = pstorage_store;
02125 
02126     err_code = pstorage_block_identifier_get(&m_storage_handle,
02127                                              p_handle->device_id,
02128                                              &block_handle);
02129 
02130     if (err_code == NRF_SUCCESS)
02131     {
02132         err_code = pstorage_load((uint8_t *)&context_len,
02133                                  &block_handle,
02134                                  sizeof(uint32_t),
02135                                  APP_CONTEXT_STORAGE_OFFSET);
02136 
02137         if ((err_code == NRF_SUCCESS) && (context_len != INVALID_CONTEXT_LEN))
02138         {
02139             //Data already exists. Need an update.
02140             store_fn = pstorage_update;
02141 
02142             DM_LOG("[DM]:[DI 0x%02X]: Updating existing application context, existing len 0x%08X, "
02143                    "new length 0x%08X.\r\n",
02144                    p_handle->device_id,
02145                    context_len,
02146                    p_context->len);
02147         }
02148         else
02149         {
02150             DM_LOG("[DM]: Storing application context.\r\n");
02151         }
02152 
02153         //Store/update context length.
02154         err_code = store_fn(&block_handle,
02155                             (uint8_t *)(&p_context->len),
02156                             sizeof(uint32_t),
02157                             APP_CONTEXT_STORAGE_OFFSET);
02158 
02159         if (err_code == NRF_SUCCESS)
02160         {
02161             //Update context data is used for application context as flash is never
02162             //cleared if a delete of application context is called.
02163             err_code = pstorage_update(&block_handle,
02164                                        p_context->p_data,
02165                                        DEVICE_MANAGER_APP_CONTEXT_SIZE,
02166                                        (APP_CONTEXT_STORAGE_OFFSET + sizeof(uint32_t)));
02167             if (err_code == NRF_SUCCESS)
02168             {
02169                 m_app_context_table[p_handle->device_id] = p_context->p_data;
02170             }
02171         }
02172     }
02173 
02174     DM_TRC("[DM]: << dm_application_context_set\r\n");
02175 
02176     DM_MUTEX_UNLOCK();
02177 
02178     return err_code;
02179 
02180 #else //DEVICE_MANAGER_APP_CONTEXT_SIZE
02181     return (FEATURE_NOT_ENABLED | DEVICE_MANAGER_ERR_BASE);
02182 #endif //DEVICE_MANAGER_APP_CONTEXT_SIZE
02183 }
02184 
02185 
02186 ret_code_t dm_application_context_get(dm_handle_t const        * p_handle,
02187                                       dm_application_context_t * p_context)
02188 {
02189 #if (DEVICE_MANAGER_APP_CONTEXT_SIZE != 0)
02190     VERIFY_MODULE_INITIALIZED();
02191     NULL_PARAM_CHECK(p_handle);
02192     NULL_PARAM_CHECK(p_context);
02193     VERIFY_APP_REGISTERED(p_handle->appl_id);
02194     VERIFY_DEVICE_INSTANCE(p_handle->device_id);
02195 
02196     DM_MUTEX_LOCK();
02197 
02198     DM_TRC("[DM]: >> dm_application_context_get\r\n");
02199 
02200     uint32_t          context_len;
02201     uint32_t          err_code;
02202     pstorage_handle_t block_handle;
02203 
02204     //Check if the context exists.
02205     if (NULL == p_context->p_data)
02206     {
02207         p_context->p_data = m_app_context_table[p_handle->device_id];
02208     }
02209     else
02210     {
02211         m_app_context_table[p_handle->device_id] = p_context->p_data;
02212     }
02213 
02214     err_code = pstorage_block_identifier_get(&m_storage_handle,
02215                                              p_handle->device_id,
02216                                              &block_handle);
02217 
02218     if (err_code == NRF_SUCCESS)
02219     {
02220         err_code = pstorage_load((uint8_t *)&context_len,
02221                                  &block_handle,
02222                                  sizeof(uint32_t),
02223                                  APP_CONTEXT_STORAGE_OFFSET);
02224 
02225         if ((err_code == NRF_SUCCESS) && (context_len != INVALID_CONTEXT_LEN))
02226         {
02227             err_code = pstorage_load(p_context->p_data,
02228                                      &block_handle,
02229                                      DEVICE_MANAGER_APP_CONTEXT_SIZE,
02230                                      (APP_CONTEXT_STORAGE_OFFSET + sizeof(uint32_t)));
02231             if (err_code == NRF_SUCCESS)
02232             {
02233                 p_context->len = context_len;
02234             }
02235         }
02236         else
02237         {
02238             err_code = DM_NO_APP_CONTEXT;
02239         }
02240     }
02241 
02242     DM_TRC("[DM]: << dm_application_context_get\r\n");
02243 
02244     DM_MUTEX_UNLOCK();
02245 
02246     return err_code;
02247 
02248 #else //DEVICE_MANAGER_APP_CONTEXT_SIZE
02249     return (FEATURE_NOT_ENABLED | DEVICE_MANAGER_ERR_BASE);
02250 #endif //DEVICE_MANAGER_APP_CONTEXT_SIZE
02251 }
02252 
02253 
02254 ret_code_t dm_application_context_delete(const dm_handle_t * p_handle)
02255 {
02256 #if (DEVICE_MANAGER_APP_CONTEXT_SIZE != 0)
02257     VERIFY_MODULE_INITIALIZED();
02258     NULL_PARAM_CHECK(p_handle);
02259     VERIFY_APP_REGISTERED(p_handle->appl_id);
02260     VERIFY_DEVICE_INSTANCE(p_handle->device_id);
02261 
02262     DM_MUTEX_LOCK();
02263 
02264     DM_TRC("[DM]: >> dm_application_context_delete\r\n");
02265 
02266     uint32_t          err_code;
02267     uint32_t          context_len;
02268     pstorage_handle_t block_handle;
02269 
02270     err_code = pstorage_block_identifier_get(&m_storage_handle,
02271                                              p_handle->device_id,
02272                                              &block_handle);
02273 
02274     if (err_code == NRF_SUCCESS)
02275     {
02276         err_code = pstorage_load((uint8_t *)&context_len,
02277                                  &block_handle,
02278                                  sizeof(uint32_t),
02279                                  APP_CONTEXT_STORAGE_OFFSET);
02280 
02281         if (context_len != m_context_init_len)
02282         {
02283             err_code = pstorage_update(&block_handle,
02284                                        (uint8_t *)&m_context_init_len,
02285                                        sizeof(uint32_t),
02286                                        APP_CONTEXT_STORAGE_OFFSET);
02287 
02288             if (err_code != NRF_SUCCESS)
02289             {
02290                 DM_ERR("[DM]: Failed to delete application context, reason 0x%08X\r\n", err_code);
02291             }
02292             else
02293             {
02294                 m_app_context_table[p_handle->device_id] = NULL;
02295             }
02296         }
02297     }
02298 
02299     DM_TRC("[DM]: << dm_application_context_delete\r\n");
02300 
02301     DM_MUTEX_UNLOCK();
02302 
02303     return err_code;
02304 #else //DEVICE_MANAGER_APP_CONTEXT_SIZE
02305     return (FEATURE_NOT_ENABLED | DEVICE_MANAGER_ERR_BASE);
02306 #endif //DEVICE_MANAGER_APP_CONTEXT_SIZE
02307 }
02308 
02309 
02310 ret_code_t dm_application_instance_set(dm_application_instance_t const * p_appl_instance,
02311                                        dm_handle_t                     * p_handle)
02312 {
02313     VERIFY_MODULE_INITIALIZED();
02314     NULL_PARAM_CHECK(p_handle);
02315     NULL_PARAM_CHECK(p_appl_instance);
02316     VERIFY_APP_REGISTERED((*p_appl_instance));
02317 
02318     p_handle->appl_id = (*p_appl_instance);
02319 
02320     return NRF_SUCCESS;
02321 }
02322 
02323 
02324 uint32_t dm_handle_initialize(dm_handle_t * p_handle)
02325 {
02326     NULL_PARAM_CHECK(p_handle);
02327 
02328     p_handle->appl_id       = DM_INVALID_ID;
02329     p_handle->connection_id = DM_INVALID_ID;
02330     p_handle->device_id     = DM_INVALID_ID;
02331     p_handle->service_id    = DM_INVALID_ID;
02332 
02333     return NRF_SUCCESS;
02334 }
02335 
02336 
02337 ret_code_t dm_peer_addr_set(dm_handle_t const    * p_handle,
02338                             ble_gap_addr_t const * p_addr)
02339 {
02340     VERIFY_MODULE_INITIALIZED();
02341     NULL_PARAM_CHECK(p_handle);
02342     NULL_PARAM_CHECK(p_addr);
02343     VERIFY_APP_REGISTERED(p_handle->appl_id);
02344     VERIFY_DEVICE_INSTANCE(p_handle->device_id);
02345 
02346     DM_MUTEX_LOCK();
02347 
02348     DM_TRC("[DM]: >> dm_peer_addr_set\r\n");
02349 
02350     ret_code_t err_code;
02351 
02352     if ((p_handle->connection_id == DM_INVALID_ID) &&
02353         (p_addr->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE))
02354     {
02355         m_peer_table[p_handle->device_id].peer_id.id_addr_info = (*p_addr);
02356         update_status_bit_set(p_handle->device_id);
02357         device_context_store(p_handle, UPDATE_PEER_ADDR);
02358         err_code = NRF_SUCCESS;
02359     }
02360     else
02361     {
02362         err_code = (NRF_ERROR_INVALID_PARAM | DEVICE_MANAGER_ERR_BASE);
02363     }
02364 
02365     DM_TRC("[DM]: << dm_peer_addr_set\r\n");
02366 
02367     DM_MUTEX_UNLOCK();
02368 
02369     return err_code;
02370 }
02371 
02372 
02373 ret_code_t dm_peer_addr_get(dm_handle_t const * p_handle,
02374                             ble_gap_addr_t    * p_addr)
02375 {
02376     VERIFY_MODULE_INITIALIZED();
02377     NULL_PARAM_CHECK(p_handle);
02378     NULL_PARAM_CHECK(p_addr);
02379     VERIFY_APP_REGISTERED(p_handle->appl_id);
02380 
02381     DM_MUTEX_LOCK();
02382 
02383     DM_TRC("[DM]: >> dm_peer_addr_get\r\n");
02384 
02385     ret_code_t err_code;
02386 
02387     err_code = (NRF_ERROR_NOT_FOUND | DEVICE_MANAGER_ERR_BASE);
02388 
02389     if (p_handle->device_id == DM_INVALID_ID)
02390     {
02391         if ((p_handle->connection_id != DM_INVALID_ID) &&
02392             ((m_connection_table[p_handle->connection_id].state & STATE_CONNECTED) ==
02393              STATE_CONNECTED))
02394         {
02395             DM_TRC("[DM]:[CI 0x%02X]: Address get for non bonded active connection.\r\n",
02396                    p_handle->connection_id);
02397 
02398             (*p_addr) = m_connection_table[p_handle->connection_id].peer_addr;
02399             err_code  = NRF_SUCCESS;
02400         }
02401     }
02402     else
02403     {
02404         if ((m_peer_table[p_handle->device_id].id_bitmap & ADDR_ENTRY) == 0)
02405         {
02406             DM_TRC("[DM]:[DI 0x%02X]: Address get for bonded device.\r\n",
02407                    p_handle->device_id);
02408 
02409             (*p_addr) = m_peer_table[p_handle->device_id].peer_id.id_addr_info;
02410             err_code  = NRF_SUCCESS;
02411         }
02412     }
02413 
02414     DM_TRC("[DM]: << dm_peer_addr_get\r\n");
02415 
02416     DM_MUTEX_UNLOCK();
02417 
02418     return err_code;
02419 }
02420 
02421 
02422 ret_code_t dm_distributed_keys_get(dm_handle_t const * p_handle,
02423                                    dm_sec_keyset_t   * p_key_dist)
02424 {
02425     VERIFY_MODULE_INITIALIZED();
02426     NULL_PARAM_CHECK(p_handle);
02427     NULL_PARAM_CHECK(p_key_dist);
02428     VERIFY_APP_REGISTERED(p_handle->appl_id);
02429     VERIFY_DEVICE_INSTANCE(p_handle->device_id);
02430 
02431     DM_MUTEX_LOCK();
02432 
02433     DM_TRC("[DM]: >> dm_distributed_keys_get\r\n");
02434 
02435     ret_code_t        err_code;
02436     ble_gap_enc_key_t peer_enc_key;
02437     pstorage_handle_t block_handle;
02438 
02439     err_code                                   = NRF_ERROR_NOT_FOUND;
02440     p_key_dist->keys_central.enc_key.p_enc_key = NULL;
02441     p_key_dist->keys_central.p_id_key          = (dm_id_key_t *)&m_peer_table[p_handle->device_id].peer_id;
02442     p_key_dist->keys_central.p_sign_key        = NULL;
02443     p_key_dist->keys_periph.p_id_key           = (dm_id_key_t *)&m_local_id_info;
02444     p_key_dist->keys_periph.p_sign_key         = NULL;
02445     p_key_dist->keys_periph.enc_key.p_enc_key  = (dm_enc_key_t *)&peer_enc_key;
02446 
02447     if ((m_peer_table[p_handle->device_id].id_bitmap & IRK_ENTRY) == 0)
02448     {
02449 //        p_key_dist->keys_periph.p_id_key->id_addr_info.addr_type = INVALID_ADDR_TYPE;
02450     }
02451 
02452     err_code = pstorage_block_identifier_get(&m_storage_handle, p_handle->device_id, &block_handle);
02453     if (err_code == NRF_SUCCESS)
02454     {
02455 
02456         err_code = pstorage_load((uint8_t *)&peer_enc_key,
02457                                  &block_handle,
02458                                  BOND_SIZE,
02459                                  BOND_STORAGE_OFFSET);
02460 
02461         if (err_code == NRF_SUCCESS)
02462         {
02463             p_key_dist->keys_central.enc_key.p_enc_key = NULL;
02464             p_key_dist->keys_central.p_id_key          = (dm_id_key_t *)&m_peer_table[p_handle->device_id].peer_id;
02465             p_key_dist->keys_central.p_sign_key        = NULL;
02466             p_key_dist->keys_periph.p_id_key           = (dm_id_key_t *)&m_local_id_info;
02467             p_key_dist->keys_periph.p_sign_key         = NULL;
02468             p_key_dist->keys_periph.enc_key.p_enc_key  = (dm_enc_key_t *)&peer_enc_key;
02469         }
02470     }
02471 
02472     DM_TRC("[DM]: << dm_distributed_keys_get\r\n");
02473 
02474     DM_MUTEX_UNLOCK();
02475 
02476     return err_code;
02477 }
02478 
02479 
02480 /**@brief Function for loading bond information for a connection instance.
02481  */
02482 void bond_data_load(dm_handle_t * p_handle)
02483 {
02484     pstorage_handle_t block_handle;
02485 
02486     uint32_t err_code = pstorage_block_identifier_get(&m_storage_handle,
02487                                                        p_handle->device_id,
02488                                                        &block_handle);
02489     if (err_code == NRF_SUCCESS)
02490     {
02491         DM_LOG(
02492             "[DM]:[%02X]:[Block ID 0x%08X]:Loading bond information at %p, size 0x%08X, offset 0x%08X.\r\n",
02493             p_handle->connection_id,
02494             block_handle.block_id,
02495             &m_bond_table[p_handle->connection_id],
02496             BOND_SIZE,
02497             BOND_STORAGE_OFFSET);
02498 
02499         err_code = pstorage_load((uint8_t *)&m_bond_table[p_handle->connection_id],
02500                                  &block_handle,
02501                                  BOND_SIZE,
02502                                  BOND_STORAGE_OFFSET);
02503 
02504         if (err_code != NRF_SUCCESS)
02505         {
02506             DM_ERR("[DM]:[%02X]: Failed to load Bond information, reason %08X\r\n",
02507                    p_handle->connection_id,
02508                    err_code);
02509         }
02510 
02511         DM_LOG(
02512             "[DM]:[%02X]:Loading service context at %p, size 0x%08X, offset 0x%08X.\r\n",
02513             p_handle->connection_id,
02514             &m_gatts_table[p_handle->connection_id],
02515             sizeof(dm_gatts_context_t),
02516             SERVICE_STORAGE_OFFSET);
02517 
02518         err_code = m_service_context_load[m_application_table[0].service](
02519             &block_handle,
02520             p_handle);
02521 
02522         if (err_code != NRF_SUCCESS)
02523         {
02524             DM_ERR(
02525                 "[DM]:[%02X]: Failed to load service information, reason %08X\r\n",
02526                 p_handle->connection_id,
02527                 err_code);
02528         }
02529     }
02530     else
02531     {
02532         DM_ERR("[DM]:[%02X]: Failed to get block identifier for "
02533                "device %08X, reason %08X.\r\n", p_handle->connection_id, p_handle->device_id, err_code);
02534     }
02535 }
02536 
02537 
02538 void dm_ble_evt_handler(ble_evt_t * p_ble_evt)
02539 {
02540     uint32_t    err_code;
02541     uint32_t    index;
02542     uint32_t    device_index        = DM_INVALID_ID;
02543     bool        notify_app          = false;
02544     dm_handle_t handle;
02545     dm_event_t  event;
02546     uint32_t    event_result;
02547     ble_gap_enc_info_t * p_enc_info = NULL;
02548 
02549     VERIFY_MODULE_INITIALIZED_VOID();
02550     VERIFY_APP_REGISTERED_VOID(0);
02551     DM_MUTEX_LOCK();
02552 
02553     err_code = dm_handle_initialize(&handle);
02554     APP_ERROR_CHECK(err_code);
02555 
02556     event_result                    = NRF_SUCCESS;
02557     err_code                        = NRF_SUCCESS;
02558     event.event_param.p_gap_param   = &p_ble_evt->evt.gap_evt;
02559     event.event_paramlen            = sizeof(ble_gap_evt_t);
02560     handle.device_id                = DM_INVALID_ID;
02561     handle.appl_id                  = 0;
02562     index                           = 0x00;
02563 
02564     if (p_ble_evt->header.evt_id != BLE_GAP_EVT_CONNECTED)
02565     {
02566         err_code = connection_instance_find(p_ble_evt->evt.gap_evt.conn_handle,
02567                                             STATE_CONNECTED,
02568                                             &index);
02569 
02570         if (err_code == NRF_SUCCESS)
02571         {
02572             handle.device_id     = m_connection_table[index].bonded_dev_id;
02573             handle.connection_id = index;
02574         }
02575     }
02576 
02577     switch (p_ble_evt->header.evt_id)
02578     {
02579         case BLE_GAP_EVT_CONNECTED:
02580             //Allocate connection instance for a new connection.
02581             err_code = connection_instance_allocate(&index);
02582 
02583             //Connection instance is successfully allocated.
02584             if (err_code == NRF_SUCCESS)
02585             {
02586                 //Application notification related information.
02587                 notify_app           = true;
02588                 event.event_id       = DM_EVT_CONNECTION;
02589                 handle.connection_id = index;
02590 
02591                 m_connection_table[index].conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
02592                 m_connection_table[index].state       = STATE_CONNECTED;
02593                 m_connection_table[index].peer_addr   =
02594                     p_ble_evt->evt.gap_evt.params.connected.peer_addr;
02595 
02596                 if (p_ble_evt->evt.gap_evt.params.connected.irk_match == 1)
02597                 {
02598                     if (m_irk_index_table[p_ble_evt->evt.gap_evt.params.connected.irk_match_idx] != DM_INVALID_ID)
02599                     {
02600                         device_index = m_irk_index_table[p_ble_evt->evt.gap_evt.params.connected.irk_match_idx];
02601                         err_code = NRF_SUCCESS;
02602                     }
02603                 }
02604                 else
02605                 {
02606                     //Use the device address to check if the device exists in the bonded device list.
02607                     err_code = device_instance_find(&p_ble_evt->evt.gap_evt.params.connected.peer_addr,
02608                                                     &device_index, EDIV_INIT_VAL);
02609                 }
02610 
02611                 if (err_code == NRF_SUCCESS)
02612                 {
02613                     m_connection_table[index].bonded_dev_id = device_index;
02614                     m_connection_table[index].state        |= STATE_BONDED;
02615                     handle.device_id                        = device_index;
02616 
02617                     bond_data_load(&handle);
02618                 }
02619             }
02620             break;
02621 
02622         case BLE_GAP_EVT_DISCONNECTED:
02623             //Disconnection could be peer or self initiated hence disconnecting and connecting
02624             //both states are permitted, however, connection handle must be known.
02625             DM_LOG("[DM]: Disconnect Reason 0x%04X\r\n",
02626                    p_ble_evt->evt.gap_evt.params.disconnected.reason);
02627 
02628             m_connection_table[index].state &= (~STATE_CONNECTED);
02629 
02630             if ((m_connection_table[index].state & STATE_BONDED) == STATE_BONDED)
02631             {
02632                 if ((m_connection_table[index].state & STATE_LINK_ENCRYPTED) == STATE_LINK_ENCRYPTED)
02633                 {
02634                     //Write bond information persistently.
02635                     device_context_store(&handle, STORE_ALL_CONTEXT);
02636                 }
02637             }
02638             else
02639             {
02640                 //Free any allocated instances for devices that is not bonded.
02641                 if (handle.device_id != DM_INVALID_ID)
02642                 {
02643                     peer_instance_init(handle.device_id);
02644                     handle.device_id = DM_INVALID_ID;
02645                 }
02646             }
02647 
02648             m_connection_table[index].state = STATE_DISCONNECTING;
02649             notify_app                      = true;
02650             event.event_id                  = DM_EVT_DISCONNECTION;
02651 
02652             break;
02653 
02654         case BLE_GAP_EVT_SEC_INFO_REQUEST:
02655             DM_LOG("[DM]: >> BLE_GAP_EVT_SEC_INFO_REQUEST\r\n");
02656 
02657             //If the device is already bonded, respond with existing info, else NULL.
02658             if (m_connection_table[index].bonded_dev_id == DM_INVALID_ID)
02659             {
02660                 //Find device based on div.
02661                 err_code = device_instance_find(NULL,&device_index, p_ble_evt->evt.gap_evt.params.sec_info_request.master_id.ediv);
02662                 if (err_code == NRF_SUCCESS)
02663                 {
02664                     //Load needed bonding information.
02665                     m_connection_table[index].bonded_dev_id = device_index;
02666                     m_connection_table[index].state        |= STATE_BONDED;
02667                     handle.device_id                        = device_index;
02668                     bond_data_load(&handle);
02669                 }
02670             }
02671 
02672             if (m_connection_table[index].bonded_dev_id != DM_INVALID_ID)
02673             {
02674                 p_enc_info = &m_bond_table[index].peer_enc_key.enc_info;
02675                 DM_DUMP((uint8_t *)p_enc_info, sizeof(ble_gap_enc_info_t));
02676             }
02677 
02678             err_code = sd_ble_gap_sec_info_reply(p_ble_evt->evt.gap_evt.conn_handle,
02679                                                  p_enc_info,
02680                                                  &m_peer_table[index].peer_id.id_info,
02681                                                  NULL);
02682 
02683             if (err_code != NRF_SUCCESS)
02684             {
02685                 DM_ERR("[DM]:[CI %02X]:[DI %02X]: Security information response failed, reason "
02686                        "0x%08X\r\n", index, m_connection_table[index].bonded_dev_id, err_code);
02687             }
02688             break;
02689 
02690         case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
02691             DM_LOG("[DM]: >> BLE_GAP_EVT_SEC_PARAMS_REQUEST\r\n");
02692 
02693             event.event_id = DM_EVT_SECURITY_SETUP;
02694 
02695             m_connection_table[index].state |= STATE_PAIRING;
02696             notify_app                       = true;
02697 
02698             if (m_connection_table[index].bonded_dev_id == DM_INVALID_ID)
02699             {
02700                 //Assign a peer index as a new bond or update existing bonds.
02701                 err_code = device_instance_allocate((uint8_t *)&device_index,
02702                                                     &m_connection_table[index].peer_addr);
02703 
02704                 //Allocation successful.
02705                 if (err_code == NRF_SUCCESS)
02706                 {
02707                     DM_LOG("[DM]:[CI 0x%02X]:[DI 0x%02X]: Bonded!\r\n",index, device_index);
02708 
02709                     handle.device_id                        = device_index;
02710                     m_connection_table[index].bonded_dev_id = device_index;
02711                 }
02712                 else
02713                 {
02714                     DM_LOG("[DM]: Security parameter request failed, reason 0x%08X.\r\n", err_code);
02715                     event_result = err_code;
02716                     notify_app   = true;
02717                 }
02718             }
02719             else
02720             {
02721                 //Bond/key refresh.
02722                 event.event_id = DM_EVT_SECURITY_SETUP_REFRESH;
02723                 memset(m_gatts_table[index].attributes, 0, DM_GATT_SERVER_ATTR_MAX_SIZE);
02724 
02725                 //Set the update flag for bond data.
02726                 m_connection_table[index].state |= STATE_BOND_INFO_UPDATE;
02727             }
02728 
02729             ble_gap_sec_keyset_t keys_exchanged;
02730 
02731             DM_LOG("[DM]: 0x%02X, 0x%02X, 0x%02X, 0x%02X\r\n",
02732                    p_ble_evt->evt.gap_evt.params.sec_params_request.peer_params.kdist_periph.enc,
02733                    p_ble_evt->evt.gap_evt.params.sec_params_request.peer_params.kdist_central.id,
02734                    p_ble_evt->evt.gap_evt.params.sec_params_request.peer_params.kdist_periph.sign,
02735                    p_ble_evt->evt.gap_evt.params.sec_params_request.peer_params.bond);
02736 
02737             keys_exchanged.keys_central.p_enc_key  = NULL;
02738             keys_exchanged.keys_central.p_id_key   = &m_peer_table[m_connection_table[index].bonded_dev_id].peer_id; 
02739             keys_exchanged.keys_central.p_sign_key = NULL;
02740             keys_exchanged.keys_periph.p_enc_key   = &m_bond_table[index].peer_enc_key;
02741             keys_exchanged.keys_periph.p_id_key    = NULL;
02742             keys_exchanged.keys_periph.p_sign_key  = NULL;
02743 
02744             err_code = sd_ble_gap_sec_params_reply(p_ble_evt->evt.gap_evt.conn_handle,
02745                                                    BLE_GAP_SEC_STATUS_SUCCESS,
02746                                                    &m_application_table[0].sec_param, 
02747                                                    &keys_exchanged);
02748 
02749             if (err_code != NRF_SUCCESS)
02750             {
02751                 DM_LOG("[DM]: Security parameter reply request failed, reason 0x%08X.\r\n", err_code);
02752                 event_result = err_code;
02753                 notify_app   = false;
02754             }
02755             break;
02756 
02757         case BLE_GAP_EVT_AUTH_STATUS:
02758         {
02759             DM_LOG("[DM]: >> BLE_GAP_EVT_AUTH_STATUS, status %08X\r\n",
02760                    p_ble_evt->evt.gap_evt.params.auth_status.auth_status);
02761 
02762             m_application_table[0].state    &= (~STATE_CONTROL_PROCEDURE_IN_PROGRESS);
02763             m_connection_table[index].state &= (~STATE_PAIRING);
02764             event.event_id                   = DM_EVT_SECURITY_SETUP_COMPLETE;
02765             notify_app                       = true;
02766 
02767             if (p_ble_evt->evt.gap_evt.params.auth_status.auth_status != BLE_GAP_SEC_STATUS_SUCCESS)
02768             {
02769                 // Free the allocation as bonding failed.
02770                 ret_code_t result = device_instance_free(m_connection_table[index].bonded_dev_id);
02771                 (void) result;
02772                 event_result = p_ble_evt->evt.gap_evt.params.auth_status.auth_status;
02773             }
02774             else
02775             {
02776                 DM_DUMP((uint8_t *)&p_ble_evt->evt.gap_evt.params.auth_status,
02777                         sizeof(ble_gap_evt_auth_status_t));
02778                 DM_DUMP((uint8_t *)&m_bond_table[index], sizeof(bond_context_t));
02779 
02780                 if (p_ble_evt->evt.gap_evt.params.auth_status.bonded == 1)
02781                 {
02782                     if (handle.device_id != DM_INVALID_ID)
02783                     {
02784                         m_connection_table[index].state |= STATE_BONDED;
02785 
02786                         //IRK and/or public address is shared, update it.
02787                         if (p_ble_evt->evt.gap_evt.params.auth_status.kdist_central.id == 1)
02788                         {
02789                             m_peer_table[handle.device_id].id_bitmap &= (~IRK_ENTRY);
02790                         }
02791 
02792                         if (m_connection_table[index].bonded_dev_id != DM_INVALID_ID)
02793                         {
02794                             DM_LOG("[DM]:[CI 0x%02X]:[DI 0x%02X]: Bonded!\r\n",
02795                                    index,
02796                                    handle.device_id);
02797 
02798                             if (m_connection_table[index].peer_addr.addr_type !=
02799                                 BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE)
02800                             {
02801                                m_peer_table[handle.device_id].peer_id.id_addr_info =
02802                                     m_connection_table[index].peer_addr;
02803                                m_peer_table[handle.device_id].id_bitmap &= (~ADDR_ENTRY);
02804 
02805                                DM_DUMP((uint8_t *)&m_peer_table[handle.device_id].peer_id.id_addr_info,
02806                                        sizeof(m_peer_table[handle.device_id].peer_id.id_addr_info));
02807                             }
02808                             else
02809                             {
02810                                 // Here we must fetch the keys from the keyset distributed.
02811                                 m_peer_table[handle.device_id].ediv       = m_bond_table[index].peer_enc_key.master_id.ediv;
02812                                 m_peer_table[handle.device_id].id_bitmap &= (~IRK_ENTRY);
02813                             }
02814 
02815                             device_context_store(&handle, FIRST_BOND_STORE);
02816                         }
02817                     }
02818                 }
02819                 else
02820                 {
02821                     //Pairing request, no need to touch the bonding info.
02822                 }
02823             }
02824             break;
02825         }
02826 
02827         case BLE_GAP_EVT_CONN_SEC_UPDATE:
02828             DM_LOG("[DM]: >> BLE_GAP_EVT_CONN_SEC_UPDATE, Mode 0x%02X, Level 0x%02X\r\n",
02829                    p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.sm,
02830                    p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv);
02831 
02832             if ((p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv == 1) &&
02833                 (p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.sm == 1) &&
02834                 ((m_connection_table[index].state & STATE_BONDED) == STATE_BONDED))
02835             {
02836                 //Lost bond case, generate a security refresh event!
02837                 memset(m_gatts_table[index].attributes, 0, DM_GATT_SERVER_ATTR_MAX_SIZE);
02838                 
02839                 event.event_id                   = DM_EVT_SECURITY_SETUP_REFRESH;
02840                 m_connection_table[index].state |= STATE_PAIRING_PENDING;
02841                 m_connection_table[index].state |= STATE_BOND_INFO_UPDATE;
02842                 m_application_table[0].state    |= STATE_QUEUED_CONTROL_REQUEST;
02843             }
02844             else
02845             {
02846                 m_connection_table[index].state |= STATE_LINK_ENCRYPTED;
02847                 event.event_id                   = DM_EVT_LINK_SECURED;
02848 
02849                 //Apply service context.
02850                 err_code = m_service_context_apply[m_application_table[0].service](&handle);
02851 
02852                 if (err_code != NRF_SUCCESS)
02853                 {
02854                     DM_ERR("[DM]:[CI 0x%02X]:[DI 0x%02X]: Failed to apply service context\r\n",
02855                             handle.connection_id, 
02856                             handle.device_id);
02857 
02858                     event_result = DM_SERVICE_CONTEXT_NOT_APPLIED;
02859                 }
02860             }
02861             event_result = NRF_SUCCESS;
02862             notify_app   = true;
02863             
02864             break;
02865 
02866         case BLE_GATTS_EVT_SYS_ATTR_MISSING:
02867             DM_LOG("[DM]: >> BLE_GATTS_EVT_SYS_ATTR_MISSING\r\n");
02868 
02869             //Apply service context.
02870             event_result = m_service_context_apply[m_application_table[0].service](&handle);
02871             break;
02872 
02873         case BLE_GAP_EVT_SEC_REQUEST:
02874             DM_LOG("[DM]: >> BLE_GAP_EVT_SEC_REQUEST\r\n");
02875             
02876             //Verify if the device is already bonded, and if it is bonded, initiate encryption.
02877             //If the device is not bonded, an instance needs to be allocated in order to initiate 
02878             //bonding. The application have to initiate the procedure, the module will not do this 
02879             //automatically.
02880             event.event_id = DM_EVT_SECURITY_SETUP;
02881             notify_app     = true;
02882             
02883             break;
02884 
02885         default:
02886             break;
02887     }
02888 
02889     if (notify_app)
02890     {
02891         app_evt_notify(&handle, &event, event_result);
02892 
02893         //Freeing the instance after the event is notified so the application can get the context.
02894         if (event.event_id == DM_EVT_DISCONNECTION)
02895         {
02896             //Free the instance.
02897             connection_instance_free(&index);
02898         }
02899     }
02900 
02901     UNUSED_VARIABLE(err_code);
02902 
02903     DM_MUTEX_UNLOCK();
02904 }
02905 
02906 
02907 ret_code_t dm_handle_get(uint16_t conn_handle, dm_handle_t * p_handle)
02908 {
02909     ret_code_t err_code;
02910     uint32_t   index;
02911 
02912     NULL_PARAM_CHECK(p_handle);
02913     VERIFY_APP_REGISTERED(p_handle->appl_id);
02914 
02915     p_handle->device_id  = DM_INVALID_ID;
02916 
02917     err_code = NRF_ERROR_NOT_FOUND;
02918 
02919     for (index = 0; index < DEVICE_MANAGER_MAX_CONNECTIONS; index++)
02920     {
02921         //Search for matching connection handle.
02922         if (conn_handle == m_connection_table[index].conn_handle)
02923         {
02924             p_handle->connection_id = index;
02925             p_handle->device_id     = m_connection_table[index].bonded_dev_id;
02926 
02927             err_code = NRF_SUCCESS;
02928             break;
02929         }
02930     }
02931     return err_code;
02932 }