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