Glimworm Beacons / nRF51822

Fork of nRF51822 by Nordic Semiconductor

Committer:
rgrover1
Date:
Thu Apr 30 08:34:38 2015 +0100
Revision:
116:fa7257f1c455
Parent:
112:737b08b3b995
Child:
343:6675661fa600
Synchronized with git rev 0466f80d
Author: Rohit Grover
remove references to app_trace from device_manager_peripheral

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 112:737b08b3b995 1 /* Copyright (C) 2013 Nordic Semiconductor. All Rights Reserved.
rgrover1 112:737b08b3b995 2 *
rgrover1 112:737b08b3b995 3 * The information contained herein is property of Nordic Semiconductor ASA.
rgrover1 112:737b08b3b995 4 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
rgrover1 112:737b08b3b995 5 *
rgrover1 112:737b08b3b995 6 * Licensees are granted free, non-transferable use of the information. NO
rgrover1 112:737b08b3b995 7 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
rgrover1 112:737b08b3b995 8 * the file.
rgrover1 112:737b08b3b995 9 *
rgrover1 112:737b08b3b995 10 */
rgrover1 112:737b08b3b995 11
rgrover1 112:737b08b3b995 12 #include "device_manager.h"
rgrover1 116:fa7257f1c455 13 // #include "app_trace.h"
rgrover1 112:737b08b3b995 14 #include "pstorage.h"
rgrover1 112:737b08b3b995 15 #include "ble_hci.h"
rgrover1 112:737b08b3b995 16 #include "app_error.h"
rgrover1 112:737b08b3b995 17
rgrover1 112:737b08b3b995 18 #if defined ( __CC_ARM )
rgrover1 112:737b08b3b995 19 #ifndef __ALIGN
rgrover1 112:737b08b3b995 20 #define __ALIGN(x) __align(x) /**< Forced aligment keyword for ARM Compiler */
rgrover1 112:737b08b3b995 21 #endif
rgrover1 112:737b08b3b995 22 #elif defined ( __ICCARM__ )
rgrover1 112:737b08b3b995 23 #ifndef __ALIGN
rgrover1 112:737b08b3b995 24 #define __ALIGN(x) /**< Forced aligment keyword for IAR Compiler */
rgrover1 112:737b08b3b995 25 #endif
rgrover1 112:737b08b3b995 26 #elif defined ( __GNUC__ )
rgrover1 112:737b08b3b995 27 #ifndef __ALIGN
rgrover1 112:737b08b3b995 28 #define __ALIGN(x) __attribute__((aligned(x))) /**< Forced aligment keyword for GNU Compiler */
rgrover1 112:737b08b3b995 29 #endif
rgrover1 112:737b08b3b995 30 #endif
rgrover1 112:737b08b3b995 31
rgrover1 112:737b08b3b995 32 #define INVALID_ADDR_TYPE 0xFF /**< Identifier for an invalid address type. */
rgrover1 112:737b08b3b995 33 #define EDIV_INIT_VAL 0xFFFF /**< Initial value for diversifier. */
rgrover1 112:737b08b3b995 34
rgrover1 112:737b08b3b995 35 /**
rgrover1 112:737b08b3b995 36 * @defgroup device_manager_app_states Connection Manager Application States
rgrover1 112:737b08b3b995 37 * @{
rgrover1 112:737b08b3b995 38 */
rgrover1 112:737b08b3b995 39 #define STATE_CONTROL_PROCEDURE_IN_PROGRESS 0x01 /**< State where a security procedure is ongoing. */
rgrover1 112:737b08b3b995 40 #define STATE_QUEUED_CONTROL_REQUEST 0x02 /**< State where it is known if there is any queued security request or not. */
rgrover1 112:737b08b3b995 41 /** @} */
rgrover1 112:737b08b3b995 42
rgrover1 112:737b08b3b995 43 /**
rgrover1 112:737b08b3b995 44 * @defgroup device_manager_conn_inst_states Connection Manager Connection Instances States.
rgrover1 112:737b08b3b995 45 * @{
rgrover1 112:737b08b3b995 46 */
rgrover1 112:737b08b3b995 47 #define STATE_IDLE 0x01 /**< State where connection instance is free. */
rgrover1 112:737b08b3b995 48 #define STATE_CONNECTED 0x02 /**< State where connection is successfully established. */
rgrover1 112:737b08b3b995 49 #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. */
rgrover1 112:737b08b3b995 50 #define STATE_BONDED 0x08 /**< State where device is bonded. */
rgrover1 112:737b08b3b995 51 #define STATE_DISCONNECTING 0x10 /**< State where disconnection is in progress, application will be notified first, but no further active procedures on the link. */
rgrover1 112:737b08b3b995 52 #define STATE_PAIRING_PENDING 0x20 /**< State where pairing request is pending on the link. */
rgrover1 112:737b08b3b995 53 #define STATE_BOND_INFO_UPDATE 0x40 /**< State where information has been updated, update the flash. */
rgrover1 112:737b08b3b995 54 #define STATE_LINK_ENCRYPTED 0x80 /**< State where link is encrypted. */
rgrover1 112:737b08b3b995 55 /** @} */
rgrover1 112:737b08b3b995 56
rgrover1 112:737b08b3b995 57 /**
rgrover1 112:737b08b3b995 58 * @defgroup device_manager_peer_id_defines Peer Identification Information Defines.
rgrover1 112:737b08b3b995 59 *
rgrover1 112:737b08b3b995 60 * @brief These defines are used to know which of the peer identification is applicable for a peer.
rgrover1 112:737b08b3b995 61 *
rgrover1 112:737b08b3b995 62 * @details These defines are used for peer identification. Here, bit map is used because it is
rgrover1 112:737b08b3b995 63 * possible that the application has both IRK and address for identification.
rgrover1 112:737b08b3b995 64 * @{
rgrover1 112:737b08b3b995 65 */
rgrover1 112:737b08b3b995 66 #define UNASSIGNED 0xFF /**< Peer instance is unassigned/unused. */
rgrover1 112:737b08b3b995 67 #define IRK_ENTRY 0x01 /**< Peer instance has IRK as identification information. */
rgrover1 112:737b08b3b995 68 #define ADDR_ENTRY 0x02 /**< Peer instance has address as identification information. */
rgrover1 112:737b08b3b995 69 #define SERVICE_CONTEXT_ENTRY 0x04 /**< Peer instance has service context set. */
rgrover1 112:737b08b3b995 70 #define APP_CONTEXT_ENTRY 0x08 /**< Peer instance has an application context set. */
rgrover1 112:737b08b3b995 71 /** @} */
rgrover1 112:737b08b3b995 72
rgrover1 112:737b08b3b995 73 /**@brief Device store state identifiers. */
rgrover1 112:737b08b3b995 74 typedef enum
rgrover1 112:737b08b3b995 75 {
rgrover1 112:737b08b3b995 76 STORE_ALL_CONTEXT, /**< Store all context. */
rgrover1 112:737b08b3b995 77 FIRST_BOND_STORE, /**< Store bond. */
rgrover1 112:737b08b3b995 78 UPDATE_PEER_ADDR /**< Update peer address. */
rgrover1 112:737b08b3b995 79 } device_store_state_t;
rgrover1 112:737b08b3b995 80
rgrover1 112:737b08b3b995 81 /**
rgrover1 112:737b08b3b995 82 * @defgroup device_manager_context_offsets Context Offsets
rgrover1 112:737b08b3b995 83 * @{
rgrover1 112:737b08b3b995 84 *
rgrover1 112:737b08b3b995 85 * @brief Context offsets each of the context information in persistent memory.
rgrover1 112:737b08b3b995 86 *
rgrover1 112:737b08b3b995 87 * @details Below is a layout showing how each how the context information is stored in persistent
rgrover1 112:737b08b3b995 88 * memory.
rgrover1 112:737b08b3b995 89 *
rgrover1 112:737b08b3b995 90 * All Device context is stored in the flash as follows:
rgrover1 112:737b08b3b995 91 * +---------+---------+---------+------------------+----------------+--------------------+
rgrover1 112:737b08b3b995 92 * | Block / Device ID + Layout of stored information in storage block |
rgrover1 112:737b08b3b995 93 * +---------+---------+---------+------------------+----------------+--------------------+
rgrover1 112:737b08b3b995 94 * | Block 0 | Device 0| Peer Id | Bond Information | Service Context| Application Context|
rgrover1 112:737b08b3b995 95 * +---------+---------+---------+------------------+----------------+--------------------+
rgrover1 112:737b08b3b995 96 * | Block 1 | Device 1| Peer Id | Bond Information | Service Context| Application Context|
rgrover1 112:737b08b3b995 97 * +---------+---------+---------+------------------+----------------+--------------------+
rgrover1 112:737b08b3b995 98 * | ... | .... |
rgrover1 112:737b08b3b995 99 * +---------+---------+---------+------------------+----------------+--------------------+
rgrover1 112:737b08b3b995 100 * | Block N | Device N| Peer Id | Bond Information | Service Context| Application Context|
rgrover1 112:737b08b3b995 101 * +---------+---------+---------+------------------+----------------+--------------------+
rgrover1 112:737b08b3b995 102 *
rgrover1 112:737b08b3b995 103 * The following defines are used to get offset of each of the components within a block.
rgrover1 112:737b08b3b995 104 */
rgrover1 112:737b08b3b995 105
rgrover1 112:737b08b3b995 106 #define PEER_ID_STORAGE_OFFSET 0 /**< Offset at which peer id is stored in the block. */
rgrover1 112:737b08b3b995 107 #define BOND_STORAGE_OFFSET PEER_ID_SIZE /**< Offset at which bond information is stored in the block. */
rgrover1 112:737b08b3b995 108 #define SERVICE_STORAGE_OFFSET (BOND_STORAGE_OFFSET + BOND_SIZE) /**< Offset at which service context is stored in the block. */
rgrover1 112:737b08b3b995 109 #define APP_CONTEXT_STORAGE_OFFSET (SERVICE_STORAGE_OFFSET + SERVICE_CONTEXT_SIZE) /**< Offset at which application context is stored in the block. */
rgrover1 112:737b08b3b995 110 /** @} */
rgrover1 112:737b08b3b995 111
rgrover1 112:737b08b3b995 112 /**
rgrover1 112:737b08b3b995 113 * @defgroup device_manager_context_size Context size.
rgrover1 112:737b08b3b995 114 * @{
rgrover1 112:737b08b3b995 115 *
rgrover1 112:737b08b3b995 116 * @brief This group defines the size of each of the context information.
rgrover1 112:737b08b3b995 117 */
rgrover1 112:737b08b3b995 118 #define PEER_ID_SIZE (sizeof(peer_id_t)) /**< Size of peer identification information. */
rgrover1 112:737b08b3b995 119 #define BOND_SIZE (sizeof(bond_context_t)) /**< Size of bond information. */
rgrover1 112:737b08b3b995 120 #define DEVICE_CONTEXT_SIZE (PEER_ID_SIZE + BOND_SIZE) /**< Size of Device context, include peer identification and bond information. */
rgrover1 112:737b08b3b995 121 #define GATTS_SERVICE_CONTEXT_SIZE (sizeof(dm_gatts_context_t)) /**< Size of GATTS service context. */
rgrover1 112:737b08b3b995 122 #define GATTC_SERVICE_CONTEXT_SIZE (sizeof(dm_gatt_client_context_t)) /**< Size of GATTC service context. */
rgrover1 112:737b08b3b995 123 #define SERVICE_CONTEXT_SIZE (GATTS_SERVICE_CONTEXT_SIZE + GATTC_SERVICE_CONTEXT_SIZE) /**< Combined size of GATTS and GATTC service contexts. */
rgrover1 112:737b08b3b995 124 #define APP_CONTEXT_MIN_SIZE 4 /**< Minimum size for application context data. */
rgrover1 112:737b08b3b995 125 #if (DEVICE_MANAGER_APP_CONTEXT_SIZE != 0)
rgrover1 112:737b08b3b995 126 #define APP_CONTEXT_SIZE (sizeof(uint32_t) + DEVICE_MANAGER_APP_CONTEXT_SIZE) /**< Size of application context including length field. */
rgrover1 112:737b08b3b995 127 #else //DEVICE_MANAGER_APP_CONTEXT_SIZE
rgrover1 112:737b08b3b995 128 #define APP_CONTEXT_SIZE 0 /**< Size of application context. */
rgrover1 112:737b08b3b995 129 #endif // DEVICE_MANAGER_APP_CONTEXT_SIZE
rgrover1 112:737b08b3b995 130 #define ALL_CONTEXT_SIZE (DEVICE_CONTEXT_SIZE + SERVICE_CONTEXT_SIZE + APP_CONTEXT_SIZE) /**< Size of all contexts. */
rgrover1 112:737b08b3b995 131 /** @} */
rgrover1 112:737b08b3b995 132
rgrover1 112:737b08b3b995 133
rgrover1 112:737b08b3b995 134 /**
rgrover1 112:737b08b3b995 135 * @defgroup device_manager_log Module's Log Macros
rgrover1 112:737b08b3b995 136 *
rgrover1 112:737b08b3b995 137 * @details Macros used for creating module logs which can be useful in understanding handling
rgrover1 112:737b08b3b995 138 * of events or actions on API requests. These are intended for debugging purposes and
rgrover1 112:737b08b3b995 139 * can be disabled by defining the DM_DISABLE_LOGS.
rgrover1 112:737b08b3b995 140 *
rgrover1 112:737b08b3b995 141 * @note That if ENABLE_DEBUG_LOG_SUPPORT is disabled, having DM_DISABLE_LOGS has no effect.
rgrover1 112:737b08b3b995 142 * @{
rgrover1 112:737b08b3b995 143 */
rgrover1 116:fa7257f1c455 144 #define DM_DISABLE_LOGS /**< Enable this macro to disable any logs from this module. */
rgrover1 112:737b08b3b995 145
rgrover1 112:737b08b3b995 146 #ifndef DM_DISABLE_LOGS
rgrover1 112:737b08b3b995 147 #define DM_LOG app_trace_log /**< Used for logging details. */
rgrover1 112:737b08b3b995 148 #define DM_ERR app_trace_log /**< Used for logging errors in the module. */
rgrover1 112:737b08b3b995 149 #define DM_TRC app_trace_log /**< Used for getting trace of execution in the module. */
rgrover1 112:737b08b3b995 150 #define DM_DUMP app_trace_dump /**< Used for dumping octet information to get details of bond information etc. */
rgrover1 112:737b08b3b995 151 #else //DM_DISABLE_LOGS
rgrover1 112:737b08b3b995 152 #define DM_DUMP(...) /**< Disables dumping of octet streams. */
rgrover1 112:737b08b3b995 153 #define DM_LOG(...) /**< Disables detailed logs. */
rgrover1 112:737b08b3b995 154 #define DM_ERR(...) /**< Disables error logs. */
rgrover1 112:737b08b3b995 155 #define DM_TRC(...) /**< Disables traces. */
rgrover1 112:737b08b3b995 156 #endif //DM_DISABLE_LOGS
rgrover1 112:737b08b3b995 157 /** @} */
rgrover1 112:737b08b3b995 158
rgrover1 112:737b08b3b995 159 /**
rgrover1 112:737b08b3b995 160 * @defgroup device_manager_mutex_lock_unlock Module's Mutex Lock/Unlock Macros.
rgrover1 112:737b08b3b995 161 *
rgrover1 112:737b08b3b995 162 * @details Macros used to lock and unlock modules. Currently the SDK does not use mutexes but
rgrover1 112:737b08b3b995 163 * framework is provided in case need arises to use an alternative architecture.
rgrover1 112:737b08b3b995 164 * @{
rgrover1 112:737b08b3b995 165 */
rgrover1 112:737b08b3b995 166 #define DM_MUTEX_LOCK() SDK_MUTEX_LOCK(m_dm_mutex) /**< Lock module using mutex. */
rgrover1 112:737b08b3b995 167 #define DM_MUTEX_UNLOCK() SDK_MUTEX_UNLOCK(m_dm_mutex) /**< Unlock module using mutex. */
rgrover1 112:737b08b3b995 168 /** @} */
rgrover1 112:737b08b3b995 169
rgrover1 112:737b08b3b995 170
rgrover1 112:737b08b3b995 171 /**
rgrover1 112:737b08b3b995 172 * @defgroup device_manager_misc_defines Miscellaneous defines used across the module.
rgrover1 112:737b08b3b995 173 * @{
rgrover1 112:737b08b3b995 174 */
rgrover1 112:737b08b3b995 175 #define DM_GATT_ATTR_SIZE 6 /**< Size of each GATT attribute to be stored persistently. */
rgrover1 112:737b08b3b995 176 #define DM_GATT_SERVER_ATTR_MAX_SIZE ((DM_GATT_ATTR_SIZE * DM_GATT_CCCD_COUNT) + 2) /**< Maximum size of GATT attributes to be stored.*/
rgrover1 112:737b08b3b995 177 #define DM_SERVICE_CONTEXT_COUNT (DM_PROTOCOL_CNTXT_ALL + 1) /**< Maximum number of service contexts. */
rgrover1 112:737b08b3b995 178 #define DM_EVT_DEVICE_CONTEXT_BASE 0x20 /**< Base for device context base. */
rgrover1 112:737b08b3b995 179 #define DM_EVT_SERVICE_CONTEXT_BASE 0x30 /**< Base for service context base. */
rgrover1 112:737b08b3b995 180 #define DM_EVT_APP_CONTEXT_BASE 0x40 /**< Base for application context base. */
rgrover1 112:737b08b3b995 181 #define DM_LOAD_OPERATION_ID 0x01 /**< Load operation identifier. */
rgrover1 112:737b08b3b995 182 #define DM_STORE_OPERATION_ID 0x02 /**< Store operation identifier. */
rgrover1 112:737b08b3b995 183 #define DM_CLEAR_OPERATION_ID 0x03 /**< Clear operation identifier. */
rgrover1 112:737b08b3b995 184 /** @} */
rgrover1 112:737b08b3b995 185
rgrover1 112:737b08b3b995 186 #define DM_GATTS_INVALID_SIZE 0xFFFFFFFF /**< Identifer for GATTS invalid size. */
rgrover1 112:737b08b3b995 187
rgrover1 112:737b08b3b995 188 /**
rgrover1 112:737b08b3b995 189 * @defgroup api_param_check API Parameters check macros.
rgrover1 112:737b08b3b995 190 *
rgrover1 112:737b08b3b995 191 * @details Macros for verifying parameters passed to the module in the APIs. These macros
rgrover1 112:737b08b3b995 192 * could be mapped to nothing in the final version of the code in order to save execution
rgrover1 112:737b08b3b995 193 * time and program size.
rgrover1 112:737b08b3b995 194 * @{
rgrover1 112:737b08b3b995 195 */
rgrover1 112:737b08b3b995 196
rgrover1 112:737b08b3b995 197 //#define DM_DISABLE_API_PARAM_CHECK /**< Macro to disable API parameters check. */
rgrover1 112:737b08b3b995 198
rgrover1 112:737b08b3b995 199 #ifndef DM_DISABLE_API_PARAM_CHECK
rgrover1 112:737b08b3b995 200
rgrover1 112:737b08b3b995 201 /**@brief Macro for verifying NULL parameters are not passed to API.
rgrover1 112:737b08b3b995 202 *
rgrover1 112:737b08b3b995 203 * @param[in] PARAM Parameter checked for NULL.
rgrover1 112:737b08b3b995 204 *
rgrover1 112:737b08b3b995 205 * @retval (NRF_ERROR_NULL | DEVICE_MANAGER_ERR_BASE) when @ref PARAM is NULL.
rgrover1 112:737b08b3b995 206 */
rgrover1 112:737b08b3b995 207 #define NULL_PARAM_CHECK(PARAM) \
rgrover1 112:737b08b3b995 208 if ((PARAM) == NULL) \
rgrover1 112:737b08b3b995 209 { \
rgrover1 112:737b08b3b995 210 return (NRF_ERROR_NULL | DEVICE_MANAGER_ERR_BASE); \
rgrover1 112:737b08b3b995 211 }
rgrover1 112:737b08b3b995 212 /**@} */
rgrover1 112:737b08b3b995 213
rgrover1 112:737b08b3b995 214
rgrover1 112:737b08b3b995 215 /**@brief Macro for verifying module's initialization status.
rgrover1 112:737b08b3b995 216 *
rgrover1 112:737b08b3b995 217 * @retval (NRF_ERROR_INVALID_STATE | DEVICE_MANAGER_ERR_BASE) when module is not initialized.
rgrover1 112:737b08b3b995 218 */
rgrover1 112:737b08b3b995 219 #define VERIFY_MODULE_INITIALIZED() \
rgrover1 112:737b08b3b995 220 do \
rgrover1 112:737b08b3b995 221 { \
rgrover1 112:737b08b3b995 222 if (!m_module_initialized) \
rgrover1 112:737b08b3b995 223 { \
rgrover1 112:737b08b3b995 224 return (NRF_ERROR_INVALID_STATE | DEVICE_MANAGER_ERR_BASE); \
rgrover1 112:737b08b3b995 225 } \
rgrover1 112:737b08b3b995 226 } while (0)
rgrover1 112:737b08b3b995 227
rgrover1 112:737b08b3b995 228
rgrover1 112:737b08b3b995 229 /**@brief Macro for verifying module's initialization status. Returns in case it is not initialized.
rgrover1 112:737b08b3b995 230 */
rgrover1 112:737b08b3b995 231 #define VERIFY_MODULE_INITIALIZED_VOID() \
rgrover1 112:737b08b3b995 232 do \
rgrover1 112:737b08b3b995 233 { \
rgrover1 112:737b08b3b995 234 if (!m_module_initialized) \
rgrover1 112:737b08b3b995 235 { \
rgrover1 112:737b08b3b995 236 return; \
rgrover1 112:737b08b3b995 237 } \
rgrover1 112:737b08b3b995 238 } while (0)
rgrover1 112:737b08b3b995 239
rgrover1 112:737b08b3b995 240
rgrover1 112:737b08b3b995 241 /**@brief Macro for verifying that the application is registered.
rgrover1 112:737b08b3b995 242 *
rgrover1 112:737b08b3b995 243 * @param[in] X Application instance identifier.
rgrover1 112:737b08b3b995 244 *
rgrover1 112:737b08b3b995 245 * @retval (NRF_ERROR_INVALID_STATE | DEVICE_MANAGER_ERR_BASE) when module API is called without
rgrover1 112:737b08b3b995 246 * registering an application with the module.
rgrover1 112:737b08b3b995 247 */
rgrover1 112:737b08b3b995 248 #define VERIFY_APP_REGISTERED(X) \
rgrover1 112:737b08b3b995 249 do \
rgrover1 112:737b08b3b995 250 { \
rgrover1 112:737b08b3b995 251 if (((X) >= DEVICE_MANAGER_MAX_APPLICATIONS) || \
rgrover1 112:737b08b3b995 252 (m_application_table[(X)].ntf_cb == NULL)) \
rgrover1 112:737b08b3b995 253 { \
rgrover1 112:737b08b3b995 254 return (NRF_ERROR_INVALID_STATE | DEVICE_MANAGER_ERR_BASE); \
rgrover1 112:737b08b3b995 255 } \
rgrover1 112:737b08b3b995 256 } while (0)
rgrover1 112:737b08b3b995 257
rgrover1 112:737b08b3b995 258
rgrover1 112:737b08b3b995 259 /**@brief Macro for verifying that the application is registered. Returns in case it is not
rgrover1 112:737b08b3b995 260 * registered.
rgrover1 112:737b08b3b995 261 *
rgrover1 112:737b08b3b995 262 * @param[in] X Application instance identifier.
rgrover1 112:737b08b3b995 263 */
rgrover1 112:737b08b3b995 264 #define VERIFY_APP_REGISTERED_VOID(X) \
rgrover1 112:737b08b3b995 265 do \
rgrover1 112:737b08b3b995 266 { \
rgrover1 112:737b08b3b995 267 if (((X) >= DEVICE_MANAGER_MAX_APPLICATIONS) || \
rgrover1 112:737b08b3b995 268 (m_application_table[(X)].ntf_cb == NULL)) \
rgrover1 112:737b08b3b995 269 { \
rgrover1 112:737b08b3b995 270 return; \
rgrover1 112:737b08b3b995 271 } \
rgrover1 112:737b08b3b995 272 } while (0)
rgrover1 112:737b08b3b995 273
rgrover1 112:737b08b3b995 274
rgrover1 112:737b08b3b995 275 /**@brief Macro for verifying connection instance is allocated.
rgrover1 112:737b08b3b995 276 *
rgrover1 112:737b08b3b995 277 * @param[in] X Connection instance identifier.
rgrover1 112:737b08b3b995 278 *
rgrover1 112:737b08b3b995 279 * @retval (NRF_ERROR_INVALID_ADDR | DEVICE_MANAGER_ERR_BASE) when connection instance is not
rgrover1 112:737b08b3b995 280 * allocated.
rgrover1 112:737b08b3b995 281 */
rgrover1 112:737b08b3b995 282 #define VERIFY_CONNECTION_INSTANCE(X) \
rgrover1 112:737b08b3b995 283 do \
rgrover1 112:737b08b3b995 284 { \
rgrover1 112:737b08b3b995 285 if (((X) >= DEVICE_MANAGER_MAX_CONNECTIONS) || \
rgrover1 112:737b08b3b995 286 (m_connection_table[(X)].state == STATE_IDLE)) \
rgrover1 112:737b08b3b995 287 { \
rgrover1 112:737b08b3b995 288 return (NRF_ERROR_INVALID_ADDR | DEVICE_MANAGER_ERR_BASE); \
rgrover1 112:737b08b3b995 289 } \
rgrover1 112:737b08b3b995 290 } while (0)
rgrover1 112:737b08b3b995 291
rgrover1 112:737b08b3b995 292
rgrover1 112:737b08b3b995 293 /**@brief Macro for verifying if device instance is allocated.
rgrover1 112:737b08b3b995 294 *
rgrover1 112:737b08b3b995 295 * @param[in] X Device instance identifier.
rgrover1 112:737b08b3b995 296 *
rgrover1 112:737b08b3b995 297 * @retval (NRF_ERROR_INVALID_ADDR | DEVICE_MANAGER_ERR_BASE) when device instance is not allocated.
rgrover1 112:737b08b3b995 298 */
rgrover1 112:737b08b3b995 299 #define VERIFY_DEVICE_INSTANCE(X) \
rgrover1 112:737b08b3b995 300 do \
rgrover1 112:737b08b3b995 301 { \
rgrover1 112:737b08b3b995 302 if (((X) >= DEVICE_MANAGER_MAX_BONDS) || \
rgrover1 112:737b08b3b995 303 (m_peer_table[(X)].id_bitmap == UNASSIGNED)) \
rgrover1 112:737b08b3b995 304 { \
rgrover1 112:737b08b3b995 305 return (NRF_ERROR_INVALID_ADDR | DEVICE_MANAGER_ERR_BASE); \
rgrover1 112:737b08b3b995 306 } \
rgrover1 112:737b08b3b995 307 } while (0)
rgrover1 112:737b08b3b995 308
rgrover1 112:737b08b3b995 309 /**@brief Macro for verifying if device is bonded and thus can store data persistantly.
rgrover1 112:737b08b3b995 310 *
rgrover1 112:737b08b3b995 311 * @param[in] X Connection instance identifier.
rgrover1 112:737b08b3b995 312 *
rgrover1 112:737b08b3b995 313 * @retval (NRF_ERROR_INVALID_STATE | DEVICE_MANAGER_ERR_BASE) when device is not bonded.
rgrover1 112:737b08b3b995 314 */
rgrover1 112:737b08b3b995 315 #define VERIFY_DEVICE_BOND(X) \
rgrover1 112:737b08b3b995 316 do \
rgrover1 112:737b08b3b995 317 { \
rgrover1 112:737b08b3b995 318 if ((m_connection_table[(X)].state & STATE_BONDED) != STATE_BONDED)\
rgrover1 112:737b08b3b995 319 { \
rgrover1 112:737b08b3b995 320 return (NRF_ERROR_INVALID_STATE | DEVICE_MANAGER_ERR_BASE); \
rgrover1 112:737b08b3b995 321 } \
rgrover1 112:737b08b3b995 322 } while (0)
rgrover1 112:737b08b3b995 323 #else
rgrover1 112:737b08b3b995 324 #define NULL_PARAM_CHECK(X)
rgrover1 112:737b08b3b995 325 #define VERIFY_MODULE_INITIALIZED()
rgrover1 112:737b08b3b995 326 #define VERIFY_MODULE_INITIALIZED_VOID()
rgrover1 112:737b08b3b995 327 #define VERIFY_APP_REGISTERED(X)
rgrover1 112:737b08b3b995 328 #define VERIFY_APP_REGISTERED_VOID(X)
rgrover1 112:737b08b3b995 329 #define VERIFY_CONNECTION_INSTANCE(X)
rgrover1 112:737b08b3b995 330 #define VERIFY_DEVICE_INSTANCE(X)
rgrover1 112:737b08b3b995 331 #endif //DM_DISABLE_API_PARAM_CHECK
rgrover1 112:737b08b3b995 332 /** @} */
rgrover1 112:737b08b3b995 333
rgrover1 112:737b08b3b995 334 #define INVALID_CONTEXT_LEN 0xFFFFFFFF /**< Identifier for invalid context length. */
rgrover1 112:737b08b3b995 335 /**@brief Macro for checking that application context size is greater that minimal size.
rgrover1 112:737b08b3b995 336 *
rgrover1 112:737b08b3b995 337 * @param[in] X Size of application context.
rgrover1 112:737b08b3b995 338 *
rgrover1 112:737b08b3b995 339 * @retval (NRF_ERROR_INVALID_PARAM) when size is smaller than minimun required size.
rgrover1 112:737b08b3b995 340 */
rgrover1 112:737b08b3b995 341 #define SIZE_CHECK_APP_CONTEXT(X) \
rgrover1 112:737b08b3b995 342 if ((X) < (APP_CONTEXT_MIN_SIZE)) \
rgrover1 112:737b08b3b995 343 { \
rgrover1 112:737b08b3b995 344 return NRF_ERROR_INVALID_PARAM; \
rgrover1 112:737b08b3b995 345 }
rgrover1 112:737b08b3b995 346
rgrover1 112:737b08b3b995 347
rgrover1 112:737b08b3b995 348 /**
rgrover1 112:737b08b3b995 349 * @defgroup dm_data_types Module's internal data types.
rgrover1 112:737b08b3b995 350 *
rgrover1 112:737b08b3b995 351 * @brief This section describes a module's internal data structures.
rgrover1 112:737b08b3b995 352 * @{
rgrover1 112:737b08b3b995 353 */
rgrover1 112:737b08b3b995 354 /**@brief Peer identification information.
rgrover1 112:737b08b3b995 355 */
rgrover1 112:737b08b3b995 356 typedef struct
rgrover1 112:737b08b3b995 357 {
rgrover1 112:737b08b3b995 358 ble_gap_id_key_t peer_id; /**< IRK and/or address of peer. */
rgrover1 112:737b08b3b995 359 uint16_t ediv; /**< Peer's encrypted diversifier. */
rgrover1 112:737b08b3b995 360 uint8_t id_bitmap; /**< Contains information if above field is valid. */
rgrover1 112:737b08b3b995 361 } peer_id_t;
rgrover1 112:737b08b3b995 362
rgrover1 112:737b08b3b995 363 STATIC_ASSERT(sizeof(peer_id_t) % 4 == 0); /**< Check to ensure Peer identification information is a multiple of 4. */
rgrover1 112:737b08b3b995 364
rgrover1 112:737b08b3b995 365 /**@brief Portion of bonding information exchanged by a device during bond creation that needs to
rgrover1 112:737b08b3b995 366 * be stored persistently.
rgrover1 112:737b08b3b995 367 *
rgrover1 112:737b08b3b995 368 * @note An entry is not made in this table unless device is bonded.
rgrover1 112:737b08b3b995 369 */
rgrover1 112:737b08b3b995 370 typedef struct
rgrover1 112:737b08b3b995 371 {
rgrover1 112:737b08b3b995 372 ble_gap_enc_key_t peer_enc_key; /**< Local LTK info, central IRK and address */
rgrover1 112:737b08b3b995 373 } bond_context_t;
rgrover1 112:737b08b3b995 374
rgrover1 112:737b08b3b995 375 STATIC_ASSERT(sizeof(bond_context_t) % 4 == 0); /**< Check to ensure bond information is a multiple of 4. */
rgrover1 112:737b08b3b995 376
rgrover1 112:737b08b3b995 377 /**@brief GATT Server Attributes size and data.
rgrover1 112:737b08b3b995 378 */
rgrover1 112:737b08b3b995 379 typedef struct
rgrover1 112:737b08b3b995 380 {
rgrover1 112:737b08b3b995 381 uint32_t flags; /**< Flags identifying the stored attributes. */
rgrover1 112:737b08b3b995 382 uint32_t size; /**< Size of stored attributes. */
rgrover1 112:737b08b3b995 383 uint8_t attributes[DM_GATT_SERVER_ATTR_MAX_SIZE]; /**< Array to hold the server attributes. */
rgrover1 112:737b08b3b995 384 } dm_gatts_context_t;
rgrover1 112:737b08b3b995 385
rgrover1 112:737b08b3b995 386 STATIC_ASSERT(sizeof(dm_gatts_context_t) % 4 == 0); /**< Check to ensure GATT Server Attributes size and data information is a multiple of 4. */
rgrover1 112:737b08b3b995 387
rgrover1 112:737b08b3b995 388 /**@brief GATT Client context information. Placeholder for now.
rgrover1 112:737b08b3b995 389 */
rgrover1 112:737b08b3b995 390 typedef struct
rgrover1 112:737b08b3b995 391 {
rgrover1 112:737b08b3b995 392 void * p_dummy; /**< Placeholder, currently unused. */
rgrover1 112:737b08b3b995 393 } dm_gatt_client_context_t;
rgrover1 112:737b08b3b995 394
rgrover1 112:737b08b3b995 395 STATIC_ASSERT(sizeof(dm_gatt_client_context_t) % 4 == 0); /**< Check to ensure GATT Client context information is a multiple of 4. */
rgrover1 112:737b08b3b995 396 STATIC_ASSERT((DEVICE_MANAGER_APP_CONTEXT_SIZE % 4) == 0); /**< Check to ensure device manager application context information is a multiple of 4. */
rgrover1 112:737b08b3b995 397
rgrover1 112:737b08b3b995 398 /**@brief Connection instance definition. Maintains information with respect to an active peer.
rgrover1 112:737b08b3b995 399 */
rgrover1 112:737b08b3b995 400 typedef struct
rgrover1 112:737b08b3b995 401 {
rgrover1 112:737b08b3b995 402 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. */
rgrover1 112:737b08b3b995 403 uint16_t conn_handle; /**< Connection handle for the device. */
rgrover1 112:737b08b3b995 404 uint8_t state; /**< Link state. */
rgrover1 112:737b08b3b995 405 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. */
rgrover1 112:737b08b3b995 406 } connection_instance_t;
rgrover1 112:737b08b3b995 407
rgrover1 112:737b08b3b995 408 /**@brief Application instance definition. Maintains information with respect to a registered
rgrover1 112:737b08b3b995 409 * application.
rgrover1 112:737b08b3b995 410 */
rgrover1 112:737b08b3b995 411 typedef struct
rgrover1 112:737b08b3b995 412 {
rgrover1 112:737b08b3b995 413 dm_event_cb_t ntf_cb; /**< Callback registered with the application. */
rgrover1 112:737b08b3b995 414 ble_gap_sec_params_t sec_param; /**< Local security parameters registered by the application. */
rgrover1 112:737b08b3b995 415 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. */
rgrover1 112:737b08b3b995 416 uint8_t service; /**< Service registered by the application. */
rgrover1 112:737b08b3b995 417 } application_instance_t;
rgrover1 112:737b08b3b995 418
rgrover1 112:737b08b3b995 419 /**@brief Function for performing necessary action of storing each of the service context as
rgrover1 112:737b08b3b995 420 * registered by the application.
rgrover1 112:737b08b3b995 421 *
rgrover1 112:737b08b3b995 422 * @param[in] p_block_handle Storage block identifier.
rgrover1 112:737b08b3b995 423 * @param[in] p_handle Device handle identifying device that is stored.
rgrover1 112:737b08b3b995 424 *
rgrover1 112:737b08b3b995 425 * @retval Operation result code.
rgrover1 112:737b08b3b995 426 */
rgrover1 112:737b08b3b995 427 typedef ret_code_t (* service_context_access_t)(pstorage_handle_t const * p_block_handle,
rgrover1 112:737b08b3b995 428 dm_handle_t const * p_handle);
rgrover1 112:737b08b3b995 429
rgrover1 112:737b08b3b995 430 /**@brief Function for performing necessary action of applying the context information.
rgrover1 112:737b08b3b995 431 *
rgrover1 112:737b08b3b995 432 * @param[in] p_handle Device handle identifying device that is stored.
rgrover1 112:737b08b3b995 433 *
rgrover1 112:737b08b3b995 434 * @retval Operation result code.
rgrover1 112:737b08b3b995 435 */
rgrover1 112:737b08b3b995 436 typedef ret_code_t (* service_context_apply_t)(dm_handle_t * p_handle);
rgrover1 112:737b08b3b995 437
rgrover1 112:737b08b3b995 438 /**@brief Function for performing necessary functions of storing or updating.
rgrover1 112:737b08b3b995 439 *
rgrover1 112:737b08b3b995 440 * @param[in] p_dest Destination address where data is stored persistently.
rgrover1 112:737b08b3b995 441 * @param[in] p_src Source address containing data to be stored.
rgrover1 112:737b08b3b995 442 * @param[in] size Size of data to be stored expressed in bytes. Must be word aligned.
rgrover1 112:737b08b3b995 443 * @param[in] offset Offset in bytes to be applied when writing to the block.
rgrover1 112:737b08b3b995 444 *
rgrover1 112:737b08b3b995 445 * @retval Operation result code.
rgrover1 112:737b08b3b995 446 */
rgrover1 112:737b08b3b995 447 typedef uint32_t (* storage_operation)(pstorage_handle_t * p_dest,
rgrover1 112:737b08b3b995 448 uint8_t * p_src,
rgrover1 112:737b08b3b995 449 pstorage_size_t size,
rgrover1 112:737b08b3b995 450 pstorage_size_t offset);
rgrover1 112:737b08b3b995 451 /** @} */
rgrover1 112:737b08b3b995 452
rgrover1 112:737b08b3b995 453 /**
rgrover1 112:737b08b3b995 454 * @defgroup dm_tables Module's internal tables.
rgrover1 112:737b08b3b995 455 *
rgrover1 112:737b08b3b995 456 * @brief This section describes the module's internal tables and the static global variables
rgrover1 112:737b08b3b995 457 * needed for its functionality.
rgrover1 112:737b08b3b995 458 * @{
rgrover1 112:737b08b3b995 459 */
rgrover1 112:737b08b3b995 460 #if (DEVICE_MANAGER_APP_CONTEXT_SIZE != 0)
rgrover1 112:737b08b3b995 461 static uint8_t * m_app_context_table[DEVICE_MANAGER_MAX_BONDS]; /**< Table to remember application contexts of bonded devices. */
rgrover1 112:737b08b3b995 462 #endif //DEVICE_MANAGER_APP_CONTEXT_SIZE
rgrover1 112:737b08b3b995 463 __ALIGN(sizeof(uint32_t))
rgrover1 112:737b08b3b995 464 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. */
rgrover1 112:737b08b3b995 465 __ALIGN(sizeof(uint32_t))
rgrover1 112:737b08b3b995 466 static bond_context_t m_bond_table[DEVICE_MANAGER_MAX_CONNECTIONS]; /**< Table to maintain bond information for active peers. */
rgrover1 112:737b08b3b995 467 static dm_gatts_context_t m_gatts_table[DEVICE_MANAGER_MAX_CONNECTIONS]; /**< Table for service information for active connection instances. */
rgrover1 112:737b08b3b995 468 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. */
rgrover1 112:737b08b3b995 469 static application_instance_t m_application_table[DEVICE_MANAGER_MAX_APPLICATIONS]; /**< Table to maintain application instances. */
rgrover1 112:737b08b3b995 470 static pstorage_handle_t m_storage_handle; /**< Persistent storage handle for blocks requested by the module. */
rgrover1 112:737b08b3b995 471 static uint32_t m_peer_addr_update; /**< 32-bit bitmap to remember peer device address update. */
rgrover1 112:737b08b3b995 472 static ble_gap_id_key_t m_local_id_info; /**< ID information of central in case resolvable address is used. */
rgrover1 112:737b08b3b995 473 static bool m_module_initialized = false; /**< State indicating if module is initialized or not. */
rgrover1 112:737b08b3b995 474 static uint8_t m_irk_index_table[DEVICE_MANAGER_MAX_BONDS]; /**< List maintaining IRK index list. */
rgrover1 112:737b08b3b995 475
rgrover1 112:737b08b3b995 476 SDK_MUTEX_DEFINE(m_dm_mutex) /**< Mutex variable. Currently unused, this declaration does not occupy any space in RAM. */
rgrover1 112:737b08b3b995 477 /** @} */
rgrover1 112:737b08b3b995 478
rgrover1 112:737b08b3b995 479 static __INLINE ret_code_t no_service_context_store(pstorage_handle_t const * p_block_handle,
rgrover1 112:737b08b3b995 480 dm_handle_t const * p_handle);
rgrover1 112:737b08b3b995 481
rgrover1 112:737b08b3b995 482 static __INLINE ret_code_t gatts_context_store(pstorage_handle_t const * p_block_handle,
rgrover1 112:737b08b3b995 483 dm_handle_t const * p_handle);
rgrover1 112:737b08b3b995 484
rgrover1 112:737b08b3b995 485 static __INLINE ret_code_t gattc_context_store(pstorage_handle_t const * p_block_handle,
rgrover1 112:737b08b3b995 486 dm_handle_t const * p_handle);
rgrover1 112:737b08b3b995 487
rgrover1 112:737b08b3b995 488 static __INLINE ret_code_t gattsc_context_store(pstorage_handle_t const * p_block_handle,
rgrover1 112:737b08b3b995 489 dm_handle_t const * p_handle);
rgrover1 112:737b08b3b995 490
rgrover1 112:737b08b3b995 491 static __INLINE ret_code_t no_service_context_load(pstorage_handle_t const * p_block_handle,
rgrover1 112:737b08b3b995 492 dm_handle_t const * p_handle);
rgrover1 112:737b08b3b995 493
rgrover1 112:737b08b3b995 494 static __INLINE ret_code_t gatts_context_load(pstorage_handle_t const * p_block_handle,
rgrover1 112:737b08b3b995 495 dm_handle_t const * p_handle);
rgrover1 112:737b08b3b995 496
rgrover1 112:737b08b3b995 497 static __INLINE ret_code_t gattc_context_load(pstorage_handle_t const * p_block_handle,
rgrover1 112:737b08b3b995 498 dm_handle_t const * p_handle);
rgrover1 112:737b08b3b995 499
rgrover1 112:737b08b3b995 500 static __INLINE ret_code_t gattsc_context_load(pstorage_handle_t const * p_block_handle,
rgrover1 112:737b08b3b995 501 dm_handle_t const * p_handle);
rgrover1 112:737b08b3b995 502
rgrover1 112:737b08b3b995 503 static __INLINE ret_code_t no_service_context_apply(dm_handle_t * p_handle);
rgrover1 112:737b08b3b995 504
rgrover1 112:737b08b3b995 505 static __INLINE ret_code_t gatts_context_apply(dm_handle_t * p_handle);
rgrover1 112:737b08b3b995 506
rgrover1 112:737b08b3b995 507 static __INLINE ret_code_t gattc_context_apply(dm_handle_t * p_handle);
rgrover1 112:737b08b3b995 508
rgrover1 112:737b08b3b995 509 static __INLINE ret_code_t gattsc_context_apply(dm_handle_t * p_handle);
rgrover1 112:737b08b3b995 510
rgrover1 112:737b08b3b995 511
rgrover1 112:737b08b3b995 512 /**< Array of function pointers based on the types of service registered. */
rgrover1 112:737b08b3b995 513 const service_context_access_t m_service_context_store[DM_SERVICE_CONTEXT_COUNT] =
rgrover1 112:737b08b3b995 514 {
rgrover1 112:737b08b3b995 515 no_service_context_store, /**< Dummy function, when there is no service context registered. */
rgrover1 112:737b08b3b995 516 gatts_context_store, /**< GATT Server context store function. */
rgrover1 112:737b08b3b995 517 gattc_context_store, /**< GATT Client context store function. */
rgrover1 112:737b08b3b995 518 gattsc_context_store /**< GATT Server & Client context store function. */
rgrover1 112:737b08b3b995 519 };
rgrover1 112:737b08b3b995 520
rgrover1 112:737b08b3b995 521
rgrover1 112:737b08b3b995 522 /**< Array of function pointers based on the types of service registered. */
rgrover1 112:737b08b3b995 523 const service_context_access_t m_service_context_load[DM_SERVICE_CONTEXT_COUNT] =
rgrover1 112:737b08b3b995 524 {
rgrover1 112:737b08b3b995 525 no_service_context_load, /**< Dummy function, when there is no service context registered. */
rgrover1 112:737b08b3b995 526 gatts_context_load, /**< GATT Server context load function. */
rgrover1 112:737b08b3b995 527 gattc_context_load, /**< GATT Client context load function. */
rgrover1 112:737b08b3b995 528 gattsc_context_load /**< GATT Server & Client context load function. */
rgrover1 112:737b08b3b995 529 };
rgrover1 112:737b08b3b995 530
rgrover1 112:737b08b3b995 531
rgrover1 112:737b08b3b995 532 /**< Array of function pointers based on the types of service registered. */
rgrover1 112:737b08b3b995 533 const service_context_apply_t m_service_context_apply[DM_SERVICE_CONTEXT_COUNT] =
rgrover1 112:737b08b3b995 534 {
rgrover1 112:737b08b3b995 535 no_service_context_apply, /**< Dummy function, when there is no service context registered. */
rgrover1 112:737b08b3b995 536 gatts_context_apply, /**< GATT Server context apply function. */
rgrover1 112:737b08b3b995 537 gattc_context_apply, /**< GATT Client context apply function. */
rgrover1 112:737b08b3b995 538 gattsc_context_apply /**< GATT Server & Client context apply function. */
rgrover1 112:737b08b3b995 539 };
rgrover1 112:737b08b3b995 540
rgrover1 112:737b08b3b995 541
rgrover1 112:737b08b3b995 542 const uint32_t m_context_init_len = 0xFFFFFFFF; /**< Constant used to update the initial value for context in the flash. */
rgrover1 112:737b08b3b995 543
rgrover1 112:737b08b3b995 544 /**@brief Function for setting update status for the device identified by 'index'.
rgrover1 112:737b08b3b995 545 *
rgrover1 112:737b08b3b995 546 * @param[in] index Device identifier.
rgrover1 112:737b08b3b995 547 */
rgrover1 112:737b08b3b995 548 static __INLINE void update_status_bit_set(uint32_t index)
rgrover1 112:737b08b3b995 549 {
rgrover1 112:737b08b3b995 550 m_peer_addr_update |= (BIT_0 << index);
rgrover1 112:737b08b3b995 551 }
rgrover1 112:737b08b3b995 552
rgrover1 112:737b08b3b995 553
rgrover1 112:737b08b3b995 554 /**@brief Function for resetting update status for device identified by 'index'.
rgrover1 112:737b08b3b995 555 *
rgrover1 112:737b08b3b995 556 * @param[in] index Device identifier.
rgrover1 112:737b08b3b995 557 */
rgrover1 112:737b08b3b995 558 static __INLINE void update_status_bit_reset(uint32_t index)
rgrover1 112:737b08b3b995 559 {
rgrover1 112:737b08b3b995 560 m_peer_addr_update &= (~((uint32_t)BIT_0 << index));
rgrover1 112:737b08b3b995 561 }
rgrover1 112:737b08b3b995 562
rgrover1 112:737b08b3b995 563
rgrover1 112:737b08b3b995 564 /**@brief Function for providing update status for the device identified by 'index'.
rgrover1 112:737b08b3b995 565 *
rgrover1 112:737b08b3b995 566 * @param[in] index Device identifier.
rgrover1 112:737b08b3b995 567 *
rgrover1 112:737b08b3b995 568 * @retval true if the bit is set, false otherwise.
rgrover1 112:737b08b3b995 569 */
rgrover1 112:737b08b3b995 570 static __INLINE bool update_status_bit_is_set(uint32_t index)
rgrover1 112:737b08b3b995 571 {
rgrover1 112:737b08b3b995 572 return ((m_peer_addr_update & (BIT_0 << index)) ? true : false);
rgrover1 112:737b08b3b995 573 }
rgrover1 112:737b08b3b995 574
rgrover1 112:737b08b3b995 575
rgrover1 112:737b08b3b995 576 /**@brief Function for initialiasing the application instance identified by 'index'.
rgrover1 112:737b08b3b995 577 *
rgrover1 112:737b08b3b995 578 * @param[in] index Device identifier.
rgrover1 112:737b08b3b995 579 */
rgrover1 112:737b08b3b995 580 static __INLINE void application_instance_init(uint32_t index)
rgrover1 112:737b08b3b995 581 {
rgrover1 112:737b08b3b995 582 DM_TRC("[DM]: Initializing Application Instance 0x%08X.\r\n", index);
rgrover1 112:737b08b3b995 583
rgrover1 112:737b08b3b995 584 m_application_table[index].ntf_cb = NULL;
rgrover1 112:737b08b3b995 585 m_application_table[index].state = 0x00;
rgrover1 112:737b08b3b995 586 m_application_table[index].service = 0x00;
rgrover1 112:737b08b3b995 587 }
rgrover1 112:737b08b3b995 588
rgrover1 112:737b08b3b995 589
rgrover1 112:737b08b3b995 590 /**@brief Function for initialiasing the connection instance identified by 'index'.
rgrover1 112:737b08b3b995 591 *
rgrover1 112:737b08b3b995 592 * @param[in] index Device identifier.
rgrover1 112:737b08b3b995 593 */
rgrover1 112:737b08b3b995 594 static __INLINE void connection_instance_init(uint32_t index)
rgrover1 112:737b08b3b995 595 {
rgrover1 112:737b08b3b995 596 DM_TRC("[DM]: Initializing Connection Instance 0x%08X.\r\n", index);
rgrover1 112:737b08b3b995 597
rgrover1 112:737b08b3b995 598 m_connection_table[index].state = STATE_IDLE;
rgrover1 112:737b08b3b995 599 m_connection_table[index].conn_handle = BLE_CONN_HANDLE_INVALID;
rgrover1 112:737b08b3b995 600 m_connection_table[index].bonded_dev_id = DM_INVALID_ID;
rgrover1 112:737b08b3b995 601
rgrover1 112:737b08b3b995 602 memset(&m_connection_table[index].peer_addr, 0, sizeof (ble_gap_addr_t));
rgrover1 112:737b08b3b995 603 }
rgrover1 112:737b08b3b995 604
rgrover1 112:737b08b3b995 605
rgrover1 112:737b08b3b995 606 /**@brief Function for initialiasing the peer device instance identified by 'index'.
rgrover1 112:737b08b3b995 607 *
rgrover1 112:737b08b3b995 608 * @param[in] index Device identifier.
rgrover1 112:737b08b3b995 609 */
rgrover1 112:737b08b3b995 610 static __INLINE void peer_instance_init(uint32_t index)
rgrover1 112:737b08b3b995 611 {
rgrover1 112:737b08b3b995 612 DM_TRC("[DM]: Initializing Peer Instance 0x%08X.\r\n", index);
rgrover1 112:737b08b3b995 613
rgrover1 112:737b08b3b995 614 memset(m_peer_table[index].peer_id.id_addr_info.addr, 0, BLE_GAP_ADDR_LEN);
rgrover1 112:737b08b3b995 615 memset(m_peer_table[index].peer_id.id_info.irk, 0, BLE_GAP_SEC_KEY_LEN);
rgrover1 112:737b08b3b995 616
rgrover1 112:737b08b3b995 617 //Initialize the address type to invalid.
rgrover1 112:737b08b3b995 618 m_peer_table[index].peer_id.id_addr_info.addr_type = INVALID_ADDR_TYPE;
rgrover1 112:737b08b3b995 619
rgrover1 112:737b08b3b995 620 //Initialize the identification bit map to unassigned.
rgrover1 112:737b08b3b995 621 m_peer_table[index].id_bitmap = UNASSIGNED;
rgrover1 112:737b08b3b995 622
rgrover1 112:737b08b3b995 623 // Initialize diversifier.
rgrover1 112:737b08b3b995 624 m_peer_table[index].ediv = EDIV_INIT_VAL;
rgrover1 112:737b08b3b995 625
rgrover1 112:737b08b3b995 626
rgrover1 112:737b08b3b995 627 //Reset the status bit.
rgrover1 112:737b08b3b995 628 update_status_bit_reset(index);
rgrover1 112:737b08b3b995 629
rgrover1 112:737b08b3b995 630 #if (DEVICE_MANAGER_APP_CONTEXT_SIZE != 0)
rgrover1 112:737b08b3b995 631 //Initialize the application context for bond device.
rgrover1 112:737b08b3b995 632 m_app_context_table[index] = NULL;
rgrover1 112:737b08b3b995 633 #endif //DEVICE_MANAGER_APP_CONTEXT_SIZE
rgrover1 112:737b08b3b995 634 }
rgrover1 112:737b08b3b995 635
rgrover1 112:737b08b3b995 636
rgrover1 112:737b08b3b995 637 /**@brief Function for searching connection instance matching the connection handle and the state
rgrover1 112:737b08b3b995 638 * requested.
rgrover1 112:737b08b3b995 639 *
rgrover1 112:737b08b3b995 640 * @details Connection handle and state information is used to get a connection instance, it
rgrover1 112:737b08b3b995 641 * is possible to ignore the connection handle by using BLE_CONN_HANDLE_INVALID.
rgrover1 112:737b08b3b995 642 *
rgrover1 112:737b08b3b995 643 * @param[in] conn_handle Connection handle.
rgrover1 112:737b08b3b995 644 * @param[in] state Connection instance state.
rgrover1 112:737b08b3b995 645 * @param[out] p_instance Connection instance.
rgrover1 112:737b08b3b995 646 *
rgrover1 112:737b08b3b995 647 * @retval NRF_SUCCESS Operation success.
rgrover1 112:737b08b3b995 648 * @retval NRF_ERROR_INVALID_STATE Operation failure. Invalid state
rgrover1 112:737b08b3b995 649 * @retval NRF_ERROR_NOT_FOUND Operation failure. Not found
rgrover1 112:737b08b3b995 650 */
rgrover1 112:737b08b3b995 651 static ret_code_t connection_instance_find(uint16_t conn_handle,
rgrover1 112:737b08b3b995 652 uint8_t state,
rgrover1 112:737b08b3b995 653 uint32_t * p_instance)
rgrover1 112:737b08b3b995 654 {
rgrover1 112:737b08b3b995 655 ret_code_t err_code;
rgrover1 112:737b08b3b995 656 uint32_t index;
rgrover1 112:737b08b3b995 657
rgrover1 112:737b08b3b995 658 err_code = NRF_ERROR_INVALID_STATE;
rgrover1 112:737b08b3b995 659
rgrover1 112:737b08b3b995 660 for (index = 0; index < DEVICE_MANAGER_MAX_CONNECTIONS; index++)
rgrover1 112:737b08b3b995 661 {
rgrover1 112:737b08b3b995 662 //Search only based on the state.
rgrover1 112:737b08b3b995 663 if (state & m_connection_table[index].state)
rgrover1 112:737b08b3b995 664 {
rgrover1 112:737b08b3b995 665 //Ignore the connection handle.
rgrover1 112:737b08b3b995 666 if ((conn_handle == BLE_CONN_HANDLE_INVALID) ||
rgrover1 112:737b08b3b995 667 (conn_handle == m_connection_table[index].conn_handle))
rgrover1 112:737b08b3b995 668 {
rgrover1 112:737b08b3b995 669 //Search for matching connection handle.
rgrover1 112:737b08b3b995 670 (*p_instance) = index;
rgrover1 112:737b08b3b995 671 err_code = NRF_SUCCESS;
rgrover1 112:737b08b3b995 672
rgrover1 112:737b08b3b995 673 break;
rgrover1 112:737b08b3b995 674 }
rgrover1 112:737b08b3b995 675 else
rgrover1 112:737b08b3b995 676 {
rgrover1 112:737b08b3b995 677 err_code = NRF_ERROR_NOT_FOUND;
rgrover1 112:737b08b3b995 678 }
rgrover1 112:737b08b3b995 679 }
rgrover1 112:737b08b3b995 680 }
rgrover1 112:737b08b3b995 681
rgrover1 112:737b08b3b995 682 return err_code;
rgrover1 112:737b08b3b995 683 }
rgrover1 112:737b08b3b995 684
rgrover1 112:737b08b3b995 685
rgrover1 112:737b08b3b995 686 /**@brief Function for allocating device instance for a bonded device.
rgrover1 112:737b08b3b995 687 *
rgrover1 112:737b08b3b995 688 * @param[out] p_device_index Device index.
rgrover1 112:737b08b3b995 689 * @param[in] p_addr Peer identification information.
rgrover1 112:737b08b3b995 690 *
rgrover1 112:737b08b3b995 691 * @retval NRF_SUCCESS Operation success.
rgrover1 112:737b08b3b995 692 * @retval DM_DEVICE_CONTEXT_FULL Operation failure.
rgrover1 112:737b08b3b995 693 */
rgrover1 112:737b08b3b995 694 static __INLINE ret_code_t device_instance_allocate(uint8_t * p_device_index,
rgrover1 112:737b08b3b995 695 ble_gap_addr_t const * p_addr)
rgrover1 112:737b08b3b995 696 {
rgrover1 112:737b08b3b995 697 ret_code_t err_code;
rgrover1 112:737b08b3b995 698 uint32_t index;
rgrover1 112:737b08b3b995 699
rgrover1 112:737b08b3b995 700 err_code = DM_DEVICE_CONTEXT_FULL;
rgrover1 112:737b08b3b995 701
rgrover1 112:737b08b3b995 702 for (index = 0; index < DEVICE_MANAGER_MAX_BONDS; index++)
rgrover1 112:737b08b3b995 703 {
rgrover1 112:737b08b3b995 704 DM_TRC("[DM]:[DI 0x%02X]: Device type 0x%02X.\r\n",
rgrover1 112:737b08b3b995 705 index, m_peer_table[index].peer_id.id_addr_info.addr_type);
rgrover1 112:737b08b3b995 706 DM_TRC("[DM]: Device Addr 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X.\r\n",
rgrover1 112:737b08b3b995 707 m_peer_table[index].peer_id.id_addr_info.addr[0],
rgrover1 112:737b08b3b995 708 m_peer_table[index].peer_id.id_addr_info.addr[1],
rgrover1 112:737b08b3b995 709 m_peer_table[index].peer_id.id_addr_info.addr[2],
rgrover1 112:737b08b3b995 710 m_peer_table[index].peer_id.id_addr_info.addr[3],
rgrover1 112:737b08b3b995 711 m_peer_table[index].peer_id.id_addr_info.addr[4],
rgrover1 112:737b08b3b995 712 m_peer_table[index].peer_id.id_addr_info.addr[5]);
rgrover1 112:737b08b3b995 713
rgrover1 112:737b08b3b995 714 if (m_peer_table[index].id_bitmap == UNASSIGNED)
rgrover1 112:737b08b3b995 715 {
rgrover1 112:737b08b3b995 716 if (p_addr->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE)
rgrover1 112:737b08b3b995 717 {
rgrover1 112:737b08b3b995 718 m_peer_table[index].id_bitmap &= (~ADDR_ENTRY);
rgrover1 112:737b08b3b995 719 m_peer_table[index].peer_id.id_addr_info = (*p_addr);
rgrover1 112:737b08b3b995 720 }
rgrover1 112:737b08b3b995 721 else
rgrover1 112:737b08b3b995 722 {
rgrover1 112:737b08b3b995 723 m_peer_table[index].id_bitmap &= (~IRK_ENTRY);
rgrover1 112:737b08b3b995 724 }
rgrover1 112:737b08b3b995 725
rgrover1 112:737b08b3b995 726 (*p_device_index) = index;
rgrover1 112:737b08b3b995 727 err_code = NRF_SUCCESS;
rgrover1 112:737b08b3b995 728
rgrover1 112:737b08b3b995 729 DM_LOG("[DM]: Allocated device instance 0x%02X\r\n", index);
rgrover1 112:737b08b3b995 730
rgrover1 112:737b08b3b995 731 break;
rgrover1 112:737b08b3b995 732 }
rgrover1 112:737b08b3b995 733 }
rgrover1 112:737b08b3b995 734
rgrover1 112:737b08b3b995 735 return err_code;
rgrover1 112:737b08b3b995 736 }
rgrover1 112:737b08b3b995 737
rgrover1 112:737b08b3b995 738
rgrover1 112:737b08b3b995 739 /**@brief Function for freeing a device instance allocated for bonded device.
rgrover1 112:737b08b3b995 740 *
rgrover1 112:737b08b3b995 741 * @param[in] device_index Device index.
rgrover1 112:737b08b3b995 742 *
rgrover1 112:737b08b3b995 743 * @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
rgrover1 112:737b08b3b995 744 */
rgrover1 112:737b08b3b995 745 static __INLINE ret_code_t device_instance_free(uint32_t device_index)
rgrover1 112:737b08b3b995 746 {
rgrover1 112:737b08b3b995 747 ret_code_t err_code;
rgrover1 112:737b08b3b995 748 pstorage_handle_t block_handle;
rgrover1 112:737b08b3b995 749
rgrover1 112:737b08b3b995 750 //Get the block handle.
rgrover1 112:737b08b3b995 751 err_code = pstorage_block_identifier_get(&m_storage_handle, device_index, &block_handle);
rgrover1 112:737b08b3b995 752
rgrover1 112:737b08b3b995 753 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 754 {
rgrover1 112:737b08b3b995 755 DM_TRC("[DM]:[DI 0x%02X]: Freeing Instance.\r\n", device_index);
rgrover1 112:737b08b3b995 756
rgrover1 112:737b08b3b995 757 //Request clearing of the block.
rgrover1 112:737b08b3b995 758 err_code = pstorage_clear(&block_handle, ALL_CONTEXT_SIZE);
rgrover1 112:737b08b3b995 759
rgrover1 112:737b08b3b995 760 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 761 {
rgrover1 112:737b08b3b995 762 peer_instance_init(device_index);
rgrover1 112:737b08b3b995 763 }
rgrover1 112:737b08b3b995 764 }
rgrover1 112:737b08b3b995 765
rgrover1 112:737b08b3b995 766 return err_code;
rgrover1 112:737b08b3b995 767 }
rgrover1 112:737b08b3b995 768
rgrover1 112:737b08b3b995 769
rgrover1 112:737b08b3b995 770 /**@brief Function for searching for the device in the bonded device list.
rgrover1 112:737b08b3b995 771 *
rgrover1 112:737b08b3b995 772 * @param[in] p_addr Peer identification information.
rgrover1 112:737b08b3b995 773 * @param[out] p_device_index Device index.
rgrover1 112:737b08b3b995 774 *
rgrover1 112:737b08b3b995 775 * @retval NRF_SUCCESS Operation success.
rgrover1 112:737b08b3b995 776 * @retval NRF_ERROR_NOT_FOUND Operation failure.
rgrover1 112:737b08b3b995 777 */
rgrover1 112:737b08b3b995 778 static ret_code_t device_instance_find(ble_gap_addr_t const * p_addr, uint32_t * p_device_index, uint16_t ediv)
rgrover1 112:737b08b3b995 779 {
rgrover1 112:737b08b3b995 780 ret_code_t err_code;
rgrover1 112:737b08b3b995 781 uint32_t index;
rgrover1 112:737b08b3b995 782
rgrover1 112:737b08b3b995 783 err_code = NRF_ERROR_NOT_FOUND;
rgrover1 112:737b08b3b995 784
rgrover1 112:737b08b3b995 785 DM_TRC("[DM]: Searching for device 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X.\r\n",
rgrover1 112:737b08b3b995 786 p_addr->addr[0],
rgrover1 112:737b08b3b995 787 p_addr->addr[1],
rgrover1 112:737b08b3b995 788 p_addr->addr[2],
rgrover1 112:737b08b3b995 789 p_addr->addr[3],
rgrover1 112:737b08b3b995 790 p_addr->addr[4],
rgrover1 112:737b08b3b995 791 p_addr->addr[5]);
rgrover1 112:737b08b3b995 792
rgrover1 112:737b08b3b995 793 for (index = 0; index < DEVICE_MANAGER_MAX_BONDS; index++)
rgrover1 112:737b08b3b995 794 {
rgrover1 112:737b08b3b995 795 DM_TRC("[DM]:[DI 0x%02X]: Device type 0x%02X.\r\n",
rgrover1 112:737b08b3b995 796 index, m_peer_table[index].peer_id.id_addr_info.addr_type);
rgrover1 112:737b08b3b995 797 DM_TRC("[DM]: Device Addr 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X.\r\n",
rgrover1 112:737b08b3b995 798 m_peer_table[index].peer_id.id_addr_info.addr[0],
rgrover1 112:737b08b3b995 799 m_peer_table[index].peer_id.id_addr_info.addr[1],
rgrover1 112:737b08b3b995 800 m_peer_table[index].peer_id.id_addr_info.addr[2],
rgrover1 112:737b08b3b995 801 m_peer_table[index].peer_id.id_addr_info.addr[3],
rgrover1 112:737b08b3b995 802 m_peer_table[index].peer_id.id_addr_info.addr[4],
rgrover1 112:737b08b3b995 803 m_peer_table[index].peer_id.id_addr_info.addr[5]);
rgrover1 112:737b08b3b995 804
rgrover1 112:737b08b3b995 805 if (((NULL == p_addr) && (ediv == m_peer_table[index].ediv)) ||
rgrover1 112:737b08b3b995 806 ((NULL != p_addr) && (memcmp(&m_peer_table[index].peer_id.id_addr_info, p_addr, sizeof(ble_gap_addr_t)) == 0)))
rgrover1 112:737b08b3b995 807 {
rgrover1 112:737b08b3b995 808 DM_LOG("[DM]: Found device at instance 0x%02X\r\n", index);
rgrover1 112:737b08b3b995 809
rgrover1 112:737b08b3b995 810 (*p_device_index) = index;
rgrover1 112:737b08b3b995 811 err_code = NRF_SUCCESS;
rgrover1 112:737b08b3b995 812
rgrover1 112:737b08b3b995 813 break;
rgrover1 112:737b08b3b995 814 }
rgrover1 112:737b08b3b995 815 }
rgrover1 112:737b08b3b995 816
rgrover1 112:737b08b3b995 817 return err_code;
rgrover1 112:737b08b3b995 818 }
rgrover1 112:737b08b3b995 819
rgrover1 112:737b08b3b995 820
rgrover1 112:737b08b3b995 821 /**@brief Function for notifying connection manager event to the application.
rgrover1 112:737b08b3b995 822 *
rgrover1 112:737b08b3b995 823 * @param[in] p_handle Device handle identifying device.
rgrover1 112:737b08b3b995 824 * @param[in] p_event Connection manager event details.
rgrover1 112:737b08b3b995 825 * @param[in] event_result Event result code.
rgrover1 112:737b08b3b995 826 */
rgrover1 112:737b08b3b995 827 static __INLINE void app_evt_notify(dm_handle_t const * const p_handle,
rgrover1 112:737b08b3b995 828 dm_event_t const * const p_event,
rgrover1 112:737b08b3b995 829 uint32_t event_result)
rgrover1 112:737b08b3b995 830 {
rgrover1 112:737b08b3b995 831 dm_event_cb_t app_cb = m_application_table[0].ntf_cb;
rgrover1 112:737b08b3b995 832
rgrover1 112:737b08b3b995 833 DM_MUTEX_UNLOCK();
rgrover1 112:737b08b3b995 834
rgrover1 112:737b08b3b995 835 DM_TRC("[DM]: Notifying application of event 0x%02X\r\n", p_event->event_id);
rgrover1 112:737b08b3b995 836
rgrover1 112:737b08b3b995 837 //No need to do any kind of return value processing thus can be supressed.
rgrover1 112:737b08b3b995 838 UNUSED_VARIABLE(app_cb(p_handle, p_event, event_result));
rgrover1 112:737b08b3b995 839
rgrover1 112:737b08b3b995 840 DM_MUTEX_LOCK();
rgrover1 112:737b08b3b995 841 }
rgrover1 112:737b08b3b995 842
rgrover1 112:737b08b3b995 843
rgrover1 112:737b08b3b995 844 /**@brief Function for allocating instance.
rgrover1 112:737b08b3b995 845 *
rgrover1 112:737b08b3b995 846 * @details The instance identifier is provided in the 'p_instance' parameter if the routine
rgrover1 112:737b08b3b995 847 * succeeds.
rgrover1 112:737b08b3b995 848 *
rgrover1 112:737b08b3b995 849 * @param[out] p_instance Connection instance.
rgrover1 112:737b08b3b995 850 *
rgrover1 112:737b08b3b995 851 * @retval NRF_SUCCESS Operation success.
rgrover1 112:737b08b3b995 852 * @retval NRF_ERROR_NO_MEM Operation failure. No memory.
rgrover1 112:737b08b3b995 853 */
rgrover1 112:737b08b3b995 854 static __INLINE uint32_t connection_instance_allocate(uint32_t * p_instance)
rgrover1 112:737b08b3b995 855 {
rgrover1 112:737b08b3b995 856 uint32_t err_code;
rgrover1 112:737b08b3b995 857
rgrover1 112:737b08b3b995 858 DM_TRC("[DM]: Request to allocation connection instance\r\n");
rgrover1 112:737b08b3b995 859
rgrover1 112:737b08b3b995 860 err_code = connection_instance_find(BLE_CONN_HANDLE_INVALID, STATE_IDLE, p_instance);
rgrover1 112:737b08b3b995 861
rgrover1 112:737b08b3b995 862 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 863 {
rgrover1 112:737b08b3b995 864 DM_LOG("[DM]:[%02X]: Connection Instance Allocated.\r\n", (*p_instance));
rgrover1 112:737b08b3b995 865 m_connection_table[*p_instance].state = STATE_CONNECTED;
rgrover1 112:737b08b3b995 866 }
rgrover1 112:737b08b3b995 867 else
rgrover1 112:737b08b3b995 868 {
rgrover1 112:737b08b3b995 869 DM_LOG("[DM]: No free connection instances available\r\n");
rgrover1 112:737b08b3b995 870 err_code = NRF_ERROR_NO_MEM;
rgrover1 112:737b08b3b995 871 }
rgrover1 112:737b08b3b995 872
rgrover1 112:737b08b3b995 873 return err_code;
rgrover1 112:737b08b3b995 874 }
rgrover1 112:737b08b3b995 875
rgrover1 112:737b08b3b995 876
rgrover1 112:737b08b3b995 877 /**@brief Function for freeing instance. Instance identifier is provided in the parameter
rgrover1 112:737b08b3b995 878 * 'p_instance' in case the routine succeeds.
rgrover1 112:737b08b3b995 879 *
rgrover1 112:737b08b3b995 880 * @param[in] p_instance Connection instance.
rgrover1 112:737b08b3b995 881 */
rgrover1 112:737b08b3b995 882 static __INLINE void connection_instance_free(uint32_t const * p_instance)
rgrover1 112:737b08b3b995 883 {
rgrover1 112:737b08b3b995 884 DM_TRC("[DM]:[CI 0x%02X]: Freeing connection instance\r\n", (*p_instance));
rgrover1 112:737b08b3b995 885
rgrover1 112:737b08b3b995 886 if (m_connection_table[*p_instance].state != STATE_IDLE)
rgrover1 112:737b08b3b995 887 {
rgrover1 112:737b08b3b995 888 DM_LOG("[DM]:[%02X]: Freed connection instance.\r\n", (*p_instance));
rgrover1 112:737b08b3b995 889 connection_instance_init(*p_instance);
rgrover1 112:737b08b3b995 890 }
rgrover1 112:737b08b3b995 891 }
rgrover1 112:737b08b3b995 892
rgrover1 112:737b08b3b995 893
rgrover1 112:737b08b3b995 894 /**@brief Function for storage operation dummy handler.
rgrover1 112:737b08b3b995 895 *
rgrover1 112:737b08b3b995 896 * @param[in] p_dest Destination address where data is to be stored persistently.
rgrover1 112:737b08b3b995 897 * @param[in] p_src Source address containing data to be stored. API assumes this to be resident
rgrover1 112:737b08b3b995 898 * memory and no intermediate copy of data is made by the API.
rgrover1 112:737b08b3b995 899 * @param[in] size Size of data to be stored expressed in bytes. Should be word aligned.
rgrover1 112:737b08b3b995 900 * @param[in] offset Offset in bytes to be applied when writing to the block.
rgrover1 112:737b08b3b995 901 * For example, if within a block of 100 bytes, application wishes to
rgrover1 112:737b08b3b995 902 * write 20 bytes at offset of 12, then this field should be set to 12.
rgrover1 112:737b08b3b995 903 * Should be word aligned.
rgrover1 112:737b08b3b995 904 *
rgrover1 112:737b08b3b995 905 * @retval NRF_SUCCESS Operation success.
rgrover1 112:737b08b3b995 906 */
rgrover1 112:737b08b3b995 907 static uint32_t storage_operation_dummy_handler(pstorage_handle_t * p_dest,
rgrover1 112:737b08b3b995 908 uint8_t * p_src,
rgrover1 112:737b08b3b995 909 pstorage_size_t size,
rgrover1 112:737b08b3b995 910 pstorage_size_t offset)
rgrover1 112:737b08b3b995 911 {
rgrover1 112:737b08b3b995 912 return NRF_SUCCESS;
rgrover1 112:737b08b3b995 913 }
rgrover1 112:737b08b3b995 914
rgrover1 112:737b08b3b995 915
rgrover1 112:737b08b3b995 916 /**@brief Function for saving the device context persistently.
rgrover1 112:737b08b3b995 917 *
rgrover1 112:737b08b3b995 918 * @param[in] p_handle Device handle identifying device.
rgrover1 112:737b08b3b995 919 * @param[in] state Device store state.
rgrover1 112:737b08b3b995 920 */
rgrover1 112:737b08b3b995 921 static __INLINE void device_context_store(dm_handle_t const * p_handle, device_store_state_t state)
rgrover1 112:737b08b3b995 922 {
rgrover1 112:737b08b3b995 923 pstorage_handle_t block_handle;
rgrover1 112:737b08b3b995 924 storage_operation store_fn;
rgrover1 112:737b08b3b995 925 ret_code_t err_code;
rgrover1 112:737b08b3b995 926
rgrover1 112:737b08b3b995 927 DM_LOG("[DM]: --> device_context_store\r\n");
rgrover1 112:737b08b3b995 928
rgrover1 112:737b08b3b995 929 err_code = pstorage_block_identifier_get(&m_storage_handle,
rgrover1 112:737b08b3b995 930 p_handle->device_id,
rgrover1 112:737b08b3b995 931 &block_handle);
rgrover1 112:737b08b3b995 932
rgrover1 112:737b08b3b995 933 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 934 {
rgrover1 112:737b08b3b995 935 if ((STATE_BOND_INFO_UPDATE ==
rgrover1 112:737b08b3b995 936 (m_connection_table[p_handle->connection_id].state & STATE_BOND_INFO_UPDATE)) ||
rgrover1 112:737b08b3b995 937 (state == UPDATE_PEER_ADDR))
rgrover1 112:737b08b3b995 938 {
rgrover1 112:737b08b3b995 939 DM_LOG("[DM]:[DI %02X]:[CI %02X]: -> Updating bonding information.\r\n",
rgrover1 112:737b08b3b995 940 p_handle->device_id, p_handle->connection_id);
rgrover1 112:737b08b3b995 941
rgrover1 112:737b08b3b995 942 store_fn = pstorage_update;
rgrover1 112:737b08b3b995 943 }
rgrover1 112:737b08b3b995 944 else if (state == FIRST_BOND_STORE)
rgrover1 112:737b08b3b995 945 {
rgrover1 112:737b08b3b995 946 DM_LOG("[DM]:[DI %02X]:[CI %02X]: -> Storing bonding information.\r\n",
rgrover1 112:737b08b3b995 947 p_handle->device_id, p_handle->connection_id);
rgrover1 112:737b08b3b995 948
rgrover1 112:737b08b3b995 949 store_fn = pstorage_store;
rgrover1 112:737b08b3b995 950 }
rgrover1 112:737b08b3b995 951 else
rgrover1 112:737b08b3b995 952 {
rgrover1 112:737b08b3b995 953 DM_LOG("[DM]:[DI %02X]:[CI %02X]: -> No update in bonding information.\r\n",
rgrover1 112:737b08b3b995 954 p_handle->device_id, p_handle->connection_id);
rgrover1 112:737b08b3b995 955
rgrover1 112:737b08b3b995 956 //No operation needed.
rgrover1 112:737b08b3b995 957 store_fn = storage_operation_dummy_handler;
rgrover1 112:737b08b3b995 958 }
rgrover1 112:737b08b3b995 959
rgrover1 112:737b08b3b995 960 //Store the peer id.
rgrover1 112:737b08b3b995 961 err_code = store_fn(&block_handle,
rgrover1 112:737b08b3b995 962 (uint8_t *)&m_peer_table[p_handle->device_id],
rgrover1 112:737b08b3b995 963 PEER_ID_SIZE,
rgrover1 112:737b08b3b995 964 PEER_ID_STORAGE_OFFSET);
rgrover1 112:737b08b3b995 965
rgrover1 112:737b08b3b995 966 if ((err_code == NRF_SUCCESS) && (state != UPDATE_PEER_ADDR))
rgrover1 112:737b08b3b995 967 {
rgrover1 112:737b08b3b995 968 m_connection_table[p_handle->connection_id].state &= (~STATE_BOND_INFO_UPDATE);
rgrover1 112:737b08b3b995 969
rgrover1 112:737b08b3b995 970 //Store the bond information.
rgrover1 112:737b08b3b995 971 err_code = store_fn(&block_handle,
rgrover1 112:737b08b3b995 972 (uint8_t *)&m_bond_table[p_handle->connection_id],
rgrover1 112:737b08b3b995 973 BOND_SIZE,
rgrover1 112:737b08b3b995 974 BOND_STORAGE_OFFSET);
rgrover1 112:737b08b3b995 975
rgrover1 112:737b08b3b995 976 if (err_code != NRF_SUCCESS)
rgrover1 112:737b08b3b995 977 {
rgrover1 112:737b08b3b995 978 DM_ERR("[DM]:[0x%02X]:Failed to store bond information, reason 0x%08X\r\n",
rgrover1 112:737b08b3b995 979 p_handle->device_id, err_code);
rgrover1 112:737b08b3b995 980 }
rgrover1 112:737b08b3b995 981 }
rgrover1 112:737b08b3b995 982
rgrover1 112:737b08b3b995 983 if (state != UPDATE_PEER_ADDR)
rgrover1 112:737b08b3b995 984 {
rgrover1 112:737b08b3b995 985 //Store the service information
rgrover1 112:737b08b3b995 986 err_code = m_service_context_store[m_application_table[p_handle->appl_id].service]
rgrover1 112:737b08b3b995 987 (
rgrover1 112:737b08b3b995 988 &block_handle,
rgrover1 112:737b08b3b995 989 p_handle
rgrover1 112:737b08b3b995 990 );
rgrover1 112:737b08b3b995 991
rgrover1 112:737b08b3b995 992 if (err_code != NRF_SUCCESS)
rgrover1 112:737b08b3b995 993 {
rgrover1 112:737b08b3b995 994 //Notify application of an error event.
rgrover1 112:737b08b3b995 995 DM_ERR("[DM]: Failed to store service context, reason %08X\r\n", err_code);
rgrover1 112:737b08b3b995 996 }
rgrover1 112:737b08b3b995 997 }
rgrover1 112:737b08b3b995 998 }
rgrover1 112:737b08b3b995 999
rgrover1 112:737b08b3b995 1000 if (err_code != NRF_SUCCESS)
rgrover1 112:737b08b3b995 1001 {
rgrover1 112:737b08b3b995 1002 //Notify application of an error event.
rgrover1 112:737b08b3b995 1003 DM_ERR("[DM]: Failed to store device context, reason %08X\r\n", err_code);
rgrover1 112:737b08b3b995 1004 }
rgrover1 112:737b08b3b995 1005 }
rgrover1 112:737b08b3b995 1006
rgrover1 112:737b08b3b995 1007
rgrover1 112:737b08b3b995 1008 /**@brief Function for storing when there is no service registered.
rgrover1 112:737b08b3b995 1009 *
rgrover1 112:737b08b3b995 1010 * @param[in] p_block_handle Storage block identifier.
rgrover1 112:737b08b3b995 1011 * @param[in] p_handle Device handle identifying device that is loaded.
rgrover1 112:737b08b3b995 1012 *
rgrover1 112:737b08b3b995 1013 * @retval NRF_SUCCESS
rgrover1 112:737b08b3b995 1014 */
rgrover1 112:737b08b3b995 1015 static __INLINE ret_code_t no_service_context_store(pstorage_handle_t const * p_block_handle,
rgrover1 112:737b08b3b995 1016 dm_handle_t const * p_handle)
rgrover1 112:737b08b3b995 1017 {
rgrover1 112:737b08b3b995 1018 DM_LOG("[DM]: --> no_service_context_store\r\n");
rgrover1 112:737b08b3b995 1019
rgrover1 112:737b08b3b995 1020 return NRF_SUCCESS;
rgrover1 112:737b08b3b995 1021 }
rgrover1 112:737b08b3b995 1022
rgrover1 112:737b08b3b995 1023
rgrover1 112:737b08b3b995 1024 /**@brief Function for storing GATT Server context.
rgrover1 112:737b08b3b995 1025 *
rgrover1 112:737b08b3b995 1026 * @param[in] p_block_handle Storage block identifier.
rgrover1 112:737b08b3b995 1027 * @param[in] p_handle Device handle identifying device that is stored.
rgrover1 112:737b08b3b995 1028 *
rgrover1 112:737b08b3b995 1029 * @retval NRF_SUCCESS Operation success.
rgrover1 112:737b08b3b995 1030 */
rgrover1 112:737b08b3b995 1031 static __INLINE ret_code_t gatts_context_store(pstorage_handle_t const * p_block_handle,
rgrover1 112:737b08b3b995 1032 dm_handle_t const * p_handle)
rgrover1 112:737b08b3b995 1033 {
rgrover1 112:737b08b3b995 1034 storage_operation store_fn;
rgrover1 112:737b08b3b995 1035 uint32_t attr_flags = BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS | BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS;
rgrover1 112:737b08b3b995 1036 uint16_t attr_len = DM_GATT_SERVER_ATTR_MAX_SIZE;
rgrover1 112:737b08b3b995 1037 uint8_t sys_data[DM_GATT_SERVER_ATTR_MAX_SIZE];
rgrover1 112:737b08b3b995 1038
rgrover1 112:737b08b3b995 1039 DM_LOG("[DM]: --> gatts_context_store\r\n");
rgrover1 112:737b08b3b995 1040
rgrover1 112:737b08b3b995 1041 uint32_t err_code = sd_ble_gatts_sys_attr_get(
rgrover1 112:737b08b3b995 1042 m_connection_table[p_handle->connection_id].conn_handle,
rgrover1 112:737b08b3b995 1043 sys_data,
rgrover1 112:737b08b3b995 1044 &attr_len,
rgrover1 112:737b08b3b995 1045 attr_flags);
rgrover1 112:737b08b3b995 1046
rgrover1 112:737b08b3b995 1047 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 1048 {
rgrover1 112:737b08b3b995 1049 if (memcmp(m_gatts_table[p_handle->connection_id].attributes, sys_data, attr_len) == 0)
rgrover1 112:737b08b3b995 1050 {
rgrover1 112:737b08b3b995 1051 //No store operation is needed.
rgrover1 112:737b08b3b995 1052 DM_LOG("[DM]:[0x%02X]: No change in GATTS Context information.\r\n",
rgrover1 112:737b08b3b995 1053 p_handle->device_id);
rgrover1 112:737b08b3b995 1054
rgrover1 112:737b08b3b995 1055 if ((m_connection_table[p_handle->connection_id].state & STATE_CONNECTED) !=
rgrover1 112:737b08b3b995 1056 STATE_CONNECTED)
rgrover1 112:737b08b3b995 1057 {
rgrover1 112:737b08b3b995 1058 DM_LOG("[DM]:[0x%02X]: Resetting GATTS for active instance.\r\n",
rgrover1 112:737b08b3b995 1059 p_handle->connection_id);
rgrover1 112:737b08b3b995 1060
rgrover1 112:737b08b3b995 1061 //Reset GATTS information for the current context.
rgrover1 112:737b08b3b995 1062 memset(&m_gatts_table[p_handle->connection_id], 0, sizeof(dm_gatts_context_t));
rgrover1 112:737b08b3b995 1063 }
rgrover1 112:737b08b3b995 1064 }
rgrover1 112:737b08b3b995 1065 else
rgrover1 112:737b08b3b995 1066 {
rgrover1 112:737b08b3b995 1067 if (m_gatts_table[p_handle->connection_id].size != 0)
rgrover1 112:737b08b3b995 1068 {
rgrover1 112:737b08b3b995 1069 //There is data already stored in persistent memory, therefore an update is needed.
rgrover1 112:737b08b3b995 1070 DM_LOG("[DM]:[0x%02X]: Updating stored service context\r\n", p_handle->device_id);
rgrover1 112:737b08b3b995 1071
rgrover1 112:737b08b3b995 1072 store_fn = pstorage_update;
rgrover1 112:737b08b3b995 1073 }
rgrover1 112:737b08b3b995 1074 else
rgrover1 112:737b08b3b995 1075 {
rgrover1 112:737b08b3b995 1076 //Fresh write, a store is needed.
rgrover1 112:737b08b3b995 1077 DM_LOG("[DM]:[0x%02X]: Storing service context\r\n", p_handle->device_id);
rgrover1 112:737b08b3b995 1078
rgrover1 112:737b08b3b995 1079 store_fn = pstorage_store;
rgrover1 112:737b08b3b995 1080 }
rgrover1 112:737b08b3b995 1081
rgrover1 112:737b08b3b995 1082 m_gatts_table[p_handle->connection_id].flags = attr_flags;
rgrover1 112:737b08b3b995 1083 m_gatts_table[p_handle->connection_id].size = attr_len;
rgrover1 112:737b08b3b995 1084 memcpy(m_gatts_table[p_handle->connection_id].attributes, sys_data, attr_len);
rgrover1 112:737b08b3b995 1085
rgrover1 112:737b08b3b995 1086 DM_DUMP((uint8_t *)&m_gatts_table[p_handle->connection_id], sizeof(dm_gatts_context_t));
rgrover1 112:737b08b3b995 1087
rgrover1 112:737b08b3b995 1088 DM_LOG("[DM]:[0x%02X]: GATTS Data size 0x%08X\r\n",
rgrover1 112:737b08b3b995 1089 p_handle->device_id,
rgrover1 112:737b08b3b995 1090 m_gatts_table[p_handle->connection_id].size);
rgrover1 112:737b08b3b995 1091
rgrover1 112:737b08b3b995 1092 //Store GATTS information.
rgrover1 112:737b08b3b995 1093 err_code = store_fn((pstorage_handle_t *)p_block_handle,
rgrover1 112:737b08b3b995 1094 (uint8_t *)&m_gatts_table[p_handle->connection_id],
rgrover1 112:737b08b3b995 1095 GATTS_SERVICE_CONTEXT_SIZE,
rgrover1 112:737b08b3b995 1096 SERVICE_STORAGE_OFFSET);
rgrover1 112:737b08b3b995 1097
rgrover1 112:737b08b3b995 1098 if (err_code != NRF_SUCCESS)
rgrover1 112:737b08b3b995 1099 {
rgrover1 112:737b08b3b995 1100 DM_ERR("[DM]:[0x%02X]:Failed to store service context, reason 0x%08X\r\n",
rgrover1 112:737b08b3b995 1101 p_handle->device_id,
rgrover1 112:737b08b3b995 1102 err_code);
rgrover1 112:737b08b3b995 1103 }
rgrover1 112:737b08b3b995 1104 else
rgrover1 112:737b08b3b995 1105 {
rgrover1 112:737b08b3b995 1106 DM_LOG("[DM]: Service context successfully stored.\r\n");
rgrover1 112:737b08b3b995 1107 }
rgrover1 112:737b08b3b995 1108 }
rgrover1 112:737b08b3b995 1109 }
rgrover1 112:737b08b3b995 1110
rgrover1 112:737b08b3b995 1111 return NRF_SUCCESS;
rgrover1 112:737b08b3b995 1112 }
rgrover1 112:737b08b3b995 1113
rgrover1 112:737b08b3b995 1114
rgrover1 112:737b08b3b995 1115 /**@brief Function for storing GATT Client context.
rgrover1 112:737b08b3b995 1116 *
rgrover1 112:737b08b3b995 1117 * @param[in] p_block_handle Storage block identifier.
rgrover1 112:737b08b3b995 1118 * @param[in] p_handle Device handle identifying device that is stored.
rgrover1 112:737b08b3b995 1119 *
rgrover1 112:737b08b3b995 1120 * @retval NRF_SUCCESS Operation success.
rgrover1 112:737b08b3b995 1121 */
rgrover1 112:737b08b3b995 1122 static __INLINE ret_code_t gattc_context_store(pstorage_handle_t const * p_block_handle,
rgrover1 112:737b08b3b995 1123 dm_handle_t const * p_handle)
rgrover1 112:737b08b3b995 1124 {
rgrover1 112:737b08b3b995 1125 DM_LOG("[DM]: --> gattc_context_store\r\n");
rgrover1 112:737b08b3b995 1126
rgrover1 112:737b08b3b995 1127 return NRF_SUCCESS;
rgrover1 112:737b08b3b995 1128 }
rgrover1 112:737b08b3b995 1129
rgrover1 112:737b08b3b995 1130
rgrover1 112:737b08b3b995 1131 /**@brief Function for storing GATT Server & Client context.
rgrover1 112:737b08b3b995 1132 *
rgrover1 112:737b08b3b995 1133 * @param[in] p_block_handle Storage block identifier.
rgrover1 112:737b08b3b995 1134 * @param[in] p_handle Device handle identifying device that is stored.
rgrover1 112:737b08b3b995 1135 *
rgrover1 112:737b08b3b995 1136 * @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
rgrover1 112:737b08b3b995 1137 */
rgrover1 112:737b08b3b995 1138 static __INLINE ret_code_t gattsc_context_store(pstorage_handle_t const * p_block_handle,
rgrover1 112:737b08b3b995 1139 dm_handle_t const * p_handle)
rgrover1 112:737b08b3b995 1140 {
rgrover1 112:737b08b3b995 1141 DM_LOG("[DM]: --> gattsc_context_store\r\n");
rgrover1 112:737b08b3b995 1142
rgrover1 112:737b08b3b995 1143 ret_code_t err_code = gatts_context_store(p_block_handle, p_handle);
rgrover1 112:737b08b3b995 1144
rgrover1 112:737b08b3b995 1145 if (NRF_SUCCESS == err_code)
rgrover1 112:737b08b3b995 1146 {
rgrover1 112:737b08b3b995 1147 err_code = gattc_context_store(p_block_handle, p_handle);
rgrover1 112:737b08b3b995 1148 }
rgrover1 112:737b08b3b995 1149
rgrover1 112:737b08b3b995 1150 return err_code;
rgrover1 112:737b08b3b995 1151 }
rgrover1 112:737b08b3b995 1152
rgrover1 112:737b08b3b995 1153
rgrover1 112:737b08b3b995 1154 /**@brief Function for loading when there is no service registered.
rgrover1 112:737b08b3b995 1155 *
rgrover1 112:737b08b3b995 1156 * @param[in] p_block_handle Storage block identifier.
rgrover1 112:737b08b3b995 1157 * @param[in] p_handle Device handle identifying device that is loaded.
rgrover1 112:737b08b3b995 1158 *
rgrover1 112:737b08b3b995 1159 * @retval NRF_SUCCESS
rgrover1 112:737b08b3b995 1160 */
rgrover1 112:737b08b3b995 1161 static __INLINE ret_code_t no_service_context_load(pstorage_handle_t const * p_block_handle,
rgrover1 112:737b08b3b995 1162 dm_handle_t const * p_handle)
rgrover1 112:737b08b3b995 1163 {
rgrover1 112:737b08b3b995 1164 DM_LOG("[DM]: --> no_service_context_load\r\n");
rgrover1 112:737b08b3b995 1165
rgrover1 112:737b08b3b995 1166 return NRF_SUCCESS;
rgrover1 112:737b08b3b995 1167 }
rgrover1 112:737b08b3b995 1168
rgrover1 112:737b08b3b995 1169
rgrover1 112:737b08b3b995 1170 /**@brief Function for loading GATT Server context.
rgrover1 112:737b08b3b995 1171 *
rgrover1 112:737b08b3b995 1172 * @param[in] p_block_handle Storage block identifier.
rgrover1 112:737b08b3b995 1173 * @param[in] p_handle Device handle identifying device that is loaded.
rgrover1 112:737b08b3b995 1174 *
rgrover1 112:737b08b3b995 1175 * @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
rgrover1 112:737b08b3b995 1176 */
rgrover1 112:737b08b3b995 1177 static __INLINE ret_code_t gatts_context_load(pstorage_handle_t const * p_block_handle,
rgrover1 112:737b08b3b995 1178 dm_handle_t const * p_handle)
rgrover1 112:737b08b3b995 1179 {
rgrover1 112:737b08b3b995 1180 DM_LOG("[DM]:[CI 0x%02X]:[DI 0x%02X]: --> gatts_context_load\r\n",
rgrover1 112:737b08b3b995 1181 p_handle->connection_id,
rgrover1 112:737b08b3b995 1182 p_handle->device_id);
rgrover1 112:737b08b3b995 1183
rgrover1 112:737b08b3b995 1184 ret_code_t err_code = pstorage_load((uint8_t *)&m_gatts_table[p_handle->connection_id],
rgrover1 112:737b08b3b995 1185 (pstorage_handle_t *)p_block_handle,
rgrover1 112:737b08b3b995 1186 GATTS_SERVICE_CONTEXT_SIZE,
rgrover1 112:737b08b3b995 1187 SERVICE_STORAGE_OFFSET);
rgrover1 112:737b08b3b995 1188
rgrover1 112:737b08b3b995 1189 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 1190 {
rgrover1 112:737b08b3b995 1191 DM_LOG("[DM]:[%02X]:[Block ID 0x%08X]: Service context loaded, size 0x%08X\r\n",
rgrover1 112:737b08b3b995 1192 p_handle->connection_id,
rgrover1 112:737b08b3b995 1193 p_block_handle->block_id,
rgrover1 112:737b08b3b995 1194 m_gatts_table[p_handle->connection_id].size);
rgrover1 112:737b08b3b995 1195 DM_DUMP((uint8_t *)&m_gatts_table[p_handle->connection_id], sizeof(dm_gatts_context_t));
rgrover1 112:737b08b3b995 1196
rgrover1 112:737b08b3b995 1197 if (m_gatts_table[p_handle->connection_id].size == DM_GATTS_INVALID_SIZE)
rgrover1 112:737b08b3b995 1198 {
rgrover1 112:737b08b3b995 1199 m_gatts_table[p_handle->connection_id].size = 0;
rgrover1 112:737b08b3b995 1200 }
rgrover1 112:737b08b3b995 1201 }
rgrover1 112:737b08b3b995 1202 else
rgrover1 112:737b08b3b995 1203 {
rgrover1 112:737b08b3b995 1204 DM_ERR("[DM]:[%02X]: Failed to load Service context, reason %08X\r\n",
rgrover1 112:737b08b3b995 1205 p_handle->connection_id,
rgrover1 112:737b08b3b995 1206 err_code);
rgrover1 112:737b08b3b995 1207 }
rgrover1 112:737b08b3b995 1208
rgrover1 112:737b08b3b995 1209 return err_code;
rgrover1 112:737b08b3b995 1210 }
rgrover1 112:737b08b3b995 1211
rgrover1 112:737b08b3b995 1212
rgrover1 112:737b08b3b995 1213 /**@brief Function for loading GATT Client context.
rgrover1 112:737b08b3b995 1214 *
rgrover1 112:737b08b3b995 1215 * @param[in] p_block_handle Storage block identifier.
rgrover1 112:737b08b3b995 1216 * @param[in] p_handle Device handle identifying device that is loaded.
rgrover1 112:737b08b3b995 1217 *
rgrover1 112:737b08b3b995 1218 * @retval NRF_SUCCESS
rgrover1 112:737b08b3b995 1219 */
rgrover1 112:737b08b3b995 1220 static __INLINE ret_code_t gattc_context_load(pstorage_handle_t const * p_block_handle,
rgrover1 112:737b08b3b995 1221 dm_handle_t const * p_handle)
rgrover1 112:737b08b3b995 1222 {
rgrover1 112:737b08b3b995 1223 DM_LOG("[DM]: --> gattc_context_load\r\n");
rgrover1 112:737b08b3b995 1224
rgrover1 112:737b08b3b995 1225 return NRF_SUCCESS;
rgrover1 112:737b08b3b995 1226 }
rgrover1 112:737b08b3b995 1227
rgrover1 112:737b08b3b995 1228
rgrover1 112:737b08b3b995 1229 /**@brief Function for loading GATT Server & Client context.
rgrover1 112:737b08b3b995 1230 *
rgrover1 112:737b08b3b995 1231 * @param[in] p_block_handle Storage block identifier.
rgrover1 112:737b08b3b995 1232 * @param[in] p_handle Device handle identifying device that is loaded.
rgrover1 112:737b08b3b995 1233 *
rgrover1 112:737b08b3b995 1234 * @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
rgrover1 112:737b08b3b995 1235 */
rgrover1 112:737b08b3b995 1236 static __INLINE ret_code_t gattsc_context_load(pstorage_handle_t const * p_block_handle,
rgrover1 112:737b08b3b995 1237 dm_handle_t const * p_handle)
rgrover1 112:737b08b3b995 1238 {
rgrover1 112:737b08b3b995 1239 DM_LOG("[DM]: --> gattsc_context_load\r\n");
rgrover1 112:737b08b3b995 1240
rgrover1 112:737b08b3b995 1241 ret_code_t err_code = gatts_context_load(p_block_handle, p_handle);
rgrover1 112:737b08b3b995 1242
rgrover1 112:737b08b3b995 1243 if (NRF_SUCCESS == err_code)
rgrover1 112:737b08b3b995 1244 {
rgrover1 112:737b08b3b995 1245 err_code = gattc_context_load(p_block_handle, p_handle);
rgrover1 112:737b08b3b995 1246 }
rgrover1 112:737b08b3b995 1247
rgrover1 112:737b08b3b995 1248 return err_code;
rgrover1 112:737b08b3b995 1249 }
rgrover1 112:737b08b3b995 1250
rgrover1 112:737b08b3b995 1251
rgrover1 112:737b08b3b995 1252 /**@brief Function for applying when there is no service registered.
rgrover1 112:737b08b3b995 1253 *
rgrover1 112:737b08b3b995 1254 * @param[in] p_handle Device handle identifying device that is applied.
rgrover1 112:737b08b3b995 1255 *
rgrover1 112:737b08b3b995 1256 * @retval NRF_SUCCESS
rgrover1 112:737b08b3b995 1257 */
rgrover1 112:737b08b3b995 1258 static __INLINE ret_code_t no_service_context_apply(dm_handle_t * p_handle)
rgrover1 112:737b08b3b995 1259 {
rgrover1 112:737b08b3b995 1260 DM_LOG("[DM]: --> no_service_context_apply\r\n");
rgrover1 112:737b08b3b995 1261 DM_LOG("[DM]:[CI 0x%02X]: No Service context\r\n", p_handle->connection_id);
rgrover1 112:737b08b3b995 1262
rgrover1 112:737b08b3b995 1263 return NRF_SUCCESS;
rgrover1 112:737b08b3b995 1264 }
rgrover1 112:737b08b3b995 1265
rgrover1 112:737b08b3b995 1266
rgrover1 112:737b08b3b995 1267 /**@brief Function for applying GATT Server context.
rgrover1 112:737b08b3b995 1268 *
rgrover1 112:737b08b3b995 1269 * @param[in] p_handle Device handle identifying device that is applied.
rgrover1 112:737b08b3b995 1270 *
rgrover1 112:737b08b3b995 1271 * @retval NRF_SUCCESS On success.
rgrover1 112:737b08b3b995 1272 * @retval DM_SERVICE_CONTEXT_NOT_APPLIED On failure.
rgrover1 112:737b08b3b995 1273 */
rgrover1 112:737b08b3b995 1274 static __INLINE ret_code_t gatts_context_apply(dm_handle_t * p_handle)
rgrover1 112:737b08b3b995 1275 {
rgrover1 112:737b08b3b995 1276 uint32_t err_code;
rgrover1 112:737b08b3b995 1277
rgrover1 112:737b08b3b995 1278 uint8_t * p_gatts_context = NULL;
rgrover1 112:737b08b3b995 1279 uint16_t context_len = 0;
rgrover1 112:737b08b3b995 1280 uint32_t context_flags = 0;
rgrover1 112:737b08b3b995 1281
rgrover1 112:737b08b3b995 1282 DM_LOG("[DM]: --> gatts_context_apply\r\n");
rgrover1 112:737b08b3b995 1283 DM_LOG("[DM]:[CI 0x%02X]: State 0x%02X, Size 0x%08X\r\n",
rgrover1 112:737b08b3b995 1284 p_handle->connection_id,
rgrover1 112:737b08b3b995 1285 m_connection_table[p_handle->connection_id].state,
rgrover1 112:737b08b3b995 1286 m_gatts_table[p_handle->connection_id].size);
rgrover1 112:737b08b3b995 1287
rgrover1 112:737b08b3b995 1288 if ((m_gatts_table[p_handle->connection_id].size != 0) &&
rgrover1 112:737b08b3b995 1289 (
rgrover1 112:737b08b3b995 1290 ((m_connection_table[p_handle->connection_id].state & STATE_LINK_ENCRYPTED) == STATE_LINK_ENCRYPTED) &&
rgrover1 112:737b08b3b995 1291 ((m_connection_table[p_handle->connection_id].state & STATE_BOND_INFO_UPDATE)
rgrover1 112:737b08b3b995 1292 != STATE_BOND_INFO_UPDATE)
rgrover1 112:737b08b3b995 1293 )
rgrover1 112:737b08b3b995 1294 )
rgrover1 112:737b08b3b995 1295 {
rgrover1 112:737b08b3b995 1296 DM_LOG("[DM]: Setting stored context.\r\n");
rgrover1 112:737b08b3b995 1297
rgrover1 112:737b08b3b995 1298 p_gatts_context = &m_gatts_table[p_handle->connection_id].attributes[0];
rgrover1 112:737b08b3b995 1299 context_len = m_gatts_table[p_handle->connection_id].size;
rgrover1 112:737b08b3b995 1300 context_flags = m_gatts_table[p_handle->connection_id].flags;
rgrover1 112:737b08b3b995 1301 }
rgrover1 112:737b08b3b995 1302
rgrover1 112:737b08b3b995 1303 err_code = sd_ble_gatts_sys_attr_set(m_connection_table[p_handle->connection_id].conn_handle,
rgrover1 112:737b08b3b995 1304 p_gatts_context,
rgrover1 112:737b08b3b995 1305 context_len,
rgrover1 112:737b08b3b995 1306 context_flags);
rgrover1 112:737b08b3b995 1307
rgrover1 112:737b08b3b995 1308 if (err_code == NRF_ERROR_INVALID_DATA)
rgrover1 112:737b08b3b995 1309 {
rgrover1 112:737b08b3b995 1310 // Indication that the ATT table has changed. Restore the system attributes to system
rgrover1 112:737b08b3b995 1311 // services only and send a service changed indication if possible.
rgrover1 112:737b08b3b995 1312 context_flags = BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS;
rgrover1 112:737b08b3b995 1313 err_code = sd_ble_gatts_sys_attr_set(m_connection_table[p_handle->connection_id].conn_handle,
rgrover1 112:737b08b3b995 1314 p_gatts_context,
rgrover1 112:737b08b3b995 1315 context_len,
rgrover1 112:737b08b3b995 1316 context_flags);
rgrover1 112:737b08b3b995 1317 }
rgrover1 112:737b08b3b995 1318
rgrover1 112:737b08b3b995 1319 if (err_code != NRF_SUCCESS)
rgrover1 112:737b08b3b995 1320 {
rgrover1 112:737b08b3b995 1321 DM_LOG("[DM]: Failed to set system attributes, reason 0x%08X.\r\n", err_code);
rgrover1 112:737b08b3b995 1322
rgrover1 112:737b08b3b995 1323 err_code = DM_SERVICE_CONTEXT_NOT_APPLIED;
rgrover1 112:737b08b3b995 1324 }
rgrover1 112:737b08b3b995 1325
rgrover1 112:737b08b3b995 1326 if (context_flags == BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS)
rgrover1 112:737b08b3b995 1327 {
rgrover1 112:737b08b3b995 1328 err_code = sd_ble_gatts_service_changed(m_connection_table[p_handle->connection_id].conn_handle,
rgrover1 112:737b08b3b995 1329 0x000C,
rgrover1 112:737b08b3b995 1330 0xFFFF);
rgrover1 112:737b08b3b995 1331 if (err_code != NRF_SUCCESS)
rgrover1 112:737b08b3b995 1332 {
rgrover1 112:737b08b3b995 1333 DM_LOG("[DM]: Failed to send Service Changed indication, reason 0x%08X.\r\n", err_code);
rgrover1 112:737b08b3b995 1334 if ((err_code != BLE_ERROR_INVALID_CONN_HANDLE) &&
rgrover1 112:737b08b3b995 1335 (err_code != NRF_ERROR_INVALID_STATE) &&
rgrover1 112:737b08b3b995 1336 (err_code != BLE_ERROR_NO_TX_BUFFERS) &&
rgrover1 112:737b08b3b995 1337 (err_code != NRF_ERROR_BUSY))
rgrover1 112:737b08b3b995 1338 {
rgrover1 112:737b08b3b995 1339 // Those errors can be expected when sending trying to send Service Changed
rgrover1 112:737b08b3b995 1340 // Indication if the CCCD is not set to indicate. Thus set the returning error
rgrover1 112:737b08b3b995 1341 // code to success.
rgrover1 112:737b08b3b995 1342 err_code = NRF_SUCCESS;
rgrover1 112:737b08b3b995 1343 }
rgrover1 112:737b08b3b995 1344 else
rgrover1 112:737b08b3b995 1345 {
rgrover1 112:737b08b3b995 1346 err_code = DM_SERVICE_CONTEXT_NOT_APPLIED;
rgrover1 112:737b08b3b995 1347 }
rgrover1 112:737b08b3b995 1348 }
rgrover1 112:737b08b3b995 1349 }
rgrover1 112:737b08b3b995 1350
rgrover1 112:737b08b3b995 1351 return err_code;
rgrover1 112:737b08b3b995 1352 }
rgrover1 112:737b08b3b995 1353
rgrover1 112:737b08b3b995 1354
rgrover1 112:737b08b3b995 1355 /**@brief Function for applying GATT Client context.
rgrover1 112:737b08b3b995 1356 *
rgrover1 112:737b08b3b995 1357 * @param[in] p_handle Device handle identifying device that is applied.
rgrover1 112:737b08b3b995 1358 *
rgrover1 112:737b08b3b995 1359 * @retval NRF_SUCCESS On success.
rgrover1 112:737b08b3b995 1360 */
rgrover1 112:737b08b3b995 1361 static __INLINE ret_code_t gattc_context_apply(dm_handle_t * p_handle)
rgrover1 112:737b08b3b995 1362 {
rgrover1 112:737b08b3b995 1363 DM_LOG("[DM]: --> gattc_context_apply\r\n");
rgrover1 112:737b08b3b995 1364
rgrover1 112:737b08b3b995 1365 return NRF_SUCCESS;
rgrover1 112:737b08b3b995 1366 }
rgrover1 112:737b08b3b995 1367
rgrover1 112:737b08b3b995 1368
rgrover1 112:737b08b3b995 1369 /**@brief Function for applying GATT Server & Client context.
rgrover1 112:737b08b3b995 1370 *
rgrover1 112:737b08b3b995 1371 * @param[in] p_handle Device handle identifying device that is applied.
rgrover1 112:737b08b3b995 1372 *
rgrover1 112:737b08b3b995 1373 * @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
rgrover1 112:737b08b3b995 1374 */
rgrover1 112:737b08b3b995 1375 static __INLINE ret_code_t gattsc_context_apply(dm_handle_t * p_handle)
rgrover1 112:737b08b3b995 1376 {
rgrover1 112:737b08b3b995 1377 uint32_t err_code;
rgrover1 112:737b08b3b995 1378
rgrover1 112:737b08b3b995 1379 DM_LOG("[DM]: --> gattsc_context_apply\r\n");
rgrover1 112:737b08b3b995 1380
rgrover1 112:737b08b3b995 1381 err_code = gatts_context_apply(p_handle);
rgrover1 112:737b08b3b995 1382
rgrover1 112:737b08b3b995 1383 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 1384 {
rgrover1 112:737b08b3b995 1385 err_code = gattc_context_apply(p_handle);
rgrover1 112:737b08b3b995 1386 }
rgrover1 112:737b08b3b995 1387
rgrover1 112:737b08b3b995 1388 return err_code;
rgrover1 112:737b08b3b995 1389 }
rgrover1 112:737b08b3b995 1390
rgrover1 112:737b08b3b995 1391
rgrover1 112:737b08b3b995 1392 /**@brief Function for pstorage module callback.
rgrover1 112:737b08b3b995 1393 *
rgrover1 112:737b08b3b995 1394 * @param[in] p_handle Identifies module and block for which callback is received.
rgrover1 112:737b08b3b995 1395 * @param[in] op_code Identifies the operation for which the event is notified.
rgrover1 112:737b08b3b995 1396 * @param[in] result Identifies the result of flash access operation.
rgrover1 112:737b08b3b995 1397 * NRF_SUCCESS implies, operation succeeded.
rgrover1 112:737b08b3b995 1398 * @param[in] p_data Identifies the application data pointer. In case of store operation, this
rgrover1 112:737b08b3b995 1399 * points to the resident source of application memory that application can now
rgrover1 112:737b08b3b995 1400 * free or reuse. In case of clear, this is NULL as no application pointer is
rgrover1 112:737b08b3b995 1401 * needed for this operation.
rgrover1 112:737b08b3b995 1402 * @param[in] data_len Length of data provided by the application for the operation.
rgrover1 112:737b08b3b995 1403 */
rgrover1 112:737b08b3b995 1404 static void dm_pstorage_cb_handler(pstorage_handle_t * p_handle,
rgrover1 112:737b08b3b995 1405 uint8_t op_code,
rgrover1 112:737b08b3b995 1406 uint32_t result,
rgrover1 112:737b08b3b995 1407 uint8_t * p_data,
rgrover1 112:737b08b3b995 1408 uint32_t data_len)
rgrover1 112:737b08b3b995 1409 {
rgrover1 112:737b08b3b995 1410 VERIFY_APP_REGISTERED_VOID(0);
rgrover1 112:737b08b3b995 1411
rgrover1 112:737b08b3b995 1412 if (data_len > ALL_CONTEXT_SIZE)
rgrover1 112:737b08b3b995 1413 {
rgrover1 112:737b08b3b995 1414 //Clearing of all bonds at initialization, no event is generated.
rgrover1 112:737b08b3b995 1415 return;
rgrover1 112:737b08b3b995 1416 }
rgrover1 112:737b08b3b995 1417
rgrover1 112:737b08b3b995 1418 DM_MUTEX_LOCK();
rgrover1 112:737b08b3b995 1419
rgrover1 112:737b08b3b995 1420 dm_event_t dm_event;
rgrover1 112:737b08b3b995 1421 dm_handle_t dm_handle;
rgrover1 112:737b08b3b995 1422 dm_context_t context_data;
rgrover1 112:737b08b3b995 1423 pstorage_handle_t block_handle;
rgrover1 112:737b08b3b995 1424 uint32_t index_count;
rgrover1 112:737b08b3b995 1425 uint32_t err_code;
rgrover1 112:737b08b3b995 1426
rgrover1 112:737b08b3b995 1427 bool app_notify = true;
rgrover1 112:737b08b3b995 1428
rgrover1 112:737b08b3b995 1429 err_code = dm_handle_initialize(&dm_handle);
rgrover1 112:737b08b3b995 1430 APP_ERROR_CHECK(err_code);
rgrover1 112:737b08b3b995 1431
rgrover1 112:737b08b3b995 1432 dm_handle.appl_id = 0;
rgrover1 112:737b08b3b995 1433 dm_event.event_id = 0x00;
rgrover1 112:737b08b3b995 1434
rgrover1 112:737b08b3b995 1435 //Construct the event which it is related to.
rgrover1 112:737b08b3b995 1436
rgrover1 112:737b08b3b995 1437 //Initialize context data information and length.
rgrover1 112:737b08b3b995 1438 context_data.p_data = p_data;
rgrover1 112:737b08b3b995 1439 context_data.len = data_len;
rgrover1 112:737b08b3b995 1440
rgrover1 112:737b08b3b995 1441 for (uint32_t index = 0; index < DEVICE_MANAGER_MAX_BONDS; index++)
rgrover1 112:737b08b3b995 1442 {
rgrover1 112:737b08b3b995 1443 err_code = pstorage_block_identifier_get(&m_storage_handle, index, &block_handle);
rgrover1 112:737b08b3b995 1444 if ((err_code == NRF_SUCCESS) &&
rgrover1 112:737b08b3b995 1445 (
rgrover1 112:737b08b3b995 1446 (memcmp(p_handle, &block_handle, sizeof(pstorage_handle_t)) == 0)
rgrover1 112:737b08b3b995 1447 )
rgrover1 112:737b08b3b995 1448 )
rgrover1 112:737b08b3b995 1449 {
rgrover1 112:737b08b3b995 1450 dm_handle.device_id = index;
rgrover1 112:737b08b3b995 1451 break;
rgrover1 112:737b08b3b995 1452 }
rgrover1 112:737b08b3b995 1453 }
rgrover1 112:737b08b3b995 1454
rgrover1 112:737b08b3b995 1455 if (dm_handle.device_id != DM_INVALID_ID)
rgrover1 112:737b08b3b995 1456 {
rgrover1 112:737b08b3b995 1457 if (op_code == PSTORAGE_CLEAR_OP_CODE)
rgrover1 112:737b08b3b995 1458 {
rgrover1 112:737b08b3b995 1459 if (data_len == ALL_CONTEXT_SIZE)
rgrover1 112:737b08b3b995 1460 {
rgrover1 112:737b08b3b995 1461 dm_event.event_id = DM_EVT_DEVICE_CONTEXT_BASE;
rgrover1 112:737b08b3b995 1462 }
rgrover1 112:737b08b3b995 1463 else
rgrover1 112:737b08b3b995 1464 {
rgrover1 112:737b08b3b995 1465 dm_event.event_id = DM_EVT_APP_CONTEXT_BASE;
rgrover1 112:737b08b3b995 1466 }
rgrover1 112:737b08b3b995 1467 }
rgrover1 112:737b08b3b995 1468 else
rgrover1 112:737b08b3b995 1469 {
rgrover1 112:737b08b3b995 1470 //Update or store operation.
rgrover1 112:737b08b3b995 1471 //Context is identified based on the pointer value. Device context, application context
rgrover1 112:737b08b3b995 1472 //and service context all have their own value range.
rgrover1 112:737b08b3b995 1473 index_count = ((uint32_t)(p_data - (uint8_t *)m_peer_table)) / PEER_ID_SIZE;
rgrover1 112:737b08b3b995 1474
rgrover1 112:737b08b3b995 1475 if (index_count < DEVICE_MANAGER_MAX_BONDS)
rgrover1 112:737b08b3b995 1476 {
rgrover1 112:737b08b3b995 1477 dm_event.event_param.p_device_context = &context_data;
rgrover1 112:737b08b3b995 1478
rgrover1 112:737b08b3b995 1479 //Only the peer identification is stored, not bond information. Hence do not notify
rgrover1 112:737b08b3b995 1480 //the application yet, unless the store operation resulted in a failure.
rgrover1 112:737b08b3b995 1481 if ((result == NRF_SUCCESS) &&
rgrover1 112:737b08b3b995 1482 (
rgrover1 112:737b08b3b995 1483 (update_status_bit_is_set(dm_handle.device_id) == false)
rgrover1 112:737b08b3b995 1484 )
rgrover1 112:737b08b3b995 1485 )
rgrover1 112:737b08b3b995 1486 {
rgrover1 112:737b08b3b995 1487 app_notify = false;
rgrover1 112:737b08b3b995 1488 }
rgrover1 112:737b08b3b995 1489 else
rgrover1 112:737b08b3b995 1490 {
rgrover1 112:737b08b3b995 1491 //Reset update status since update is complete.
rgrover1 112:737b08b3b995 1492 update_status_bit_reset(dm_handle.device_id);
rgrover1 112:737b08b3b995 1493
rgrover1 112:737b08b3b995 1494 //Notify application of error in storing the context.
rgrover1 112:737b08b3b995 1495 dm_event.event_id = DM_EVT_DEVICE_CONTEXT_BASE;
rgrover1 112:737b08b3b995 1496 }
rgrover1 112:737b08b3b995 1497 }
rgrover1 112:737b08b3b995 1498 else
rgrover1 112:737b08b3b995 1499 {
rgrover1 112:737b08b3b995 1500 index_count = ((uint32_t)(p_data - (uint8_t *)m_bond_table)) / BOND_SIZE;
rgrover1 112:737b08b3b995 1501
rgrover1 112:737b08b3b995 1502 if (index_count < DEVICE_MANAGER_MAX_CONNECTIONS)
rgrover1 112:737b08b3b995 1503 {
rgrover1 112:737b08b3b995 1504 DM_LOG("[DM]:[0x%02X]:[0x%02X]: Bond context Event\r\n",
rgrover1 112:737b08b3b995 1505 dm_handle.device_id,
rgrover1 112:737b08b3b995 1506 dm_handle.connection_id);
rgrover1 112:737b08b3b995 1507
rgrover1 112:737b08b3b995 1508 dm_event.event_param.p_device_context = &context_data;
rgrover1 112:737b08b3b995 1509 dm_event.event_id = DM_EVT_DEVICE_CONTEXT_BASE;
rgrover1 112:737b08b3b995 1510 dm_handle.connection_id = index_count;
rgrover1 112:737b08b3b995 1511
rgrover1 112:737b08b3b995 1512 ble_gap_sec_keyset_t keys_exchanged;
rgrover1 112:737b08b3b995 1513 keys_exchanged.keys_central.p_enc_key = NULL;
rgrover1 112:737b08b3b995 1514 keys_exchanged.keys_central.p_id_key = &m_local_id_info;
rgrover1 112:737b08b3b995 1515 keys_exchanged.keys_periph.p_enc_key = &m_bond_table[index_count].peer_enc_key;
rgrover1 112:737b08b3b995 1516 keys_exchanged.keys_periph.p_id_key =
rgrover1 112:737b08b3b995 1517 &m_peer_table[dm_handle.device_id].peer_id;
rgrover1 112:737b08b3b995 1518
rgrover1 112:737b08b3b995 1519 //Context information updated to provide the keys.
rgrover1 112:737b08b3b995 1520 context_data.p_data = (uint8_t *)&keys_exchanged;
rgrover1 112:737b08b3b995 1521 context_data.len = sizeof(ble_gap_sec_keyset_t);
rgrover1 112:737b08b3b995 1522 }
rgrover1 112:737b08b3b995 1523 else
rgrover1 112:737b08b3b995 1524 {
rgrover1 112:737b08b3b995 1525 index_count = ((uint32_t)(p_data - (uint8_t *)m_gatts_table)) /
rgrover1 112:737b08b3b995 1526 GATTS_SERVICE_CONTEXT_SIZE;
rgrover1 112:737b08b3b995 1527
rgrover1 112:737b08b3b995 1528 if (index_count < DEVICE_MANAGER_MAX_CONNECTIONS)
rgrover1 112:737b08b3b995 1529 {
rgrover1 112:737b08b3b995 1530 DM_LOG("[DM]:[0x%02X]:[0x%02X]: Service context Event\r\n",
rgrover1 112:737b08b3b995 1531 dm_handle.device_id,
rgrover1 112:737b08b3b995 1532 dm_handle.connection_id);
rgrover1 112:737b08b3b995 1533
rgrover1 112:737b08b3b995 1534 //Notify application.
rgrover1 112:737b08b3b995 1535 dm_event.event_id = DM_EVT_SERVICE_CONTEXT_BASE;
rgrover1 112:737b08b3b995 1536 dm_handle.connection_id = index_count;
rgrover1 112:737b08b3b995 1537 dm_handle.service_id = DM_PROTOCOL_CNTXT_GATT_SRVR_ID;
rgrover1 112:737b08b3b995 1538
rgrover1 112:737b08b3b995 1539 //Reset the service context now that it was successfully written to the
rgrover1 112:737b08b3b995 1540 //application and the link is disconnected.
rgrover1 112:737b08b3b995 1541 if ((m_connection_table[index_count].state & STATE_CONNECTED) !=
rgrover1 112:737b08b3b995 1542 STATE_CONNECTED)
rgrover1 112:737b08b3b995 1543 {
rgrover1 112:737b08b3b995 1544 DM_LOG("[DM]:[0x%02X]:[0x%02X]: Resetting bond information for "
rgrover1 112:737b08b3b995 1545 "active instance.\r\n",
rgrover1 112:737b08b3b995 1546 dm_handle.device_id,
rgrover1 112:737b08b3b995 1547 dm_handle.connection_id);
rgrover1 112:737b08b3b995 1548
rgrover1 112:737b08b3b995 1549 memset(&m_gatts_table[dm_handle.connection_id],
rgrover1 112:737b08b3b995 1550 0,
rgrover1 112:737b08b3b995 1551 sizeof(dm_gatts_context_t));
rgrover1 112:737b08b3b995 1552 }
rgrover1 112:737b08b3b995 1553 }
rgrover1 112:737b08b3b995 1554 else
rgrover1 112:737b08b3b995 1555 {
rgrover1 112:737b08b3b995 1556 DM_LOG("[DM]:[0x%02X]:[0x%02X]: App context Event\r\n",
rgrover1 112:737b08b3b995 1557 dm_handle.device_id,
rgrover1 112:737b08b3b995 1558 dm_handle.connection_id);
rgrover1 112:737b08b3b995 1559
rgrover1 112:737b08b3b995 1560 app_notify = false;
rgrover1 112:737b08b3b995 1561 dm_event.event_id = DM_EVT_APP_CONTEXT_BASE;
rgrover1 112:737b08b3b995 1562 #if (DEVICE_MANAGER_APP_CONTEXT_SIZE != 0)
rgrover1 112:737b08b3b995 1563
rgrover1 112:737b08b3b995 1564 if (p_data == (uint8_t *)(&m_context_init_len))
rgrover1 112:737b08b3b995 1565 {
rgrover1 112:737b08b3b995 1566 //Context data is deleted.
rgrover1 112:737b08b3b995 1567 //This is a workaround to get the right event as on delete operation
rgrover1 112:737b08b3b995 1568 //update operation is used instead of clear.
rgrover1 112:737b08b3b995 1569 op_code = PSTORAGE_CLEAR_OP_CODE;
rgrover1 112:737b08b3b995 1570 app_notify = true;
rgrover1 112:737b08b3b995 1571 }
rgrover1 112:737b08b3b995 1572 else if (m_app_context_table[dm_handle.device_id] == p_data)
rgrover1 112:737b08b3b995 1573 {
rgrover1 112:737b08b3b995 1574 app_notify = true;
rgrover1 112:737b08b3b995 1575 dm_event.event_param.p_app_context = &context_data;
rgrover1 112:737b08b3b995 1576
rgrover1 112:737b08b3b995 1577 //Verify if the device is connected, if yes set connection instance.
rgrover1 112:737b08b3b995 1578 for (uint32_t index = 0;
rgrover1 112:737b08b3b995 1579 index < DEVICE_MANAGER_MAX_CONNECTIONS;
rgrover1 112:737b08b3b995 1580 index++)
rgrover1 112:737b08b3b995 1581 {
rgrover1 112:737b08b3b995 1582 if (dm_handle.device_id == m_connection_table[index].bonded_dev_id)
rgrover1 112:737b08b3b995 1583 {
rgrover1 112:737b08b3b995 1584 dm_handle.connection_id = index;
rgrover1 112:737b08b3b995 1585 break;
rgrover1 112:737b08b3b995 1586 }
rgrover1 112:737b08b3b995 1587 }
rgrover1 112:737b08b3b995 1588 }
rgrover1 112:737b08b3b995 1589 else
rgrover1 112:737b08b3b995 1590 {
rgrover1 112:737b08b3b995 1591 //No implementation needed.
rgrover1 112:737b08b3b995 1592 }
rgrover1 112:737b08b3b995 1593 #endif //DEVICE_MANAGER_APP_CONTEXT_SIZE
rgrover1 112:737b08b3b995 1594 }
rgrover1 112:737b08b3b995 1595 }
rgrover1 112:737b08b3b995 1596 }
rgrover1 112:737b08b3b995 1597 }
rgrover1 112:737b08b3b995 1598
rgrover1 112:737b08b3b995 1599 if (app_notify == true)
rgrover1 112:737b08b3b995 1600 {
rgrover1 112:737b08b3b995 1601 if (op_code == PSTORAGE_CLEAR_OP_CODE)
rgrover1 112:737b08b3b995 1602 {
rgrover1 112:737b08b3b995 1603 dm_event.event_id |= DM_CLEAR_OPERATION_ID;
rgrover1 112:737b08b3b995 1604 }
rgrover1 112:737b08b3b995 1605 else if (op_code == PSTORAGE_LOAD_OP_CODE)
rgrover1 112:737b08b3b995 1606 {
rgrover1 112:737b08b3b995 1607 dm_event.event_id |= DM_LOAD_OPERATION_ID;
rgrover1 112:737b08b3b995 1608 }
rgrover1 112:737b08b3b995 1609 else
rgrover1 112:737b08b3b995 1610 {
rgrover1 112:737b08b3b995 1611 dm_event.event_id |= DM_STORE_OPERATION_ID;
rgrover1 112:737b08b3b995 1612 }
rgrover1 112:737b08b3b995 1613
rgrover1 112:737b08b3b995 1614 dm_event.event_param.p_app_context = &context_data;
rgrover1 112:737b08b3b995 1615 app_evt_notify(&dm_handle, &dm_event, result);
rgrover1 112:737b08b3b995 1616 }
rgrover1 112:737b08b3b995 1617 }
rgrover1 112:737b08b3b995 1618
rgrover1 112:737b08b3b995 1619 DM_MUTEX_UNLOCK();
rgrover1 112:737b08b3b995 1620 }
rgrover1 112:737b08b3b995 1621
rgrover1 112:737b08b3b995 1622
rgrover1 112:737b08b3b995 1623 ret_code_t dm_init(dm_init_param_t const * const p_init_param)
rgrover1 112:737b08b3b995 1624 {
rgrover1 112:737b08b3b995 1625 pstorage_module_param_t param;
rgrover1 112:737b08b3b995 1626 pstorage_handle_t block_handle;
rgrover1 112:737b08b3b995 1627 ret_code_t err_code;
rgrover1 112:737b08b3b995 1628 uint32_t index;
rgrover1 112:737b08b3b995 1629
rgrover1 112:737b08b3b995 1630 DM_LOG("[DM]: >> dm_init.\r\n");
rgrover1 112:737b08b3b995 1631
rgrover1 112:737b08b3b995 1632 NULL_PARAM_CHECK(p_init_param);
rgrover1 112:737b08b3b995 1633
rgrover1 112:737b08b3b995 1634 SDK_MUTEX_INIT(m_dm_mutex);
rgrover1 112:737b08b3b995 1635
rgrover1 112:737b08b3b995 1636 DM_MUTEX_LOCK();
rgrover1 112:737b08b3b995 1637
rgrover1 112:737b08b3b995 1638 for (index = 0; index < DEVICE_MANAGER_MAX_APPLICATIONS; index++)
rgrover1 112:737b08b3b995 1639 {
rgrover1 112:737b08b3b995 1640 application_instance_init(index);
rgrover1 112:737b08b3b995 1641 }
rgrover1 112:737b08b3b995 1642
rgrover1 112:737b08b3b995 1643 for (index = 0; index < DEVICE_MANAGER_MAX_CONNECTIONS; index++)
rgrover1 112:737b08b3b995 1644 {
rgrover1 112:737b08b3b995 1645 connection_instance_init(index);
rgrover1 112:737b08b3b995 1646 }
rgrover1 112:737b08b3b995 1647
rgrover1 112:737b08b3b995 1648 memset(m_gatts_table, 0, sizeof(m_gatts_table));
rgrover1 112:737b08b3b995 1649
rgrover1 112:737b08b3b995 1650 //Initialization of all device instances.
rgrover1 112:737b08b3b995 1651 for (index = 0; index < DEVICE_MANAGER_MAX_BONDS; index++)
rgrover1 112:737b08b3b995 1652 {
rgrover1 112:737b08b3b995 1653 peer_instance_init(index);
rgrover1 112:737b08b3b995 1654 m_irk_index_table[index] = DM_INVALID_ID;
rgrover1 112:737b08b3b995 1655 }
rgrover1 112:737b08b3b995 1656
rgrover1 112:737b08b3b995 1657 //All context with respect to a particular device is stored contiguously.
rgrover1 112:737b08b3b995 1658 param.block_size = ALL_CONTEXT_SIZE;
rgrover1 112:737b08b3b995 1659 param.block_count = DEVICE_MANAGER_MAX_BONDS;
rgrover1 112:737b08b3b995 1660 param.cb = dm_pstorage_cb_handler;
rgrover1 112:737b08b3b995 1661
rgrover1 112:737b08b3b995 1662 err_code = pstorage_register(&param, &m_storage_handle);
rgrover1 112:737b08b3b995 1663
rgrover1 112:737b08b3b995 1664 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 1665 {
rgrover1 112:737b08b3b995 1666 m_module_initialized = true;
rgrover1 112:737b08b3b995 1667
rgrover1 112:737b08b3b995 1668 if (p_init_param->clear_persistent_data == false)
rgrover1 112:737b08b3b995 1669 {
rgrover1 112:737b08b3b995 1670 DM_LOG("[DM]: Storage handle 0x%08X.\r\n", m_storage_handle.block_id);
rgrover1 112:737b08b3b995 1671
rgrover1 112:737b08b3b995 1672 //Copy bonded peer device address and IRK to RAM table.
rgrover1 112:737b08b3b995 1673
rgrover1 112:737b08b3b995 1674 //Bonded devices are stored in range (0,DEVICE_MANAGER_MAX_BONDS-1). The remaining
rgrover1 112:737b08b3b995 1675 //range is for active connections that may or may not be bonded.
rgrover1 112:737b08b3b995 1676 for (index = 0; index < DEVICE_MANAGER_MAX_BONDS; index++)
rgrover1 112:737b08b3b995 1677 {
rgrover1 112:737b08b3b995 1678 err_code = pstorage_block_identifier_get(&m_storage_handle, index, &block_handle);
rgrover1 112:737b08b3b995 1679
rgrover1 112:737b08b3b995 1680 //Issue read request if you successfully get the block identifier.
rgrover1 112:737b08b3b995 1681 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 1682 {
rgrover1 112:737b08b3b995 1683 DM_TRC("[DM]:[0x%02X]: Block handle 0x%08X.\r\n", index, block_handle.block_id);
rgrover1 112:737b08b3b995 1684
rgrover1 112:737b08b3b995 1685 err_code = pstorage_load((uint8_t *)&m_peer_table[index],
rgrover1 112:737b08b3b995 1686 &block_handle,
rgrover1 112:737b08b3b995 1687 sizeof(peer_id_t),
rgrover1 112:737b08b3b995 1688 0);
rgrover1 112:737b08b3b995 1689
rgrover1 112:737b08b3b995 1690 if (err_code != NRF_SUCCESS)
rgrover1 112:737b08b3b995 1691 {
rgrover1 112:737b08b3b995 1692 // In case a peer device could not be loaded successfully, rest of the
rgrover1 112:737b08b3b995 1693 // initialization procedure are skipped and an error is sent to the
rgrover1 112:737b08b3b995 1694 // application.
rgrover1 112:737b08b3b995 1695 DM_ERR(
rgrover1 112:737b08b3b995 1696 "[DM]: Failed to load peer device %08X from storage, reason %08X.\r\n",
rgrover1 112:737b08b3b995 1697 index,
rgrover1 112:737b08b3b995 1698 err_code);
rgrover1 112:737b08b3b995 1699
rgrover1 112:737b08b3b995 1700 m_module_initialized = false;
rgrover1 112:737b08b3b995 1701 break;
rgrover1 112:737b08b3b995 1702 }
rgrover1 112:737b08b3b995 1703 else
rgrover1 112:737b08b3b995 1704 {
rgrover1 112:737b08b3b995 1705 DM_TRC("[DM]:[DI 0x%02X]: Device type 0x%02X.\r\n",
rgrover1 112:737b08b3b995 1706 index,
rgrover1 112:737b08b3b995 1707 m_peer_table[index].peer_id.id_addr_info.addr_type);
rgrover1 112:737b08b3b995 1708 DM_TRC("[DM]: Device Addr 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X.\r\n",
rgrover1 112:737b08b3b995 1709 m_peer_table[index].peer_id.id_addr_info.addr[0],
rgrover1 112:737b08b3b995 1710 m_peer_table[index].peer_id.id_addr_info.addr[1],
rgrover1 112:737b08b3b995 1711 m_peer_table[index].peer_id.id_addr_info.addr[2],
rgrover1 112:737b08b3b995 1712 m_peer_table[index].peer_id.id_addr_info.addr[3],
rgrover1 112:737b08b3b995 1713 m_peer_table[index].peer_id.id_addr_info.addr[4],
rgrover1 112:737b08b3b995 1714 m_peer_table[index].peer_id.id_addr_info.addr[5]);
rgrover1 112:737b08b3b995 1715 }
rgrover1 112:737b08b3b995 1716 }
rgrover1 112:737b08b3b995 1717 else
rgrover1 112:737b08b3b995 1718 {
rgrover1 112:737b08b3b995 1719 //In case a peer device could not be loaded successfully, rest of the
rgrover1 112:737b08b3b995 1720 //initialization procedure are skipped and an error is sent to the application.
rgrover1 112:737b08b3b995 1721 DM_LOG("[DM]: Failed to get block handle for instance %08X, reason %08X.\r\n",
rgrover1 112:737b08b3b995 1722 index,
rgrover1 112:737b08b3b995 1723 err_code);
rgrover1 112:737b08b3b995 1724
rgrover1 112:737b08b3b995 1725 m_module_initialized = false;
rgrover1 112:737b08b3b995 1726 break;
rgrover1 112:737b08b3b995 1727 }
rgrover1 112:737b08b3b995 1728 }
rgrover1 112:737b08b3b995 1729 }
rgrover1 112:737b08b3b995 1730 else
rgrover1 112:737b08b3b995 1731 {
rgrover1 112:737b08b3b995 1732 err_code = pstorage_clear(&m_storage_handle, (param.block_size * param.block_count));
rgrover1 112:737b08b3b995 1733 DM_ERR("[DM]: Successfully requested clear of persistent data.\r\n");
rgrover1 112:737b08b3b995 1734 }
rgrover1 112:737b08b3b995 1735 }
rgrover1 112:737b08b3b995 1736 else
rgrover1 112:737b08b3b995 1737 {
rgrover1 112:737b08b3b995 1738 DM_ERR("[DM]: Failed to register with storage module, reason 0x%08X.\r\n", err_code);
rgrover1 112:737b08b3b995 1739 }
rgrover1 112:737b08b3b995 1740
rgrover1 112:737b08b3b995 1741 DM_MUTEX_UNLOCK();
rgrover1 112:737b08b3b995 1742
rgrover1 112:737b08b3b995 1743 DM_TRC("[DM]: << dm_init.\r\n");
rgrover1 112:737b08b3b995 1744
rgrover1 112:737b08b3b995 1745 return err_code;
rgrover1 112:737b08b3b995 1746 }
rgrover1 112:737b08b3b995 1747
rgrover1 112:737b08b3b995 1748
rgrover1 112:737b08b3b995 1749 ret_code_t dm_register(dm_application_instance_t * p_appl_instance,
rgrover1 112:737b08b3b995 1750 dm_application_param_t const * p_appl_param)
rgrover1 112:737b08b3b995 1751 {
rgrover1 112:737b08b3b995 1752 VERIFY_MODULE_INITIALIZED();
rgrover1 112:737b08b3b995 1753 NULL_PARAM_CHECK(p_appl_instance);
rgrover1 112:737b08b3b995 1754 NULL_PARAM_CHECK(p_appl_param);
rgrover1 112:737b08b3b995 1755 NULL_PARAM_CHECK(p_appl_param->evt_handler);
rgrover1 112:737b08b3b995 1756
rgrover1 112:737b08b3b995 1757 DM_MUTEX_LOCK();
rgrover1 112:737b08b3b995 1758
rgrover1 112:737b08b3b995 1759 DM_LOG("[DM]: >> dm_register.\r\n");
rgrover1 112:737b08b3b995 1760
rgrover1 112:737b08b3b995 1761 uint32_t err_code;
rgrover1 112:737b08b3b995 1762
rgrover1 112:737b08b3b995 1763 //Verify if an application instance is available. Currently only one instance is supported.
rgrover1 112:737b08b3b995 1764 if (m_application_table[0].ntf_cb == NULL)
rgrover1 112:737b08b3b995 1765 {
rgrover1 112:737b08b3b995 1766 DM_LOG("[DM]: Application Instance allocated.\r\n");
rgrover1 112:737b08b3b995 1767
rgrover1 112:737b08b3b995 1768 //Mark instance as allocated.
rgrover1 112:737b08b3b995 1769 m_application_table[0].ntf_cb = p_appl_param->evt_handler;
rgrover1 112:737b08b3b995 1770 m_application_table[0].sec_param = p_appl_param->sec_param;
rgrover1 112:737b08b3b995 1771 m_application_table[0].service = p_appl_param->service_type;
rgrover1 112:737b08b3b995 1772
rgrover1 112:737b08b3b995 1773 m_application_table[0].sec_param.kdist_central.enc = 0;
rgrover1 112:737b08b3b995 1774 m_application_table[0].sec_param.kdist_central.id = 1;
rgrover1 112:737b08b3b995 1775 m_application_table[0].sec_param.kdist_central.sign = 0;
rgrover1 112:737b08b3b995 1776 m_application_table[0].sec_param.kdist_periph.enc = 1;
rgrover1 112:737b08b3b995 1777 m_application_table[0].sec_param.kdist_periph.id = 1;
rgrover1 112:737b08b3b995 1778 m_application_table[0].sec_param.kdist_periph.sign = 0;
rgrover1 112:737b08b3b995 1779 //Populate application's instance variable with the assigned allocation instance.
rgrover1 112:737b08b3b995 1780 *p_appl_instance = 0;
rgrover1 112:737b08b3b995 1781 err_code = NRF_SUCCESS;
rgrover1 112:737b08b3b995 1782 }
rgrover1 112:737b08b3b995 1783 else
rgrover1 112:737b08b3b995 1784 {
rgrover1 112:737b08b3b995 1785 err_code = (NRF_ERROR_NO_MEM | DEVICE_MANAGER_ERR_BASE);
rgrover1 112:737b08b3b995 1786 }
rgrover1 112:737b08b3b995 1787
rgrover1 112:737b08b3b995 1788 DM_MUTEX_UNLOCK();
rgrover1 112:737b08b3b995 1789
rgrover1 112:737b08b3b995 1790 DM_TRC("[DM]: << dm_register.\r\n");
rgrover1 112:737b08b3b995 1791
rgrover1 112:737b08b3b995 1792 return err_code;
rgrover1 112:737b08b3b995 1793 }
rgrover1 112:737b08b3b995 1794
rgrover1 112:737b08b3b995 1795
rgrover1 112:737b08b3b995 1796 ret_code_t dm_security_setup_req(dm_handle_t * p_handle)
rgrover1 112:737b08b3b995 1797 {
rgrover1 112:737b08b3b995 1798 VERIFY_MODULE_INITIALIZED();
rgrover1 112:737b08b3b995 1799 NULL_PARAM_CHECK(p_handle);
rgrover1 112:737b08b3b995 1800 VERIFY_APP_REGISTERED(p_handle->appl_id);
rgrover1 112:737b08b3b995 1801 VERIFY_CONNECTION_INSTANCE(p_handle->connection_id);
rgrover1 112:737b08b3b995 1802
rgrover1 112:737b08b3b995 1803 DM_MUTEX_LOCK();
rgrover1 112:737b08b3b995 1804
rgrover1 112:737b08b3b995 1805 DM_LOG("[DM]: >> dm_security_setup_req\r\n");
rgrover1 112:737b08b3b995 1806
rgrover1 112:737b08b3b995 1807 uint32_t err_code = (NRF_ERROR_INVALID_STATE | DEVICE_MANAGER_ERR_BASE);
rgrover1 112:737b08b3b995 1808
rgrover1 112:737b08b3b995 1809 if ((m_connection_table[p_handle->connection_id].state & STATE_CONNECTED) == STATE_CONNECTED)
rgrover1 112:737b08b3b995 1810 {
rgrover1 112:737b08b3b995 1811 err_code = sd_ble_gap_authenticate(m_connection_table[p_handle->connection_id].conn_handle,
rgrover1 112:737b08b3b995 1812 &m_application_table[0].sec_param);
rgrover1 112:737b08b3b995 1813 }
rgrover1 112:737b08b3b995 1814
rgrover1 112:737b08b3b995 1815 DM_TRC("[DM]: << dm_security_setup_req, 0x%08X\r\n", err_code);
rgrover1 112:737b08b3b995 1816
rgrover1 112:737b08b3b995 1817 DM_MUTEX_UNLOCK();
rgrover1 112:737b08b3b995 1818
rgrover1 112:737b08b3b995 1819 return err_code;
rgrover1 112:737b08b3b995 1820 }
rgrover1 112:737b08b3b995 1821
rgrover1 112:737b08b3b995 1822
rgrover1 112:737b08b3b995 1823 ret_code_t dm_security_status_req(dm_handle_t const * p_handle,
rgrover1 112:737b08b3b995 1824 dm_security_status_t * p_status)
rgrover1 112:737b08b3b995 1825 {
rgrover1 112:737b08b3b995 1826 VERIFY_MODULE_INITIALIZED();
rgrover1 112:737b08b3b995 1827 NULL_PARAM_CHECK(p_handle);
rgrover1 112:737b08b3b995 1828 NULL_PARAM_CHECK(p_status);
rgrover1 112:737b08b3b995 1829 VERIFY_APP_REGISTERED(p_handle->appl_id);
rgrover1 112:737b08b3b995 1830 VERIFY_CONNECTION_INSTANCE(p_handle->connection_id);
rgrover1 112:737b08b3b995 1831
rgrover1 112:737b08b3b995 1832 DM_MUTEX_LOCK();
rgrover1 112:737b08b3b995 1833
rgrover1 112:737b08b3b995 1834 DM_LOG("[DM]: >> dm_security_status_req\r\n");
rgrover1 112:737b08b3b995 1835
rgrover1 112:737b08b3b995 1836 if ((m_connection_table[p_handle->connection_id].state & STATE_PAIRING) ||
rgrover1 112:737b08b3b995 1837 (m_connection_table[p_handle->connection_id].state & STATE_PAIRING_PENDING))
rgrover1 112:737b08b3b995 1838 {
rgrover1 112:737b08b3b995 1839 (*p_status) = ENCRYPTION_IN_PROGRESS;
rgrover1 112:737b08b3b995 1840 }
rgrover1 112:737b08b3b995 1841 else if (m_connection_table[p_handle->connection_id].state & STATE_LINK_ENCRYPTED)
rgrover1 112:737b08b3b995 1842 {
rgrover1 112:737b08b3b995 1843 (*p_status) = ENCRYPTED;
rgrover1 112:737b08b3b995 1844 }
rgrover1 112:737b08b3b995 1845 else
rgrover1 112:737b08b3b995 1846 {
rgrover1 112:737b08b3b995 1847 (*p_status) = NOT_ENCRYPTED;
rgrover1 112:737b08b3b995 1848 }
rgrover1 112:737b08b3b995 1849
rgrover1 112:737b08b3b995 1850 DM_TRC("[DM]: << dm_security_status_req\r\n");
rgrover1 112:737b08b3b995 1851
rgrover1 112:737b08b3b995 1852 DM_MUTEX_UNLOCK();
rgrover1 112:737b08b3b995 1853
rgrover1 112:737b08b3b995 1854 return NRF_SUCCESS;
rgrover1 112:737b08b3b995 1855 }
rgrover1 112:737b08b3b995 1856
rgrover1 112:737b08b3b995 1857
rgrover1 112:737b08b3b995 1858 ret_code_t dm_whitelist_create(dm_application_instance_t const * p_handle,
rgrover1 112:737b08b3b995 1859 ble_gap_whitelist_t * p_whitelist)
rgrover1 112:737b08b3b995 1860 {
rgrover1 112:737b08b3b995 1861 VERIFY_MODULE_INITIALIZED();
rgrover1 112:737b08b3b995 1862 NULL_PARAM_CHECK(p_handle);
rgrover1 112:737b08b3b995 1863 NULL_PARAM_CHECK(p_whitelist);
rgrover1 112:737b08b3b995 1864 NULL_PARAM_CHECK(p_whitelist->pp_addrs);
rgrover1 112:737b08b3b995 1865 NULL_PARAM_CHECK(p_whitelist->pp_irks);
rgrover1 112:737b08b3b995 1866 VERIFY_APP_REGISTERED(*p_handle);
rgrover1 112:737b08b3b995 1867
rgrover1 112:737b08b3b995 1868 DM_MUTEX_LOCK();
rgrover1 112:737b08b3b995 1869
rgrover1 112:737b08b3b995 1870 DM_LOG("[DM]: >> dm_whitelist_create\r\n");
rgrover1 112:737b08b3b995 1871
rgrover1 112:737b08b3b995 1872 uint32_t addr_count = 0;
rgrover1 112:737b08b3b995 1873 uint32_t irk_count = 0;
rgrover1 112:737b08b3b995 1874 bool connected = false;
rgrover1 112:737b08b3b995 1875
rgrover1 112:737b08b3b995 1876 for (uint32_t index = 0; index < DEVICE_MANAGER_MAX_BONDS; index++)
rgrover1 112:737b08b3b995 1877 {
rgrover1 112:737b08b3b995 1878 connected = false;
rgrover1 112:737b08b3b995 1879
rgrover1 112:737b08b3b995 1880 for (uint32_t c_index = 0; c_index < DEVICE_MANAGER_MAX_CONNECTIONS; c_index++)
rgrover1 112:737b08b3b995 1881 {
rgrover1 112:737b08b3b995 1882 if ((index == m_connection_table[c_index].bonded_dev_id) &&
rgrover1 112:737b08b3b995 1883 ((m_connection_table[c_index].state & STATE_CONNECTED) == STATE_CONNECTED))
rgrover1 112:737b08b3b995 1884 {
rgrover1 112:737b08b3b995 1885 connected = true;
rgrover1 112:737b08b3b995 1886 break;
rgrover1 112:737b08b3b995 1887 }
rgrover1 112:737b08b3b995 1888 }
rgrover1 112:737b08b3b995 1889
rgrover1 112:737b08b3b995 1890 if (connected == false)
rgrover1 112:737b08b3b995 1891 {
rgrover1 112:737b08b3b995 1892 if ((irk_count < p_whitelist->irk_count) &&
rgrover1 112:737b08b3b995 1893 ((m_peer_table[index].id_bitmap & IRK_ENTRY) == 0))
rgrover1 112:737b08b3b995 1894 {
rgrover1 112:737b08b3b995 1895 p_whitelist->pp_irks[irk_count] = &m_peer_table[index].peer_id.id_info;
rgrover1 112:737b08b3b995 1896 m_irk_index_table[irk_count] = index;
rgrover1 112:737b08b3b995 1897 irk_count++;
rgrover1 112:737b08b3b995 1898 }
rgrover1 112:737b08b3b995 1899
rgrover1 112:737b08b3b995 1900 if ((addr_count < p_whitelist->addr_count) &&
rgrover1 112:737b08b3b995 1901 (m_peer_table[index].id_bitmap & ADDR_ENTRY) == 0)
rgrover1 112:737b08b3b995 1902 {
rgrover1 112:737b08b3b995 1903 p_whitelist->pp_addrs[addr_count] = &m_peer_table[index].peer_id.id_addr_info;
rgrover1 112:737b08b3b995 1904 addr_count++;
rgrover1 112:737b08b3b995 1905 }
rgrover1 112:737b08b3b995 1906 }
rgrover1 112:737b08b3b995 1907 }
rgrover1 112:737b08b3b995 1908
rgrover1 112:737b08b3b995 1909 p_whitelist->addr_count = addr_count;
rgrover1 112:737b08b3b995 1910 p_whitelist->irk_count = irk_count;
rgrover1 112:737b08b3b995 1911
rgrover1 112:737b08b3b995 1912 DM_LOG("[DM]: Created whitelist, number of IRK = 0x%02X, number of addr = 0x%02X\r\n",
rgrover1 112:737b08b3b995 1913 irk_count,
rgrover1 112:737b08b3b995 1914 addr_count);
rgrover1 112:737b08b3b995 1915
rgrover1 112:737b08b3b995 1916 DM_TRC("[DM]: << dm_whitelist_create\r\n");
rgrover1 112:737b08b3b995 1917
rgrover1 112:737b08b3b995 1918 DM_MUTEX_UNLOCK();
rgrover1 112:737b08b3b995 1919
rgrover1 112:737b08b3b995 1920 return NRF_SUCCESS;
rgrover1 112:737b08b3b995 1921 }
rgrover1 112:737b08b3b995 1922
rgrover1 112:737b08b3b995 1923
rgrover1 112:737b08b3b995 1924 ret_code_t dm_device_add(dm_handle_t * p_handle,
rgrover1 112:737b08b3b995 1925 dm_device_context_t const * p_context)
rgrover1 112:737b08b3b995 1926 {
rgrover1 112:737b08b3b995 1927 return (API_NOT_IMPLEMENTED | DEVICE_MANAGER_ERR_BASE);
rgrover1 112:737b08b3b995 1928 }
rgrover1 112:737b08b3b995 1929
rgrover1 112:737b08b3b995 1930
rgrover1 112:737b08b3b995 1931 ret_code_t dm_device_delete(dm_handle_t const * p_handle)
rgrover1 112:737b08b3b995 1932 {
rgrover1 112:737b08b3b995 1933 VERIFY_MODULE_INITIALIZED();
rgrover1 112:737b08b3b995 1934 NULL_PARAM_CHECK(p_handle);
rgrover1 112:737b08b3b995 1935 VERIFY_APP_REGISTERED(p_handle->appl_id);
rgrover1 112:737b08b3b995 1936 VERIFY_DEVICE_INSTANCE(p_handle->device_id);
rgrover1 112:737b08b3b995 1937
rgrover1 112:737b08b3b995 1938 DM_MUTEX_LOCK();
rgrover1 112:737b08b3b995 1939
rgrover1 112:737b08b3b995 1940 DM_TRC("[DM]: >> dm_device_delete\r\n");
rgrover1 112:737b08b3b995 1941
rgrover1 112:737b08b3b995 1942 uint32_t err_code = device_instance_free(p_handle->device_id);
rgrover1 112:737b08b3b995 1943
rgrover1 112:737b08b3b995 1944 DM_TRC("[DM]: << dm_device_delete\r\n");
rgrover1 112:737b08b3b995 1945
rgrover1 112:737b08b3b995 1946 DM_MUTEX_UNLOCK();
rgrover1 112:737b08b3b995 1947
rgrover1 112:737b08b3b995 1948 return err_code;
rgrover1 112:737b08b3b995 1949 }
rgrover1 112:737b08b3b995 1950
rgrover1 112:737b08b3b995 1951
rgrover1 112:737b08b3b995 1952 ret_code_t dm_device_delete_all(dm_application_instance_t const * p_handle)
rgrover1 112:737b08b3b995 1953 {
rgrover1 112:737b08b3b995 1954 VERIFY_MODULE_INITIALIZED();
rgrover1 112:737b08b3b995 1955 NULL_PARAM_CHECK(p_handle);
rgrover1 112:737b08b3b995 1956 VERIFY_APP_REGISTERED((*p_handle));
rgrover1 112:737b08b3b995 1957
rgrover1 112:737b08b3b995 1958 DM_MUTEX_LOCK();
rgrover1 112:737b08b3b995 1959
rgrover1 112:737b08b3b995 1960 uint32_t err_code = NRF_SUCCESS;
rgrover1 112:737b08b3b995 1961
rgrover1 112:737b08b3b995 1962 DM_TRC("[DM]: >> dm_device_delete_all\r\n");
rgrover1 112:737b08b3b995 1963
rgrover1 112:737b08b3b995 1964 for (uint32_t index = 0; index < DEVICE_MANAGER_MAX_BONDS; index++)
rgrover1 112:737b08b3b995 1965 {
rgrover1 112:737b08b3b995 1966 if (m_peer_table[index].id_bitmap != UNASSIGNED)
rgrover1 112:737b08b3b995 1967 {
rgrover1 112:737b08b3b995 1968 err_code = device_instance_free(index);
rgrover1 112:737b08b3b995 1969 }
rgrover1 112:737b08b3b995 1970 }
rgrover1 112:737b08b3b995 1971
rgrover1 112:737b08b3b995 1972 DM_TRC("[DM]: << dm_device_delete_all\r\n");
rgrover1 112:737b08b3b995 1973
rgrover1 112:737b08b3b995 1974 DM_MUTEX_UNLOCK();
rgrover1 112:737b08b3b995 1975
rgrover1 112:737b08b3b995 1976 return err_code;
rgrover1 112:737b08b3b995 1977 }
rgrover1 112:737b08b3b995 1978
rgrover1 112:737b08b3b995 1979
rgrover1 112:737b08b3b995 1980 ret_code_t dm_service_context_set(dm_handle_t const * p_handle,
rgrover1 112:737b08b3b995 1981 dm_service_context_t const * p_context)
rgrover1 112:737b08b3b995 1982 {
rgrover1 112:737b08b3b995 1983 VERIFY_MODULE_INITIALIZED();
rgrover1 112:737b08b3b995 1984 NULL_PARAM_CHECK(p_handle);
rgrover1 112:737b08b3b995 1985 NULL_PARAM_CHECK(p_context);
rgrover1 112:737b08b3b995 1986 VERIFY_APP_REGISTERED(p_handle->appl_id);
rgrover1 112:737b08b3b995 1987 VERIFY_CONNECTION_INSTANCE(p_handle->connection_id);
rgrover1 112:737b08b3b995 1988 VERIFY_DEVICE_INSTANCE(p_handle->device_id);
rgrover1 112:737b08b3b995 1989
rgrover1 112:737b08b3b995 1990 DM_MUTEX_LOCK();
rgrover1 112:737b08b3b995 1991
rgrover1 112:737b08b3b995 1992 DM_TRC("[DM]: >> dm_service_context_set\r\n");
rgrover1 112:737b08b3b995 1993
rgrover1 112:737b08b3b995 1994 if ((p_context->context_data.p_data != NULL) &&
rgrover1 112:737b08b3b995 1995 (
rgrover1 112:737b08b3b995 1996 (p_context->context_data.len != 0) &&
rgrover1 112:737b08b3b995 1997 (p_context->context_data.len < DM_GATT_SERVER_ATTR_MAX_SIZE)
rgrover1 112:737b08b3b995 1998 )
rgrover1 112:737b08b3b995 1999 )
rgrover1 112:737b08b3b995 2000 {
rgrover1 112:737b08b3b995 2001 if (p_context->service_type == DM_PROTOCOL_CNTXT_GATT_SRVR_ID)
rgrover1 112:737b08b3b995 2002 {
rgrover1 112:737b08b3b995 2003 memcpy(m_gatts_table[p_handle->connection_id].attributes,
rgrover1 112:737b08b3b995 2004 p_context->context_data.p_data,
rgrover1 112:737b08b3b995 2005 p_context->context_data.len);
rgrover1 112:737b08b3b995 2006 }
rgrover1 112:737b08b3b995 2007 }
rgrover1 112:737b08b3b995 2008
rgrover1 112:737b08b3b995 2009 pstorage_handle_t block_handle;
rgrover1 112:737b08b3b995 2010 uint32_t err_code = pstorage_block_identifier_get(&m_storage_handle,
rgrover1 112:737b08b3b995 2011 p_handle->device_id,
rgrover1 112:737b08b3b995 2012 &block_handle);
rgrover1 112:737b08b3b995 2013
rgrover1 112:737b08b3b995 2014 err_code = m_service_context_store[p_context->service_type](&block_handle, p_handle);
rgrover1 112:737b08b3b995 2015
rgrover1 112:737b08b3b995 2016 DM_TRC("[DM]: << dm_service_context_set\r\n");
rgrover1 112:737b08b3b995 2017
rgrover1 112:737b08b3b995 2018 DM_MUTEX_UNLOCK();
rgrover1 112:737b08b3b995 2019
rgrover1 112:737b08b3b995 2020 return err_code;
rgrover1 112:737b08b3b995 2021 }
rgrover1 112:737b08b3b995 2022
rgrover1 112:737b08b3b995 2023
rgrover1 112:737b08b3b995 2024 ret_code_t dm_service_context_get(dm_handle_t const * p_handle,
rgrover1 112:737b08b3b995 2025 dm_service_context_t * p_context)
rgrover1 112:737b08b3b995 2026 {
rgrover1 112:737b08b3b995 2027 VERIFY_MODULE_INITIALIZED();
rgrover1 112:737b08b3b995 2028 NULL_PARAM_CHECK(p_handle);
rgrover1 112:737b08b3b995 2029 NULL_PARAM_CHECK(p_context);
rgrover1 112:737b08b3b995 2030 VERIFY_APP_REGISTERED(p_handle->appl_id);
rgrover1 112:737b08b3b995 2031 VERIFY_DEVICE_INSTANCE(p_handle->device_id);
rgrover1 112:737b08b3b995 2032
rgrover1 112:737b08b3b995 2033 if ((m_connection_table[p_handle->connection_id].state & STATE_CONNECTED) != STATE_CONNECTED)
rgrover1 112:737b08b3b995 2034 {
rgrover1 112:737b08b3b995 2035 DM_TRC("[DM]: Device must be connected to get context. \r\n");
rgrover1 112:737b08b3b995 2036
rgrover1 112:737b08b3b995 2037 return (FEATURE_NOT_ENABLED | DEVICE_MANAGER_ERR_BASE);
rgrover1 112:737b08b3b995 2038 }
rgrover1 112:737b08b3b995 2039
rgrover1 112:737b08b3b995 2040 DM_MUTEX_LOCK();
rgrover1 112:737b08b3b995 2041
rgrover1 112:737b08b3b995 2042 DM_TRC("[DM]: >> dm_service_context_get\r\n");
rgrover1 112:737b08b3b995 2043
rgrover1 112:737b08b3b995 2044 if ((p_context->context_data.p_data == NULL) &&
rgrover1 112:737b08b3b995 2045 (p_context->context_data.len < DM_GATT_SERVER_ATTR_MAX_SIZE))
rgrover1 112:737b08b3b995 2046 {
rgrover1 112:737b08b3b995 2047 if (p_context->service_type == DM_PROTOCOL_CNTXT_GATT_SRVR_ID)
rgrover1 112:737b08b3b995 2048 {
rgrover1 112:737b08b3b995 2049 p_context->context_data.p_data = m_gatts_table[p_handle->connection_id].attributes;
rgrover1 112:737b08b3b995 2050 p_context->context_data.len = m_gatts_table[p_handle->connection_id].size;
rgrover1 112:737b08b3b995 2051 }
rgrover1 112:737b08b3b995 2052 }
rgrover1 112:737b08b3b995 2053
rgrover1 112:737b08b3b995 2054 pstorage_handle_t block_handle;
rgrover1 112:737b08b3b995 2055 uint32_t err_code = pstorage_block_identifier_get(&m_storage_handle,
rgrover1 112:737b08b3b995 2056 p_handle->device_id,
rgrover1 112:737b08b3b995 2057 &block_handle);
rgrover1 112:737b08b3b995 2058
rgrover1 112:737b08b3b995 2059 err_code = m_service_context_load[p_context->service_type](&block_handle, p_handle);
rgrover1 112:737b08b3b995 2060
rgrover1 112:737b08b3b995 2061 DM_TRC("[DM]: << dm_service_context_get\r\n");
rgrover1 112:737b08b3b995 2062
rgrover1 112:737b08b3b995 2063 DM_MUTEX_UNLOCK();
rgrover1 112:737b08b3b995 2064
rgrover1 112:737b08b3b995 2065 return err_code;
rgrover1 112:737b08b3b995 2066 }
rgrover1 112:737b08b3b995 2067
rgrover1 112:737b08b3b995 2068
rgrover1 112:737b08b3b995 2069 ret_code_t dm_service_context_delete(dm_handle_t const * p_handle)
rgrover1 112:737b08b3b995 2070 {
rgrover1 112:737b08b3b995 2071 VERIFY_MODULE_INITIALIZED();
rgrover1 112:737b08b3b995 2072 NULL_PARAM_CHECK(p_handle);
rgrover1 112:737b08b3b995 2073 VERIFY_APP_REGISTERED(p_handle->appl_id);
rgrover1 112:737b08b3b995 2074 VERIFY_DEVICE_INSTANCE(p_handle->device_id);
rgrover1 112:737b08b3b995 2075
rgrover1 112:737b08b3b995 2076 DM_LOG("[DM]: Context delete is not supported yet.\r\n");
rgrover1 112:737b08b3b995 2077
rgrover1 112:737b08b3b995 2078 return (API_NOT_IMPLEMENTED | DEVICE_MANAGER_ERR_BASE);
rgrover1 112:737b08b3b995 2079 }
rgrover1 112:737b08b3b995 2080
rgrover1 112:737b08b3b995 2081
rgrover1 112:737b08b3b995 2082 ret_code_t dm_application_context_set(dm_handle_t const * p_handle,
rgrover1 112:737b08b3b995 2083 dm_application_context_t const * p_context)
rgrover1 112:737b08b3b995 2084 {
rgrover1 112:737b08b3b995 2085 #if (DEVICE_MANAGER_APP_CONTEXT_SIZE != 0)
rgrover1 112:737b08b3b995 2086 VERIFY_MODULE_INITIALIZED();
rgrover1 112:737b08b3b995 2087 NULL_PARAM_CHECK(p_handle);
rgrover1 112:737b08b3b995 2088 NULL_PARAM_CHECK(p_context);
rgrover1 112:737b08b3b995 2089 NULL_PARAM_CHECK(p_context->p_data);
rgrover1 112:737b08b3b995 2090 VERIFY_APP_REGISTERED(p_handle->appl_id);
rgrover1 112:737b08b3b995 2091 VERIFY_DEVICE_INSTANCE(p_handle->device_id);
rgrover1 112:737b08b3b995 2092 VERIFY_DEVICE_BOND(p_handle->connection_id);
rgrover1 112:737b08b3b995 2093 SIZE_CHECK_APP_CONTEXT(p_context->len);
rgrover1 112:737b08b3b995 2094
rgrover1 112:737b08b3b995 2095 DM_MUTEX_LOCK();
rgrover1 112:737b08b3b995 2096
rgrover1 112:737b08b3b995 2097 DM_TRC("[DM]: >> dm_application_context_set\r\n");
rgrover1 112:737b08b3b995 2098
rgrover1 112:737b08b3b995 2099 uint32_t err_code;
rgrover1 112:737b08b3b995 2100 uint32_t context_len;
rgrover1 112:737b08b3b995 2101 pstorage_handle_t block_handle;
rgrover1 112:737b08b3b995 2102
rgrover1 112:737b08b3b995 2103 storage_operation store_fn = pstorage_store;
rgrover1 112:737b08b3b995 2104
rgrover1 112:737b08b3b995 2105 err_code = pstorage_block_identifier_get(&m_storage_handle,
rgrover1 112:737b08b3b995 2106 p_handle->device_id,
rgrover1 112:737b08b3b995 2107 &block_handle);
rgrover1 112:737b08b3b995 2108
rgrover1 112:737b08b3b995 2109 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 2110 {
rgrover1 112:737b08b3b995 2111 err_code = pstorage_load((uint8_t *)&context_len,
rgrover1 112:737b08b3b995 2112 &block_handle,
rgrover1 112:737b08b3b995 2113 sizeof(uint32_t),
rgrover1 112:737b08b3b995 2114 APP_CONTEXT_STORAGE_OFFSET);
rgrover1 112:737b08b3b995 2115
rgrover1 112:737b08b3b995 2116 if ((err_code == NRF_SUCCESS) && (context_len != INVALID_CONTEXT_LEN))
rgrover1 112:737b08b3b995 2117 {
rgrover1 112:737b08b3b995 2118 //Data already exists. Need an update.
rgrover1 112:737b08b3b995 2119 store_fn = pstorage_update;
rgrover1 112:737b08b3b995 2120
rgrover1 112:737b08b3b995 2121 DM_LOG("[DM]:[DI 0x%02X]: Updating existing application context, existing len 0x%08X, "
rgrover1 112:737b08b3b995 2122 "new length 0x%08X.\r\n",
rgrover1 112:737b08b3b995 2123 p_handle->device_id,
rgrover1 112:737b08b3b995 2124 context_len,
rgrover1 112:737b08b3b995 2125 p_context->len);
rgrover1 112:737b08b3b995 2126 }
rgrover1 112:737b08b3b995 2127 else
rgrover1 112:737b08b3b995 2128 {
rgrover1 112:737b08b3b995 2129 DM_LOG("[DM]: Storing application context.\r\n");
rgrover1 112:737b08b3b995 2130 }
rgrover1 112:737b08b3b995 2131
rgrover1 112:737b08b3b995 2132 //Store/update context length.
rgrover1 112:737b08b3b995 2133 err_code = store_fn(&block_handle,
rgrover1 112:737b08b3b995 2134 (uint8_t *)(&p_context->len),
rgrover1 112:737b08b3b995 2135 sizeof(uint32_t),
rgrover1 112:737b08b3b995 2136 APP_CONTEXT_STORAGE_OFFSET);
rgrover1 112:737b08b3b995 2137
rgrover1 112:737b08b3b995 2138 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 2139 {
rgrover1 112:737b08b3b995 2140 //Update context data is used for application context as flash is never
rgrover1 112:737b08b3b995 2141 //cleared if a delete of application context is called.
rgrover1 112:737b08b3b995 2142 err_code = pstorage_update(&block_handle,
rgrover1 112:737b08b3b995 2143 p_context->p_data,
rgrover1 112:737b08b3b995 2144 DEVICE_MANAGER_APP_CONTEXT_SIZE,
rgrover1 112:737b08b3b995 2145 (APP_CONTEXT_STORAGE_OFFSET + sizeof(uint32_t)));
rgrover1 112:737b08b3b995 2146 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 2147 {
rgrover1 112:737b08b3b995 2148 m_app_context_table[p_handle->device_id] = p_context->p_data;
rgrover1 112:737b08b3b995 2149 }
rgrover1 112:737b08b3b995 2150 }
rgrover1 112:737b08b3b995 2151 }
rgrover1 112:737b08b3b995 2152
rgrover1 112:737b08b3b995 2153 DM_TRC("[DM]: << dm_application_context_set\r\n");
rgrover1 112:737b08b3b995 2154
rgrover1 112:737b08b3b995 2155 DM_MUTEX_UNLOCK();
rgrover1 112:737b08b3b995 2156
rgrover1 112:737b08b3b995 2157 return err_code;
rgrover1 112:737b08b3b995 2158
rgrover1 112:737b08b3b995 2159 #else //DEVICE_MANAGER_APP_CONTEXT_SIZE
rgrover1 112:737b08b3b995 2160 return (FEATURE_NOT_ENABLED | DEVICE_MANAGER_ERR_BASE);
rgrover1 112:737b08b3b995 2161 #endif //DEVICE_MANAGER_APP_CONTEXT_SIZE
rgrover1 112:737b08b3b995 2162 }
rgrover1 112:737b08b3b995 2163
rgrover1 112:737b08b3b995 2164
rgrover1 112:737b08b3b995 2165 ret_code_t dm_application_context_get(dm_handle_t const * p_handle,
rgrover1 112:737b08b3b995 2166 dm_application_context_t * p_context)
rgrover1 112:737b08b3b995 2167 {
rgrover1 112:737b08b3b995 2168 #if (DEVICE_MANAGER_APP_CONTEXT_SIZE != 0)
rgrover1 112:737b08b3b995 2169 VERIFY_MODULE_INITIALIZED();
rgrover1 112:737b08b3b995 2170 NULL_PARAM_CHECK(p_handle);
rgrover1 112:737b08b3b995 2171 NULL_PARAM_CHECK(p_context);
rgrover1 112:737b08b3b995 2172 VERIFY_APP_REGISTERED(p_handle->appl_id);
rgrover1 112:737b08b3b995 2173 VERIFY_DEVICE_INSTANCE(p_handle->device_id);
rgrover1 112:737b08b3b995 2174
rgrover1 112:737b08b3b995 2175 DM_MUTEX_LOCK();
rgrover1 112:737b08b3b995 2176
rgrover1 112:737b08b3b995 2177 DM_TRC("[DM]: >> dm_application_context_get\r\n");
rgrover1 112:737b08b3b995 2178
rgrover1 112:737b08b3b995 2179 uint32_t context_len;
rgrover1 112:737b08b3b995 2180 uint32_t err_code;
rgrover1 112:737b08b3b995 2181 pstorage_handle_t block_handle;
rgrover1 112:737b08b3b995 2182
rgrover1 112:737b08b3b995 2183 //Check if the context exists.
rgrover1 112:737b08b3b995 2184 if (NULL == p_context->p_data)
rgrover1 112:737b08b3b995 2185 {
rgrover1 112:737b08b3b995 2186 p_context->p_data = m_app_context_table[p_handle->device_id];
rgrover1 112:737b08b3b995 2187 }
rgrover1 112:737b08b3b995 2188 else
rgrover1 112:737b08b3b995 2189 {
rgrover1 112:737b08b3b995 2190 m_app_context_table[p_handle->device_id] = p_context->p_data;
rgrover1 112:737b08b3b995 2191 }
rgrover1 112:737b08b3b995 2192
rgrover1 112:737b08b3b995 2193 err_code = pstorage_block_identifier_get(&m_storage_handle,
rgrover1 112:737b08b3b995 2194 p_handle->device_id,
rgrover1 112:737b08b3b995 2195 &block_handle);
rgrover1 112:737b08b3b995 2196
rgrover1 112:737b08b3b995 2197 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 2198 {
rgrover1 112:737b08b3b995 2199 err_code = pstorage_load((uint8_t *)&context_len,
rgrover1 112:737b08b3b995 2200 &block_handle,
rgrover1 112:737b08b3b995 2201 sizeof(uint32_t),
rgrover1 112:737b08b3b995 2202 APP_CONTEXT_STORAGE_OFFSET);
rgrover1 112:737b08b3b995 2203
rgrover1 112:737b08b3b995 2204 if ((err_code == NRF_SUCCESS) && (context_len != INVALID_CONTEXT_LEN))
rgrover1 112:737b08b3b995 2205 {
rgrover1 112:737b08b3b995 2206 err_code = pstorage_load(p_context->p_data,
rgrover1 112:737b08b3b995 2207 &block_handle,
rgrover1 112:737b08b3b995 2208 DEVICE_MANAGER_APP_CONTEXT_SIZE,
rgrover1 112:737b08b3b995 2209 (APP_CONTEXT_STORAGE_OFFSET + sizeof(uint32_t)));
rgrover1 112:737b08b3b995 2210 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 2211 {
rgrover1 112:737b08b3b995 2212 p_context->len = context_len;
rgrover1 112:737b08b3b995 2213 }
rgrover1 112:737b08b3b995 2214 }
rgrover1 112:737b08b3b995 2215 else
rgrover1 112:737b08b3b995 2216 {
rgrover1 112:737b08b3b995 2217 err_code = DM_NO_APP_CONTEXT;
rgrover1 112:737b08b3b995 2218 }
rgrover1 112:737b08b3b995 2219 }
rgrover1 112:737b08b3b995 2220
rgrover1 112:737b08b3b995 2221 DM_TRC("[DM]: << dm_application_context_get\r\n");
rgrover1 112:737b08b3b995 2222
rgrover1 112:737b08b3b995 2223 DM_MUTEX_UNLOCK();
rgrover1 112:737b08b3b995 2224
rgrover1 112:737b08b3b995 2225 return err_code;
rgrover1 112:737b08b3b995 2226
rgrover1 112:737b08b3b995 2227 #else //DEVICE_MANAGER_APP_CONTEXT_SIZE
rgrover1 112:737b08b3b995 2228 return (FEATURE_NOT_ENABLED | DEVICE_MANAGER_ERR_BASE);
rgrover1 112:737b08b3b995 2229 #endif //DEVICE_MANAGER_APP_CONTEXT_SIZE
rgrover1 112:737b08b3b995 2230 }
rgrover1 112:737b08b3b995 2231
rgrover1 112:737b08b3b995 2232
rgrover1 112:737b08b3b995 2233 ret_code_t dm_application_context_delete(const dm_handle_t * p_handle)
rgrover1 112:737b08b3b995 2234 {
rgrover1 112:737b08b3b995 2235 #if (DEVICE_MANAGER_APP_CONTEXT_SIZE != 0)
rgrover1 112:737b08b3b995 2236 VERIFY_MODULE_INITIALIZED();
rgrover1 112:737b08b3b995 2237 NULL_PARAM_CHECK(p_handle);
rgrover1 112:737b08b3b995 2238 VERIFY_APP_REGISTERED(p_handle->appl_id);
rgrover1 112:737b08b3b995 2239 VERIFY_DEVICE_INSTANCE(p_handle->device_id);
rgrover1 112:737b08b3b995 2240
rgrover1 112:737b08b3b995 2241 DM_MUTEX_LOCK();
rgrover1 112:737b08b3b995 2242
rgrover1 112:737b08b3b995 2243 DM_TRC("[DM]: >> dm_application_context_delete\r\n");
rgrover1 112:737b08b3b995 2244
rgrover1 112:737b08b3b995 2245 uint32_t err_code;
rgrover1 112:737b08b3b995 2246 uint32_t context_len;
rgrover1 112:737b08b3b995 2247 pstorage_handle_t block_handle;
rgrover1 112:737b08b3b995 2248
rgrover1 112:737b08b3b995 2249 err_code = pstorage_block_identifier_get(&m_storage_handle,
rgrover1 112:737b08b3b995 2250 p_handle->device_id,
rgrover1 112:737b08b3b995 2251 &block_handle);
rgrover1 112:737b08b3b995 2252
rgrover1 112:737b08b3b995 2253 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 2254 {
rgrover1 112:737b08b3b995 2255 err_code = pstorage_load((uint8_t *)&context_len,
rgrover1 112:737b08b3b995 2256 &block_handle,
rgrover1 112:737b08b3b995 2257 sizeof(uint32_t),
rgrover1 112:737b08b3b995 2258 APP_CONTEXT_STORAGE_OFFSET);
rgrover1 112:737b08b3b995 2259
rgrover1 112:737b08b3b995 2260 if (context_len != m_context_init_len)
rgrover1 112:737b08b3b995 2261 {
rgrover1 112:737b08b3b995 2262 err_code = pstorage_update(&block_handle,
rgrover1 112:737b08b3b995 2263 (uint8_t *)&m_context_init_len,
rgrover1 112:737b08b3b995 2264 sizeof(uint32_t),
rgrover1 112:737b08b3b995 2265 APP_CONTEXT_STORAGE_OFFSET);
rgrover1 112:737b08b3b995 2266
rgrover1 112:737b08b3b995 2267 if (err_code != NRF_SUCCESS)
rgrover1 112:737b08b3b995 2268 {
rgrover1 112:737b08b3b995 2269 DM_ERR("[DM]: Failed to delete application context, reason 0x%08X\r\n", err_code);
rgrover1 112:737b08b3b995 2270 }
rgrover1 112:737b08b3b995 2271 else
rgrover1 112:737b08b3b995 2272 {
rgrover1 112:737b08b3b995 2273 m_app_context_table[p_handle->device_id] = NULL;
rgrover1 112:737b08b3b995 2274 }
rgrover1 112:737b08b3b995 2275 }
rgrover1 112:737b08b3b995 2276 }
rgrover1 112:737b08b3b995 2277
rgrover1 112:737b08b3b995 2278 DM_TRC("[DM]: << dm_application_context_delete\r\n");
rgrover1 112:737b08b3b995 2279
rgrover1 112:737b08b3b995 2280 DM_MUTEX_UNLOCK();
rgrover1 112:737b08b3b995 2281
rgrover1 112:737b08b3b995 2282 return err_code;
rgrover1 112:737b08b3b995 2283 #else //DEVICE_MANAGER_APP_CONTEXT_SIZE
rgrover1 112:737b08b3b995 2284 return (FEATURE_NOT_ENABLED | DEVICE_MANAGER_ERR_BASE);
rgrover1 112:737b08b3b995 2285 #endif //DEVICE_MANAGER_APP_CONTEXT_SIZE
rgrover1 112:737b08b3b995 2286 }
rgrover1 112:737b08b3b995 2287
rgrover1 112:737b08b3b995 2288
rgrover1 112:737b08b3b995 2289 ret_code_t dm_application_instance_set(dm_application_instance_t const * p_appl_instance,
rgrover1 112:737b08b3b995 2290 dm_handle_t * p_handle)
rgrover1 112:737b08b3b995 2291 {
rgrover1 112:737b08b3b995 2292 VERIFY_MODULE_INITIALIZED();
rgrover1 112:737b08b3b995 2293 NULL_PARAM_CHECK(p_handle);
rgrover1 112:737b08b3b995 2294 NULL_PARAM_CHECK(p_appl_instance);
rgrover1 112:737b08b3b995 2295 VERIFY_APP_REGISTERED((*p_appl_instance));
rgrover1 112:737b08b3b995 2296
rgrover1 112:737b08b3b995 2297 p_handle->appl_id = (*p_appl_instance);
rgrover1 112:737b08b3b995 2298
rgrover1 112:737b08b3b995 2299 return NRF_SUCCESS;
rgrover1 112:737b08b3b995 2300 }
rgrover1 112:737b08b3b995 2301
rgrover1 112:737b08b3b995 2302
rgrover1 112:737b08b3b995 2303 uint32_t dm_handle_initialize(dm_handle_t * p_handle)
rgrover1 112:737b08b3b995 2304 {
rgrover1 112:737b08b3b995 2305 NULL_PARAM_CHECK(p_handle);
rgrover1 112:737b08b3b995 2306
rgrover1 112:737b08b3b995 2307 p_handle->appl_id = DM_INVALID_ID;
rgrover1 112:737b08b3b995 2308 p_handle->connection_id = DM_INVALID_ID;
rgrover1 112:737b08b3b995 2309 p_handle->device_id = DM_INVALID_ID;
rgrover1 112:737b08b3b995 2310 p_handle->service_id = DM_INVALID_ID;
rgrover1 112:737b08b3b995 2311
rgrover1 112:737b08b3b995 2312 return NRF_SUCCESS;
rgrover1 112:737b08b3b995 2313 }
rgrover1 112:737b08b3b995 2314
rgrover1 112:737b08b3b995 2315
rgrover1 112:737b08b3b995 2316 ret_code_t dm_peer_addr_set(dm_handle_t const * p_handle,
rgrover1 112:737b08b3b995 2317 ble_gap_addr_t const * p_addr)
rgrover1 112:737b08b3b995 2318 {
rgrover1 112:737b08b3b995 2319 VERIFY_MODULE_INITIALIZED();
rgrover1 112:737b08b3b995 2320 NULL_PARAM_CHECK(p_handle);
rgrover1 112:737b08b3b995 2321 NULL_PARAM_CHECK(p_addr);
rgrover1 112:737b08b3b995 2322 VERIFY_APP_REGISTERED(p_handle->appl_id);
rgrover1 112:737b08b3b995 2323 VERIFY_DEVICE_INSTANCE(p_handle->device_id);
rgrover1 112:737b08b3b995 2324
rgrover1 112:737b08b3b995 2325 DM_MUTEX_LOCK();
rgrover1 112:737b08b3b995 2326
rgrover1 112:737b08b3b995 2327 DM_TRC("[DM]: >> dm_peer_addr_set\r\n");
rgrover1 112:737b08b3b995 2328
rgrover1 112:737b08b3b995 2329 ret_code_t err_code;
rgrover1 112:737b08b3b995 2330
rgrover1 112:737b08b3b995 2331 if ((p_handle->connection_id == DM_INVALID_ID) &&
rgrover1 112:737b08b3b995 2332 (p_addr->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE))
rgrover1 112:737b08b3b995 2333 {
rgrover1 112:737b08b3b995 2334 m_peer_table[p_handle->device_id].peer_id.id_addr_info = (*p_addr);
rgrover1 112:737b08b3b995 2335 update_status_bit_set(p_handle->device_id);
rgrover1 112:737b08b3b995 2336 device_context_store(p_handle, UPDATE_PEER_ADDR);
rgrover1 112:737b08b3b995 2337 err_code = NRF_SUCCESS;
rgrover1 112:737b08b3b995 2338 }
rgrover1 112:737b08b3b995 2339 else
rgrover1 112:737b08b3b995 2340 {
rgrover1 112:737b08b3b995 2341 err_code = (NRF_ERROR_INVALID_PARAM | DEVICE_MANAGER_ERR_BASE);
rgrover1 112:737b08b3b995 2342 }
rgrover1 112:737b08b3b995 2343
rgrover1 112:737b08b3b995 2344 DM_TRC("[DM]: << dm_peer_addr_set\r\n");
rgrover1 112:737b08b3b995 2345
rgrover1 112:737b08b3b995 2346 DM_MUTEX_UNLOCK();
rgrover1 112:737b08b3b995 2347
rgrover1 112:737b08b3b995 2348 return err_code;
rgrover1 112:737b08b3b995 2349 }
rgrover1 112:737b08b3b995 2350
rgrover1 112:737b08b3b995 2351
rgrover1 112:737b08b3b995 2352 ret_code_t dm_peer_addr_get(dm_handle_t const * p_handle,
rgrover1 112:737b08b3b995 2353 ble_gap_addr_t * p_addr)
rgrover1 112:737b08b3b995 2354 {
rgrover1 112:737b08b3b995 2355 VERIFY_MODULE_INITIALIZED();
rgrover1 112:737b08b3b995 2356 NULL_PARAM_CHECK(p_handle);
rgrover1 112:737b08b3b995 2357 NULL_PARAM_CHECK(p_addr);
rgrover1 112:737b08b3b995 2358 VERIFY_APP_REGISTERED(p_handle->appl_id);
rgrover1 112:737b08b3b995 2359
rgrover1 112:737b08b3b995 2360 DM_MUTEX_LOCK();
rgrover1 112:737b08b3b995 2361
rgrover1 112:737b08b3b995 2362 DM_TRC("[DM]: >> dm_peer_addr_get\r\n");
rgrover1 112:737b08b3b995 2363
rgrover1 112:737b08b3b995 2364 ret_code_t err_code;
rgrover1 112:737b08b3b995 2365
rgrover1 112:737b08b3b995 2366 err_code = (NRF_ERROR_NOT_FOUND | DEVICE_MANAGER_ERR_BASE);
rgrover1 112:737b08b3b995 2367
rgrover1 112:737b08b3b995 2368 if (p_handle->device_id == DM_INVALID_ID)
rgrover1 112:737b08b3b995 2369 {
rgrover1 112:737b08b3b995 2370 if ((p_handle->connection_id != DM_INVALID_ID) &&
rgrover1 112:737b08b3b995 2371 ((m_connection_table[p_handle->connection_id].state & STATE_CONNECTED) ==
rgrover1 112:737b08b3b995 2372 STATE_CONNECTED))
rgrover1 112:737b08b3b995 2373 {
rgrover1 112:737b08b3b995 2374 DM_TRC("[DM]:[CI 0x%02X]: Address get for non bonded active connection.\r\n",
rgrover1 112:737b08b3b995 2375 p_handle->connection_id);
rgrover1 112:737b08b3b995 2376
rgrover1 112:737b08b3b995 2377 (*p_addr) = m_connection_table[p_handle->connection_id].peer_addr;
rgrover1 112:737b08b3b995 2378 err_code = NRF_SUCCESS;
rgrover1 112:737b08b3b995 2379 }
rgrover1 112:737b08b3b995 2380 }
rgrover1 112:737b08b3b995 2381 else
rgrover1 112:737b08b3b995 2382 {
rgrover1 112:737b08b3b995 2383 if ((m_peer_table[p_handle->device_id].id_bitmap & ADDR_ENTRY) == 0)
rgrover1 112:737b08b3b995 2384 {
rgrover1 112:737b08b3b995 2385 DM_TRC("[DM]:[DI 0x%02X]: Address get for bonded device.\r\n",
rgrover1 112:737b08b3b995 2386 p_handle->device_id);
rgrover1 112:737b08b3b995 2387
rgrover1 112:737b08b3b995 2388 (*p_addr) = m_peer_table[p_handle->device_id].peer_id.id_addr_info;
rgrover1 112:737b08b3b995 2389 err_code = NRF_SUCCESS;
rgrover1 112:737b08b3b995 2390 }
rgrover1 112:737b08b3b995 2391 }
rgrover1 112:737b08b3b995 2392
rgrover1 112:737b08b3b995 2393 DM_TRC("[DM]: << dm_peer_addr_get\r\n");
rgrover1 112:737b08b3b995 2394
rgrover1 112:737b08b3b995 2395 DM_MUTEX_UNLOCK();
rgrover1 112:737b08b3b995 2396
rgrover1 112:737b08b3b995 2397 return err_code;
rgrover1 112:737b08b3b995 2398 }
rgrover1 112:737b08b3b995 2399
rgrover1 112:737b08b3b995 2400
rgrover1 112:737b08b3b995 2401 ret_code_t dm_distributed_keys_get(dm_handle_t const * p_handle,
rgrover1 112:737b08b3b995 2402 dm_sec_keyset_t * p_key_dist)
rgrover1 112:737b08b3b995 2403 {
rgrover1 112:737b08b3b995 2404 VERIFY_MODULE_INITIALIZED();
rgrover1 112:737b08b3b995 2405 NULL_PARAM_CHECK(p_handle);
rgrover1 112:737b08b3b995 2406 NULL_PARAM_CHECK(p_key_dist);
rgrover1 112:737b08b3b995 2407 VERIFY_APP_REGISTERED(p_handle->appl_id);
rgrover1 112:737b08b3b995 2408 VERIFY_DEVICE_INSTANCE(p_handle->device_id);
rgrover1 112:737b08b3b995 2409
rgrover1 112:737b08b3b995 2410 DM_MUTEX_LOCK();
rgrover1 112:737b08b3b995 2411
rgrover1 112:737b08b3b995 2412 DM_TRC("[DM]: >> dm_distributed_keys_get\r\n");
rgrover1 112:737b08b3b995 2413
rgrover1 112:737b08b3b995 2414 ret_code_t err_code;
rgrover1 112:737b08b3b995 2415 ble_gap_enc_key_t peer_enc_key;
rgrover1 112:737b08b3b995 2416 pstorage_handle_t block_handle;
rgrover1 112:737b08b3b995 2417
rgrover1 112:737b08b3b995 2418 err_code = NRF_ERROR_NOT_FOUND;
rgrover1 112:737b08b3b995 2419 p_key_dist->keys_central.enc_key.p_enc_key = NULL;
rgrover1 112:737b08b3b995 2420 p_key_dist->keys_central.p_id_key = (dm_id_key_t *)&m_peer_table[p_handle->device_id].peer_id;
rgrover1 112:737b08b3b995 2421 p_key_dist->keys_central.p_sign_key = NULL;
rgrover1 112:737b08b3b995 2422 p_key_dist->keys_periph.p_id_key = (dm_id_key_t *)&m_local_id_info;
rgrover1 112:737b08b3b995 2423 p_key_dist->keys_periph.p_sign_key = NULL;
rgrover1 112:737b08b3b995 2424 p_key_dist->keys_periph.enc_key.p_enc_key = (dm_enc_key_t *)&peer_enc_key;
rgrover1 112:737b08b3b995 2425
rgrover1 112:737b08b3b995 2426 if ((m_peer_table[p_handle->device_id].id_bitmap & IRK_ENTRY) == 0)
rgrover1 112:737b08b3b995 2427 {
rgrover1 112:737b08b3b995 2428 // p_key_dist->keys_periph.p_id_key->id_addr_info.addr_type = INVALID_ADDR_TYPE;
rgrover1 112:737b08b3b995 2429 }
rgrover1 112:737b08b3b995 2430
rgrover1 112:737b08b3b995 2431 err_code = pstorage_block_identifier_get(&m_storage_handle, p_handle->device_id, &block_handle);
rgrover1 112:737b08b3b995 2432 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 2433 {
rgrover1 112:737b08b3b995 2434
rgrover1 112:737b08b3b995 2435 err_code = pstorage_load((uint8_t *)&peer_enc_key,
rgrover1 112:737b08b3b995 2436 &block_handle,
rgrover1 112:737b08b3b995 2437 BOND_SIZE,
rgrover1 112:737b08b3b995 2438 BOND_STORAGE_OFFSET);
rgrover1 112:737b08b3b995 2439
rgrover1 112:737b08b3b995 2440 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 2441 {
rgrover1 112:737b08b3b995 2442 p_key_dist->keys_central.enc_key.p_enc_key = NULL;
rgrover1 112:737b08b3b995 2443 p_key_dist->keys_central.p_id_key = (dm_id_key_t *)&m_peer_table[p_handle->device_id].peer_id;
rgrover1 112:737b08b3b995 2444 p_key_dist->keys_central.p_sign_key = NULL;
rgrover1 112:737b08b3b995 2445 p_key_dist->keys_periph.p_id_key = (dm_id_key_t *)&m_local_id_info;
rgrover1 112:737b08b3b995 2446 p_key_dist->keys_periph.p_sign_key = NULL;
rgrover1 112:737b08b3b995 2447 p_key_dist->keys_periph.enc_key.p_enc_key = (dm_enc_key_t *)&peer_enc_key;
rgrover1 112:737b08b3b995 2448 }
rgrover1 112:737b08b3b995 2449 }
rgrover1 112:737b08b3b995 2450
rgrover1 112:737b08b3b995 2451 DM_TRC("[DM]: << dm_distributed_keys_get\r\n");
rgrover1 112:737b08b3b995 2452
rgrover1 112:737b08b3b995 2453 DM_MUTEX_UNLOCK();
rgrover1 112:737b08b3b995 2454
rgrover1 112:737b08b3b995 2455 return err_code;
rgrover1 112:737b08b3b995 2456 }
rgrover1 112:737b08b3b995 2457
rgrover1 112:737b08b3b995 2458
rgrover1 112:737b08b3b995 2459 /**@brief Function for loading bond information for a connection instance.
rgrover1 112:737b08b3b995 2460 */
rgrover1 112:737b08b3b995 2461 void bond_data_load(dm_handle_t * p_handle)
rgrover1 112:737b08b3b995 2462 {
rgrover1 112:737b08b3b995 2463 pstorage_handle_t block_handle;
rgrover1 112:737b08b3b995 2464
rgrover1 112:737b08b3b995 2465 uint32_t err_code = pstorage_block_identifier_get(&m_storage_handle,
rgrover1 112:737b08b3b995 2466 p_handle->device_id,
rgrover1 112:737b08b3b995 2467 &block_handle);
rgrover1 112:737b08b3b995 2468 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 2469 {
rgrover1 112:737b08b3b995 2470 DM_LOG(
rgrover1 112:737b08b3b995 2471 "[DM]:[%02X]:[Block ID 0x%08X]:Loading bond information at %p, size 0x%08X, offset 0x%08X.\r\n",
rgrover1 112:737b08b3b995 2472 p_handle->connection_id,
rgrover1 112:737b08b3b995 2473 block_handle.block_id,
rgrover1 112:737b08b3b995 2474 &m_bond_table[p_handle->connection_id],
rgrover1 112:737b08b3b995 2475 BOND_SIZE,
rgrover1 112:737b08b3b995 2476 BOND_STORAGE_OFFSET);
rgrover1 112:737b08b3b995 2477
rgrover1 112:737b08b3b995 2478 err_code = pstorage_load((uint8_t *)&m_bond_table[p_handle->connection_id],
rgrover1 112:737b08b3b995 2479 &block_handle,
rgrover1 112:737b08b3b995 2480 BOND_SIZE,
rgrover1 112:737b08b3b995 2481 BOND_STORAGE_OFFSET);
rgrover1 112:737b08b3b995 2482
rgrover1 112:737b08b3b995 2483 if (err_code != NRF_SUCCESS)
rgrover1 112:737b08b3b995 2484 {
rgrover1 112:737b08b3b995 2485 DM_ERR("[DM]:[%02X]: Failed to load Bond information, reason %08X\r\n",
rgrover1 112:737b08b3b995 2486 p_handle->connection_id,
rgrover1 112:737b08b3b995 2487 err_code);
rgrover1 112:737b08b3b995 2488 }
rgrover1 112:737b08b3b995 2489
rgrover1 112:737b08b3b995 2490 DM_LOG(
rgrover1 112:737b08b3b995 2491 "[DM]:[%02X]:Loading service context at %p, size 0x%08X, offset 0x%08X.\r\n",
rgrover1 112:737b08b3b995 2492 p_handle->connection_id,
rgrover1 112:737b08b3b995 2493 &m_gatts_table[p_handle->connection_id],
rgrover1 112:737b08b3b995 2494 sizeof(dm_gatts_context_t),
rgrover1 112:737b08b3b995 2495 SERVICE_STORAGE_OFFSET);
rgrover1 112:737b08b3b995 2496
rgrover1 112:737b08b3b995 2497 err_code = m_service_context_load[m_application_table[0].service](
rgrover1 112:737b08b3b995 2498 &block_handle,
rgrover1 112:737b08b3b995 2499 p_handle);
rgrover1 112:737b08b3b995 2500
rgrover1 112:737b08b3b995 2501 if (err_code != NRF_SUCCESS)
rgrover1 112:737b08b3b995 2502 {
rgrover1 112:737b08b3b995 2503 DM_ERR(
rgrover1 112:737b08b3b995 2504 "[DM]:[%02X]: Failed to load service information, reason %08X\r\n",
rgrover1 112:737b08b3b995 2505 p_handle->connection_id,
rgrover1 112:737b08b3b995 2506 err_code);
rgrover1 112:737b08b3b995 2507 }
rgrover1 112:737b08b3b995 2508 }
rgrover1 112:737b08b3b995 2509 else
rgrover1 112:737b08b3b995 2510 {
rgrover1 112:737b08b3b995 2511 DM_ERR("[DM]:[%02X]: Failed to get block identifier for "
rgrover1 112:737b08b3b995 2512 "device %08X, reason %08X.\r\n", p_handle->connection_id, p_handle->device_id, err_code);
rgrover1 112:737b08b3b995 2513 }
rgrover1 112:737b08b3b995 2514 }
rgrover1 112:737b08b3b995 2515
rgrover1 112:737b08b3b995 2516
rgrover1 112:737b08b3b995 2517 void dm_ble_evt_handler(ble_evt_t * p_ble_evt)
rgrover1 112:737b08b3b995 2518 {
rgrover1 112:737b08b3b995 2519 uint32_t err_code;
rgrover1 112:737b08b3b995 2520 uint32_t index;
rgrover1 112:737b08b3b995 2521 uint32_t device_index = DM_INVALID_ID;
rgrover1 112:737b08b3b995 2522 bool notify_app = false;
rgrover1 112:737b08b3b995 2523 dm_handle_t handle;
rgrover1 112:737b08b3b995 2524 dm_event_t event;
rgrover1 112:737b08b3b995 2525 uint32_t event_result;
rgrover1 112:737b08b3b995 2526 ble_gap_enc_info_t * p_enc_info = NULL;
rgrover1 112:737b08b3b995 2527
rgrover1 112:737b08b3b995 2528 VERIFY_MODULE_INITIALIZED_VOID();
rgrover1 112:737b08b3b995 2529 VERIFY_APP_REGISTERED_VOID(0);
rgrover1 112:737b08b3b995 2530 DM_MUTEX_LOCK();
rgrover1 112:737b08b3b995 2531
rgrover1 112:737b08b3b995 2532 err_code = dm_handle_initialize(&handle);
rgrover1 112:737b08b3b995 2533 APP_ERROR_CHECK(err_code);
rgrover1 112:737b08b3b995 2534
rgrover1 112:737b08b3b995 2535 event_result = NRF_SUCCESS;
rgrover1 112:737b08b3b995 2536 err_code = NRF_SUCCESS;
rgrover1 112:737b08b3b995 2537 event.event_param.p_gap_param = &p_ble_evt->evt.gap_evt;
rgrover1 112:737b08b3b995 2538 event.event_paramlen = sizeof(ble_gap_evt_t);
rgrover1 112:737b08b3b995 2539 handle.device_id = DM_INVALID_ID;
rgrover1 112:737b08b3b995 2540 handle.appl_id = 0;
rgrover1 112:737b08b3b995 2541 index = 0x00;
rgrover1 112:737b08b3b995 2542
rgrover1 112:737b08b3b995 2543 if (p_ble_evt->header.evt_id != BLE_GAP_EVT_CONNECTED)
rgrover1 112:737b08b3b995 2544 {
rgrover1 112:737b08b3b995 2545 err_code = connection_instance_find(p_ble_evt->evt.gap_evt.conn_handle,
rgrover1 112:737b08b3b995 2546 STATE_CONNECTED,
rgrover1 112:737b08b3b995 2547 &index);
rgrover1 112:737b08b3b995 2548
rgrover1 112:737b08b3b995 2549 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 2550 {
rgrover1 112:737b08b3b995 2551 handle.device_id = m_connection_table[index].bonded_dev_id;
rgrover1 112:737b08b3b995 2552 handle.connection_id = index;
rgrover1 112:737b08b3b995 2553 }
rgrover1 112:737b08b3b995 2554 }
rgrover1 112:737b08b3b995 2555
rgrover1 112:737b08b3b995 2556 switch (p_ble_evt->header.evt_id)
rgrover1 112:737b08b3b995 2557 {
rgrover1 112:737b08b3b995 2558 case BLE_GAP_EVT_CONNECTED:
rgrover1 112:737b08b3b995 2559 //Allocate connection instance for a new connection.
rgrover1 112:737b08b3b995 2560 err_code = connection_instance_allocate(&index);
rgrover1 112:737b08b3b995 2561
rgrover1 112:737b08b3b995 2562 //Connection instance is successfully allocated.
rgrover1 112:737b08b3b995 2563 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 2564 {
rgrover1 112:737b08b3b995 2565 //Application notification related information.
rgrover1 112:737b08b3b995 2566 notify_app = true;
rgrover1 112:737b08b3b995 2567 event.event_id = DM_EVT_CONNECTION;
rgrover1 112:737b08b3b995 2568 handle.connection_id = index;
rgrover1 112:737b08b3b995 2569
rgrover1 112:737b08b3b995 2570 m_connection_table[index].conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
rgrover1 112:737b08b3b995 2571 m_connection_table[index].state = STATE_CONNECTED;
rgrover1 112:737b08b3b995 2572 m_connection_table[index].peer_addr =
rgrover1 112:737b08b3b995 2573 p_ble_evt->evt.gap_evt.params.connected.peer_addr;
rgrover1 112:737b08b3b995 2574
rgrover1 112:737b08b3b995 2575 if (p_ble_evt->evt.gap_evt.params.connected.irk_match == 1)
rgrover1 112:737b08b3b995 2576 {
rgrover1 112:737b08b3b995 2577 if (m_irk_index_table[p_ble_evt->evt.gap_evt.params.connected.irk_match_idx] != DM_INVALID_ID)
rgrover1 112:737b08b3b995 2578 {
rgrover1 112:737b08b3b995 2579 device_index = m_irk_index_table[p_ble_evt->evt.gap_evt.params.connected.irk_match_idx];
rgrover1 112:737b08b3b995 2580 err_code = NRF_SUCCESS;
rgrover1 112:737b08b3b995 2581 }
rgrover1 112:737b08b3b995 2582 }
rgrover1 112:737b08b3b995 2583 else
rgrover1 112:737b08b3b995 2584 {
rgrover1 112:737b08b3b995 2585 //Use the device address to check if the device exists in the bonded device list.
rgrover1 112:737b08b3b995 2586 err_code = device_instance_find(&p_ble_evt->evt.gap_evt.params.connected.peer_addr,
rgrover1 112:737b08b3b995 2587 &device_index, EDIV_INIT_VAL);
rgrover1 112:737b08b3b995 2588 }
rgrover1 112:737b08b3b995 2589
rgrover1 112:737b08b3b995 2590 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 2591 {
rgrover1 112:737b08b3b995 2592 m_connection_table[index].bonded_dev_id = device_index;
rgrover1 112:737b08b3b995 2593 m_connection_table[index].state |= STATE_BONDED;
rgrover1 112:737b08b3b995 2594 handle.device_id = device_index;
rgrover1 112:737b08b3b995 2595
rgrover1 112:737b08b3b995 2596 bond_data_load(&handle);
rgrover1 112:737b08b3b995 2597 }
rgrover1 112:737b08b3b995 2598 }
rgrover1 112:737b08b3b995 2599 break;
rgrover1 112:737b08b3b995 2600
rgrover1 112:737b08b3b995 2601 case BLE_GAP_EVT_DISCONNECTED:
rgrover1 112:737b08b3b995 2602 //Disconnection could be peer or self initiated hence disconnecting and connecting
rgrover1 112:737b08b3b995 2603 //both states are permitted, however, connection handle must be known.
rgrover1 112:737b08b3b995 2604 DM_LOG("[DM]: Disconnect Reason 0x%04X\r\n",
rgrover1 112:737b08b3b995 2605 p_ble_evt->evt.gap_evt.params.disconnected.reason);
rgrover1 112:737b08b3b995 2606
rgrover1 112:737b08b3b995 2607 m_connection_table[index].state &= (~STATE_CONNECTED);
rgrover1 112:737b08b3b995 2608
rgrover1 112:737b08b3b995 2609 if ((m_connection_table[index].state & STATE_BONDED) == STATE_BONDED)
rgrover1 112:737b08b3b995 2610 {
rgrover1 112:737b08b3b995 2611 if ((m_connection_table[index].state & STATE_LINK_ENCRYPTED) == STATE_LINK_ENCRYPTED)
rgrover1 112:737b08b3b995 2612 {
rgrover1 112:737b08b3b995 2613 //Write bond information persistently.
rgrover1 112:737b08b3b995 2614 device_context_store(&handle, STORE_ALL_CONTEXT);
rgrover1 112:737b08b3b995 2615 }
rgrover1 112:737b08b3b995 2616 }
rgrover1 112:737b08b3b995 2617 else
rgrover1 112:737b08b3b995 2618 {
rgrover1 112:737b08b3b995 2619 //Free any allocated instances for devices that is not bonded.
rgrover1 112:737b08b3b995 2620 if (handle.device_id != DM_INVALID_ID)
rgrover1 112:737b08b3b995 2621 {
rgrover1 112:737b08b3b995 2622 peer_instance_init(handle.device_id);
rgrover1 112:737b08b3b995 2623 handle.device_id = DM_INVALID_ID;
rgrover1 112:737b08b3b995 2624 }
rgrover1 112:737b08b3b995 2625 }
rgrover1 112:737b08b3b995 2626
rgrover1 112:737b08b3b995 2627 m_connection_table[index].state = STATE_DISCONNECTING;
rgrover1 112:737b08b3b995 2628 notify_app = true;
rgrover1 112:737b08b3b995 2629 event.event_id = DM_EVT_DISCONNECTION;
rgrover1 112:737b08b3b995 2630
rgrover1 112:737b08b3b995 2631 break;
rgrover1 112:737b08b3b995 2632
rgrover1 112:737b08b3b995 2633 case BLE_GAP_EVT_SEC_INFO_REQUEST:
rgrover1 112:737b08b3b995 2634 DM_LOG("[DM]: >> BLE_GAP_EVT_SEC_INFO_REQUEST\r\n");
rgrover1 112:737b08b3b995 2635
rgrover1 112:737b08b3b995 2636 //If the device is already bonded, respond with existing info, else NULL.
rgrover1 112:737b08b3b995 2637 if (m_connection_table[index].bonded_dev_id == DM_INVALID_ID)
rgrover1 112:737b08b3b995 2638 {
rgrover1 112:737b08b3b995 2639 //Find device based on div.
rgrover1 112:737b08b3b995 2640 err_code = device_instance_find(NULL,&device_index, p_ble_evt->evt.gap_evt.params.sec_info_request.master_id.ediv);
rgrover1 112:737b08b3b995 2641 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 2642 {
rgrover1 112:737b08b3b995 2643 //Load needed bonding information.
rgrover1 112:737b08b3b995 2644 m_connection_table[index].bonded_dev_id = device_index;
rgrover1 112:737b08b3b995 2645 m_connection_table[index].state |= STATE_BONDED;
rgrover1 112:737b08b3b995 2646 handle.device_id = device_index;
rgrover1 112:737b08b3b995 2647 bond_data_load(&handle);
rgrover1 112:737b08b3b995 2648 }
rgrover1 112:737b08b3b995 2649 }
rgrover1 112:737b08b3b995 2650
rgrover1 112:737b08b3b995 2651 if (m_connection_table[index].bonded_dev_id != DM_INVALID_ID)
rgrover1 112:737b08b3b995 2652 {
rgrover1 112:737b08b3b995 2653 p_enc_info = &m_bond_table[index].peer_enc_key.enc_info;
rgrover1 112:737b08b3b995 2654 DM_DUMP((uint8_t *)p_enc_info, sizeof(ble_gap_enc_info_t));
rgrover1 112:737b08b3b995 2655 }
rgrover1 112:737b08b3b995 2656
rgrover1 112:737b08b3b995 2657 err_code = sd_ble_gap_sec_info_reply(p_ble_evt->evt.gap_evt.conn_handle,
rgrover1 112:737b08b3b995 2658 p_enc_info,
rgrover1 112:737b08b3b995 2659 &m_peer_table[index].peer_id.id_info,
rgrover1 112:737b08b3b995 2660 NULL);
rgrover1 112:737b08b3b995 2661
rgrover1 112:737b08b3b995 2662 if (err_code != NRF_SUCCESS)
rgrover1 112:737b08b3b995 2663 {
rgrover1 112:737b08b3b995 2664 DM_ERR("[DM]:[CI %02X]:[DI %02X]: Security information response failed, reason "
rgrover1 112:737b08b3b995 2665 "0x%08X\r\n", index, m_connection_table[index].bonded_dev_id, err_code);
rgrover1 112:737b08b3b995 2666 }
rgrover1 112:737b08b3b995 2667 break;
rgrover1 112:737b08b3b995 2668
rgrover1 112:737b08b3b995 2669 case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
rgrover1 112:737b08b3b995 2670 DM_LOG("[DM]: >> BLE_GAP_EVT_SEC_PARAMS_REQUEST\r\n");
rgrover1 112:737b08b3b995 2671
rgrover1 112:737b08b3b995 2672 event.event_id = DM_EVT_SECURITY_SETUP;
rgrover1 112:737b08b3b995 2673
rgrover1 112:737b08b3b995 2674 m_connection_table[index].state |= STATE_PAIRING;
rgrover1 112:737b08b3b995 2675 notify_app = true;
rgrover1 112:737b08b3b995 2676
rgrover1 112:737b08b3b995 2677 if (m_connection_table[index].bonded_dev_id == DM_INVALID_ID)
rgrover1 112:737b08b3b995 2678 {
rgrover1 112:737b08b3b995 2679 //Assign a peer index as a new bond or update existing bonds.
rgrover1 112:737b08b3b995 2680 err_code = device_instance_allocate((uint8_t *)&device_index,
rgrover1 112:737b08b3b995 2681 &m_connection_table[index].peer_addr);
rgrover1 112:737b08b3b995 2682
rgrover1 112:737b08b3b995 2683 //Allocation successful.
rgrover1 112:737b08b3b995 2684 if (err_code == NRF_SUCCESS)
rgrover1 112:737b08b3b995 2685 {
rgrover1 112:737b08b3b995 2686 DM_LOG("[DM]:[CI 0x%02X]:[DI 0x%02X]: Bonded!\r\n",index, device_index);
rgrover1 112:737b08b3b995 2687
rgrover1 112:737b08b3b995 2688 handle.device_id = device_index;
rgrover1 112:737b08b3b995 2689 m_connection_table[index].bonded_dev_id = device_index;
rgrover1 112:737b08b3b995 2690 }
rgrover1 112:737b08b3b995 2691 else
rgrover1 112:737b08b3b995 2692 {
rgrover1 112:737b08b3b995 2693 DM_LOG("[DM]: Security parameter request failed, reason 0x%08X.\r\n", err_code);
rgrover1 112:737b08b3b995 2694 event_result = err_code;
rgrover1 112:737b08b3b995 2695 notify_app = true;
rgrover1 112:737b08b3b995 2696 }
rgrover1 112:737b08b3b995 2697 }
rgrover1 112:737b08b3b995 2698 else
rgrover1 112:737b08b3b995 2699 {
rgrover1 112:737b08b3b995 2700 //Bond/key refresh.
rgrover1 112:737b08b3b995 2701 event.event_id = DM_EVT_SECURITY_SETUP_REFRESH;
rgrover1 112:737b08b3b995 2702 memset(m_gatts_table[index].attributes, 0, DM_GATT_SERVER_ATTR_MAX_SIZE);
rgrover1 112:737b08b3b995 2703
rgrover1 112:737b08b3b995 2704 //Set the update flag for bond data.
rgrover1 112:737b08b3b995 2705 m_connection_table[index].state |= STATE_BOND_INFO_UPDATE;
rgrover1 112:737b08b3b995 2706 }
rgrover1 112:737b08b3b995 2707
rgrover1 112:737b08b3b995 2708 ble_gap_sec_keyset_t keys_exchanged;
rgrover1 112:737b08b3b995 2709
rgrover1 112:737b08b3b995 2710 DM_LOG("[DM]: 0x%02X, 0x%02X, 0x%02X, 0x%02X\r\n",
rgrover1 112:737b08b3b995 2711 p_ble_evt->evt.gap_evt.params.sec_params_request.peer_params.kdist_periph.enc,
rgrover1 112:737b08b3b995 2712 p_ble_evt->evt.gap_evt.params.sec_params_request.peer_params.kdist_central.id,
rgrover1 112:737b08b3b995 2713 p_ble_evt->evt.gap_evt.params.sec_params_request.peer_params.kdist_periph.sign,
rgrover1 112:737b08b3b995 2714 p_ble_evt->evt.gap_evt.params.sec_params_request.peer_params.bond);
rgrover1 112:737b08b3b995 2715
rgrover1 112:737b08b3b995 2716 keys_exchanged.keys_central.p_enc_key = NULL;
rgrover1 112:737b08b3b995 2717 keys_exchanged.keys_central.p_id_key = &m_peer_table[m_connection_table[index].bonded_dev_id].peer_id;
rgrover1 112:737b08b3b995 2718 keys_exchanged.keys_central.p_sign_key = NULL;
rgrover1 112:737b08b3b995 2719 keys_exchanged.keys_periph.p_enc_key = &m_bond_table[index].peer_enc_key;
rgrover1 112:737b08b3b995 2720 keys_exchanged.keys_periph.p_id_key = NULL;
rgrover1 112:737b08b3b995 2721 keys_exchanged.keys_periph.p_sign_key = NULL;
rgrover1 112:737b08b3b995 2722
rgrover1 112:737b08b3b995 2723 err_code = sd_ble_gap_sec_params_reply(p_ble_evt->evt.gap_evt.conn_handle,
rgrover1 112:737b08b3b995 2724 BLE_GAP_SEC_STATUS_SUCCESS,
rgrover1 112:737b08b3b995 2725 &m_application_table[0].sec_param,
rgrover1 112:737b08b3b995 2726 &keys_exchanged);
rgrover1 112:737b08b3b995 2727
rgrover1 112:737b08b3b995 2728 if (err_code != NRF_SUCCESS)
rgrover1 112:737b08b3b995 2729 {
rgrover1 112:737b08b3b995 2730 DM_LOG("[DM]: Security parameter reply request failed, reason 0x%08X.\r\n", err_code);
rgrover1 112:737b08b3b995 2731 event_result = err_code;
rgrover1 112:737b08b3b995 2732 notify_app = false;
rgrover1 112:737b08b3b995 2733 }
rgrover1 112:737b08b3b995 2734 break;
rgrover1 112:737b08b3b995 2735
rgrover1 112:737b08b3b995 2736 case BLE_GAP_EVT_AUTH_STATUS:
rgrover1 112:737b08b3b995 2737 {
rgrover1 112:737b08b3b995 2738 DM_LOG("[DM]: >> BLE_GAP_EVT_AUTH_STATUS, status %08X\r\n",
rgrover1 112:737b08b3b995 2739 p_ble_evt->evt.gap_evt.params.auth_status.auth_status);
rgrover1 112:737b08b3b995 2740
rgrover1 112:737b08b3b995 2741 m_application_table[0].state &= (~STATE_CONTROL_PROCEDURE_IN_PROGRESS);
rgrover1 112:737b08b3b995 2742 m_connection_table[index].state &= (~STATE_PAIRING);
rgrover1 112:737b08b3b995 2743 event.event_id = DM_EVT_SECURITY_SETUP_COMPLETE;
rgrover1 112:737b08b3b995 2744 notify_app = true;
rgrover1 112:737b08b3b995 2745
rgrover1 112:737b08b3b995 2746 if (p_ble_evt->evt.gap_evt.params.auth_status.auth_status != BLE_GAP_SEC_STATUS_SUCCESS)
rgrover1 112:737b08b3b995 2747 {
rgrover1 112:737b08b3b995 2748 // Free the allocation as bonding failed.
rgrover1 112:737b08b3b995 2749 ret_code_t result = device_instance_free(m_connection_table[index].bonded_dev_id);
rgrover1 112:737b08b3b995 2750 (void) result;
rgrover1 112:737b08b3b995 2751 event_result = p_ble_evt->evt.gap_evt.params.auth_status.auth_status;
rgrover1 112:737b08b3b995 2752 }
rgrover1 112:737b08b3b995 2753 else
rgrover1 112:737b08b3b995 2754 {
rgrover1 112:737b08b3b995 2755 DM_DUMP((uint8_t *)&p_ble_evt->evt.gap_evt.params.auth_status,
rgrover1 112:737b08b3b995 2756 sizeof(ble_gap_evt_auth_status_t));
rgrover1 112:737b08b3b995 2757 DM_DUMP((uint8_t *)&m_bond_table[index], sizeof(bond_context_t));
rgrover1 112:737b08b3b995 2758
rgrover1 112:737b08b3b995 2759 if (p_ble_evt->evt.gap_evt.params.auth_status.bonded == 1)
rgrover1 112:737b08b3b995 2760 {
rgrover1 112:737b08b3b995 2761 if (handle.device_id != DM_INVALID_ID)
rgrover1 112:737b08b3b995 2762 {
rgrover1 112:737b08b3b995 2763 m_connection_table[index].state |= STATE_BONDED;
rgrover1 112:737b08b3b995 2764
rgrover1 112:737b08b3b995 2765 //IRK and/or public address is shared, update it.
rgrover1 112:737b08b3b995 2766 if (p_ble_evt->evt.gap_evt.params.auth_status.kdist_central.id == 1)
rgrover1 112:737b08b3b995 2767 {
rgrover1 112:737b08b3b995 2768 m_peer_table[handle.device_id].id_bitmap &= (~IRK_ENTRY);
rgrover1 112:737b08b3b995 2769 }
rgrover1 112:737b08b3b995 2770
rgrover1 112:737b08b3b995 2771 if (m_connection_table[index].bonded_dev_id != DM_INVALID_ID)
rgrover1 112:737b08b3b995 2772 {
rgrover1 112:737b08b3b995 2773 DM_LOG("[DM]:[CI 0x%02X]:[DI 0x%02X]: Bonded!\r\n",
rgrover1 112:737b08b3b995 2774 index,
rgrover1 112:737b08b3b995 2775 handle.device_id);
rgrover1 112:737b08b3b995 2776
rgrover1 112:737b08b3b995 2777 if (m_connection_table[index].peer_addr.addr_type !=
rgrover1 112:737b08b3b995 2778 BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE)
rgrover1 112:737b08b3b995 2779 {
rgrover1 112:737b08b3b995 2780 m_peer_table[handle.device_id].peer_id.id_addr_info =
rgrover1 112:737b08b3b995 2781 m_connection_table[index].peer_addr;
rgrover1 112:737b08b3b995 2782 m_peer_table[handle.device_id].id_bitmap &= (~ADDR_ENTRY);
rgrover1 112:737b08b3b995 2783
rgrover1 112:737b08b3b995 2784 DM_DUMP((uint8_t *)&m_peer_table[handle.device_id].peer_id.id_addr_info,
rgrover1 112:737b08b3b995 2785 sizeof(m_peer_table[handle.device_id].peer_id.id_addr_info));
rgrover1 112:737b08b3b995 2786 }
rgrover1 112:737b08b3b995 2787 else
rgrover1 112:737b08b3b995 2788 {
rgrover1 112:737b08b3b995 2789 // Here we must fetch the keys from the keyset distributed.
rgrover1 112:737b08b3b995 2790 m_peer_table[handle.device_id].ediv = m_bond_table[index].peer_enc_key.master_id.ediv;
rgrover1 112:737b08b3b995 2791 m_peer_table[handle.device_id].id_bitmap &= (~IRK_ENTRY);
rgrover1 112:737b08b3b995 2792 }
rgrover1 112:737b08b3b995 2793
rgrover1 112:737b08b3b995 2794 device_context_store(&handle, FIRST_BOND_STORE);
rgrover1 112:737b08b3b995 2795 }
rgrover1 112:737b08b3b995 2796 }
rgrover1 112:737b08b3b995 2797 }
rgrover1 112:737b08b3b995 2798 else
rgrover1 112:737b08b3b995 2799 {
rgrover1 112:737b08b3b995 2800 //Pairing request, no need to touch the bonding info.
rgrover1 112:737b08b3b995 2801 }
rgrover1 112:737b08b3b995 2802 }
rgrover1 112:737b08b3b995 2803 break;
rgrover1 112:737b08b3b995 2804 }
rgrover1 112:737b08b3b995 2805
rgrover1 112:737b08b3b995 2806 case BLE_GAP_EVT_CONN_SEC_UPDATE:
rgrover1 112:737b08b3b995 2807 DM_LOG("[DM]: >> BLE_GAP_EVT_CONN_SEC_UPDATE, Mode 0x%02X, Level 0x%02X\r\n",
rgrover1 112:737b08b3b995 2808 p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.sm,
rgrover1 112:737b08b3b995 2809 p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv);
rgrover1 112:737b08b3b995 2810
rgrover1 112:737b08b3b995 2811 if ((p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv == 1) &&
rgrover1 112:737b08b3b995 2812 (p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.sm == 1) &&
rgrover1 112:737b08b3b995 2813 ((m_connection_table[index].state & STATE_BONDED) == STATE_BONDED))
rgrover1 112:737b08b3b995 2814 {
rgrover1 112:737b08b3b995 2815 //Lost bond case, generate a security refresh event!
rgrover1 112:737b08b3b995 2816 memset(m_gatts_table[index].attributes, 0, DM_GATT_SERVER_ATTR_MAX_SIZE);
rgrover1 112:737b08b3b995 2817
rgrover1 112:737b08b3b995 2818 event.event_id = DM_EVT_SECURITY_SETUP_REFRESH;
rgrover1 112:737b08b3b995 2819 m_connection_table[index].state |= STATE_PAIRING_PENDING;
rgrover1 112:737b08b3b995 2820 m_connection_table[index].state |= STATE_BOND_INFO_UPDATE;
rgrover1 112:737b08b3b995 2821 m_application_table[0].state |= STATE_QUEUED_CONTROL_REQUEST;
rgrover1 112:737b08b3b995 2822 }
rgrover1 112:737b08b3b995 2823 else
rgrover1 112:737b08b3b995 2824 {
rgrover1 112:737b08b3b995 2825 m_connection_table[index].state |= STATE_LINK_ENCRYPTED;
rgrover1 112:737b08b3b995 2826 event.event_id = DM_EVT_LINK_SECURED;
rgrover1 112:737b08b3b995 2827
rgrover1 112:737b08b3b995 2828 //Apply service context.
rgrover1 112:737b08b3b995 2829 err_code = m_service_context_apply[m_application_table[0].service](&handle);
rgrover1 112:737b08b3b995 2830
rgrover1 112:737b08b3b995 2831 if (err_code != NRF_SUCCESS)
rgrover1 112:737b08b3b995 2832 {
rgrover1 112:737b08b3b995 2833 DM_ERR("[DM]:[CI 0x%02X]:[DI 0x%02X]: Failed to apply service context\r\n",
rgrover1 112:737b08b3b995 2834 handle.connection_id,
rgrover1 112:737b08b3b995 2835 handle.device_id);
rgrover1 112:737b08b3b995 2836
rgrover1 112:737b08b3b995 2837 event_result = DM_SERVICE_CONTEXT_NOT_APPLIED;
rgrover1 112:737b08b3b995 2838 }
rgrover1 112:737b08b3b995 2839 }
rgrover1 112:737b08b3b995 2840 event_result = NRF_SUCCESS;
rgrover1 112:737b08b3b995 2841 notify_app = true;
rgrover1 112:737b08b3b995 2842
rgrover1 112:737b08b3b995 2843 break;
rgrover1 112:737b08b3b995 2844
rgrover1 112:737b08b3b995 2845 case BLE_GATTS_EVT_SYS_ATTR_MISSING:
rgrover1 112:737b08b3b995 2846 DM_LOG("[DM]: >> BLE_GATTS_EVT_SYS_ATTR_MISSING\r\n");
rgrover1 112:737b08b3b995 2847
rgrover1 112:737b08b3b995 2848 //Apply service context.
rgrover1 112:737b08b3b995 2849 event_result = m_service_context_apply[m_application_table[0].service](&handle);
rgrover1 112:737b08b3b995 2850 break;
rgrover1 112:737b08b3b995 2851
rgrover1 112:737b08b3b995 2852 case BLE_GAP_EVT_SEC_REQUEST:
rgrover1 112:737b08b3b995 2853 DM_LOG("[DM]: >> BLE_GAP_EVT_SEC_REQUEST\r\n");
rgrover1 112:737b08b3b995 2854
rgrover1 112:737b08b3b995 2855 //Verify if the device is already bonded, and if it is bonded, initiate encryption.
rgrover1 112:737b08b3b995 2856 //If the device is not bonded, an instance needs to be allocated in order to initiate
rgrover1 112:737b08b3b995 2857 //bonding. The application have to initiate the procedure, the module will not do this
rgrover1 112:737b08b3b995 2858 //automatically.
rgrover1 112:737b08b3b995 2859 event.event_id = DM_EVT_SECURITY_SETUP;
rgrover1 112:737b08b3b995 2860 notify_app = true;
rgrover1 112:737b08b3b995 2861
rgrover1 112:737b08b3b995 2862 break;
rgrover1 112:737b08b3b995 2863
rgrover1 112:737b08b3b995 2864 default:
rgrover1 112:737b08b3b995 2865 break;
rgrover1 112:737b08b3b995 2866 }
rgrover1 112:737b08b3b995 2867
rgrover1 112:737b08b3b995 2868 if (notify_app)
rgrover1 112:737b08b3b995 2869 {
rgrover1 112:737b08b3b995 2870 app_evt_notify(&handle, &event, event_result);
rgrover1 112:737b08b3b995 2871
rgrover1 112:737b08b3b995 2872 //Freeing the instance after the event is notified so the application can get the context.
rgrover1 112:737b08b3b995 2873 if (event.event_id == DM_EVT_DISCONNECTION)
rgrover1 112:737b08b3b995 2874 {
rgrover1 112:737b08b3b995 2875 //Free the instance.
rgrover1 112:737b08b3b995 2876 connection_instance_free(&index);
rgrover1 112:737b08b3b995 2877 }
rgrover1 112:737b08b3b995 2878 }
rgrover1 112:737b08b3b995 2879
rgrover1 112:737b08b3b995 2880 UNUSED_VARIABLE(err_code);
rgrover1 112:737b08b3b995 2881
rgrover1 112:737b08b3b995 2882 DM_MUTEX_UNLOCK();
rgrover1 112:737b08b3b995 2883 }
rgrover1 112:737b08b3b995 2884
rgrover1 112:737b08b3b995 2885
rgrover1 112:737b08b3b995 2886 ret_code_t dm_handle_get(uint16_t conn_handle, dm_handle_t * p_handle)
rgrover1 112:737b08b3b995 2887 {
rgrover1 112:737b08b3b995 2888 ret_code_t err_code;
rgrover1 112:737b08b3b995 2889 uint32_t index;
rgrover1 112:737b08b3b995 2890
rgrover1 112:737b08b3b995 2891 NULL_PARAM_CHECK(p_handle);
rgrover1 112:737b08b3b995 2892 VERIFY_APP_REGISTERED(p_handle->appl_id);
rgrover1 112:737b08b3b995 2893
rgrover1 112:737b08b3b995 2894 p_handle->device_id = DM_INVALID_ID;
rgrover1 112:737b08b3b995 2895
rgrover1 112:737b08b3b995 2896 err_code = NRF_ERROR_NOT_FOUND;
rgrover1 112:737b08b3b995 2897
rgrover1 112:737b08b3b995 2898 for (index = 0; index < DEVICE_MANAGER_MAX_CONNECTIONS; index++)
rgrover1 112:737b08b3b995 2899 {
rgrover1 112:737b08b3b995 2900 //Search for matching connection handle.
rgrover1 112:737b08b3b995 2901 if (conn_handle == m_connection_table[index].conn_handle)
rgrover1 112:737b08b3b995 2902 {
rgrover1 112:737b08b3b995 2903 p_handle->connection_id = index;
rgrover1 112:737b08b3b995 2904 p_handle->device_id = m_connection_table[index].bonded_dev_id;
rgrover1 112:737b08b3b995 2905
rgrover1 112:737b08b3b995 2906 err_code = NRF_SUCCESS;
rgrover1 112:737b08b3b995 2907 break;
rgrover1 112:737b08b3b995 2908 }
rgrover1 112:737b08b3b995 2909 }
rgrover1 112:737b08b3b995 2910 return err_code;
rgrover1 112:737b08b3b995 2911 }