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