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 BLE_WallbotBLE_Challenge by
ble_bondmngr.cpp
00001 /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved. 00002 * 00003 * The information contained herein is property of Nordic Semiconductor ASA. 00004 * Terms and conditions of usage are described in detail in NORDIC 00005 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. 00006 * 00007 * Licensees are granted free, non-transferable use of the information. NO 00008 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from 00009 * the file. 00010 * 00011 */ 00012 00013 #if NEED_BOND_MANAGER /* disabled by default */ 00014 00015 #include "ble_bondmngr.h" 00016 #include <stdlib.h> 00017 #include <stdint.h> 00018 #include <string.h> 00019 #include "nordic_common.h" 00020 #include "nrf_error.h" 00021 #include "ble_gap.h" 00022 #include "ble_srv_common.h " 00023 #include "app_util.h " 00024 #include "nrf_assert.h" 00025 //#include "nrf.h" 00026 #include "nrf51_bitfields.h" 00027 #include "crc16.h " 00028 #include "pstorage.h " 00029 #include "ble_bondmngr_cfg.h" 00030 00031 #define CCCD_SIZE 6 /**< Number of bytes needed for storing the state of one CCCD. */ 00032 #define CRC_SIZE 2 /**< Size of CRC in sys_attribute data. */ 00033 #define SYS_ATTR_BUFFER_MAX_LEN (((BLE_BONDMNGR_CCCD_COUNT + 1) * CCCD_SIZE) + CRC_SIZE) /**< Size of sys_attribute data. */ 00034 #define MAX_NUM_CENTRAL_WHITE_LIST MIN(BLE_BONDMNGR_MAX_BONDED_CENTRALS, 8) /**< Maximum number of whitelisted centrals supported.*/ 00035 #define MAX_BONDS_IN_FLASH 10 /**< Maximum number of bonds that can be stored in flash. */ 00036 #define BOND_MANAGER_DATA_SIGNATURE 0x53240000 00037 00038 /**@defgroup ble_bond_mngr_sec_access Bond Manager Security Status Access Macros 00039 * @brief The following group of macros abstract access to Security Status with a peer. 00040 * @{ 00041 */ 00042 00043 #define SEC_STATUS_INIT_VAL 0x00 /**< Initialization value for security status flags. */ 00044 #define ENC_STATUS_SET_VAL 0x01 /**< Bitmask for encryption status. */ 00045 #define BOND_IN_PROGRESS_SET_VAL 0x02 /**< Bitmask for 'bonding in progress'. */ 00046 00047 00048 /**@brief Macro for setting the Encryption Status for current link. 00049 * 00050 * @details Macro for setting the Encryption Status for current link. 00051 */ 00052 #define ENCRYPTION_STATUS_SET() \ 00053 do \ 00054 { \ 00055 m_sec_con_status |= ENC_STATUS_SET_VAL; \ 00056 } while (0) 00057 00058 /**@brief Macro for getting the Encryption Status for current link. 00059 * 00060 * @details Macro for getting the Encryption Status for current link. 00061 */ 00062 #define ENCRYPTION_STATUS_GET() \ 00063 (((m_sec_con_status & ENC_STATUS_SET_VAL) == 0) ? false : true) 00064 00065 /**@brief Macro for resetting the Encryption Status for current link. 00066 * 00067 * @details Macro for resetting the Encryption Status for current link. 00068 */ 00069 #define ENCRYPTION_STATUS_RESET() \ 00070 do \ 00071 { \ 00072 m_sec_con_status &= (~ENC_STATUS_SET_VAL); \ 00073 } while (0) 00074 00075 00076 /**@brief Macro for resetting the Bonding In Progress status for current link. 00077 * 00078 * @details Macro for resetting the Bonding In Progress status for current link. 00079 */ 00080 #define BONDING_IN_PROGRESS_STATUS_SET() \ 00081 do \ 00082 { \ 00083 m_sec_con_status |= BOND_IN_PROGRESS_SET_VAL; \ 00084 } while (0) 00085 00086 /**@brief Macro for setting the Bonding In Progress status for current link. 00087 * 00088 * @details Macro for setting the Bonding In Progress status for current link. 00089 */ 00090 #define BONDING_IN_PROGRESS_STATUS_GET() \ 00091 (((m_sec_con_status & BOND_IN_PROGRESS_SET_VAL) == 0) ? false: true) 00092 00093 /**@brief Macro for resetting the Bonding In Progress status for current link. 00094 * 00095 * @details Macro for resetting the Bonding In Progress status for current link. 00096 */ 00097 #define BONDING_IN_PROGRESS_STATUS_RESET() \ 00098 do \ 00099 { \ 00100 m_sec_con_status &= (~BOND_IN_PROGRESS_SET_VAL); \ 00101 } while (0) 00102 00103 /**@brief Macro for resetting all security status flags for current link. 00104 * 00105 * @details Macro for resetting all security status flags for current link. 00106 */ 00107 #define SECURITY_STATUS_RESET() \ 00108 do \ 00109 { \ 00110 m_sec_con_status = SEC_STATUS_INIT_VAL; \ 00111 } while (0) 00112 00113 /** @} */ 00114 00115 /**@brief Verify module's initialization status. 00116 * 00117 * @details Verify module's initialization status. Returns NRF_INVALID_STATE in case a module API 00118 * is called without initializing the module. 00119 */ 00120 #define VERIFY_MODULE_INITIALIZED() \ 00121 do \ 00122 { \ 00123 if (!m_is_bondmngr_initialized) \ 00124 { \ 00125 return NRF_ERROR_INVALID_STATE; \ 00126 } \ 00127 } while(0) 00128 00129 00130 /**@brief This structure contains the Bonding Information for one central. 00131 */ 00132 typedef struct 00133 { 00134 int32_t central_handle; /**< Central's handle (NOTE: Size is 32 bits just to make struct size dividable by 4). */ 00135 ble_gap_evt_auth_status_t auth_status; /**< Central authentication data. */ 00136 ble_gap_evt_sec_info_request_t central_id_info; /**< Central identification info. */ 00137 ble_gap_addr_t central_addr; /**< Central's address. */ 00138 } central_bond_t; 00139 00140 STATIC_ASSERT(sizeof(central_bond_t) % 4 == 0); 00141 00142 /**@brief This structure contains the System Attributes information related to one central. 00143 */ 00144 typedef struct 00145 { 00146 int32_t central_handle; /**< Central's handle (NOTE: Size is 32 bits just to make struct size dividable by 4). */ 00147 uint8_t sys_attr[SYS_ATTR_BUFFER_MAX_LEN]; /**< Central sys_attribute data. */ 00148 uint32_t sys_attr_size; /**< Central sys_attribute data's size (NOTE: Size is 32 bits just to make struct size dividable by 4). */ 00149 } central_sys_attr_t; 00150 00151 STATIC_ASSERT(sizeof(central_sys_attr_t) % 4 == 0); 00152 00153 /**@brief This structure contains the Bonding Information and System Attributes related to one 00154 * central. 00155 */ 00156 typedef struct 00157 { 00158 central_bond_t bond; /**< Bonding information. */ 00159 central_sys_attr_t sys_attr; /**< System attribute information. */ 00160 } central_t; 00161 00162 /**@brief This structure contains the whitelisted addresses. 00163 */ 00164 typedef struct 00165 { 00166 int8_t central_handle; /**< Central's handle. */ 00167 ble_gap_addr_t * p_addr; /**< Pointer to the central's address if BLE_GAP_ADDR_TYPE_PUBLIC. */ 00168 } whitelist_addr_t; 00169 00170 /**@brief This structure contains the whitelisted IRKs. 00171 */ 00172 typedef struct 00173 { 00174 int8_t central_handle; /**< Central's handle. */ 00175 ble_gap_irk_t * p_irk; /**< Pointer to the central's irk if available. */ 00176 } whitelist_irk_t; 00177 00178 static bool m_is_bondmngr_initialized = false; /**< Flag for checking if module has been initialized. */ 00179 static ble_bondmngr_init_t m_bondmngr_config; /**< Configuration as specified by the application. */ 00180 static uint16_t m_conn_handle; /**< Current connection handle. */ 00181 static central_t m_central; /**< Current central data. */ 00182 static central_t m_centrals_db[BLE_BONDMNGR_MAX_BONDED_CENTRALS]; /**< Pointer to start of bonded centrals database. */ 00183 static uint8_t m_centrals_in_db_count; /**< Number of bonded centrals. */ 00184 static whitelist_addr_t m_whitelist_addr[MAX_NUM_CENTRAL_WHITE_LIST]; /**< List of central's addresses for the whitelist. */ 00185 static whitelist_irk_t m_whitelist_irk[MAX_NUM_CENTRAL_WHITE_LIST]; /**< List of central's IRKs for the whitelist. */ 00186 static uint8_t m_addr_count; /**< Number of addresses in the whitelist. */ 00187 static uint8_t m_irk_count; /**< Number of IRKs in the whitelist. */ 00188 static uint16_t m_crc_bond_info; /**< Combined CRC for all Bonding Information currently stored in flash. */ 00189 static uint16_t m_crc_sys_attr; /**< Combined CRC for all System Attributes currently stored in flash. */ 00190 static pstorage_handle_t mp_flash_bond_info; /**< Pointer to flash location to write next Bonding Information. */ 00191 static pstorage_handle_t mp_flash_sys_attr; /**< Pointer to flash location to write next System Attribute information. */ 00192 static uint8_t m_bond_info_in_flash_count; /**< Number of Bonding Information currently stored in flash. */ 00193 static uint8_t m_sys_attr_in_flash_count; /**< Number of System Attributes currently stored in flash. */ 00194 static uint8_t m_sec_con_status; /**< Variable to denote security status.*/ 00195 static bool m_bond_loaded; /**< Variable to indicate if the bonding information of the currently connected central is available in the RAM.*/ 00196 static bool m_sys_attr_loaded; /**< Variable to indicate if the system attribute information of the currently connected central is loaded from the database and set in the S110 SoftDevice.*/ 00197 static uint32_t m_bond_crc_array[BLE_BONDMNGR_MAX_BONDED_CENTRALS]; 00198 static uint32_t m_sys_crc_array[BLE_BONDMNGR_MAX_BONDED_CENTRALS]; 00199 00200 /**@brief Function for extracting the CRC from an encoded 32 bit number that typical resides in 00201 * the flash memory 00202 * 00203 * @param[in] header Header containing CRC and magic number. 00204 * @param[out] p_crc Extracted CRC. 00205 * 00206 * @retval NRF_SUCCESS CRC successfully extracted. 00207 * @retval NRF_ERROR_NOT_FOUND Flash seems to be empty. 00208 * @retval NRF_ERROR_INVALID_DATA Header does not contain the magic number. 00209 */ 00210 static uint32_t crc_extract(uint32_t header, uint16_t * p_crc) 00211 { 00212 if ((header & 0xFFFF0000U) == BOND_MANAGER_DATA_SIGNATURE) 00213 { 00214 *p_crc = (uint16_t)(header & 0x0000FFFFU); 00215 00216 return NRF_SUCCESS; 00217 } 00218 else if (header == 0xFFFFFFFFU) 00219 { 00220 return NRF_ERROR_NOT_FOUND; 00221 } 00222 else 00223 { 00224 return NRF_ERROR_INVALID_DATA; 00225 } 00226 } 00227 00228 00229 /**@brief Function for storing the Bonding Information of the specified central to the flash. 00230 * 00231 * @param[in] p_bond Bonding information to be stored. 00232 * 00233 * @return NRF_SUCCESS on success, an error_code otherwise. 00234 */ 00235 static uint32_t bond_info_store(central_bond_t * p_bond) 00236 { 00237 uint32_t err_code; 00238 pstorage_handle_t dest_block; 00239 00240 // Check if flash is full 00241 if (m_bond_info_in_flash_count >= MAX_BONDS_IN_FLASH) 00242 { 00243 return NRF_ERROR_NO_MEM; 00244 } 00245 00246 // Check if this is the first bond to be stored 00247 if (m_bond_info_in_flash_count == 0) 00248 { 00249 // Initialize CRC 00250 m_crc_bond_info = crc16_compute(NULL, 0, NULL); 00251 } 00252 00253 // Get block pointer from base 00254 err_code = pstorage_block_identifier_get(&mp_flash_bond_info,m_bond_info_in_flash_count,&dest_block); 00255 if (err_code != NRF_SUCCESS) 00256 { 00257 return err_code; 00258 } 00259 00260 // Write Bonding Information 00261 err_code = pstorage_store(&dest_block, 00262 (uint8_t *)p_bond, 00263 sizeof(central_bond_t), 00264 sizeof(uint32_t)); 00265 00266 if (err_code != NRF_SUCCESS) 00267 { 00268 return err_code; 00269 } 00270 m_crc_bond_info = crc16_compute((uint8_t *)p_bond, 00271 sizeof(central_bond_t), 00272 &m_crc_bond_info); 00273 00274 // Write header 00275 m_bond_crc_array[m_bond_info_in_flash_count] = (BOND_MANAGER_DATA_SIGNATURE | m_crc_bond_info); 00276 00277 err_code = pstorage_store (&dest_block, (uint8_t *)&m_bond_crc_array[m_bond_info_in_flash_count],sizeof(uint32_t),0); 00278 if (err_code != NRF_SUCCESS) 00279 { 00280 return err_code; 00281 } 00282 00283 m_bond_info_in_flash_count++; 00284 return NRF_SUCCESS; 00285 } 00286 00287 00288 /**@brief Function for storing the System Attributes related to a specified central in flash. 00289 * 00290 * @param[in] p_sys_attr System Attributes to be stored. 00291 * 00292 * @return NRF_SUCCESS on success, an error_code otherwise. 00293 */ 00294 static uint32_t sys_attr_store(central_sys_attr_t * p_sys_attr) 00295 { 00296 uint32_t err_code; 00297 pstorage_handle_t dest_block; 00298 00299 // Check if flash is full. 00300 if (m_sys_attr_in_flash_count >= MAX_BONDS_IN_FLASH) 00301 { 00302 return NRF_ERROR_NO_MEM; 00303 } 00304 00305 // Check if this is the first time any System Attributes is stored. 00306 if (m_sys_attr_in_flash_count == 0) 00307 { 00308 // Initialize CRC 00309 m_crc_sys_attr = crc16_compute(NULL, 0, NULL); 00310 } 00311 00312 00313 // Get block pointer from base 00314 err_code = pstorage_block_identifier_get(&mp_flash_sys_attr,m_sys_attr_in_flash_count,&dest_block); 00315 if (err_code != NRF_SUCCESS) 00316 { 00317 return err_code; 00318 } 00319 00320 // Write System Attributes in flash. 00321 err_code = pstorage_store(&dest_block, 00322 (uint8_t *)p_sys_attr, 00323 sizeof(central_sys_attr_t), 00324 sizeof(uint32_t)); 00325 00326 if (err_code != NRF_SUCCESS) 00327 { 00328 return err_code; 00329 } 00330 m_crc_sys_attr = crc16_compute((uint8_t *)p_sys_attr, 00331 sizeof(central_sys_attr_t), 00332 &m_crc_sys_attr); 00333 00334 // Write header. 00335 m_sys_crc_array[m_sys_attr_in_flash_count] = (BOND_MANAGER_DATA_SIGNATURE | m_crc_sys_attr); 00336 00337 err_code = pstorage_store (&dest_block, 00338 (uint8_t *)&m_sys_crc_array[m_sys_attr_in_flash_count], 00339 sizeof(uint32_t), 00340 0); 00341 if (err_code != NRF_SUCCESS) 00342 { 00343 return err_code; 00344 } 00345 00346 m_sys_attr_in_flash_count++; 00347 00348 00349 return NRF_SUCCESS; 00350 } 00351 00352 00353 /**@brief Function for loading the Bonding Information of one central from flash. 00354 * 00355 * @param[out] p_bond Loaded Bonding Information. 00356 * 00357 * @return NRF_SUCCESS on success, otherwise an error code. 00358 */ 00359 static uint32_t bonding_info_load_from_flash(central_bond_t * p_bond) 00360 { 00361 pstorage_handle_t source_block; 00362 uint32_t err_code; 00363 uint32_t crc; 00364 uint16_t crc_header; 00365 00366 // Check if this is the first bond to be loaded, in which case the 00367 // m_bond_info_in_flash_count variable would have the intial value 0. 00368 if (m_bond_info_in_flash_count == 0) 00369 { 00370 // Initialize CRC. 00371 m_crc_bond_info = crc16_compute(NULL, 0, NULL); 00372 } 00373 00374 // Get block pointer from base 00375 err_code = pstorage_block_identifier_get(&mp_flash_bond_info, 00376 m_bond_info_in_flash_count, 00377 &source_block); 00378 if (err_code != NRF_SUCCESS) 00379 { 00380 return err_code; 00381 } 00382 00383 err_code = pstorage_load((uint8_t *)&crc, &source_block, sizeof(uint32_t), 0); 00384 if (err_code != NRF_SUCCESS) 00385 { 00386 return err_code; 00387 } 00388 00389 // Extract CRC from header. 00390 err_code = crc_extract(crc, &crc_header); 00391 if (err_code != NRF_SUCCESS) 00392 { 00393 return err_code; 00394 } 00395 00396 // Load central. 00397 err_code = pstorage_load((uint8_t *)p_bond, 00398 &source_block, 00399 sizeof(central_bond_t), 00400 sizeof(uint32_t)); 00401 if (err_code != NRF_SUCCESS) 00402 { 00403 return err_code; 00404 } 00405 00406 // Check CRC. 00407 m_crc_bond_info = crc16_compute((uint8_t *)p_bond, 00408 sizeof(central_bond_t), 00409 &m_crc_bond_info); 00410 if (m_crc_bond_info == crc_header) 00411 { 00412 m_bond_info_in_flash_count++; 00413 return NRF_SUCCESS; 00414 } 00415 else 00416 { 00417 return NRF_ERROR_INVALID_DATA; 00418 } 00419 } 00420 00421 00422 00423 /**@brief Function for loading the System Attributes related to one central from flash. 00424 * 00425 * @param[out] p_sys_attr Loaded System Attributes. 00426 * 00427 * @return NRF_SUCCESS on success, otherwise an error code. 00428 */ 00429 static uint32_t sys_attr_load_from_flash(central_sys_attr_t * p_sys_attr) 00430 { 00431 pstorage_handle_t source_block; 00432 uint32_t err_code; 00433 uint32_t crc; 00434 uint16_t crc_header; 00435 00436 // Check if this is the first time System Attributes is loaded from flash, in which case the 00437 // m_sys_attr_in_flash_count variable would have the initial value 0. 00438 if (m_sys_attr_in_flash_count == 0) 00439 { 00440 // Initialize CRC. 00441 m_crc_sys_attr = crc16_compute(NULL, 0, NULL); 00442 } 00443 00444 // Get block pointer from base 00445 err_code = pstorage_block_identifier_get(&mp_flash_sys_attr, 00446 m_sys_attr_in_flash_count, 00447 &source_block); 00448 if (err_code != NRF_SUCCESS) 00449 { 00450 return err_code; 00451 } 00452 00453 err_code = pstorage_load((uint8_t *)&crc, &source_block, sizeof(uint32_t), 0); 00454 if (err_code != NRF_SUCCESS) 00455 { 00456 return err_code; 00457 } 00458 00459 // Extract CRC from header. 00460 err_code = crc_extract(crc, &crc_header); 00461 if (err_code != NRF_SUCCESS) 00462 { 00463 return err_code; 00464 } 00465 00466 err_code = pstorage_load((uint8_t *)p_sys_attr, 00467 &source_block, 00468 sizeof(central_sys_attr_t), 00469 sizeof(uint32_t)); 00470 if (err_code != NRF_SUCCESS) 00471 { 00472 return err_code; 00473 } 00474 00475 // Check CRC. 00476 m_crc_sys_attr = crc16_compute((uint8_t *)p_sys_attr, 00477 sizeof(central_sys_attr_t), 00478 &m_crc_sys_attr); 00479 00480 if (m_crc_sys_attr == crc_header) 00481 { 00482 m_sys_attr_in_flash_count++; 00483 return NRF_SUCCESS; 00484 } 00485 else 00486 { 00487 return NRF_ERROR_INVALID_DATA; 00488 } 00489 } 00490 00491 00492 /**@brief Function for erasing the flash pages that contain Bonding Information and System 00493 * Attributes. 00494 * 00495 * @return NRF_SUCCESS on success, otherwise an error code. 00496 */ 00497 static uint32_t flash_pages_erase(void) 00498 { 00499 uint32_t err_code; 00500 00501 err_code = pstorage_clear(&mp_flash_bond_info, MAX_BONDS_IN_FLASH); 00502 00503 if (err_code == NRF_SUCCESS) 00504 { 00505 err_code = pstorage_clear(&mp_flash_sys_attr, MAX_BONDS_IN_FLASH); 00506 } 00507 00508 return err_code; 00509 } 00510 00511 00512 /**@brief Function for checking if Bonding Information in RAM is different from that in 00513 * flash. 00514 * 00515 * @return TRUE if Bonding Information in flash and RAM are different, FALSE otherwise. 00516 */ 00517 static bool bond_info_changed(void) 00518 { 00519 int i; 00520 uint16_t crc = crc16_compute(NULL, 0, NULL); 00521 00522 // Compute CRC for all bonds in database. 00523 for (i = 0; i < m_centrals_in_db_count; i++) 00524 { 00525 crc = crc16_compute((uint8_t *)&m_centrals_db[i].bond, 00526 sizeof(central_bond_t), 00527 &crc); 00528 } 00529 00530 // Compare the computed CRS to CRC stored in flash. 00531 return (crc != m_crc_bond_info); 00532 } 00533 00534 00535 /**@brief Function for checking if System Attributes in RAM is different from that in flash. 00536 * 00537 * @return TRUE if System Attributes in flash and RAM are different, FALSE otherwise. 00538 */ 00539 static bool sys_attr_changed(void) 00540 { 00541 int i; 00542 uint16_t crc = crc16_compute(NULL, 0, NULL); 00543 00544 // Compute CRC for all System Attributes in database. 00545 for (i = 0; i < m_centrals_in_db_count; i++) 00546 { 00547 crc = crc16_compute((uint8_t *)&m_centrals_db[i].sys_attr, 00548 sizeof(central_sys_attr_t), 00549 &crc); 00550 } 00551 00552 // Compare the CRC of System Attributes in flash with that of the System Attributes in memory. 00553 return (crc != m_crc_sys_attr); 00554 } 00555 00556 00557 /**@brief Function for setting the System Attributes for specified central to the SoftDevice, or 00558 * clearing the System Attributes if central is a previously unknown. 00559 * 00560 * @param[in] p_central Central for which the System Attributes is to be set. 00561 * 00562 * @return NRF_SUCCESS on success, otherwise an error code. 00563 */ 00564 static uint32_t central_sys_attr_set(central_t * p_central) 00565 { 00566 uint8_t * p_sys_attr; 00567 00568 if (m_central.sys_attr.sys_attr_size != 0) 00569 { 00570 if (m_central.sys_attr.sys_attr_size > SYS_ATTR_BUFFER_MAX_LEN) 00571 { 00572 return NRF_ERROR_INTERNAL; 00573 } 00574 00575 p_sys_attr = m_central.sys_attr.sys_attr; 00576 } 00577 else 00578 { 00579 p_sys_attr = NULL; 00580 } 00581 00582 return sd_ble_gatts_sys_attr_set(m_conn_handle, p_sys_attr, m_central.sys_attr.sys_attr_size); 00583 } 00584 00585 00586 /**@brief Function for updating the whitelist data structures. 00587 */ 00588 static void update_whitelist(void) 00589 { 00590 int i; 00591 00592 for (i = 0, m_addr_count = 0, m_irk_count = 0; i < m_centrals_in_db_count; i++) 00593 { 00594 central_bond_t * p_bond = &m_centrals_db[i].bond; 00595 00596 if (p_bond->auth_status.central_kex.irk) 00597 { 00598 m_whitelist_irk[m_irk_count].central_handle = p_bond->central_handle; 00599 m_whitelist_irk[m_irk_count].p_irk = &(p_bond->auth_status.central_keys.irk); 00600 00601 m_irk_count++; 00602 } 00603 00604 if (p_bond->central_addr.addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) 00605 { 00606 m_whitelist_addr[m_addr_count].central_handle = p_bond->central_handle; 00607 m_whitelist_addr[m_addr_count].p_addr = &(p_bond->central_addr); 00608 00609 m_addr_count++; 00610 } 00611 } 00612 } 00613 00614 00615 /**@brief Function for handling the authentication status event related to a new central. 00616 * 00617 * @details This function adds the new central to the database and stores the central's Bonding 00618 * Information to flash. It also notifies the application when the new bond is created, 00619 * and sets the System Attributes to prepare the stack for connection with the new 00620 * central. 00621 * 00622 * @param[in] p_auth_status New authentication status. 00623 * 00624 * @return NRF_SUCCESS on success, otherwise an error code. 00625 */ 00626 static uint32_t on_auth_status_from_new_central(ble_gap_evt_auth_status_t * p_auth_status) 00627 { 00628 uint32_t err_code; 00629 00630 if (m_centrals_in_db_count >= BLE_BONDMNGR_MAX_BONDED_CENTRALS) 00631 { 00632 return NRF_ERROR_NO_MEM; 00633 } 00634 00635 // Update central. 00636 m_central.bond.auth_status = *p_auth_status; 00637 m_central.bond.central_id_info.div = p_auth_status->periph_keys.enc_info.div; 00638 m_central.sys_attr.sys_attr_size = 0; 00639 00640 // Add new central to database. 00641 m_central.bond.central_handle = m_centrals_in_db_count; 00642 m_centrals_db[m_centrals_in_db_count++] = m_central; 00643 00644 update_whitelist(); 00645 00646 m_bond_loaded = true; 00647 00648 // Clear System Attributes. 00649 err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0); 00650 if (err_code != NRF_SUCCESS) 00651 { 00652 return err_code; 00653 } 00654 00655 // Write new central's Bonding Information to flash. 00656 err_code = bond_info_store(&m_central.bond); 00657 if ((err_code == NRF_ERROR_NO_MEM) && (m_bondmngr_config.evt_handler != NULL)) 00658 { 00659 ble_bondmngr_evt_t evt; 00660 00661 evt.evt_type = BLE_BONDMNGR_EVT_BOND_FLASH_FULL; 00662 evt.central_handle = m_central.bond.central_handle; 00663 evt.central_id = m_central.bond.central_id_info.div; 00664 00665 m_bondmngr_config.evt_handler(&evt); 00666 } 00667 else if (err_code != NRF_SUCCESS) 00668 { 00669 return err_code; 00670 } 00671 00672 // Pass the event to application. 00673 if (m_bondmngr_config.evt_handler != NULL) 00674 { 00675 ble_bondmngr_evt_t evt; 00676 00677 evt.evt_type = BLE_BONDMNGR_EVT_NEW_BOND; 00678 evt.central_handle = m_central.bond.central_handle; 00679 evt.central_id = m_central.bond.central_id_info.div; 00680 00681 m_bondmngr_config.evt_handler(&evt); 00682 } 00683 00684 return NRF_SUCCESS; 00685 } 00686 00687 00688 /**@brief Function for updating the current central's entry in the database. 00689 */ 00690 static uint32_t central_update(void) 00691 { 00692 uint32_t err_code; 00693 int32_t central_handle = m_central.bond.central_handle; 00694 00695 if ((central_handle >= 0) && (central_handle < m_centrals_in_db_count)) 00696 { 00697 // Update the database based on whether the bond and system attributes have 00698 // been loaded or not to avoid overwriting information that was not used in the 00699 // connection session. 00700 if (m_bond_loaded) 00701 { 00702 m_centrals_db[central_handle].bond = m_central.bond; 00703 } 00704 00705 if (m_sys_attr_loaded) 00706 { 00707 m_centrals_db[central_handle].sys_attr = m_central.sys_attr; 00708 } 00709 00710 update_whitelist(); 00711 00712 err_code = NRF_SUCCESS; 00713 } 00714 else 00715 { 00716 err_code = NRF_ERROR_INTERNAL; 00717 } 00718 00719 return err_code; 00720 } 00721 00722 00723 /**@brief Function for searching for the central in the database of known centrals. 00724 * 00725 * @details If the central is found, the variable m_central will be populated with all the 00726 * information (Bonding Information and System Attributes) related to that central. 00727 * 00728 * @param[in] central_id Central Identifier. 00729 * @return NRF_SUCCESS on success, otherwise an error code. 00730 */ 00731 static uint32_t central_find_in_db(uint16_t central_id) 00732 { 00733 int i; 00734 00735 for (i = 0; i < m_centrals_in_db_count; i++) 00736 { 00737 if (central_id == m_centrals_db[i].bond.central_id_info.div) 00738 { 00739 m_central = m_centrals_db[i]; 00740 return NRF_SUCCESS; 00741 } 00742 } 00743 00744 return NRF_ERROR_NOT_FOUND; 00745 } 00746 00747 00748 /**@brief Function for loading all Bonding Information and System Attributes from flash. 00749 * 00750 * @return NRF_SUCCESS on success, otherwise an error code. 00751 */ 00752 static uint32_t load_all_from_flash(void) 00753 { 00754 uint32_t err_code; 00755 int i; 00756 00757 m_centrals_in_db_count = 0; 00758 00759 while (m_centrals_in_db_count < BLE_BONDMNGR_MAX_BONDED_CENTRALS) 00760 { 00761 central_bond_t central_bond_info; 00762 int central_handle; 00763 00764 // Load Bonding Information. 00765 err_code = bonding_info_load_from_flash(¢ral_bond_info); 00766 if (err_code == NRF_ERROR_NOT_FOUND) 00767 { 00768 // No more bonds in flash. 00769 break; 00770 } 00771 else if (err_code != NRF_SUCCESS) 00772 { 00773 return err_code; 00774 } 00775 00776 central_handle = central_bond_info.central_handle; 00777 if (central_handle > m_centrals_in_db_count) 00778 { 00779 // Central handle value(s) missing in flash. This should never happen. 00780 return NRF_ERROR_INVALID_DATA; 00781 } 00782 else 00783 { 00784 // Add/update Bonding Information in central array. 00785 m_centrals_db[central_handle].bond = central_bond_info; 00786 if (central_handle == m_centrals_in_db_count) 00787 { 00788 // New central handle, clear System Attributes. 00789 m_centrals_db[central_handle].sys_attr.sys_attr_size = 0; 00790 m_centrals_db[central_handle].sys_attr.central_handle = INVALID_CENTRAL_HANDLE; 00791 m_centrals_in_db_count++; 00792 } 00793 else 00794 { 00795 // Entry was updated, do nothing. 00796 } 00797 } 00798 } 00799 00800 // Load System Attributes for all previously known centrals. 00801 for (i = 0; i < m_centrals_in_db_count; i++) 00802 { 00803 central_sys_attr_t central_sys_attr; 00804 00805 // Load System Attributes. 00806 err_code = sys_attr_load_from_flash(¢ral_sys_attr); 00807 if (err_code == NRF_ERROR_NOT_FOUND) 00808 { 00809 // No more System Attributes in flash. 00810 break; 00811 } 00812 else if (err_code != NRF_SUCCESS) 00813 { 00814 return err_code; 00815 } 00816 00817 if (central_sys_attr.central_handle > m_centrals_in_db_count) 00818 { 00819 // Central handle value(s) missing in flash. This should never happen. 00820 return NRF_ERROR_INVALID_DATA; 00821 } 00822 else 00823 { 00824 // Add/update Bonding Information in central array. 00825 m_centrals_db[central_sys_attr.central_handle].sys_attr = central_sys_attr; 00826 } 00827 } 00828 00829 // Initialize the remaining empty bond entries in the memory. 00830 for (i = m_centrals_in_db_count; i < BLE_BONDMNGR_MAX_BONDED_CENTRALS; i++) 00831 { 00832 m_centrals_db[i].bond.central_handle = INVALID_CENTRAL_HANDLE; 00833 m_centrals_db[i].sys_attr.sys_attr_size = 0; 00834 m_centrals_db[i].sys_attr.central_handle = INVALID_CENTRAL_HANDLE; 00835 } 00836 00837 // Update whitelist data structures. 00838 update_whitelist(); 00839 00840 return NRF_SUCCESS; 00841 } 00842 00843 00844 /**@brief Function for handling the connected event received from the BLE stack. 00845 * 00846 * @param[in] p_ble_evt Event received from the BLE stack. 00847 */ 00848 static void on_connect(ble_evt_t * p_ble_evt) 00849 { 00850 m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; 00851 00852 m_central.bond.central_handle = INVALID_CENTRAL_HANDLE; 00853 m_central.bond.central_addr = p_ble_evt->evt.gap_evt.params.connected.peer_addr; 00854 m_central.sys_attr.sys_attr_size = 0; 00855 00856 if (p_ble_evt->evt.gap_evt.params.connected.irk_match) 00857 { 00858 uint8_t irk_idx = p_ble_evt->evt.gap_evt.params.connected.irk_match_idx; 00859 00860 if ((irk_idx >= MAX_NUM_CENTRAL_WHITE_LIST) || 00861 (m_whitelist_irk[irk_idx].central_handle >= BLE_BONDMNGR_MAX_BONDED_CENTRALS)) 00862 { 00863 m_bondmngr_config.error_handler(NRF_ERROR_INTERNAL); 00864 } 00865 else 00866 { 00867 m_central = m_centrals_db[m_whitelist_irk[irk_idx].central_handle]; 00868 } 00869 } 00870 else 00871 { 00872 int i; 00873 00874 for (i = 0; i < m_addr_count; i++) 00875 { 00876 ble_gap_addr_t * p_cur_addr = m_whitelist_addr[i].p_addr; 00877 00878 if (memcmp(p_cur_addr->addr, m_central.bond.central_addr.addr, BLE_GAP_ADDR_LEN) == 0) 00879 { 00880 m_central = m_centrals_db[m_whitelist_addr[i].central_handle]; 00881 break; 00882 } 00883 } 00884 } 00885 00886 if (m_central.bond.central_handle != INVALID_CENTRAL_HANDLE) 00887 { 00888 // Reset bond and system attributes loaded variables. 00889 m_bond_loaded = false; 00890 m_sys_attr_loaded = false; 00891 00892 // Do not set the system attributes of the central on connection. 00893 if (m_bondmngr_config.evt_handler != NULL) 00894 { 00895 ble_bondmngr_evt_t evt; 00896 00897 evt.evt_type = BLE_BONDMNGR_EVT_CONN_TO_BONDED_CENTRAL; 00898 evt.central_handle = m_central.bond.central_handle; 00899 evt.central_id = m_central.bond.central_id_info.div; 00900 00901 m_bondmngr_config.evt_handler(&evt); 00902 } 00903 } 00904 } 00905 00906 00907 /**@brief Function for handling the 'System Attributes Missing' event received from the 00908 * SoftDevice. 00909 * 00910 * @param[in] p_ble_evt Event received from the BLE stack. 00911 */ 00912 static void on_sys_attr_missing(ble_evt_t * p_ble_evt) 00913 { 00914 uint32_t err_code; 00915 00916 if ( 00917 (m_central.bond.central_handle == INVALID_CENTRAL_HANDLE) || 00918 !ENCRYPTION_STATUS_GET() || 00919 BONDING_IN_PROGRESS_STATUS_GET() 00920 ) 00921 { 00922 err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0); 00923 } 00924 else 00925 { 00926 // Current central is valid, use its data. Set the corresponding sys_attr. 00927 err_code = central_sys_attr_set(&m_central); 00928 if (err_code == NRF_SUCCESS) 00929 { 00930 // Set System Attributes loaded status variable. 00931 m_sys_attr_loaded = true; 00932 } 00933 } 00934 00935 if (err_code != NRF_SUCCESS) 00936 { 00937 m_bondmngr_config.error_handler(err_code); 00938 } 00939 } 00940 00941 00942 /**@brief Function for handling the new authentication status event, received from the 00943 * SoftDevice, related to an already bonded central. 00944 * 00945 * @details This function also writes the updated Bonding Information to flash and notifies the 00946 * application. 00947 * 00948 * @param[in] p_auth_status Updated authentication status. 00949 */ 00950 static void auth_status_update(ble_gap_evt_auth_status_t * p_auth_status) 00951 { 00952 uint32_t err_code; 00953 00954 // Authentication status changed, update Bonding Information. 00955 m_central.bond.auth_status = *p_auth_status; 00956 m_central.bond.central_id_info.div = p_auth_status->periph_keys.enc_info.div; 00957 00958 memset(&(m_centrals_db[m_central.bond.central_handle]), 0, sizeof(central_t)); 00959 m_centrals_db[m_central.bond.central_handle] = m_central; 00960 00961 // Write updated Bonding Information to flash. 00962 err_code = bond_info_store(&m_central.bond); 00963 if ((err_code == NRF_ERROR_NO_MEM) && (m_bondmngr_config.evt_handler != NULL)) 00964 { 00965 ble_bondmngr_evt_t evt; 00966 00967 evt.evt_type = BLE_BONDMNGR_EVT_BOND_FLASH_FULL; 00968 evt.central_handle = m_central.bond.central_handle; 00969 evt.central_id = m_central.bond.central_id_info.div; 00970 00971 m_bondmngr_config.evt_handler(&evt); 00972 } 00973 else if (err_code != NRF_SUCCESS) 00974 { 00975 m_bondmngr_config.error_handler(err_code); 00976 } 00977 00978 // Pass the event to the application. 00979 if (m_bondmngr_config.evt_handler != NULL) 00980 { 00981 ble_bondmngr_evt_t evt; 00982 00983 evt.evt_type = BLE_BONDMNGR_EVT_AUTH_STATUS_UPDATED; 00984 evt.central_handle = m_central.bond.central_handle; 00985 evt.central_id = m_central.bond.central_id_info.div; 00986 00987 m_bondmngr_config.evt_handler(&evt); 00988 } 00989 } 00990 00991 00992 /**@brief Function for handling the Authentication Status event received from the BLE stack. 00993 * 00994 * @param[in] p_ble_evt Event received from the BLE stack. 00995 */ 00996 static void on_auth_status(ble_gap_evt_auth_status_t * p_auth_status) 00997 { 00998 if (p_auth_status->auth_status != BLE_GAP_SEC_STATUS_SUCCESS) 00999 { 01000 return; 01001 } 01002 01003 // Verify if its pairing and not bonding 01004 if (!ENCRYPTION_STATUS_GET()) 01005 { 01006 return; 01007 } 01008 01009 if (m_central.bond.central_handle == INVALID_CENTRAL_HANDLE) 01010 { 01011 uint32_t err_code = central_find_in_db(p_auth_status->periph_keys.enc_info.div); 01012 01013 if (err_code == NRF_SUCCESS) 01014 { 01015 // Possible DIV Collision indicate error to application, 01016 // not storing the new LTK 01017 err_code = NRF_ERROR_FORBIDDEN; 01018 } 01019 else 01020 { 01021 // Add the new device to data base 01022 err_code = on_auth_status_from_new_central(p_auth_status); 01023 } 01024 01025 if (err_code != NRF_SUCCESS) 01026 { 01027 m_bondmngr_config.error_handler(err_code); 01028 } 01029 } 01030 else 01031 { 01032 m_bond_loaded = true; 01033 01034 // Receiving a auth status again when already in have existing information! 01035 auth_status_update(p_auth_status); 01036 } 01037 } 01038 01039 01040 /**@brief Function for handling the Security Info Request event received from the BLE stack. 01041 * 01042 * @param[in] p_ble_evt Event received from the BLE stack. 01043 */ 01044 static void on_sec_info_request(ble_evt_t * p_ble_evt) 01045 { 01046 uint32_t err_code; 01047 01048 err_code = central_find_in_db(p_ble_evt->evt.gap_evt.params.sec_info_request.div); 01049 if (err_code == NRF_SUCCESS) 01050 { 01051 // Bond information has been found and loaded for security procedures. Reflect this in the 01052 // status variable 01053 m_bond_loaded = true; 01054 01055 // Central found in the list of bonded central. Use the encryption info for this central. 01056 err_code = sd_ble_gap_sec_info_reply(m_conn_handle, 01057 &m_central.bond.auth_status.periph_keys.enc_info, 01058 NULL); 01059 if (err_code != NRF_SUCCESS) 01060 { 01061 m_bondmngr_config.error_handler(err_code); 01062 } 01063 01064 // Do not set the sys_attr yet, should be set only when sec_update is successful. 01065 } 01066 else if (err_code == NRF_ERROR_NOT_FOUND) 01067 { 01068 m_central.bond.central_id_info = p_ble_evt->evt.gap_evt.params.sec_info_request; 01069 01070 // New central. 01071 err_code = sd_ble_gap_sec_info_reply(m_conn_handle, NULL, NULL); 01072 if (err_code != NRF_SUCCESS) 01073 { 01074 m_bondmngr_config.error_handler(err_code); 01075 } 01076 01077 // Initialize the sys_attr. 01078 err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0); 01079 } 01080 01081 if (err_code != NRF_SUCCESS) 01082 { 01083 m_bondmngr_config.error_handler(err_code); 01084 } 01085 } 01086 01087 01088 /**@brief Function for handling the Connection Security Update event received from the BLE 01089 * stack. 01090 * 01091 * @param[in] p_ble_evt Event received from the BLE stack. 01092 */ 01093 static void on_sec_update(ble_gap_evt_conn_sec_update_t * p_sec_update) 01094 { 01095 uint8_t security_mode = p_sec_update->conn_sec.sec_mode.sm; 01096 uint8_t security_level = p_sec_update->conn_sec.sec_mode.lv; 01097 01098 if (((security_mode == 1) && (security_level > 1)) || 01099 ((security_mode == 2) && (security_level != 0))) 01100 { 01101 ENCRYPTION_STATUS_SET(); 01102 01103 uint32_t err_code = central_sys_attr_set(&m_central); 01104 01105 if (err_code != NRF_SUCCESS) 01106 { 01107 m_bondmngr_config.error_handler(err_code); 01108 } 01109 else 01110 { 01111 m_sys_attr_loaded = true; 01112 } 01113 01114 if (m_bondmngr_config.evt_handler != NULL) 01115 { 01116 ble_bondmngr_evt_t evt; 01117 01118 evt.evt_type = BLE_BONDMNGR_EVT_ENCRYPTED; 01119 evt.central_handle = m_central.bond.central_handle; 01120 evt.central_id = m_central.bond.central_id_info.div; 01121 01122 m_bondmngr_config.evt_handler(&evt); 01123 } 01124 } 01125 } 01126 01127 01128 /**@brief Function for handling the Connection Security Parameters Request event received from 01129 * the BLE stack. 01130 * 01131 * @param[in] p_ble_evt Event received from the BLE stack. 01132 */ 01133 static void on_sec_param_request(ble_gap_evt_sec_params_request_t * p_sec_update) 01134 { 01135 if (p_sec_update->peer_params.bond) 01136 { 01137 BONDING_IN_PROGRESS_STATUS_SET(); 01138 01139 if (m_central.bond.central_handle != INVALID_CENTRAL_HANDLE) 01140 { 01141 // Bonding request received from a bonded central, make all system attributes null 01142 m_central.sys_attr.sys_attr_size = 0; 01143 memset(m_central.sys_attr.sys_attr, 0, SYS_ATTR_BUFFER_MAX_LEN); 01144 } 01145 } 01146 } 01147 01148 01149 void ble_bondmngr_on_ble_evt(ble_evt_t * p_ble_evt) 01150 { 01151 if (!m_is_bondmngr_initialized) 01152 { 01153 m_bondmngr_config.error_handler(NRF_ERROR_INVALID_STATE); 01154 } 01155 01156 switch (p_ble_evt->header.evt_id) 01157 { 01158 case BLE_GAP_EVT_CONNECTED: 01159 on_connect(p_ble_evt); 01160 break; 01161 01162 // NOTE: All actions to be taken on the Disconnected event are performed in 01163 // ble_bondmngr_bonded_centrals_store(). This function must be called from the 01164 // Disconnected handler of the application before advertising is restarted (to make 01165 // sure the flash blocks are cleared while the radio is inactive). 01166 case BLE_GAP_EVT_DISCONNECTED: 01167 SECURITY_STATUS_RESET(); 01168 break; 01169 01170 case BLE_GATTS_EVT_SYS_ATTR_MISSING: 01171 on_sys_attr_missing(p_ble_evt); 01172 break; 01173 01174 case BLE_GAP_EVT_AUTH_STATUS: 01175 on_auth_status(&p_ble_evt->evt.gap_evt.params.auth_status); 01176 break; 01177 01178 case BLE_GAP_EVT_SEC_INFO_REQUEST: 01179 on_sec_info_request(p_ble_evt); 01180 break; 01181 01182 case BLE_GAP_EVT_SEC_PARAMS_REQUEST: 01183 on_sec_param_request(&p_ble_evt->evt.gap_evt.params.sec_params_request); 01184 break; 01185 01186 case BLE_GAP_EVT_CONN_SEC_UPDATE: 01187 on_sec_update(&p_ble_evt->evt.gap_evt.params.conn_sec_update); 01188 break; 01189 01190 default: 01191 // No implementation needed. 01192 break; 01193 } 01194 } 01195 01196 01197 uint32_t ble_bondmngr_bonded_centrals_store(void) 01198 { 01199 uint32_t err_code; 01200 int i; 01201 01202 VERIFY_MODULE_INITIALIZED(); 01203 01204 if (m_central.bond.central_handle != INVALID_CENTRAL_HANDLE) 01205 { 01206 // Fetch System Attributes from stack. 01207 uint16_t sys_attr_size = SYS_ATTR_BUFFER_MAX_LEN; 01208 01209 err_code = sd_ble_gatts_sys_attr_get(m_conn_handle, 01210 m_central.sys_attr.sys_attr, 01211 &sys_attr_size); 01212 if (err_code != NRF_SUCCESS) 01213 { 01214 return err_code; 01215 } 01216 01217 m_central.sys_attr.central_handle = m_central.bond.central_handle; 01218 m_central.sys_attr.sys_attr_size = (uint16_t)sys_attr_size; 01219 01220 // Update the current central. 01221 err_code = central_update(); 01222 if (err_code != NRF_SUCCESS) 01223 { 01224 return err_code; 01225 } 01226 } 01227 01228 // Save Bonding Information if changed. 01229 if (bond_info_changed()) 01230 { 01231 // Erase flash page. 01232 err_code = pstorage_clear(&mp_flash_bond_info,MAX_BONDS_IN_FLASH); 01233 if (err_code != NRF_SUCCESS) 01234 { 01235 return err_code; 01236 } 01237 01238 // Store bond information for all centrals. 01239 m_bond_info_in_flash_count = 0; 01240 for (i = 0; i < m_centrals_in_db_count; i++) 01241 { 01242 err_code = bond_info_store(&m_centrals_db[i].bond); 01243 if (err_code != NRF_SUCCESS) 01244 { 01245 return err_code; 01246 } 01247 } 01248 } 01249 01250 // Save System Attributes, if changed. 01251 if (sys_attr_changed()) 01252 { 01253 // Erase flash page. 01254 err_code = pstorage_clear(&mp_flash_sys_attr, MAX_BONDS_IN_FLASH); 01255 if (err_code != NRF_SUCCESS) 01256 { 01257 return err_code; 01258 } 01259 01260 // Store System Attributes for all centrals. 01261 m_sys_attr_in_flash_count = 0; 01262 for (i = 0; i < m_centrals_in_db_count; i++) 01263 { 01264 err_code = sys_attr_store(&m_centrals_db[i].sys_attr); 01265 if (err_code != NRF_SUCCESS) 01266 { 01267 return err_code; 01268 } 01269 } 01270 } 01271 01272 m_conn_handle = BLE_CONN_HANDLE_INVALID; 01273 m_central.bond.central_handle = INVALID_CENTRAL_HANDLE; 01274 m_central.sys_attr.central_handle = INVALID_CENTRAL_HANDLE; 01275 m_central.sys_attr.sys_attr_size = 0; 01276 m_bond_loaded = false; 01277 m_sys_attr_loaded = false; 01278 01279 return NRF_SUCCESS; 01280 } 01281 01282 01283 uint32_t ble_bondmngr_sys_attr_store(void) 01284 { 01285 uint32_t err_code; 01286 01287 if (m_central.sys_attr.sys_attr_size == 0) 01288 { 01289 // Connected to new central. So the flash block for System Attributes for this 01290 // central is empty. Hence no erase is needed. 01291 01292 uint16_t sys_attr_size = SYS_ATTR_BUFFER_MAX_LEN; 01293 01294 // Fetch System Attributes from stack. 01295 err_code = sd_ble_gatts_sys_attr_get(m_conn_handle, 01296 m_central.sys_attr.sys_attr, 01297 &sys_attr_size); 01298 01299 if (err_code != NRF_SUCCESS) 01300 { 01301 return err_code; 01302 } 01303 01304 m_central.sys_attr.central_handle = m_central.bond.central_handle; 01305 m_central.sys_attr.sys_attr_size = (uint16_t)sys_attr_size; 01306 01307 // Copy the System Attributes to database. 01308 m_centrals_db[m_central.bond.central_handle].sys_attr = m_central.sys_attr; 01309 01310 // Write new central's System Attributes to flash. 01311 return (sys_attr_store(&m_central.sys_attr)); 01312 } 01313 else 01314 { 01315 // Will not write to flash because System Attributes of an old central would already be 01316 // in flash and so this operation needs a flash erase operation. 01317 return NRF_ERROR_INVALID_STATE; 01318 } 01319 } 01320 01321 01322 uint32_t ble_bondmngr_bonded_centrals_delete(void) 01323 { 01324 VERIFY_MODULE_INITIALIZED(); 01325 01326 m_centrals_in_db_count = 0; 01327 m_bond_info_in_flash_count = 0; 01328 m_sys_attr_in_flash_count = 0; 01329 01330 return flash_pages_erase(); 01331 } 01332 01333 01334 uint32_t ble_bondmngr_central_addr_get(int8_t central_handle, ble_gap_addr_t * p_central_addr) 01335 { 01336 if ( 01337 (central_handle == INVALID_CENTRAL_HANDLE) || 01338 (central_handle >= m_centrals_in_db_count) || 01339 (p_central_addr == NULL) || 01340 ( 01341 m_centrals_db[central_handle].bond.central_addr.addr_type 01342 == 01343 BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE 01344 ) 01345 ) 01346 { 01347 return NRF_ERROR_INVALID_PARAM; 01348 } 01349 01350 *p_central_addr = m_centrals_db[central_handle].bond.central_addr; 01351 return NRF_SUCCESS; 01352 } 01353 01354 01355 uint32_t ble_bondmngr_whitelist_get(ble_gap_whitelist_t * p_whitelist) 01356 { 01357 static ble_gap_addr_t * s_addr[MAX_NUM_CENTRAL_WHITE_LIST]; 01358 static ble_gap_irk_t * s_irk[MAX_NUM_CENTRAL_WHITE_LIST]; 01359 01360 int i; 01361 01362 for (i = 0; i < m_irk_count; i++) 01363 { 01364 s_irk[i] = m_whitelist_irk[i].p_irk; 01365 } 01366 for (i = 0; i < m_addr_count; i++) 01367 { 01368 s_addr[i] = m_whitelist_addr[i].p_addr; 01369 } 01370 01371 p_whitelist->addr_count = m_addr_count; 01372 p_whitelist->pp_addrs = (m_addr_count != 0) ? s_addr : NULL; 01373 p_whitelist->irk_count = m_irk_count; 01374 p_whitelist->pp_irks = (m_irk_count != 0) ? s_irk : NULL; 01375 01376 return NRF_SUCCESS; 01377 } 01378 01379 01380 static void bm_pstorage_cb_handler(pstorage_handle_t * handle, 01381 uint8_t op_code, 01382 uint32_t result, 01383 uint8_t * p_data, 01384 uint32_t data_len) 01385 { 01386 if (result != NRF_SUCCESS) 01387 { 01388 m_bondmngr_config.error_handler(result); 01389 } 01390 } 01391 01392 01393 uint32_t ble_bondmngr_init(ble_bondmngr_init_t * p_init) 01394 { 01395 pstorage_module_param_t param; 01396 uint32_t err_code; 01397 01398 if (p_init->error_handler == NULL) 01399 { 01400 return NRF_ERROR_INVALID_PARAM; 01401 } 01402 01403 if (BLE_BONDMNGR_MAX_BONDED_CENTRALS > MAX_BONDS_IN_FLASH) 01404 { 01405 return NRF_ERROR_DATA_SIZE; 01406 } 01407 01408 param.block_size = sizeof (central_bond_t) + sizeof (uint32_t); 01409 param.block_count = MAX_BONDS_IN_FLASH; 01410 param.cb = bm_pstorage_cb_handler; 01411 01412 // Blocks are requested twice, once for bond information and once for system attributes. 01413 // The number of blocks requested has to be the maximum number of bonded devices that 01414 // need to be supported. However, the size of blocks can be different if the sizes of 01415 // system attributes and bonds are not too close. 01416 err_code = pstorage_register(¶m, &mp_flash_bond_info); 01417 if (err_code != NRF_SUCCESS) 01418 { 01419 return err_code; 01420 } 01421 01422 param.block_size = sizeof(central_sys_attr_t) + sizeof(uint32_t); 01423 01424 err_code = pstorage_register(¶m, &mp_flash_sys_attr); 01425 if (err_code != NRF_SUCCESS) 01426 { 01427 return err_code; 01428 } 01429 01430 m_bondmngr_config = *p_init; 01431 01432 memset(&m_central, 0, sizeof(central_t)); 01433 01434 m_central.bond.central_handle = INVALID_CENTRAL_HANDLE; 01435 m_conn_handle = BLE_CONN_HANDLE_INVALID; 01436 m_centrals_in_db_count = 0; 01437 m_bond_info_in_flash_count = 0; 01438 m_sys_attr_in_flash_count = 0; 01439 01440 SECURITY_STATUS_RESET(); 01441 01442 // Erase all stored centrals if specified. 01443 if (m_bondmngr_config.bonds_delete) 01444 { 01445 err_code = flash_pages_erase(); 01446 if (err_code != NRF_SUCCESS) 01447 { 01448 return err_code; 01449 } 01450 01451 m_centrals_in_db_count = 0; 01452 int i; 01453 for (i = m_centrals_in_db_count; i < BLE_BONDMNGR_MAX_BONDED_CENTRALS; i++) 01454 { 01455 m_centrals_db[i].bond.central_handle = INVALID_CENTRAL_HANDLE; 01456 m_centrals_db[i].sys_attr.sys_attr_size = 0; 01457 m_centrals_db[i].sys_attr.central_handle = INVALID_CENTRAL_HANDLE; 01458 } 01459 } 01460 else 01461 { 01462 // Load bond manager data from flash. 01463 err_code = load_all_from_flash(); 01464 if (err_code != NRF_SUCCESS) 01465 { 01466 return err_code; 01467 } 01468 } 01469 01470 m_is_bondmngr_initialized = true; 01471 01472 return NRF_SUCCESS; 01473 } 01474 01475 01476 uint32_t ble_bondmngr_central_ids_get(uint16_t * p_central_ids, uint16_t * p_length) 01477 { 01478 VERIFY_MODULE_INITIALIZED(); 01479 int i; 01480 if (p_length == NULL) 01481 { 01482 return NRF_ERROR_NULL; 01483 } 01484 01485 if (*p_length < m_centrals_in_db_count) 01486 { 01487 // Length of the input array is not enough to fit all known central identifiers. 01488 return NRF_ERROR_DATA_SIZE; 01489 } 01490 01491 *p_length = m_centrals_in_db_count; 01492 if (p_central_ids == NULL) 01493 { 01494 // Only the length field was required to be filled. 01495 return NRF_SUCCESS; 01496 } 01497 01498 for (i = 0; i < m_centrals_in_db_count; i++) 01499 { 01500 p_central_ids[i] = m_centrals_db[i].bond.central_id_info.div; 01501 } 01502 01503 return NRF_SUCCESS; 01504 } 01505 01506 01507 uint32_t ble_bondmngr_bonded_central_delete(uint16_t central_id) 01508 { 01509 VERIFY_MODULE_INITIALIZED(); 01510 01511 int8_t central_handle_to_be_deleted = INVALID_CENTRAL_HANDLE; 01512 uint8_t i; 01513 01514 // Search for the handle of the central. 01515 for (i = 0; i < m_centrals_in_db_count; i++) 01516 { 01517 if (m_centrals_db[i].bond.central_id_info.div == central_id) 01518 { 01519 central_handle_to_be_deleted = i; 01520 break; 01521 } 01522 } 01523 01524 if (central_handle_to_be_deleted == INVALID_CENTRAL_HANDLE) 01525 { 01526 // Central ID not found. 01527 return NRF_ERROR_NOT_FOUND; 01528 } 01529 01530 // Delete the central in RAM. 01531 for (i = central_handle_to_be_deleted; i < (m_centrals_in_db_count - 1); i++) 01532 { 01533 // Overwrite the current central entry with the next one. 01534 m_centrals_db[i] = m_centrals_db[i + 1]; 01535 01536 // Decrement the value of handle. 01537 m_centrals_db[i].bond.central_handle--; 01538 if (INVALID_CENTRAL_HANDLE != m_centrals_db[i].sys_attr.central_handle) 01539 { 01540 m_centrals_db[i].sys_attr.central_handle--; 01541 } 01542 } 01543 01544 // Clear the last database entry. 01545 memset(&(m_centrals_db[m_centrals_in_db_count - 1]), 0, sizeof(central_t)); 01546 01547 m_centrals_in_db_count--; 01548 01549 uint32_t err_code; 01550 01551 // Reinitialize the pointers to the memory where bonding info and System Attributes are stored 01552 // in flash. 01553 // Refresh the data in the flash memory (both Bonding Information and System Attributes). 01554 // Erase and rewrite bonding info and System Attributes. 01555 01556 err_code = flash_pages_erase(); 01557 if (err_code != NRF_SUCCESS) 01558 { 01559 return err_code; 01560 } 01561 01562 m_bond_info_in_flash_count = 0; 01563 m_sys_attr_in_flash_count = 0; 01564 01565 for (i = 0; i < m_centrals_in_db_count; i++) 01566 { 01567 err_code = bond_info_store(&(m_centrals_db[i].bond)); 01568 if (err_code != NRF_SUCCESS) 01569 { 01570 return err_code; 01571 } 01572 } 01573 01574 for (i = 0; i < m_centrals_in_db_count; i++) 01575 { 01576 err_code = sys_attr_store(&(m_centrals_db[i].sys_attr)); 01577 if (err_code != NRF_SUCCESS) 01578 { 01579 return err_code; 01580 } 01581 } 01582 01583 update_whitelist(); 01584 01585 return NRF_SUCCESS; 01586 } 01587 01588 01589 uint32_t ble_bondmngr_is_link_encrypted (bool * status) 01590 { 01591 VERIFY_MODULE_INITIALIZED(); 01592 01593 (*status) = ENCRYPTION_STATUS_GET(); 01594 01595 return NRF_SUCCESS; 01596 } 01597 01598 #endif /* #if NEED_BOND_MANAGER */
Generated on Tue Jul 12 2022 13:52:30 by
