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