from bbc microbit library

Fork of nrf51-sdk by Lancaster University

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers device_manager_peripheral.c Source File

device_manager_peripheral.c

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