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