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