Nordic nrf51 sdk sources. Mirrored from https://github.com/ARMmbed/nrf51-sdk.
Embed:
(wiki syntax)
Show/hide line numbers
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_TRC("[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_TRC("[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_TRC("[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_TRC("[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_TRC("[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_TRC("[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_TRC("[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_ERR( 01719 "[DM]: Failed to load peer device %08X from storage, reason %08X.\r\n", 01720 index, 01721 err_code); 01722 01723 m_module_initialized = false; 01724 break; 01725 } 01726 else 01727 { 01728 DM_TRC("[DM]:[DI 0x%02X]: Device type 0x%02X.\r\n", 01729 index, 01730 m_peer_table[index].peer_id.id_addr_info.addr_type); 01731 DM_TRC("[DM]: Device Addr 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X.\r\n", 01732 m_peer_table[index].peer_id.id_addr_info.addr[0], 01733 m_peer_table[index].peer_id.id_addr_info.addr[1], 01734 m_peer_table[index].peer_id.id_addr_info.addr[2], 01735 m_peer_table[index].peer_id.id_addr_info.addr[3], 01736 m_peer_table[index].peer_id.id_addr_info.addr[4], 01737 m_peer_table[index].peer_id.id_addr_info.addr[5]); 01738 } 01739 } 01740 else 01741 { 01742 //In case a peer device could not be loaded successfully, rest of the 01743 //initialization procedure are skipped and an error is sent to the application. 01744 DM_LOG("[DM]: Failed to get block handle for instance %08X, reason %08X.\r\n", 01745 index, 01746 err_code); 01747 01748 m_module_initialized = false; 01749 break; 01750 } 01751 } 01752 } 01753 else 01754 { 01755 err_code = pstorage_clear(&m_storage_handle, (param.block_size * param.block_count)); 01756 DM_ERR("[DM]: Successfully requested clear of persistent data.\r\n"); 01757 } 01758 } 01759 else 01760 { 01761 DM_ERR("[DM]: Failed to register with storage module, reason 0x%08X.\r\n", err_code); 01762 } 01763 01764 DM_MUTEX_UNLOCK(); 01765 01766 DM_TRC("[DM]: << dm_init.\r\n"); 01767 01768 return err_code; 01769 } 01770 01771 01772 ret_code_t dm_register(dm_application_instance_t * p_appl_instance, 01773 dm_application_param_t const * p_appl_param) 01774 { 01775 VERIFY_MODULE_INITIALIZED(); 01776 NULL_PARAM_CHECK(p_appl_instance); 01777 NULL_PARAM_CHECK(p_appl_param); 01778 NULL_PARAM_CHECK(p_appl_param->evt_handler); 01779 01780 DM_MUTEX_LOCK(); 01781 01782 DM_LOG("[DM]: >> dm_register.\r\n"); 01783 01784 uint32_t err_code; 01785 01786 //Verify if an application instance is available. Currently only one instance is supported. 01787 if (m_application_table[0].ntf_cb == NULL) 01788 { 01789 DM_LOG("[DM]: Application Instance allocated.\r\n"); 01790 01791 //Mark instance as allocated. 01792 m_application_table[0].ntf_cb = p_appl_param->evt_handler; 01793 m_application_table[0].sec_param = p_appl_param->sec_param; 01794 m_application_table[0].service = p_appl_param->service_type; 01795 01796 m_application_table[0].sec_param.kdist_central.enc = 0; 01797 m_application_table[0].sec_param.kdist_central.id = 1; 01798 m_application_table[0].sec_param.kdist_central.sign = 0; 01799 m_application_table[0].sec_param.kdist_periph.enc = 1; 01800 m_application_table[0].sec_param.kdist_periph.id = 1; 01801 m_application_table[0].sec_param.kdist_periph.sign = 0; 01802 //Populate application's instance variable with the assigned allocation instance. 01803 *p_appl_instance = 0; 01804 err_code = NRF_SUCCESS; 01805 } 01806 else 01807 { 01808 err_code = (NRF_ERROR_NO_MEM | DEVICE_MANAGER_ERR_BASE); 01809 } 01810 01811 DM_MUTEX_UNLOCK(); 01812 01813 DM_TRC("[DM]: << dm_register.\r\n"); 01814 01815 return err_code; 01816 } 01817 01818 01819 ret_code_t dm_security_setup_req(dm_handle_t * p_handle) 01820 { 01821 VERIFY_MODULE_INITIALIZED(); 01822 NULL_PARAM_CHECK(p_handle); 01823 VERIFY_APP_REGISTERED(p_handle->appl_id); 01824 VERIFY_CONNECTION_INSTANCE(p_handle->connection_id); 01825 01826 DM_MUTEX_LOCK(); 01827 01828 DM_LOG("[DM]: >> dm_security_setup_req\r\n"); 01829 01830 uint32_t err_code = (NRF_ERROR_INVALID_STATE | DEVICE_MANAGER_ERR_BASE); 01831 01832 if ((m_connection_table[p_handle->connection_id].state & STATE_CONNECTED) == STATE_CONNECTED) 01833 { 01834 err_code = sd_ble_gap_authenticate(m_connection_table[p_handle->connection_id].conn_handle, 01835 &m_application_table[0].sec_param); 01836 } 01837 01838 DM_TRC("[DM]: << dm_security_setup_req, 0x%08X\r\n", err_code); 01839 01840 DM_MUTEX_UNLOCK(); 01841 01842 return err_code; 01843 } 01844 01845 01846 ret_code_t dm_security_status_req(dm_handle_t const * p_handle, 01847 dm_security_status_t * p_status) 01848 { 01849 VERIFY_MODULE_INITIALIZED(); 01850 NULL_PARAM_CHECK(p_handle); 01851 NULL_PARAM_CHECK(p_status); 01852 VERIFY_APP_REGISTERED(p_handle->appl_id); 01853 VERIFY_CONNECTION_INSTANCE(p_handle->connection_id); 01854 01855 DM_MUTEX_LOCK(); 01856 01857 DM_LOG("[DM]: >> dm_security_status_req\r\n"); 01858 01859 if ((m_connection_table[p_handle->connection_id].state & STATE_PAIRING) || 01860 (m_connection_table[p_handle->connection_id].state & STATE_PAIRING_PENDING)) 01861 { 01862 (*p_status) = ENCRYPTION_IN_PROGRESS; 01863 } 01864 else if (m_connection_table[p_handle->connection_id].state & STATE_LINK_ENCRYPTED) 01865 { 01866 (*p_status) = ENCRYPTED; 01867 } 01868 else 01869 { 01870 (*p_status) = NOT_ENCRYPTED; 01871 } 01872 01873 DM_TRC("[DM]: << dm_security_status_req\r\n"); 01874 01875 DM_MUTEX_UNLOCK(); 01876 01877 return NRF_SUCCESS; 01878 } 01879 01880 01881 ret_code_t dm_whitelist_create(dm_application_instance_t const * p_handle, 01882 ble_gap_whitelist_t * p_whitelist) 01883 { 01884 VERIFY_MODULE_INITIALIZED(); 01885 NULL_PARAM_CHECK(p_handle); 01886 NULL_PARAM_CHECK(p_whitelist); 01887 NULL_PARAM_CHECK(p_whitelist->pp_addrs); 01888 NULL_PARAM_CHECK(p_whitelist->pp_irks); 01889 VERIFY_APP_REGISTERED(*p_handle); 01890 01891 DM_MUTEX_LOCK(); 01892 01893 DM_LOG("[DM]: >> dm_whitelist_create\r\n"); 01894 01895 uint32_t addr_count = 0; 01896 uint32_t irk_count = 0; 01897 bool connected = false; 01898 01899 for (uint32_t index = 0; index < DEVICE_MANAGER_MAX_BONDS; index++) 01900 { 01901 connected = false; 01902 01903 for (uint32_t c_index = 0; c_index < DEVICE_MANAGER_MAX_CONNECTIONS; c_index++) 01904 { 01905 if ((index == m_connection_table[c_index].bonded_dev_id) && 01906 ((m_connection_table[c_index].state & STATE_CONNECTED) == STATE_CONNECTED)) 01907 { 01908 connected = true; 01909 break; 01910 } 01911 } 01912 01913 if (connected == false) 01914 { 01915 if ((irk_count < p_whitelist->irk_count) && 01916 ((m_peer_table[index].id_bitmap & IRK_ENTRY) == 0)) 01917 { 01918 p_whitelist->pp_irks[irk_count] = &m_peer_table[index].peer_id.id_info; 01919 m_irk_index_table[irk_count] = index; 01920 irk_count++; 01921 } 01922 01923 if ((addr_count < p_whitelist->addr_count) && 01924 (m_peer_table[index].id_bitmap & ADDR_ENTRY) == 0) 01925 { 01926 p_whitelist->pp_addrs[addr_count] = &m_peer_table[index].peer_id.id_addr_info; 01927 addr_count++; 01928 } 01929 } 01930 } 01931 01932 p_whitelist->addr_count = addr_count; 01933 p_whitelist->irk_count = irk_count; 01934 01935 DM_LOG("[DM]: Created whitelist, number of IRK = 0x%02X, number of addr = 0x%02X\r\n", 01936 irk_count, 01937 addr_count); 01938 01939 DM_TRC("[DM]: << dm_whitelist_create\r\n"); 01940 01941 DM_MUTEX_UNLOCK(); 01942 01943 return NRF_SUCCESS; 01944 } 01945 01946 01947 ret_code_t dm_device_add(dm_handle_t * p_handle, 01948 dm_device_context_t const * p_context) 01949 { 01950 return (API_NOT_IMPLEMENTED | DEVICE_MANAGER_ERR_BASE); 01951 } 01952 01953 01954 ret_code_t dm_device_delete(dm_handle_t const * p_handle) 01955 { 01956 VERIFY_MODULE_INITIALIZED(); 01957 NULL_PARAM_CHECK(p_handle); 01958 VERIFY_APP_REGISTERED(p_handle->appl_id); 01959 VERIFY_DEVICE_INSTANCE(p_handle->device_id); 01960 01961 DM_MUTEX_LOCK(); 01962 01963 DM_TRC("[DM]: >> dm_device_delete\r\n"); 01964 01965 uint32_t err_code = device_instance_free(p_handle->device_id); 01966 01967 DM_TRC("[DM]: << dm_device_delete\r\n"); 01968 01969 DM_MUTEX_UNLOCK(); 01970 01971 return err_code; 01972 } 01973 01974 01975 ret_code_t dm_device_delete_all(dm_application_instance_t const * p_handle) 01976 { 01977 VERIFY_MODULE_INITIALIZED(); 01978 NULL_PARAM_CHECK(p_handle); 01979 VERIFY_APP_REGISTERED((*p_handle)); 01980 01981 DM_MUTEX_LOCK(); 01982 01983 uint32_t err_code = NRF_SUCCESS; 01984 01985 DM_TRC("[DM]: >> dm_device_delete_all\r\n"); 01986 01987 for (uint32_t index = 0; index < DEVICE_MANAGER_MAX_BONDS; index++) 01988 { 01989 if (m_peer_table[index].id_bitmap != UNASSIGNED) 01990 { 01991 err_code = device_instance_free(index); 01992 } 01993 } 01994 01995 DM_TRC("[DM]: << dm_device_delete_all\r\n"); 01996 01997 DM_MUTEX_UNLOCK(); 01998 01999 return err_code; 02000 } 02001 02002 02003 ret_code_t dm_service_context_set(dm_handle_t const * p_handle, 02004 dm_service_context_t const * p_context) 02005 { 02006 VERIFY_MODULE_INITIALIZED(); 02007 NULL_PARAM_CHECK(p_handle); 02008 NULL_PARAM_CHECK(p_context); 02009 VERIFY_APP_REGISTERED(p_handle->appl_id); 02010 VERIFY_CONNECTION_INSTANCE(p_handle->connection_id); 02011 VERIFY_DEVICE_INSTANCE(p_handle->device_id); 02012 02013 DM_MUTEX_LOCK(); 02014 02015 DM_TRC("[DM]: >> dm_service_context_set\r\n"); 02016 02017 if ((p_context->context_data.p_data != NULL) && 02018 ( 02019 (p_context->context_data.len != 0) && 02020 (p_context->context_data.len < DM_GATT_SERVER_ATTR_MAX_SIZE) 02021 ) 02022 ) 02023 { 02024 if (p_context->service_type == DM_PROTOCOL_CNTXT_GATT_SRVR_ID) 02025 { 02026 memcpy(m_gatts_table[p_handle->connection_id].attributes, 02027 p_context->context_data.p_data, 02028 p_context->context_data.len); 02029 } 02030 } 02031 02032 pstorage_handle_t block_handle; 02033 uint32_t err_code = pstorage_block_identifier_get(&m_storage_handle, 02034 p_handle->device_id, 02035 &block_handle); 02036 02037 err_code = m_service_context_store[p_context->service_type](&block_handle, p_handle); 02038 02039 DM_TRC("[DM]: << dm_service_context_set\r\n"); 02040 02041 DM_MUTEX_UNLOCK(); 02042 02043 return err_code; 02044 } 02045 02046 02047 ret_code_t dm_service_context_get(dm_handle_t const * p_handle, 02048 dm_service_context_t * p_context) 02049 { 02050 VERIFY_MODULE_INITIALIZED(); 02051 NULL_PARAM_CHECK(p_handle); 02052 NULL_PARAM_CHECK(p_context); 02053 VERIFY_APP_REGISTERED(p_handle->appl_id); 02054 VERIFY_DEVICE_INSTANCE(p_handle->device_id); 02055 02056 if ((m_connection_table[p_handle->connection_id].state & STATE_CONNECTED) != STATE_CONNECTED) 02057 { 02058 DM_TRC("[DM]: Device must be connected to get context. \r\n"); 02059 02060 return (FEATURE_NOT_ENABLED | DEVICE_MANAGER_ERR_BASE); 02061 } 02062 02063 DM_MUTEX_LOCK(); 02064 02065 DM_TRC("[DM]: >> dm_service_context_get\r\n"); 02066 02067 if ((p_context->context_data.p_data == NULL) && 02068 (p_context->context_data.len < DM_GATT_SERVER_ATTR_MAX_SIZE)) 02069 { 02070 if (p_context->service_type == DM_PROTOCOL_CNTXT_GATT_SRVR_ID) 02071 { 02072 p_context->context_data.p_data = m_gatts_table[p_handle->connection_id].attributes; 02073 p_context->context_data.len = m_gatts_table[p_handle->connection_id].size; 02074 } 02075 } 02076 02077 pstorage_handle_t block_handle; 02078 uint32_t err_code = pstorage_block_identifier_get(&m_storage_handle, 02079 p_handle->device_id, 02080 &block_handle); 02081 02082 err_code = m_service_context_load[p_context->service_type](&block_handle, p_handle); 02083 02084 DM_TRC("[DM]: << dm_service_context_get\r\n"); 02085 02086 DM_MUTEX_UNLOCK(); 02087 02088 return err_code; 02089 } 02090 02091 02092 ret_code_t dm_service_context_delete(dm_handle_t const * p_handle) 02093 { 02094 VERIFY_MODULE_INITIALIZED(); 02095 NULL_PARAM_CHECK(p_handle); 02096 VERIFY_APP_REGISTERED(p_handle->appl_id); 02097 VERIFY_DEVICE_INSTANCE(p_handle->device_id); 02098 02099 DM_LOG("[DM]: Context delete is not supported yet.\r\n"); 02100 02101 return (API_NOT_IMPLEMENTED | DEVICE_MANAGER_ERR_BASE); 02102 } 02103 02104 02105 ret_code_t dm_application_context_set(dm_handle_t const * p_handle, 02106 dm_application_context_t const * p_context) 02107 { 02108 #if (DEVICE_MANAGER_APP_CONTEXT_SIZE != 0) 02109 VERIFY_MODULE_INITIALIZED(); 02110 NULL_PARAM_CHECK(p_handle); 02111 NULL_PARAM_CHECK(p_context); 02112 NULL_PARAM_CHECK(p_context->p_data); 02113 VERIFY_APP_REGISTERED(p_handle->appl_id); 02114 VERIFY_DEVICE_INSTANCE(p_handle->device_id); 02115 VERIFY_DEVICE_BOND(p_handle->connection_id); 02116 SIZE_CHECK_APP_CONTEXT(p_context->len); 02117 02118 DM_MUTEX_LOCK(); 02119 02120 DM_TRC("[DM]: >> dm_application_context_set\r\n"); 02121 02122 uint32_t err_code; 02123 uint32_t context_len; 02124 pstorage_handle_t block_handle; 02125 02126 storage_operation store_fn = pstorage_store; 02127 02128 err_code = pstorage_block_identifier_get(&m_storage_handle, 02129 p_handle->device_id, 02130 &block_handle); 02131 02132 if (err_code == NRF_SUCCESS) 02133 { 02134 err_code = pstorage_load((uint8_t *)&context_len, 02135 &block_handle, 02136 sizeof(uint32_t), 02137 APP_CONTEXT_STORAGE_OFFSET); 02138 02139 if ((err_code == NRF_SUCCESS) && (context_len != INVALID_CONTEXT_LEN)) 02140 { 02141 //Data already exists. Need an update. 02142 store_fn = pstorage_update; 02143 02144 DM_LOG("[DM]:[DI 0x%02X]: Updating existing application context, existing len 0x%08X, " 02145 "new length 0x%08X.\r\n", 02146 p_handle->device_id, 02147 context_len, 02148 p_context->len); 02149 } 02150 else 02151 { 02152 DM_LOG("[DM]: Storing application context.\r\n"); 02153 } 02154 02155 //Store/update context length. 02156 err_code = store_fn(&block_handle, 02157 (uint8_t *)(&p_context->len), 02158 sizeof(uint32_t), 02159 APP_CONTEXT_STORAGE_OFFSET); 02160 02161 if (err_code == NRF_SUCCESS) 02162 { 02163 //Update context data is used for application context as flash is never 02164 //cleared if a delete of application context is called. 02165 err_code = pstorage_update(&block_handle, 02166 p_context->p_data, 02167 DEVICE_MANAGER_APP_CONTEXT_SIZE, 02168 (APP_CONTEXT_STORAGE_OFFSET + sizeof(uint32_t))); 02169 if (err_code == NRF_SUCCESS) 02170 { 02171 m_app_context_table[p_handle->device_id] = p_context->p_data; 02172 } 02173 } 02174 } 02175 02176 DM_TRC("[DM]: << dm_application_context_set\r\n"); 02177 02178 DM_MUTEX_UNLOCK(); 02179 02180 return err_code; 02181 02182 #else //DEVICE_MANAGER_APP_CONTEXT_SIZE 02183 return (FEATURE_NOT_ENABLED | DEVICE_MANAGER_ERR_BASE); 02184 #endif //DEVICE_MANAGER_APP_CONTEXT_SIZE 02185 } 02186 02187 02188 ret_code_t dm_application_context_get(dm_handle_t const * p_handle, 02189 dm_application_context_t * p_context) 02190 { 02191 #if (DEVICE_MANAGER_APP_CONTEXT_SIZE != 0) 02192 VERIFY_MODULE_INITIALIZED(); 02193 NULL_PARAM_CHECK(p_handle); 02194 NULL_PARAM_CHECK(p_context); 02195 VERIFY_APP_REGISTERED(p_handle->appl_id); 02196 VERIFY_DEVICE_INSTANCE(p_handle->device_id); 02197 02198 DM_MUTEX_LOCK(); 02199 02200 DM_TRC("[DM]: >> dm_application_context_get\r\n"); 02201 02202 uint32_t context_len; 02203 uint32_t err_code; 02204 pstorage_handle_t block_handle; 02205 02206 //Check if the context exists. 02207 if (NULL == p_context->p_data) 02208 { 02209 p_context->p_data = m_app_context_table[p_handle->device_id]; 02210 } 02211 else 02212 { 02213 m_app_context_table[p_handle->device_id] = p_context->p_data; 02214 } 02215 02216 err_code = pstorage_block_identifier_get(&m_storage_handle, 02217 p_handle->device_id, 02218 &block_handle); 02219 02220 if (err_code == NRF_SUCCESS) 02221 { 02222 err_code = pstorage_load((uint8_t *)&context_len, 02223 &block_handle, 02224 sizeof(uint32_t), 02225 APP_CONTEXT_STORAGE_OFFSET); 02226 02227 if ((err_code == NRF_SUCCESS) && (context_len != INVALID_CONTEXT_LEN)) 02228 { 02229 err_code = pstorage_load(p_context->p_data, 02230 &block_handle, 02231 DEVICE_MANAGER_APP_CONTEXT_SIZE, 02232 (APP_CONTEXT_STORAGE_OFFSET + sizeof(uint32_t))); 02233 if (err_code == NRF_SUCCESS) 02234 { 02235 p_context->len = context_len; 02236 } 02237 } 02238 else 02239 { 02240 err_code = DM_NO_APP_CONTEXT; 02241 } 02242 } 02243 02244 DM_TRC("[DM]: << dm_application_context_get\r\n"); 02245 02246 DM_MUTEX_UNLOCK(); 02247 02248 return err_code; 02249 02250 #else //DEVICE_MANAGER_APP_CONTEXT_SIZE 02251 return (FEATURE_NOT_ENABLED | DEVICE_MANAGER_ERR_BASE); 02252 #endif //DEVICE_MANAGER_APP_CONTEXT_SIZE 02253 } 02254 02255 02256 ret_code_t dm_application_context_delete(const dm_handle_t * p_handle) 02257 { 02258 #if (DEVICE_MANAGER_APP_CONTEXT_SIZE != 0) 02259 VERIFY_MODULE_INITIALIZED(); 02260 NULL_PARAM_CHECK(p_handle); 02261 VERIFY_APP_REGISTERED(p_handle->appl_id); 02262 VERIFY_DEVICE_INSTANCE(p_handle->device_id); 02263 02264 DM_MUTEX_LOCK(); 02265 02266 DM_TRC("[DM]: >> dm_application_context_delete\r\n"); 02267 02268 uint32_t err_code; 02269 uint32_t context_len; 02270 pstorage_handle_t block_handle; 02271 02272 err_code = pstorage_block_identifier_get(&m_storage_handle, 02273 p_handle->device_id, 02274 &block_handle); 02275 02276 if (err_code == NRF_SUCCESS) 02277 { 02278 err_code = pstorage_load((uint8_t *)&context_len, 02279 &block_handle, 02280 sizeof(uint32_t), 02281 APP_CONTEXT_STORAGE_OFFSET); 02282 02283 if (context_len != m_context_init_len) 02284 { 02285 err_code = pstorage_update(&block_handle, 02286 (uint8_t *)&m_context_init_len, 02287 sizeof(uint32_t), 02288 APP_CONTEXT_STORAGE_OFFSET); 02289 02290 if (err_code != NRF_SUCCESS) 02291 { 02292 DM_ERR("[DM]: Failed to delete application context, reason 0x%08X\r\n", err_code); 02293 } 02294 else 02295 { 02296 m_app_context_table[p_handle->device_id] = NULL; 02297 } 02298 } 02299 } 02300 02301 DM_TRC("[DM]: << dm_application_context_delete\r\n"); 02302 02303 DM_MUTEX_UNLOCK(); 02304 02305 return err_code; 02306 #else //DEVICE_MANAGER_APP_CONTEXT_SIZE 02307 return (FEATURE_NOT_ENABLED | DEVICE_MANAGER_ERR_BASE); 02308 #endif //DEVICE_MANAGER_APP_CONTEXT_SIZE 02309 } 02310 02311 02312 ret_code_t dm_application_instance_set(dm_application_instance_t const * p_appl_instance, 02313 dm_handle_t * p_handle) 02314 { 02315 VERIFY_MODULE_INITIALIZED(); 02316 NULL_PARAM_CHECK(p_handle); 02317 NULL_PARAM_CHECK(p_appl_instance); 02318 VERIFY_APP_REGISTERED((*p_appl_instance)); 02319 02320 p_handle->appl_id = (*p_appl_instance); 02321 02322 return NRF_SUCCESS; 02323 } 02324 02325 02326 uint32_t dm_handle_initialize(dm_handle_t * p_handle) 02327 { 02328 NULL_PARAM_CHECK(p_handle); 02329 02330 p_handle->appl_id = DM_INVALID_ID; 02331 p_handle->connection_id = DM_INVALID_ID; 02332 p_handle->device_id = DM_INVALID_ID; 02333 p_handle->service_id = DM_INVALID_ID; 02334 02335 return NRF_SUCCESS; 02336 } 02337 02338 02339 ret_code_t dm_peer_addr_set(dm_handle_t const * p_handle, 02340 ble_gap_addr_t const * p_addr) 02341 { 02342 VERIFY_MODULE_INITIALIZED(); 02343 NULL_PARAM_CHECK(p_handle); 02344 NULL_PARAM_CHECK(p_addr); 02345 VERIFY_APP_REGISTERED(p_handle->appl_id); 02346 VERIFY_DEVICE_INSTANCE(p_handle->device_id); 02347 02348 DM_MUTEX_LOCK(); 02349 02350 DM_TRC("[DM]: >> dm_peer_addr_set\r\n"); 02351 02352 ret_code_t err_code; 02353 02354 if ((p_handle->connection_id == DM_INVALID_ID) && 02355 (p_addr->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE)) 02356 { 02357 m_peer_table[p_handle->device_id].peer_id.id_addr_info = (*p_addr); 02358 update_status_bit_set(p_handle->device_id); 02359 device_context_store(p_handle, UPDATE_PEER_ADDR); 02360 err_code = NRF_SUCCESS; 02361 } 02362 else 02363 { 02364 err_code = (NRF_ERROR_INVALID_PARAM | DEVICE_MANAGER_ERR_BASE); 02365 } 02366 02367 DM_TRC("[DM]: << dm_peer_addr_set\r\n"); 02368 02369 DM_MUTEX_UNLOCK(); 02370 02371 return err_code; 02372 } 02373 02374 02375 ret_code_t dm_peer_addr_get(dm_handle_t const * p_handle, 02376 ble_gap_addr_t * p_addr) 02377 { 02378 VERIFY_MODULE_INITIALIZED(); 02379 NULL_PARAM_CHECK(p_handle); 02380 NULL_PARAM_CHECK(p_addr); 02381 VERIFY_APP_REGISTERED(p_handle->appl_id); 02382 02383 DM_MUTEX_LOCK(); 02384 02385 DM_TRC("[DM]: >> dm_peer_addr_get\r\n"); 02386 02387 ret_code_t err_code; 02388 02389 err_code = (NRF_ERROR_NOT_FOUND | DEVICE_MANAGER_ERR_BASE); 02390 02391 if (p_handle->device_id == DM_INVALID_ID) 02392 { 02393 if ((p_handle->connection_id != DM_INVALID_ID) && 02394 ((m_connection_table[p_handle->connection_id].state & STATE_CONNECTED) == 02395 STATE_CONNECTED)) 02396 { 02397 DM_TRC("[DM]:[CI 0x%02X]: Address get for non bonded active connection.\r\n", 02398 p_handle->connection_id); 02399 02400 (*p_addr) = m_connection_table[p_handle->connection_id].peer_addr; 02401 err_code = NRF_SUCCESS; 02402 } 02403 } 02404 else 02405 { 02406 if ((m_peer_table[p_handle->device_id].id_bitmap & ADDR_ENTRY) == 0) 02407 { 02408 DM_TRC("[DM]:[DI 0x%02X]: Address get for bonded device.\r\n", 02409 p_handle->device_id); 02410 02411 (*p_addr) = m_peer_table[p_handle->device_id].peer_id.id_addr_info; 02412 err_code = NRF_SUCCESS; 02413 } 02414 } 02415 02416 DM_TRC("[DM]: << dm_peer_addr_get\r\n"); 02417 02418 DM_MUTEX_UNLOCK(); 02419 02420 return err_code; 02421 } 02422 02423 02424 ret_code_t dm_distributed_keys_get(dm_handle_t const * p_handle, 02425 dm_sec_keyset_t * p_key_dist) 02426 { 02427 VERIFY_MODULE_INITIALIZED(); 02428 NULL_PARAM_CHECK(p_handle); 02429 NULL_PARAM_CHECK(p_key_dist); 02430 VERIFY_APP_REGISTERED(p_handle->appl_id); 02431 VERIFY_DEVICE_INSTANCE(p_handle->device_id); 02432 02433 DM_MUTEX_LOCK(); 02434 02435 DM_TRC("[DM]: >> dm_distributed_keys_get\r\n"); 02436 02437 ret_code_t err_code; 02438 ble_gap_enc_key_t peer_enc_key; 02439 pstorage_handle_t block_handle; 02440 02441 err_code = NRF_ERROR_NOT_FOUND; 02442 p_key_dist->keys_central.enc_key.p_enc_key = NULL; 02443 p_key_dist->keys_central.p_id_key = (dm_id_key_t *)&m_peer_table[p_handle->device_id].peer_id; 02444 p_key_dist->keys_central.p_sign_key = NULL; 02445 p_key_dist->keys_periph.p_id_key = (dm_id_key_t *)&m_local_id_info; 02446 p_key_dist->keys_periph.p_sign_key = NULL; 02447 p_key_dist->keys_periph.enc_key.p_enc_key = (dm_enc_key_t *)&peer_enc_key; 02448 02449 if ((m_peer_table[p_handle->device_id].id_bitmap & IRK_ENTRY) == 0) 02450 { 02451 // p_key_dist->keys_periph.p_id_key->id_addr_info.addr_type = INVALID_ADDR_TYPE; 02452 } 02453 02454 err_code = pstorage_block_identifier_get(&m_storage_handle, p_handle->device_id, &block_handle); 02455 if (err_code == NRF_SUCCESS) 02456 { 02457 02458 err_code = pstorage_load((uint8_t *)&peer_enc_key, 02459 &block_handle, 02460 BOND_SIZE, 02461 BOND_STORAGE_OFFSET); 02462 02463 if (err_code == NRF_SUCCESS) 02464 { 02465 p_key_dist->keys_central.enc_key.p_enc_key = NULL; 02466 p_key_dist->keys_central.p_id_key = (dm_id_key_t *)&m_peer_table[p_handle->device_id].peer_id; 02467 p_key_dist->keys_central.p_sign_key = NULL; 02468 p_key_dist->keys_periph.p_id_key = (dm_id_key_t *)&m_local_id_info; 02469 p_key_dist->keys_periph.p_sign_key = NULL; 02470 p_key_dist->keys_periph.enc_key.p_enc_key = (dm_enc_key_t *)&peer_enc_key; 02471 } 02472 } 02473 02474 DM_TRC("[DM]: << dm_distributed_keys_get\r\n"); 02475 02476 DM_MUTEX_UNLOCK(); 02477 02478 return err_code; 02479 } 02480 02481 02482 /**@brief Function for loading bond information for a connection instance. 02483 */ 02484 void bond_data_load(dm_handle_t * p_handle) 02485 { 02486 pstorage_handle_t block_handle; 02487 02488 uint32_t err_code = pstorage_block_identifier_get(&m_storage_handle, 02489 p_handle->device_id, 02490 &block_handle); 02491 if (err_code == NRF_SUCCESS) 02492 { 02493 DM_LOG( 02494 "[DM]:[%02X]:[Block ID 0x%08X]:Loading bond information at %p, size 0x%08X, offset 0x%08X.\r\n", 02495 p_handle->connection_id, 02496 block_handle.block_id, 02497 &m_bond_table[p_handle->connection_id], 02498 BOND_SIZE, 02499 BOND_STORAGE_OFFSET); 02500 02501 err_code = pstorage_load((uint8_t *)&m_bond_table[p_handle->connection_id], 02502 &block_handle, 02503 BOND_SIZE, 02504 BOND_STORAGE_OFFSET); 02505 02506 if (err_code != NRF_SUCCESS) 02507 { 02508 DM_ERR("[DM]:[%02X]: Failed to load Bond information, reason %08X\r\n", 02509 p_handle->connection_id, 02510 err_code); 02511 } 02512 02513 DM_LOG( 02514 "[DM]:[%02X]:Loading service context at %p, size 0x%08X, offset 0x%08X.\r\n", 02515 p_handle->connection_id, 02516 &m_gatts_table[p_handle->connection_id], 02517 sizeof(dm_gatts_context_t), 02518 SERVICE_STORAGE_OFFSET); 02519 02520 err_code = m_service_context_load[m_application_table[0].service]( 02521 &block_handle, 02522 p_handle); 02523 02524 if (err_code != NRF_SUCCESS) 02525 { 02526 DM_ERR( 02527 "[DM]:[%02X]: Failed to load service information, reason %08X\r\n", 02528 p_handle->connection_id, 02529 err_code); 02530 } 02531 } 02532 else 02533 { 02534 DM_ERR("[DM]:[%02X]: Failed to get block identifier for " 02535 "device %08X, reason %08X.\r\n", p_handle->connection_id, p_handle->device_id, err_code); 02536 } 02537 } 02538 02539 02540 void dm_ble_evt_handler(ble_evt_t * p_ble_evt) 02541 { 02542 uint32_t err_code; 02543 uint32_t index; 02544 uint32_t device_index = DM_INVALID_ID; 02545 bool notify_app = false; 02546 dm_handle_t handle; 02547 dm_event_t event; 02548 uint32_t event_result; 02549 ble_gap_enc_info_t * p_enc_info = NULL; 02550 02551 VERIFY_MODULE_INITIALIZED_VOID(); 02552 VERIFY_APP_REGISTERED_VOID(0); 02553 DM_MUTEX_LOCK(); 02554 02555 err_code = dm_handle_initialize(&handle); 02556 APP_ERROR_CHECK(err_code); 02557 02558 event_result = NRF_SUCCESS; 02559 err_code = NRF_SUCCESS; 02560 event.event_param.p_gap_param = &p_ble_evt->evt.gap_evt; 02561 event.event_paramlen = sizeof(ble_gap_evt_t); 02562 handle.device_id = DM_INVALID_ID; 02563 handle.appl_id = 0; 02564 index = 0x00; 02565 02566 if (p_ble_evt->header.evt_id != BLE_GAP_EVT_CONNECTED) 02567 { 02568 err_code = connection_instance_find(p_ble_evt->evt.gap_evt.conn_handle, 02569 STATE_CONNECTED, 02570 &index); 02571 02572 if (err_code == NRF_SUCCESS) 02573 { 02574 handle.device_id = m_connection_table[index].bonded_dev_id; 02575 handle.connection_id = index; 02576 } 02577 } 02578 02579 switch (p_ble_evt->header.evt_id) 02580 { 02581 case BLE_GAP_EVT_CONNECTED: 02582 //Allocate connection instance for a new connection. 02583 err_code = connection_instance_allocate(&index); 02584 02585 //Connection instance is successfully allocated. 02586 if (err_code == NRF_SUCCESS) 02587 { 02588 //Application notification related information. 02589 notify_app = true; 02590 event.event_id = DM_EVT_CONNECTION; 02591 handle.connection_id = index; 02592 02593 m_connection_table[index].conn_handle = p_ble_evt->evt.gap_evt.conn_handle; 02594 m_connection_table[index].state = STATE_CONNECTED; 02595 m_connection_table[index].peer_addr = 02596 p_ble_evt->evt.gap_evt.params.connected.peer_addr; 02597 02598 if (p_ble_evt->evt.gap_evt.params.connected.irk_match == 1) 02599 { 02600 if (m_irk_index_table[p_ble_evt->evt.gap_evt.params.connected.irk_match_idx] != DM_INVALID_ID) 02601 { 02602 device_index = m_irk_index_table[p_ble_evt->evt.gap_evt.params.connected.irk_match_idx]; 02603 err_code = NRF_SUCCESS; 02604 } 02605 } 02606 else 02607 { 02608 //Use the device address to check if the device exists in the bonded device list. 02609 err_code = device_instance_find(&p_ble_evt->evt.gap_evt.params.connected.peer_addr, 02610 &device_index, EDIV_INIT_VAL); 02611 } 02612 02613 if (err_code == NRF_SUCCESS) 02614 { 02615 m_connection_table[index].bonded_dev_id = device_index; 02616 m_connection_table[index].state |= STATE_BONDED; 02617 handle.device_id = device_index; 02618 02619 bond_data_load(&handle); 02620 } 02621 } 02622 break; 02623 02624 case BLE_GAP_EVT_DISCONNECTED: 02625 //Disconnection could be peer or self initiated hence disconnecting and connecting 02626 //both states are permitted, however, connection handle must be known. 02627 DM_LOG("[DM]: Disconnect Reason 0x%04X\r\n", 02628 p_ble_evt->evt.gap_evt.params.disconnected.reason); 02629 02630 m_connection_table[index].state &= (~STATE_CONNECTED); 02631 02632 if ((m_connection_table[index].state & STATE_BONDED) == STATE_BONDED) 02633 { 02634 if ((m_connection_table[index].state & STATE_LINK_ENCRYPTED) == STATE_LINK_ENCRYPTED) 02635 { 02636 //Write bond information persistently. 02637 device_context_store(&handle, STORE_ALL_CONTEXT); 02638 } 02639 } 02640 else 02641 { 02642 //Free any allocated instances for devices that is not bonded. 02643 if (handle.device_id != DM_INVALID_ID) 02644 { 02645 peer_instance_init(handle.device_id); 02646 handle.device_id = DM_INVALID_ID; 02647 } 02648 } 02649 02650 m_connection_table[index].state = STATE_DISCONNECTING; 02651 notify_app = true; 02652 event.event_id = DM_EVT_DISCONNECTION; 02653 02654 break; 02655 02656 case BLE_GAP_EVT_SEC_INFO_REQUEST: 02657 DM_LOG("[DM]: >> BLE_GAP_EVT_SEC_INFO_REQUEST\r\n"); 02658 02659 //If the device is already bonded, respond with existing info, else NULL. 02660 if (m_connection_table[index].bonded_dev_id == DM_INVALID_ID) 02661 { 02662 //Find device based on div. 02663 err_code = device_instance_find(NULL,&device_index, p_ble_evt->evt.gap_evt.params.sec_info_request.master_id.ediv); 02664 if (err_code == NRF_SUCCESS) 02665 { 02666 //Load needed bonding information. 02667 m_connection_table[index].bonded_dev_id = device_index; 02668 m_connection_table[index].state |= STATE_BONDED; 02669 handle.device_id = device_index; 02670 bond_data_load(&handle); 02671 } 02672 } 02673 02674 if (m_connection_table[index].bonded_dev_id != DM_INVALID_ID) 02675 { 02676 p_enc_info = &m_bond_table[index].peer_enc_key.enc_info; 02677 DM_DUMP((uint8_t *)p_enc_info, sizeof(ble_gap_enc_info_t)); 02678 } 02679 02680 err_code = sd_ble_gap_sec_info_reply(p_ble_evt->evt.gap_evt.conn_handle, 02681 p_enc_info, 02682 &m_peer_table[index].peer_id.id_info, 02683 NULL); 02684 02685 if (err_code != NRF_SUCCESS) 02686 { 02687 DM_ERR("[DM]:[CI %02X]:[DI %02X]: Security information response failed, reason " 02688 "0x%08X\r\n", index, m_connection_table[index].bonded_dev_id, err_code); 02689 } 02690 break; 02691 02692 case BLE_GAP_EVT_SEC_PARAMS_REQUEST: 02693 DM_LOG("[DM]: >> BLE_GAP_EVT_SEC_PARAMS_REQUEST\r\n"); 02694 02695 event.event_id = DM_EVT_SECURITY_SETUP; 02696 02697 m_connection_table[index].state |= STATE_PAIRING; 02698 notify_app = true; 02699 02700 if (m_connection_table[index].bonded_dev_id == DM_INVALID_ID) 02701 { 02702 //Assign a peer index as a new bond or update existing bonds. 02703 err_code = device_instance_allocate((uint8_t *)&device_index, 02704 &m_connection_table[index].peer_addr); 02705 02706 //Allocation successful. 02707 if (err_code == NRF_SUCCESS) 02708 { 02709 DM_LOG("[DM]:[CI 0x%02X]:[DI 0x%02X]: Bonded!\r\n",index, device_index); 02710 02711 handle.device_id = device_index; 02712 m_connection_table[index].bonded_dev_id = device_index; 02713 } 02714 else 02715 { 02716 DM_LOG("[DM]: Security parameter request failed, reason 0x%08X.\r\n", err_code); 02717 event_result = err_code; 02718 notify_app = true; 02719 } 02720 } 02721 else 02722 { 02723 //Bond/key refresh. 02724 event.event_id = DM_EVT_SECURITY_SETUP_REFRESH; 02725 memset(m_gatts_table[index].attributes, 0, DM_GATT_SERVER_ATTR_MAX_SIZE); 02726 02727 //Set the update flag for bond data. 02728 m_connection_table[index].state |= STATE_BOND_INFO_UPDATE; 02729 } 02730 02731 ble_gap_sec_keyset_t keys_exchanged; 02732 02733 DM_LOG("[DM]: 0x%02X, 0x%02X, 0x%02X, 0x%02X\r\n", 02734 p_ble_evt->evt.gap_evt.params.sec_params_request.peer_params.kdist_periph.enc, 02735 p_ble_evt->evt.gap_evt.params.sec_params_request.peer_params.kdist_central.id, 02736 p_ble_evt->evt.gap_evt.params.sec_params_request.peer_params.kdist_periph.sign, 02737 p_ble_evt->evt.gap_evt.params.sec_params_request.peer_params.bond); 02738 02739 keys_exchanged.keys_central.p_enc_key = NULL; 02740 keys_exchanged.keys_central.p_id_key = &m_peer_table[m_connection_table[index].bonded_dev_id].peer_id; 02741 keys_exchanged.keys_central.p_sign_key = NULL; 02742 keys_exchanged.keys_periph.p_enc_key = &m_bond_table[index].peer_enc_key; 02743 keys_exchanged.keys_periph.p_id_key = NULL; 02744 keys_exchanged.keys_periph.p_sign_key = NULL; 02745 02746 err_code = sd_ble_gap_sec_params_reply(p_ble_evt->evt.gap_evt.conn_handle, 02747 BLE_GAP_SEC_STATUS_SUCCESS, 02748 &m_application_table[0].sec_param, 02749 &keys_exchanged); 02750 02751 if (err_code != NRF_SUCCESS) 02752 { 02753 DM_LOG("[DM]: Security parameter reply request failed, reason 0x%08X.\r\n", err_code); 02754 event_result = err_code; 02755 notify_app = false; 02756 } 02757 break; 02758 02759 case BLE_GAP_EVT_AUTH_STATUS: 02760 { 02761 DM_LOG("[DM]: >> BLE_GAP_EVT_AUTH_STATUS, status %08X\r\n", 02762 p_ble_evt->evt.gap_evt.params.auth_status.auth_status); 02763 02764 m_application_table[0].state &= (~STATE_CONTROL_PROCEDURE_IN_PROGRESS); 02765 m_connection_table[index].state &= (~STATE_PAIRING); 02766 event.event_id = DM_EVT_SECURITY_SETUP_COMPLETE; 02767 notify_app = true; 02768 02769 if (p_ble_evt->evt.gap_evt.params.auth_status.auth_status != BLE_GAP_SEC_STATUS_SUCCESS) 02770 { 02771 // Free the allocation as bonding failed. 02772 ret_code_t result = device_instance_free(m_connection_table[index].bonded_dev_id); 02773 (void) result; 02774 event_result = p_ble_evt->evt.gap_evt.params.auth_status.auth_status; 02775 } 02776 else 02777 { 02778 DM_DUMP((uint8_t *)&p_ble_evt->evt.gap_evt.params.auth_status, 02779 sizeof(ble_gap_evt_auth_status_t)); 02780 DM_DUMP((uint8_t *)&m_bond_table[index], sizeof(bond_context_t)); 02781 02782 if (p_ble_evt->evt.gap_evt.params.auth_status.bonded == 1) 02783 { 02784 if (handle.device_id != DM_INVALID_ID) 02785 { 02786 m_connection_table[index].state |= STATE_BONDED; 02787 02788 //IRK and/or public address is shared, update it. 02789 if (p_ble_evt->evt.gap_evt.params.auth_status.kdist_central.id == 1) 02790 { 02791 m_peer_table[handle.device_id].id_bitmap &= (~IRK_ENTRY); 02792 } 02793 02794 if (m_connection_table[index].bonded_dev_id != DM_INVALID_ID) 02795 { 02796 DM_LOG("[DM]:[CI 0x%02X]:[DI 0x%02X]: Bonded!\r\n", 02797 index, 02798 handle.device_id); 02799 02800 if (m_connection_table[index].peer_addr.addr_type != 02801 BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) 02802 { 02803 m_peer_table[handle.device_id].peer_id.id_addr_info = 02804 m_connection_table[index].peer_addr; 02805 m_peer_table[handle.device_id].id_bitmap &= (~ADDR_ENTRY); 02806 02807 DM_DUMP((uint8_t *)&m_peer_table[handle.device_id].peer_id.id_addr_info, 02808 sizeof(m_peer_table[handle.device_id].peer_id.id_addr_info)); 02809 } 02810 else 02811 { 02812 // Here we must fetch the keys from the keyset distributed. 02813 m_peer_table[handle.device_id].ediv = m_bond_table[index].peer_enc_key.master_id.ediv; 02814 m_peer_table[handle.device_id].id_bitmap &= (~IRK_ENTRY); 02815 } 02816 02817 device_context_store(&handle, FIRST_BOND_STORE); 02818 } 02819 } 02820 } 02821 else 02822 { 02823 //Pairing request, no need to touch the bonding info. 02824 } 02825 } 02826 break; 02827 } 02828 02829 case BLE_GAP_EVT_CONN_SEC_UPDATE: 02830 DM_LOG("[DM]: >> BLE_GAP_EVT_CONN_SEC_UPDATE, Mode 0x%02X, Level 0x%02X\r\n", 02831 p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.sm, 02832 p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv); 02833 02834 if ((p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv == 1) && 02835 (p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.sm == 1) && 02836 ((m_connection_table[index].state & STATE_BONDED) == STATE_BONDED)) 02837 { 02838 //Lost bond case, generate a security refresh event! 02839 memset(m_gatts_table[index].attributes, 0, DM_GATT_SERVER_ATTR_MAX_SIZE); 02840 02841 event.event_id = DM_EVT_SECURITY_SETUP_REFRESH; 02842 m_connection_table[index].state |= STATE_PAIRING_PENDING; 02843 m_connection_table[index].state |= STATE_BOND_INFO_UPDATE; 02844 m_application_table[0].state |= STATE_QUEUED_CONTROL_REQUEST; 02845 } 02846 else 02847 { 02848 m_connection_table[index].state |= STATE_LINK_ENCRYPTED; 02849 event.event_id = DM_EVT_LINK_SECURED; 02850 02851 //Apply service context. 02852 err_code = m_service_context_apply[m_application_table[0].service](&handle); 02853 02854 if (err_code != NRF_SUCCESS) 02855 { 02856 DM_ERR("[DM]:[CI 0x%02X]:[DI 0x%02X]: Failed to apply service context\r\n", 02857 handle.connection_id, 02858 handle.device_id); 02859 02860 event_result = DM_SERVICE_CONTEXT_NOT_APPLIED; 02861 } 02862 } 02863 event_result = NRF_SUCCESS; 02864 notify_app = true; 02865 02866 break; 02867 02868 case BLE_GATTS_EVT_SYS_ATTR_MISSING: 02869 DM_LOG("[DM]: >> BLE_GATTS_EVT_SYS_ATTR_MISSING\r\n"); 02870 02871 //Apply service context. 02872 event_result = m_service_context_apply[m_application_table[0].service](&handle); 02873 break; 02874 02875 case BLE_GAP_EVT_SEC_REQUEST: 02876 DM_LOG("[DM]: >> BLE_GAP_EVT_SEC_REQUEST\r\n"); 02877 02878 //Verify if the device is already bonded, and if it is bonded, initiate encryption. 02879 //If the device is not bonded, an instance needs to be allocated in order to initiate 02880 //bonding. The application have to initiate the procedure, the module will not do this 02881 //automatically. 02882 event.event_id = DM_EVT_SECURITY_SETUP; 02883 notify_app = true; 02884 02885 break; 02886 02887 default: 02888 break; 02889 } 02890 02891 if (notify_app) 02892 { 02893 app_evt_notify(&handle, &event, event_result); 02894 02895 //Freeing the instance after the event is notified so the application can get the context. 02896 if (event.event_id == DM_EVT_DISCONNECTION) 02897 { 02898 //Free the instance. 02899 connection_instance_free(&index); 02900 } 02901 } 02902 02903 UNUSED_VARIABLE(err_code); 02904 02905 DM_MUTEX_UNLOCK(); 02906 } 02907 02908 02909 ret_code_t dm_handle_get(uint16_t conn_handle, dm_handle_t * p_handle) 02910 { 02911 ret_code_t err_code; 02912 uint32_t index; 02913 02914 NULL_PARAM_CHECK(p_handle); 02915 VERIFY_APP_REGISTERED(p_handle->appl_id); 02916 02917 p_handle->device_id = DM_INVALID_ID; 02918 02919 err_code = NRF_ERROR_NOT_FOUND; 02920 02921 for (index = 0; index < DEVICE_MANAGER_MAX_CONNECTIONS; index++) 02922 { 02923 //Search for matching connection handle. 02924 if (conn_handle == m_connection_table[index].conn_handle) 02925 { 02926 p_handle->connection_id = index; 02927 p_handle->device_id = m_connection_table[index].bonded_dev_id; 02928 02929 err_code = NRF_SUCCESS; 02930 break; 02931 } 02932 } 02933 return err_code; 02934 }
Generated on Tue Jul 12 2022 15:05:58 by 1.7.2