Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of nrf51-sdk by
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 14:11:19 by
