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