David Kester / nRF51822

Dependents:   GonioTrainer

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