test

Fork of nRF51822 by Nordic Semiconductor

Committer:
GlimwormBeacons
Date:
Sat Oct 10 09:19:50 2015 +0000
Revision:
448:b71e96a821de
Parent:
387:b13ab9a7ddb9
test

Who changed what in which revision?

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