BLE FOTA APP

Dependencies:   BLE_API mbed

It doesn't work with the default FOTA bootloader. It use NVIC_SystemReset() to enter a bootloader.

Committer:
yihui
Date:
Fri Oct 10 03:36:28 2014 +0000
Revision:
1:a607cd9655d7
use NVIC_SystemReset() to run bootloader

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yihui 1:a607cd9655d7 1 /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
yihui 1:a607cd9655d7 2 *
yihui 1:a607cd9655d7 3 * The information contained herein is property of Nordic Semiconductor ASA.
yihui 1:a607cd9655d7 4 * Terms and conditions of usage are described in detail in NORDIC
yihui 1:a607cd9655d7 5 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
yihui 1:a607cd9655d7 6 *
yihui 1:a607cd9655d7 7 * Licensees are granted free, non-transferable use of the information. NO
yihui 1:a607cd9655d7 8 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
yihui 1:a607cd9655d7 9 * the file.
yihui 1:a607cd9655d7 10 *
yihui 1:a607cd9655d7 11 */
yihui 1:a607cd9655d7 12
yihui 1:a607cd9655d7 13 #if NEED_BOND_MANAGER /* disabled by default */
yihui 1:a607cd9655d7 14
yihui 1:a607cd9655d7 15 #include "ble_bondmngr.h"
yihui 1:a607cd9655d7 16 #include <stdlib.h>
yihui 1:a607cd9655d7 17 #include <stdint.h>
yihui 1:a607cd9655d7 18 #include <string.h>
yihui 1:a607cd9655d7 19 #include "nordic_common.h"
yihui 1:a607cd9655d7 20 #include "nrf_error.h"
yihui 1:a607cd9655d7 21 #include "ble_gap.h"
yihui 1:a607cd9655d7 22 #include "ble_srv_common.h"
yihui 1:a607cd9655d7 23 #include "app_util.h"
yihui 1:a607cd9655d7 24 #include "nrf_assert.h"
yihui 1:a607cd9655d7 25 //#include "nrf.h"
yihui 1:a607cd9655d7 26 #include "nrf51_bitfields.h"
yihui 1:a607cd9655d7 27 #include "crc16.h"
yihui 1:a607cd9655d7 28 #include "pstorage.h"
yihui 1:a607cd9655d7 29 #include "ble_bondmngr_cfg.h"
yihui 1:a607cd9655d7 30
yihui 1:a607cd9655d7 31 #define CCCD_SIZE 6 /**< Number of bytes needed for storing the state of one CCCD. */
yihui 1:a607cd9655d7 32 #define CRC_SIZE 2 /**< Size of CRC in sys_attribute data. */
yihui 1:a607cd9655d7 33 #define SYS_ATTR_BUFFER_MAX_LEN (((BLE_BONDMNGR_CCCD_COUNT + 1) * CCCD_SIZE) + CRC_SIZE) /**< Size of sys_attribute data. */
yihui 1:a607cd9655d7 34 #define MAX_NUM_CENTRAL_WHITE_LIST MIN(BLE_BONDMNGR_MAX_BONDED_CENTRALS, 8) /**< Maximum number of whitelisted centrals supported.*/
yihui 1:a607cd9655d7 35 #define MAX_BONDS_IN_FLASH 10 /**< Maximum number of bonds that can be stored in flash. */
yihui 1:a607cd9655d7 36 #define BOND_MANAGER_DATA_SIGNATURE 0x53240000
yihui 1:a607cd9655d7 37
yihui 1:a607cd9655d7 38 /**@defgroup ble_bond_mngr_sec_access Bond Manager Security Status Access Macros
yihui 1:a607cd9655d7 39 * @brief The following group of macros abstract access to Security Status with a peer.
yihui 1:a607cd9655d7 40 * @{
yihui 1:a607cd9655d7 41 */
yihui 1:a607cd9655d7 42
yihui 1:a607cd9655d7 43 #define SEC_STATUS_INIT_VAL 0x00 /**< Initialization value for security status flags. */
yihui 1:a607cd9655d7 44 #define ENC_STATUS_SET_VAL 0x01 /**< Bitmask for encryption status. */
yihui 1:a607cd9655d7 45 #define BOND_IN_PROGRESS_SET_VAL 0x02 /**< Bitmask for 'bonding in progress'. */
yihui 1:a607cd9655d7 46
yihui 1:a607cd9655d7 47
yihui 1:a607cd9655d7 48 /**@brief Macro for setting the Encryption Status for current link.
yihui 1:a607cd9655d7 49 *
yihui 1:a607cd9655d7 50 * @details Macro for setting the Encryption Status for current link.
yihui 1:a607cd9655d7 51 */
yihui 1:a607cd9655d7 52 #define ENCRYPTION_STATUS_SET() \
yihui 1:a607cd9655d7 53 do \
yihui 1:a607cd9655d7 54 { \
yihui 1:a607cd9655d7 55 m_sec_con_status |= ENC_STATUS_SET_VAL; \
yihui 1:a607cd9655d7 56 } while (0)
yihui 1:a607cd9655d7 57
yihui 1:a607cd9655d7 58 /**@brief Macro for getting the Encryption Status for current link.
yihui 1:a607cd9655d7 59 *
yihui 1:a607cd9655d7 60 * @details Macro for getting the Encryption Status for current link.
yihui 1:a607cd9655d7 61 */
yihui 1:a607cd9655d7 62 #define ENCRYPTION_STATUS_GET() \
yihui 1:a607cd9655d7 63 (((m_sec_con_status & ENC_STATUS_SET_VAL) == 0) ? false : true)
yihui 1:a607cd9655d7 64
yihui 1:a607cd9655d7 65 /**@brief Macro for resetting the Encryption Status for current link.
yihui 1:a607cd9655d7 66 *
yihui 1:a607cd9655d7 67 * @details Macro for resetting the Encryption Status for current link.
yihui 1:a607cd9655d7 68 */
yihui 1:a607cd9655d7 69 #define ENCRYPTION_STATUS_RESET() \
yihui 1:a607cd9655d7 70 do \
yihui 1:a607cd9655d7 71 { \
yihui 1:a607cd9655d7 72 m_sec_con_status &= (~ENC_STATUS_SET_VAL); \
yihui 1:a607cd9655d7 73 } while (0)
yihui 1:a607cd9655d7 74
yihui 1:a607cd9655d7 75
yihui 1:a607cd9655d7 76 /**@brief Macro for resetting the Bonding In Progress status for current link.
yihui 1:a607cd9655d7 77 *
yihui 1:a607cd9655d7 78 * @details Macro for resetting the Bonding In Progress status for current link.
yihui 1:a607cd9655d7 79 */
yihui 1:a607cd9655d7 80 #define BONDING_IN_PROGRESS_STATUS_SET() \
yihui 1:a607cd9655d7 81 do \
yihui 1:a607cd9655d7 82 { \
yihui 1:a607cd9655d7 83 m_sec_con_status |= BOND_IN_PROGRESS_SET_VAL; \
yihui 1:a607cd9655d7 84 } while (0)
yihui 1:a607cd9655d7 85
yihui 1:a607cd9655d7 86 /**@brief Macro for setting the Bonding In Progress status for current link.
yihui 1:a607cd9655d7 87 *
yihui 1:a607cd9655d7 88 * @details Macro for setting the Bonding In Progress status for current link.
yihui 1:a607cd9655d7 89 */
yihui 1:a607cd9655d7 90 #define BONDING_IN_PROGRESS_STATUS_GET() \
yihui 1:a607cd9655d7 91 (((m_sec_con_status & BOND_IN_PROGRESS_SET_VAL) == 0) ? false: true)
yihui 1:a607cd9655d7 92
yihui 1:a607cd9655d7 93 /**@brief Macro for resetting the Bonding In Progress status for current link.
yihui 1:a607cd9655d7 94 *
yihui 1:a607cd9655d7 95 * @details Macro for resetting the Bonding In Progress status for current link.
yihui 1:a607cd9655d7 96 */
yihui 1:a607cd9655d7 97 #define BONDING_IN_PROGRESS_STATUS_RESET() \
yihui 1:a607cd9655d7 98 do \
yihui 1:a607cd9655d7 99 { \
yihui 1:a607cd9655d7 100 m_sec_con_status &= (~BOND_IN_PROGRESS_SET_VAL); \
yihui 1:a607cd9655d7 101 } while (0)
yihui 1:a607cd9655d7 102
yihui 1:a607cd9655d7 103 /**@brief Macro for resetting all security status flags for current link.
yihui 1:a607cd9655d7 104 *
yihui 1:a607cd9655d7 105 * @details Macro for resetting all security status flags for current link.
yihui 1:a607cd9655d7 106 */
yihui 1:a607cd9655d7 107 #define SECURITY_STATUS_RESET() \
yihui 1:a607cd9655d7 108 do \
yihui 1:a607cd9655d7 109 { \
yihui 1:a607cd9655d7 110 m_sec_con_status = SEC_STATUS_INIT_VAL; \
yihui 1:a607cd9655d7 111 } while (0)
yihui 1:a607cd9655d7 112
yihui 1:a607cd9655d7 113 /** @} */
yihui 1:a607cd9655d7 114
yihui 1:a607cd9655d7 115 /**@brief Verify module's initialization status.
yihui 1:a607cd9655d7 116 *
yihui 1:a607cd9655d7 117 * @details Verify module's initialization status. Returns NRF_INVALID_STATE in case a module API
yihui 1:a607cd9655d7 118 * is called without initializing the module.
yihui 1:a607cd9655d7 119 */
yihui 1:a607cd9655d7 120 #define VERIFY_MODULE_INITIALIZED() \
yihui 1:a607cd9655d7 121 do \
yihui 1:a607cd9655d7 122 { \
yihui 1:a607cd9655d7 123 if (!m_is_bondmngr_initialized) \
yihui 1:a607cd9655d7 124 { \
yihui 1:a607cd9655d7 125 return NRF_ERROR_INVALID_STATE; \
yihui 1:a607cd9655d7 126 } \
yihui 1:a607cd9655d7 127 } while(0)
yihui 1:a607cd9655d7 128
yihui 1:a607cd9655d7 129
yihui 1:a607cd9655d7 130 /**@brief This structure contains the Bonding Information for one central.
yihui 1:a607cd9655d7 131 */
yihui 1:a607cd9655d7 132 typedef struct
yihui 1:a607cd9655d7 133 {
yihui 1:a607cd9655d7 134 int32_t central_handle; /**< Central's handle (NOTE: Size is 32 bits just to make struct size dividable by 4). */
yihui 1:a607cd9655d7 135 ble_gap_evt_auth_status_t auth_status; /**< Central authentication data. */
yihui 1:a607cd9655d7 136 ble_gap_evt_sec_info_request_t central_id_info; /**< Central identification info. */
yihui 1:a607cd9655d7 137 ble_gap_addr_t central_addr; /**< Central's address. */
yihui 1:a607cd9655d7 138 } central_bond_t;
yihui 1:a607cd9655d7 139
yihui 1:a607cd9655d7 140 STATIC_ASSERT(sizeof(central_bond_t) % 4 == 0);
yihui 1:a607cd9655d7 141
yihui 1:a607cd9655d7 142 /**@brief This structure contains the System Attributes information related to one central.
yihui 1:a607cd9655d7 143 */
yihui 1:a607cd9655d7 144 typedef struct
yihui 1:a607cd9655d7 145 {
yihui 1:a607cd9655d7 146 int32_t central_handle; /**< Central's handle (NOTE: Size is 32 bits just to make struct size dividable by 4). */
yihui 1:a607cd9655d7 147 uint8_t sys_attr[SYS_ATTR_BUFFER_MAX_LEN]; /**< Central sys_attribute data. */
yihui 1:a607cd9655d7 148 uint32_t sys_attr_size; /**< Central sys_attribute data's size (NOTE: Size is 32 bits just to make struct size dividable by 4). */
yihui 1:a607cd9655d7 149 } central_sys_attr_t;
yihui 1:a607cd9655d7 150
yihui 1:a607cd9655d7 151 STATIC_ASSERT(sizeof(central_sys_attr_t) % 4 == 0);
yihui 1:a607cd9655d7 152
yihui 1:a607cd9655d7 153 /**@brief This structure contains the Bonding Information and System Attributes related to one
yihui 1:a607cd9655d7 154 * central.
yihui 1:a607cd9655d7 155 */
yihui 1:a607cd9655d7 156 typedef struct
yihui 1:a607cd9655d7 157 {
yihui 1:a607cd9655d7 158 central_bond_t bond; /**< Bonding information. */
yihui 1:a607cd9655d7 159 central_sys_attr_t sys_attr; /**< System attribute information. */
yihui 1:a607cd9655d7 160 } central_t;
yihui 1:a607cd9655d7 161
yihui 1:a607cd9655d7 162 /**@brief This structure contains the whitelisted addresses.
yihui 1:a607cd9655d7 163 */
yihui 1:a607cd9655d7 164 typedef struct
yihui 1:a607cd9655d7 165 {
yihui 1:a607cd9655d7 166 int8_t central_handle; /**< Central's handle. */
yihui 1:a607cd9655d7 167 ble_gap_addr_t * p_addr; /**< Pointer to the central's address if BLE_GAP_ADDR_TYPE_PUBLIC. */
yihui 1:a607cd9655d7 168 } whitelist_addr_t;
yihui 1:a607cd9655d7 169
yihui 1:a607cd9655d7 170 /**@brief This structure contains the whitelisted IRKs.
yihui 1:a607cd9655d7 171 */
yihui 1:a607cd9655d7 172 typedef struct
yihui 1:a607cd9655d7 173 {
yihui 1:a607cd9655d7 174 int8_t central_handle; /**< Central's handle. */
yihui 1:a607cd9655d7 175 ble_gap_irk_t * p_irk; /**< Pointer to the central's irk if available. */
yihui 1:a607cd9655d7 176 } whitelist_irk_t;
yihui 1:a607cd9655d7 177
yihui 1:a607cd9655d7 178 static bool m_is_bondmngr_initialized = false; /**< Flag for checking if module has been initialized. */
yihui 1:a607cd9655d7 179 static ble_bondmngr_init_t m_bondmngr_config; /**< Configuration as specified by the application. */
yihui 1:a607cd9655d7 180 static uint16_t m_conn_handle; /**< Current connection handle. */
yihui 1:a607cd9655d7 181 static central_t m_central; /**< Current central data. */
yihui 1:a607cd9655d7 182 static central_t m_centrals_db[BLE_BONDMNGR_MAX_BONDED_CENTRALS]; /**< Pointer to start of bonded centrals database. */
yihui 1:a607cd9655d7 183 static uint8_t m_centrals_in_db_count; /**< Number of bonded centrals. */
yihui 1:a607cd9655d7 184 static whitelist_addr_t m_whitelist_addr[MAX_NUM_CENTRAL_WHITE_LIST]; /**< List of central's addresses for the whitelist. */
yihui 1:a607cd9655d7 185 static whitelist_irk_t m_whitelist_irk[MAX_NUM_CENTRAL_WHITE_LIST]; /**< List of central's IRKs for the whitelist. */
yihui 1:a607cd9655d7 186 static uint8_t m_addr_count; /**< Number of addresses in the whitelist. */
yihui 1:a607cd9655d7 187 static uint8_t m_irk_count; /**< Number of IRKs in the whitelist. */
yihui 1:a607cd9655d7 188 static uint16_t m_crc_bond_info; /**< Combined CRC for all Bonding Information currently stored in flash. */
yihui 1:a607cd9655d7 189 static uint16_t m_crc_sys_attr; /**< Combined CRC for all System Attributes currently stored in flash. */
yihui 1:a607cd9655d7 190 static pstorage_handle_t mp_flash_bond_info; /**< Pointer to flash location to write next Bonding Information. */
yihui 1:a607cd9655d7 191 static pstorage_handle_t mp_flash_sys_attr; /**< Pointer to flash location to write next System Attribute information. */
yihui 1:a607cd9655d7 192 static uint8_t m_bond_info_in_flash_count; /**< Number of Bonding Information currently stored in flash. */
yihui 1:a607cd9655d7 193 static uint8_t m_sys_attr_in_flash_count; /**< Number of System Attributes currently stored in flash. */
yihui 1:a607cd9655d7 194 static uint8_t m_sec_con_status; /**< Variable to denote security status.*/
yihui 1:a607cd9655d7 195 static bool m_bond_loaded; /**< Variable to indicate if the bonding information of the currently connected central is available in the RAM.*/
yihui 1:a607cd9655d7 196 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.*/
yihui 1:a607cd9655d7 197 static uint32_t m_bond_crc_array[BLE_BONDMNGR_MAX_BONDED_CENTRALS];
yihui 1:a607cd9655d7 198 static uint32_t m_sys_crc_array[BLE_BONDMNGR_MAX_BONDED_CENTRALS];
yihui 1:a607cd9655d7 199
yihui 1:a607cd9655d7 200 /**@brief Function for extracting the CRC from an encoded 32 bit number that typical resides in
yihui 1:a607cd9655d7 201 * the flash memory
yihui 1:a607cd9655d7 202 *
yihui 1:a607cd9655d7 203 * @param[in] header Header containing CRC and magic number.
yihui 1:a607cd9655d7 204 * @param[out] p_crc Extracted CRC.
yihui 1:a607cd9655d7 205 *
yihui 1:a607cd9655d7 206 * @retval NRF_SUCCESS CRC successfully extracted.
yihui 1:a607cd9655d7 207 * @retval NRF_ERROR_NOT_FOUND Flash seems to be empty.
yihui 1:a607cd9655d7 208 * @retval NRF_ERROR_INVALID_DATA Header does not contain the magic number.
yihui 1:a607cd9655d7 209 */
yihui 1:a607cd9655d7 210 static uint32_t crc_extract(uint32_t header, uint16_t * p_crc)
yihui 1:a607cd9655d7 211 {
yihui 1:a607cd9655d7 212 if ((header & 0xFFFF0000U) == BOND_MANAGER_DATA_SIGNATURE)
yihui 1:a607cd9655d7 213 {
yihui 1:a607cd9655d7 214 *p_crc = (uint16_t)(header & 0x0000FFFFU);
yihui 1:a607cd9655d7 215
yihui 1:a607cd9655d7 216 return NRF_SUCCESS;
yihui 1:a607cd9655d7 217 }
yihui 1:a607cd9655d7 218 else if (header == 0xFFFFFFFFU)
yihui 1:a607cd9655d7 219 {
yihui 1:a607cd9655d7 220 return NRF_ERROR_NOT_FOUND;
yihui 1:a607cd9655d7 221 }
yihui 1:a607cd9655d7 222 else
yihui 1:a607cd9655d7 223 {
yihui 1:a607cd9655d7 224 return NRF_ERROR_INVALID_DATA;
yihui 1:a607cd9655d7 225 }
yihui 1:a607cd9655d7 226 }
yihui 1:a607cd9655d7 227
yihui 1:a607cd9655d7 228
yihui 1:a607cd9655d7 229 /**@brief Function for storing the Bonding Information of the specified central to the flash.
yihui 1:a607cd9655d7 230 *
yihui 1:a607cd9655d7 231 * @param[in] p_bond Bonding information to be stored.
yihui 1:a607cd9655d7 232 *
yihui 1:a607cd9655d7 233 * @return NRF_SUCCESS on success, an error_code otherwise.
yihui 1:a607cd9655d7 234 */
yihui 1:a607cd9655d7 235 static uint32_t bond_info_store(central_bond_t * p_bond)
yihui 1:a607cd9655d7 236 {
yihui 1:a607cd9655d7 237 uint32_t err_code;
yihui 1:a607cd9655d7 238 pstorage_handle_t dest_block;
yihui 1:a607cd9655d7 239
yihui 1:a607cd9655d7 240 // Check if flash is full
yihui 1:a607cd9655d7 241 if (m_bond_info_in_flash_count >= MAX_BONDS_IN_FLASH)
yihui 1:a607cd9655d7 242 {
yihui 1:a607cd9655d7 243 return NRF_ERROR_NO_MEM;
yihui 1:a607cd9655d7 244 }
yihui 1:a607cd9655d7 245
yihui 1:a607cd9655d7 246 // Check if this is the first bond to be stored
yihui 1:a607cd9655d7 247 if (m_bond_info_in_flash_count == 0)
yihui 1:a607cd9655d7 248 {
yihui 1:a607cd9655d7 249 // Initialize CRC
yihui 1:a607cd9655d7 250 m_crc_bond_info = crc16_compute(NULL, 0, NULL);
yihui 1:a607cd9655d7 251 }
yihui 1:a607cd9655d7 252
yihui 1:a607cd9655d7 253 // Get block pointer from base
yihui 1:a607cd9655d7 254 err_code = pstorage_block_identifier_get(&mp_flash_bond_info,m_bond_info_in_flash_count,&dest_block);
yihui 1:a607cd9655d7 255 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 256 {
yihui 1:a607cd9655d7 257 return err_code;
yihui 1:a607cd9655d7 258 }
yihui 1:a607cd9655d7 259
yihui 1:a607cd9655d7 260 // Write Bonding Information
yihui 1:a607cd9655d7 261 err_code = pstorage_store(&dest_block,
yihui 1:a607cd9655d7 262 (uint8_t *)p_bond,
yihui 1:a607cd9655d7 263 sizeof(central_bond_t),
yihui 1:a607cd9655d7 264 sizeof(uint32_t));
yihui 1:a607cd9655d7 265
yihui 1:a607cd9655d7 266 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 267 {
yihui 1:a607cd9655d7 268 return err_code;
yihui 1:a607cd9655d7 269 }
yihui 1:a607cd9655d7 270 m_crc_bond_info = crc16_compute((uint8_t *)p_bond,
yihui 1:a607cd9655d7 271 sizeof(central_bond_t),
yihui 1:a607cd9655d7 272 &m_crc_bond_info);
yihui 1:a607cd9655d7 273
yihui 1:a607cd9655d7 274 // Write header
yihui 1:a607cd9655d7 275 m_bond_crc_array[m_bond_info_in_flash_count] = (BOND_MANAGER_DATA_SIGNATURE | m_crc_bond_info);
yihui 1:a607cd9655d7 276
yihui 1:a607cd9655d7 277 err_code = pstorage_store (&dest_block, (uint8_t *)&m_bond_crc_array[m_bond_info_in_flash_count],sizeof(uint32_t),0);
yihui 1:a607cd9655d7 278 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 279 {
yihui 1:a607cd9655d7 280 return err_code;
yihui 1:a607cd9655d7 281 }
yihui 1:a607cd9655d7 282
yihui 1:a607cd9655d7 283 m_bond_info_in_flash_count++;
yihui 1:a607cd9655d7 284 return NRF_SUCCESS;
yihui 1:a607cd9655d7 285 }
yihui 1:a607cd9655d7 286
yihui 1:a607cd9655d7 287
yihui 1:a607cd9655d7 288 /**@brief Function for storing the System Attributes related to a specified central in flash.
yihui 1:a607cd9655d7 289 *
yihui 1:a607cd9655d7 290 * @param[in] p_sys_attr System Attributes to be stored.
yihui 1:a607cd9655d7 291 *
yihui 1:a607cd9655d7 292 * @return NRF_SUCCESS on success, an error_code otherwise.
yihui 1:a607cd9655d7 293 */
yihui 1:a607cd9655d7 294 static uint32_t sys_attr_store(central_sys_attr_t * p_sys_attr)
yihui 1:a607cd9655d7 295 {
yihui 1:a607cd9655d7 296 uint32_t err_code;
yihui 1:a607cd9655d7 297 pstorage_handle_t dest_block;
yihui 1:a607cd9655d7 298
yihui 1:a607cd9655d7 299 // Check if flash is full.
yihui 1:a607cd9655d7 300 if (m_sys_attr_in_flash_count >= MAX_BONDS_IN_FLASH)
yihui 1:a607cd9655d7 301 {
yihui 1:a607cd9655d7 302 return NRF_ERROR_NO_MEM;
yihui 1:a607cd9655d7 303 }
yihui 1:a607cd9655d7 304
yihui 1:a607cd9655d7 305 // Check if this is the first time any System Attributes is stored.
yihui 1:a607cd9655d7 306 if (m_sys_attr_in_flash_count == 0)
yihui 1:a607cd9655d7 307 {
yihui 1:a607cd9655d7 308 // Initialize CRC
yihui 1:a607cd9655d7 309 m_crc_sys_attr = crc16_compute(NULL, 0, NULL);
yihui 1:a607cd9655d7 310 }
yihui 1:a607cd9655d7 311
yihui 1:a607cd9655d7 312
yihui 1:a607cd9655d7 313 // Get block pointer from base
yihui 1:a607cd9655d7 314 err_code = pstorage_block_identifier_get(&mp_flash_sys_attr,m_sys_attr_in_flash_count,&dest_block);
yihui 1:a607cd9655d7 315 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 316 {
yihui 1:a607cd9655d7 317 return err_code;
yihui 1:a607cd9655d7 318 }
yihui 1:a607cd9655d7 319
yihui 1:a607cd9655d7 320 // Write System Attributes in flash.
yihui 1:a607cd9655d7 321 err_code = pstorage_store(&dest_block,
yihui 1:a607cd9655d7 322 (uint8_t *)p_sys_attr,
yihui 1:a607cd9655d7 323 sizeof(central_sys_attr_t),
yihui 1:a607cd9655d7 324 sizeof(uint32_t));
yihui 1:a607cd9655d7 325
yihui 1:a607cd9655d7 326 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 327 {
yihui 1:a607cd9655d7 328 return err_code;
yihui 1:a607cd9655d7 329 }
yihui 1:a607cd9655d7 330 m_crc_sys_attr = crc16_compute((uint8_t *)p_sys_attr,
yihui 1:a607cd9655d7 331 sizeof(central_sys_attr_t),
yihui 1:a607cd9655d7 332 &m_crc_sys_attr);
yihui 1:a607cd9655d7 333
yihui 1:a607cd9655d7 334 // Write header.
yihui 1:a607cd9655d7 335 m_sys_crc_array[m_sys_attr_in_flash_count] = (BOND_MANAGER_DATA_SIGNATURE | m_crc_sys_attr);
yihui 1:a607cd9655d7 336
yihui 1:a607cd9655d7 337 err_code = pstorage_store (&dest_block,
yihui 1:a607cd9655d7 338 (uint8_t *)&m_sys_crc_array[m_sys_attr_in_flash_count],
yihui 1:a607cd9655d7 339 sizeof(uint32_t),
yihui 1:a607cd9655d7 340 0);
yihui 1:a607cd9655d7 341 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 342 {
yihui 1:a607cd9655d7 343 return err_code;
yihui 1:a607cd9655d7 344 }
yihui 1:a607cd9655d7 345
yihui 1:a607cd9655d7 346 m_sys_attr_in_flash_count++;
yihui 1:a607cd9655d7 347
yihui 1:a607cd9655d7 348
yihui 1:a607cd9655d7 349 return NRF_SUCCESS;
yihui 1:a607cd9655d7 350 }
yihui 1:a607cd9655d7 351
yihui 1:a607cd9655d7 352
yihui 1:a607cd9655d7 353 /**@brief Function for loading the Bonding Information of one central from flash.
yihui 1:a607cd9655d7 354 *
yihui 1:a607cd9655d7 355 * @param[out] p_bond Loaded Bonding Information.
yihui 1:a607cd9655d7 356 *
yihui 1:a607cd9655d7 357 * @return NRF_SUCCESS on success, otherwise an error code.
yihui 1:a607cd9655d7 358 */
yihui 1:a607cd9655d7 359 static uint32_t bonding_info_load_from_flash(central_bond_t * p_bond)
yihui 1:a607cd9655d7 360 {
yihui 1:a607cd9655d7 361 pstorage_handle_t source_block;
yihui 1:a607cd9655d7 362 uint32_t err_code;
yihui 1:a607cd9655d7 363 uint32_t crc;
yihui 1:a607cd9655d7 364 uint16_t crc_header;
yihui 1:a607cd9655d7 365
yihui 1:a607cd9655d7 366 // Check if this is the first bond to be loaded, in which case the
yihui 1:a607cd9655d7 367 // m_bond_info_in_flash_count variable would have the intial value 0.
yihui 1:a607cd9655d7 368 if (m_bond_info_in_flash_count == 0)
yihui 1:a607cd9655d7 369 {
yihui 1:a607cd9655d7 370 // Initialize CRC.
yihui 1:a607cd9655d7 371 m_crc_bond_info = crc16_compute(NULL, 0, NULL);
yihui 1:a607cd9655d7 372 }
yihui 1:a607cd9655d7 373
yihui 1:a607cd9655d7 374 // Get block pointer from base
yihui 1:a607cd9655d7 375 err_code = pstorage_block_identifier_get(&mp_flash_bond_info,
yihui 1:a607cd9655d7 376 m_bond_info_in_flash_count,
yihui 1:a607cd9655d7 377 &source_block);
yihui 1:a607cd9655d7 378 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 379 {
yihui 1:a607cd9655d7 380 return err_code;
yihui 1:a607cd9655d7 381 }
yihui 1:a607cd9655d7 382
yihui 1:a607cd9655d7 383 err_code = pstorage_load((uint8_t *)&crc, &source_block, sizeof(uint32_t), 0);
yihui 1:a607cd9655d7 384 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 385 {
yihui 1:a607cd9655d7 386 return err_code;
yihui 1:a607cd9655d7 387 }
yihui 1:a607cd9655d7 388
yihui 1:a607cd9655d7 389 // Extract CRC from header.
yihui 1:a607cd9655d7 390 err_code = crc_extract(crc, &crc_header);
yihui 1:a607cd9655d7 391 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 392 {
yihui 1:a607cd9655d7 393 return err_code;
yihui 1:a607cd9655d7 394 }
yihui 1:a607cd9655d7 395
yihui 1:a607cd9655d7 396 // Load central.
yihui 1:a607cd9655d7 397 err_code = pstorage_load((uint8_t *)p_bond,
yihui 1:a607cd9655d7 398 &source_block,
yihui 1:a607cd9655d7 399 sizeof(central_bond_t),
yihui 1:a607cd9655d7 400 sizeof(uint32_t));
yihui 1:a607cd9655d7 401 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 402 {
yihui 1:a607cd9655d7 403 return err_code;
yihui 1:a607cd9655d7 404 }
yihui 1:a607cd9655d7 405
yihui 1:a607cd9655d7 406 // Check CRC.
yihui 1:a607cd9655d7 407 m_crc_bond_info = crc16_compute((uint8_t *)p_bond,
yihui 1:a607cd9655d7 408 sizeof(central_bond_t),
yihui 1:a607cd9655d7 409 &m_crc_bond_info);
yihui 1:a607cd9655d7 410 if (m_crc_bond_info == crc_header)
yihui 1:a607cd9655d7 411 {
yihui 1:a607cd9655d7 412 m_bond_info_in_flash_count++;
yihui 1:a607cd9655d7 413 return NRF_SUCCESS;
yihui 1:a607cd9655d7 414 }
yihui 1:a607cd9655d7 415 else
yihui 1:a607cd9655d7 416 {
yihui 1:a607cd9655d7 417 return NRF_ERROR_INVALID_DATA;
yihui 1:a607cd9655d7 418 }
yihui 1:a607cd9655d7 419 }
yihui 1:a607cd9655d7 420
yihui 1:a607cd9655d7 421
yihui 1:a607cd9655d7 422
yihui 1:a607cd9655d7 423 /**@brief Function for loading the System Attributes related to one central from flash.
yihui 1:a607cd9655d7 424 *
yihui 1:a607cd9655d7 425 * @param[out] p_sys_attr Loaded System Attributes.
yihui 1:a607cd9655d7 426 *
yihui 1:a607cd9655d7 427 * @return NRF_SUCCESS on success, otherwise an error code.
yihui 1:a607cd9655d7 428 */
yihui 1:a607cd9655d7 429 static uint32_t sys_attr_load_from_flash(central_sys_attr_t * p_sys_attr)
yihui 1:a607cd9655d7 430 {
yihui 1:a607cd9655d7 431 pstorage_handle_t source_block;
yihui 1:a607cd9655d7 432 uint32_t err_code;
yihui 1:a607cd9655d7 433 uint32_t crc;
yihui 1:a607cd9655d7 434 uint16_t crc_header;
yihui 1:a607cd9655d7 435
yihui 1:a607cd9655d7 436 // Check if this is the first time System Attributes is loaded from flash, in which case the
yihui 1:a607cd9655d7 437 // m_sys_attr_in_flash_count variable would have the initial value 0.
yihui 1:a607cd9655d7 438 if (m_sys_attr_in_flash_count == 0)
yihui 1:a607cd9655d7 439 {
yihui 1:a607cd9655d7 440 // Initialize CRC.
yihui 1:a607cd9655d7 441 m_crc_sys_attr = crc16_compute(NULL, 0, NULL);
yihui 1:a607cd9655d7 442 }
yihui 1:a607cd9655d7 443
yihui 1:a607cd9655d7 444 // Get block pointer from base
yihui 1:a607cd9655d7 445 err_code = pstorage_block_identifier_get(&mp_flash_sys_attr,
yihui 1:a607cd9655d7 446 m_sys_attr_in_flash_count,
yihui 1:a607cd9655d7 447 &source_block);
yihui 1:a607cd9655d7 448 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 449 {
yihui 1:a607cd9655d7 450 return err_code;
yihui 1:a607cd9655d7 451 }
yihui 1:a607cd9655d7 452
yihui 1:a607cd9655d7 453 err_code = pstorage_load((uint8_t *)&crc, &source_block, sizeof(uint32_t), 0);
yihui 1:a607cd9655d7 454 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 455 {
yihui 1:a607cd9655d7 456 return err_code;
yihui 1:a607cd9655d7 457 }
yihui 1:a607cd9655d7 458
yihui 1:a607cd9655d7 459 // Extract CRC from header.
yihui 1:a607cd9655d7 460 err_code = crc_extract(crc, &crc_header);
yihui 1:a607cd9655d7 461 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 462 {
yihui 1:a607cd9655d7 463 return err_code;
yihui 1:a607cd9655d7 464 }
yihui 1:a607cd9655d7 465
yihui 1:a607cd9655d7 466 err_code = pstorage_load((uint8_t *)p_sys_attr,
yihui 1:a607cd9655d7 467 &source_block,
yihui 1:a607cd9655d7 468 sizeof(central_sys_attr_t),
yihui 1:a607cd9655d7 469 sizeof(uint32_t));
yihui 1:a607cd9655d7 470 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 471 {
yihui 1:a607cd9655d7 472 return err_code;
yihui 1:a607cd9655d7 473 }
yihui 1:a607cd9655d7 474
yihui 1:a607cd9655d7 475 // Check CRC.
yihui 1:a607cd9655d7 476 m_crc_sys_attr = crc16_compute((uint8_t *)p_sys_attr,
yihui 1:a607cd9655d7 477 sizeof(central_sys_attr_t),
yihui 1:a607cd9655d7 478 &m_crc_sys_attr);
yihui 1:a607cd9655d7 479
yihui 1:a607cd9655d7 480 if (m_crc_sys_attr == crc_header)
yihui 1:a607cd9655d7 481 {
yihui 1:a607cd9655d7 482 m_sys_attr_in_flash_count++;
yihui 1:a607cd9655d7 483 return NRF_SUCCESS;
yihui 1:a607cd9655d7 484 }
yihui 1:a607cd9655d7 485 else
yihui 1:a607cd9655d7 486 {
yihui 1:a607cd9655d7 487 return NRF_ERROR_INVALID_DATA;
yihui 1:a607cd9655d7 488 }
yihui 1:a607cd9655d7 489 }
yihui 1:a607cd9655d7 490
yihui 1:a607cd9655d7 491
yihui 1:a607cd9655d7 492 /**@brief Function for erasing the flash pages that contain Bonding Information and System
yihui 1:a607cd9655d7 493 * Attributes.
yihui 1:a607cd9655d7 494 *
yihui 1:a607cd9655d7 495 * @return NRF_SUCCESS on success, otherwise an error code.
yihui 1:a607cd9655d7 496 */
yihui 1:a607cd9655d7 497 static uint32_t flash_pages_erase(void)
yihui 1:a607cd9655d7 498 {
yihui 1:a607cd9655d7 499 uint32_t err_code;
yihui 1:a607cd9655d7 500
yihui 1:a607cd9655d7 501 err_code = pstorage_clear(&mp_flash_bond_info, MAX_BONDS_IN_FLASH);
yihui 1:a607cd9655d7 502
yihui 1:a607cd9655d7 503 if (err_code == NRF_SUCCESS)
yihui 1:a607cd9655d7 504 {
yihui 1:a607cd9655d7 505 err_code = pstorage_clear(&mp_flash_sys_attr, MAX_BONDS_IN_FLASH);
yihui 1:a607cd9655d7 506 }
yihui 1:a607cd9655d7 507
yihui 1:a607cd9655d7 508 return err_code;
yihui 1:a607cd9655d7 509 }
yihui 1:a607cd9655d7 510
yihui 1:a607cd9655d7 511
yihui 1:a607cd9655d7 512 /**@brief Function for checking if Bonding Information in RAM is different from that in
yihui 1:a607cd9655d7 513 * flash.
yihui 1:a607cd9655d7 514 *
yihui 1:a607cd9655d7 515 * @return TRUE if Bonding Information in flash and RAM are different, FALSE otherwise.
yihui 1:a607cd9655d7 516 */
yihui 1:a607cd9655d7 517 static bool bond_info_changed(void)
yihui 1:a607cd9655d7 518 {
yihui 1:a607cd9655d7 519 int i;
yihui 1:a607cd9655d7 520 uint16_t crc = crc16_compute(NULL, 0, NULL);
yihui 1:a607cd9655d7 521
yihui 1:a607cd9655d7 522 // Compute CRC for all bonds in database.
yihui 1:a607cd9655d7 523 for (i = 0; i < m_centrals_in_db_count; i++)
yihui 1:a607cd9655d7 524 {
yihui 1:a607cd9655d7 525 crc = crc16_compute((uint8_t *)&m_centrals_db[i].bond,
yihui 1:a607cd9655d7 526 sizeof(central_bond_t),
yihui 1:a607cd9655d7 527 &crc);
yihui 1:a607cd9655d7 528 }
yihui 1:a607cd9655d7 529
yihui 1:a607cd9655d7 530 // Compare the computed CRS to CRC stored in flash.
yihui 1:a607cd9655d7 531 return (crc != m_crc_bond_info);
yihui 1:a607cd9655d7 532 }
yihui 1:a607cd9655d7 533
yihui 1:a607cd9655d7 534
yihui 1:a607cd9655d7 535 /**@brief Function for checking if System Attributes in RAM is different from that in flash.
yihui 1:a607cd9655d7 536 *
yihui 1:a607cd9655d7 537 * @return TRUE if System Attributes in flash and RAM are different, FALSE otherwise.
yihui 1:a607cd9655d7 538 */
yihui 1:a607cd9655d7 539 static bool sys_attr_changed(void)
yihui 1:a607cd9655d7 540 {
yihui 1:a607cd9655d7 541 int i;
yihui 1:a607cd9655d7 542 uint16_t crc = crc16_compute(NULL, 0, NULL);
yihui 1:a607cd9655d7 543
yihui 1:a607cd9655d7 544 // Compute CRC for all System Attributes in database.
yihui 1:a607cd9655d7 545 for (i = 0; i < m_centrals_in_db_count; i++)
yihui 1:a607cd9655d7 546 {
yihui 1:a607cd9655d7 547 crc = crc16_compute((uint8_t *)&m_centrals_db[i].sys_attr,
yihui 1:a607cd9655d7 548 sizeof(central_sys_attr_t),
yihui 1:a607cd9655d7 549 &crc);
yihui 1:a607cd9655d7 550 }
yihui 1:a607cd9655d7 551
yihui 1:a607cd9655d7 552 // Compare the CRC of System Attributes in flash with that of the System Attributes in memory.
yihui 1:a607cd9655d7 553 return (crc != m_crc_sys_attr);
yihui 1:a607cd9655d7 554 }
yihui 1:a607cd9655d7 555
yihui 1:a607cd9655d7 556
yihui 1:a607cd9655d7 557 /**@brief Function for setting the System Attributes for specified central to the SoftDevice, or
yihui 1:a607cd9655d7 558 * clearing the System Attributes if central is a previously unknown.
yihui 1:a607cd9655d7 559 *
yihui 1:a607cd9655d7 560 * @param[in] p_central Central for which the System Attributes is to be set.
yihui 1:a607cd9655d7 561 *
yihui 1:a607cd9655d7 562 * @return NRF_SUCCESS on success, otherwise an error code.
yihui 1:a607cd9655d7 563 */
yihui 1:a607cd9655d7 564 static uint32_t central_sys_attr_set(central_t * p_central)
yihui 1:a607cd9655d7 565 {
yihui 1:a607cd9655d7 566 uint8_t * p_sys_attr;
yihui 1:a607cd9655d7 567
yihui 1:a607cd9655d7 568 if (m_central.sys_attr.sys_attr_size != 0)
yihui 1:a607cd9655d7 569 {
yihui 1:a607cd9655d7 570 if (m_central.sys_attr.sys_attr_size > SYS_ATTR_BUFFER_MAX_LEN)
yihui 1:a607cd9655d7 571 {
yihui 1:a607cd9655d7 572 return NRF_ERROR_INTERNAL;
yihui 1:a607cd9655d7 573 }
yihui 1:a607cd9655d7 574
yihui 1:a607cd9655d7 575 p_sys_attr = m_central.sys_attr.sys_attr;
yihui 1:a607cd9655d7 576 }
yihui 1:a607cd9655d7 577 else
yihui 1:a607cd9655d7 578 {
yihui 1:a607cd9655d7 579 p_sys_attr = NULL;
yihui 1:a607cd9655d7 580 }
yihui 1:a607cd9655d7 581
yihui 1:a607cd9655d7 582 return sd_ble_gatts_sys_attr_set(m_conn_handle, p_sys_attr, m_central.sys_attr.sys_attr_size);
yihui 1:a607cd9655d7 583 }
yihui 1:a607cd9655d7 584
yihui 1:a607cd9655d7 585
yihui 1:a607cd9655d7 586 /**@brief Function for updating the whitelist data structures.
yihui 1:a607cd9655d7 587 */
yihui 1:a607cd9655d7 588 static void update_whitelist(void)
yihui 1:a607cd9655d7 589 {
yihui 1:a607cd9655d7 590 int i;
yihui 1:a607cd9655d7 591
yihui 1:a607cd9655d7 592 for (i = 0, m_addr_count = 0, m_irk_count = 0; i < m_centrals_in_db_count; i++)
yihui 1:a607cd9655d7 593 {
yihui 1:a607cd9655d7 594 central_bond_t * p_bond = &m_centrals_db[i].bond;
yihui 1:a607cd9655d7 595
yihui 1:a607cd9655d7 596 if (p_bond->auth_status.central_kex.irk)
yihui 1:a607cd9655d7 597 {
yihui 1:a607cd9655d7 598 m_whitelist_irk[m_irk_count].central_handle = p_bond->central_handle;
yihui 1:a607cd9655d7 599 m_whitelist_irk[m_irk_count].p_irk = &(p_bond->auth_status.central_keys.irk);
yihui 1:a607cd9655d7 600
yihui 1:a607cd9655d7 601 m_irk_count++;
yihui 1:a607cd9655d7 602 }
yihui 1:a607cd9655d7 603
yihui 1:a607cd9655d7 604 if (p_bond->central_addr.addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE)
yihui 1:a607cd9655d7 605 {
yihui 1:a607cd9655d7 606 m_whitelist_addr[m_addr_count].central_handle = p_bond->central_handle;
yihui 1:a607cd9655d7 607 m_whitelist_addr[m_addr_count].p_addr = &(p_bond->central_addr);
yihui 1:a607cd9655d7 608
yihui 1:a607cd9655d7 609 m_addr_count++;
yihui 1:a607cd9655d7 610 }
yihui 1:a607cd9655d7 611 }
yihui 1:a607cd9655d7 612 }
yihui 1:a607cd9655d7 613
yihui 1:a607cd9655d7 614
yihui 1:a607cd9655d7 615 /**@brief Function for handling the authentication status event related to a new central.
yihui 1:a607cd9655d7 616 *
yihui 1:a607cd9655d7 617 * @details This function adds the new central to the database and stores the central's Bonding
yihui 1:a607cd9655d7 618 * Information to flash. It also notifies the application when the new bond is created,
yihui 1:a607cd9655d7 619 * and sets the System Attributes to prepare the stack for connection with the new
yihui 1:a607cd9655d7 620 * central.
yihui 1:a607cd9655d7 621 *
yihui 1:a607cd9655d7 622 * @param[in] p_auth_status New authentication status.
yihui 1:a607cd9655d7 623 *
yihui 1:a607cd9655d7 624 * @return NRF_SUCCESS on success, otherwise an error code.
yihui 1:a607cd9655d7 625 */
yihui 1:a607cd9655d7 626 static uint32_t on_auth_status_from_new_central(ble_gap_evt_auth_status_t * p_auth_status)
yihui 1:a607cd9655d7 627 {
yihui 1:a607cd9655d7 628 uint32_t err_code;
yihui 1:a607cd9655d7 629
yihui 1:a607cd9655d7 630 if (m_centrals_in_db_count >= BLE_BONDMNGR_MAX_BONDED_CENTRALS)
yihui 1:a607cd9655d7 631 {
yihui 1:a607cd9655d7 632 return NRF_ERROR_NO_MEM;
yihui 1:a607cd9655d7 633 }
yihui 1:a607cd9655d7 634
yihui 1:a607cd9655d7 635 // Update central.
yihui 1:a607cd9655d7 636 m_central.bond.auth_status = *p_auth_status;
yihui 1:a607cd9655d7 637 m_central.bond.central_id_info.div = p_auth_status->periph_keys.enc_info.div;
yihui 1:a607cd9655d7 638 m_central.sys_attr.sys_attr_size = 0;
yihui 1:a607cd9655d7 639
yihui 1:a607cd9655d7 640 // Add new central to database.
yihui 1:a607cd9655d7 641 m_central.bond.central_handle = m_centrals_in_db_count;
yihui 1:a607cd9655d7 642 m_centrals_db[m_centrals_in_db_count++] = m_central;
yihui 1:a607cd9655d7 643
yihui 1:a607cd9655d7 644 update_whitelist();
yihui 1:a607cd9655d7 645
yihui 1:a607cd9655d7 646 m_bond_loaded = true;
yihui 1:a607cd9655d7 647
yihui 1:a607cd9655d7 648 // Clear System Attributes.
yihui 1:a607cd9655d7 649 err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0);
yihui 1:a607cd9655d7 650 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 651 {
yihui 1:a607cd9655d7 652 return err_code;
yihui 1:a607cd9655d7 653 }
yihui 1:a607cd9655d7 654
yihui 1:a607cd9655d7 655 // Write new central's Bonding Information to flash.
yihui 1:a607cd9655d7 656 err_code = bond_info_store(&m_central.bond);
yihui 1:a607cd9655d7 657 if ((err_code == NRF_ERROR_NO_MEM) && (m_bondmngr_config.evt_handler != NULL))
yihui 1:a607cd9655d7 658 {
yihui 1:a607cd9655d7 659 ble_bondmngr_evt_t evt;
yihui 1:a607cd9655d7 660
yihui 1:a607cd9655d7 661 evt.evt_type = BLE_BONDMNGR_EVT_BOND_FLASH_FULL;
yihui 1:a607cd9655d7 662 evt.central_handle = m_central.bond.central_handle;
yihui 1:a607cd9655d7 663 evt.central_id = m_central.bond.central_id_info.div;
yihui 1:a607cd9655d7 664
yihui 1:a607cd9655d7 665 m_bondmngr_config.evt_handler(&evt);
yihui 1:a607cd9655d7 666 }
yihui 1:a607cd9655d7 667 else if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 668 {
yihui 1:a607cd9655d7 669 return err_code;
yihui 1:a607cd9655d7 670 }
yihui 1:a607cd9655d7 671
yihui 1:a607cd9655d7 672 // Pass the event to application.
yihui 1:a607cd9655d7 673 if (m_bondmngr_config.evt_handler != NULL)
yihui 1:a607cd9655d7 674 {
yihui 1:a607cd9655d7 675 ble_bondmngr_evt_t evt;
yihui 1:a607cd9655d7 676
yihui 1:a607cd9655d7 677 evt.evt_type = BLE_BONDMNGR_EVT_NEW_BOND;
yihui 1:a607cd9655d7 678 evt.central_handle = m_central.bond.central_handle;
yihui 1:a607cd9655d7 679 evt.central_id = m_central.bond.central_id_info.div;
yihui 1:a607cd9655d7 680
yihui 1:a607cd9655d7 681 m_bondmngr_config.evt_handler(&evt);
yihui 1:a607cd9655d7 682 }
yihui 1:a607cd9655d7 683
yihui 1:a607cd9655d7 684 return NRF_SUCCESS;
yihui 1:a607cd9655d7 685 }
yihui 1:a607cd9655d7 686
yihui 1:a607cd9655d7 687
yihui 1:a607cd9655d7 688 /**@brief Function for updating the current central's entry in the database.
yihui 1:a607cd9655d7 689 */
yihui 1:a607cd9655d7 690 static uint32_t central_update(void)
yihui 1:a607cd9655d7 691 {
yihui 1:a607cd9655d7 692 uint32_t err_code;
yihui 1:a607cd9655d7 693 int32_t central_handle = m_central.bond.central_handle;
yihui 1:a607cd9655d7 694
yihui 1:a607cd9655d7 695 if ((central_handle >= 0) && (central_handle < m_centrals_in_db_count))
yihui 1:a607cd9655d7 696 {
yihui 1:a607cd9655d7 697 // Update the database based on whether the bond and system attributes have
yihui 1:a607cd9655d7 698 // been loaded or not to avoid overwriting information that was not used in the
yihui 1:a607cd9655d7 699 // connection session.
yihui 1:a607cd9655d7 700 if (m_bond_loaded)
yihui 1:a607cd9655d7 701 {
yihui 1:a607cd9655d7 702 m_centrals_db[central_handle].bond = m_central.bond;
yihui 1:a607cd9655d7 703 }
yihui 1:a607cd9655d7 704
yihui 1:a607cd9655d7 705 if (m_sys_attr_loaded)
yihui 1:a607cd9655d7 706 {
yihui 1:a607cd9655d7 707 m_centrals_db[central_handle].sys_attr = m_central.sys_attr;
yihui 1:a607cd9655d7 708 }
yihui 1:a607cd9655d7 709
yihui 1:a607cd9655d7 710 update_whitelist();
yihui 1:a607cd9655d7 711
yihui 1:a607cd9655d7 712 err_code = NRF_SUCCESS;
yihui 1:a607cd9655d7 713 }
yihui 1:a607cd9655d7 714 else
yihui 1:a607cd9655d7 715 {
yihui 1:a607cd9655d7 716 err_code = NRF_ERROR_INTERNAL;
yihui 1:a607cd9655d7 717 }
yihui 1:a607cd9655d7 718
yihui 1:a607cd9655d7 719 return err_code;
yihui 1:a607cd9655d7 720 }
yihui 1:a607cd9655d7 721
yihui 1:a607cd9655d7 722
yihui 1:a607cd9655d7 723 /**@brief Function for searching for the central in the database of known centrals.
yihui 1:a607cd9655d7 724 *
yihui 1:a607cd9655d7 725 * @details If the central is found, the variable m_central will be populated with all the
yihui 1:a607cd9655d7 726 * information (Bonding Information and System Attributes) related to that central.
yihui 1:a607cd9655d7 727 *
yihui 1:a607cd9655d7 728 * @param[in] central_id Central Identifier.
yihui 1:a607cd9655d7 729 * @return NRF_SUCCESS on success, otherwise an error code.
yihui 1:a607cd9655d7 730 */
yihui 1:a607cd9655d7 731 static uint32_t central_find_in_db(uint16_t central_id)
yihui 1:a607cd9655d7 732 {
yihui 1:a607cd9655d7 733 int i;
yihui 1:a607cd9655d7 734
yihui 1:a607cd9655d7 735 for (i = 0; i < m_centrals_in_db_count; i++)
yihui 1:a607cd9655d7 736 {
yihui 1:a607cd9655d7 737 if (central_id == m_centrals_db[i].bond.central_id_info.div)
yihui 1:a607cd9655d7 738 {
yihui 1:a607cd9655d7 739 m_central = m_centrals_db[i];
yihui 1:a607cd9655d7 740 return NRF_SUCCESS;
yihui 1:a607cd9655d7 741 }
yihui 1:a607cd9655d7 742 }
yihui 1:a607cd9655d7 743
yihui 1:a607cd9655d7 744 return NRF_ERROR_NOT_FOUND;
yihui 1:a607cd9655d7 745 }
yihui 1:a607cd9655d7 746
yihui 1:a607cd9655d7 747
yihui 1:a607cd9655d7 748 /**@brief Function for loading all Bonding Information and System Attributes from flash.
yihui 1:a607cd9655d7 749 *
yihui 1:a607cd9655d7 750 * @return NRF_SUCCESS on success, otherwise an error code.
yihui 1:a607cd9655d7 751 */
yihui 1:a607cd9655d7 752 static uint32_t load_all_from_flash(void)
yihui 1:a607cd9655d7 753 {
yihui 1:a607cd9655d7 754 uint32_t err_code;
yihui 1:a607cd9655d7 755 int i;
yihui 1:a607cd9655d7 756
yihui 1:a607cd9655d7 757 m_centrals_in_db_count = 0;
yihui 1:a607cd9655d7 758
yihui 1:a607cd9655d7 759 while (m_centrals_in_db_count < BLE_BONDMNGR_MAX_BONDED_CENTRALS)
yihui 1:a607cd9655d7 760 {
yihui 1:a607cd9655d7 761 central_bond_t central_bond_info;
yihui 1:a607cd9655d7 762 int central_handle;
yihui 1:a607cd9655d7 763
yihui 1:a607cd9655d7 764 // Load Bonding Information.
yihui 1:a607cd9655d7 765 err_code = bonding_info_load_from_flash(&central_bond_info);
yihui 1:a607cd9655d7 766 if (err_code == NRF_ERROR_NOT_FOUND)
yihui 1:a607cd9655d7 767 {
yihui 1:a607cd9655d7 768 // No more bonds in flash.
yihui 1:a607cd9655d7 769 break;
yihui 1:a607cd9655d7 770 }
yihui 1:a607cd9655d7 771 else if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 772 {
yihui 1:a607cd9655d7 773 return err_code;
yihui 1:a607cd9655d7 774 }
yihui 1:a607cd9655d7 775
yihui 1:a607cd9655d7 776 central_handle = central_bond_info.central_handle;
yihui 1:a607cd9655d7 777 if (central_handle > m_centrals_in_db_count)
yihui 1:a607cd9655d7 778 {
yihui 1:a607cd9655d7 779 // Central handle value(s) missing in flash. This should never happen.
yihui 1:a607cd9655d7 780 return NRF_ERROR_INVALID_DATA;
yihui 1:a607cd9655d7 781 }
yihui 1:a607cd9655d7 782 else
yihui 1:a607cd9655d7 783 {
yihui 1:a607cd9655d7 784 // Add/update Bonding Information in central array.
yihui 1:a607cd9655d7 785 m_centrals_db[central_handle].bond = central_bond_info;
yihui 1:a607cd9655d7 786 if (central_handle == m_centrals_in_db_count)
yihui 1:a607cd9655d7 787 {
yihui 1:a607cd9655d7 788 // New central handle, clear System Attributes.
yihui 1:a607cd9655d7 789 m_centrals_db[central_handle].sys_attr.sys_attr_size = 0;
yihui 1:a607cd9655d7 790 m_centrals_db[central_handle].sys_attr.central_handle = INVALID_CENTRAL_HANDLE;
yihui 1:a607cd9655d7 791 m_centrals_in_db_count++;
yihui 1:a607cd9655d7 792 }
yihui 1:a607cd9655d7 793 else
yihui 1:a607cd9655d7 794 {
yihui 1:a607cd9655d7 795 // Entry was updated, do nothing.
yihui 1:a607cd9655d7 796 }
yihui 1:a607cd9655d7 797 }
yihui 1:a607cd9655d7 798 }
yihui 1:a607cd9655d7 799
yihui 1:a607cd9655d7 800 // Load System Attributes for all previously known centrals.
yihui 1:a607cd9655d7 801 for (i = 0; i < m_centrals_in_db_count; i++)
yihui 1:a607cd9655d7 802 {
yihui 1:a607cd9655d7 803 central_sys_attr_t central_sys_attr;
yihui 1:a607cd9655d7 804
yihui 1:a607cd9655d7 805 // Load System Attributes.
yihui 1:a607cd9655d7 806 err_code = sys_attr_load_from_flash(&central_sys_attr);
yihui 1:a607cd9655d7 807 if (err_code == NRF_ERROR_NOT_FOUND)
yihui 1:a607cd9655d7 808 {
yihui 1:a607cd9655d7 809 // No more System Attributes in flash.
yihui 1:a607cd9655d7 810 break;
yihui 1:a607cd9655d7 811 }
yihui 1:a607cd9655d7 812 else if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 813 {
yihui 1:a607cd9655d7 814 return err_code;
yihui 1:a607cd9655d7 815 }
yihui 1:a607cd9655d7 816
yihui 1:a607cd9655d7 817 if (central_sys_attr.central_handle > m_centrals_in_db_count)
yihui 1:a607cd9655d7 818 {
yihui 1:a607cd9655d7 819 // Central handle value(s) missing in flash. This should never happen.
yihui 1:a607cd9655d7 820 return NRF_ERROR_INVALID_DATA;
yihui 1:a607cd9655d7 821 }
yihui 1:a607cd9655d7 822 else
yihui 1:a607cd9655d7 823 {
yihui 1:a607cd9655d7 824 // Add/update Bonding Information in central array.
yihui 1:a607cd9655d7 825 m_centrals_db[central_sys_attr.central_handle].sys_attr = central_sys_attr;
yihui 1:a607cd9655d7 826 }
yihui 1:a607cd9655d7 827 }
yihui 1:a607cd9655d7 828
yihui 1:a607cd9655d7 829 // Initialize the remaining empty bond entries in the memory.
yihui 1:a607cd9655d7 830 for (i = m_centrals_in_db_count; i < BLE_BONDMNGR_MAX_BONDED_CENTRALS; i++)
yihui 1:a607cd9655d7 831 {
yihui 1:a607cd9655d7 832 m_centrals_db[i].bond.central_handle = INVALID_CENTRAL_HANDLE;
yihui 1:a607cd9655d7 833 m_centrals_db[i].sys_attr.sys_attr_size = 0;
yihui 1:a607cd9655d7 834 m_centrals_db[i].sys_attr.central_handle = INVALID_CENTRAL_HANDLE;
yihui 1:a607cd9655d7 835 }
yihui 1:a607cd9655d7 836
yihui 1:a607cd9655d7 837 // Update whitelist data structures.
yihui 1:a607cd9655d7 838 update_whitelist();
yihui 1:a607cd9655d7 839
yihui 1:a607cd9655d7 840 return NRF_SUCCESS;
yihui 1:a607cd9655d7 841 }
yihui 1:a607cd9655d7 842
yihui 1:a607cd9655d7 843
yihui 1:a607cd9655d7 844 /**@brief Function for handling the connected event received from the BLE stack.
yihui 1:a607cd9655d7 845 *
yihui 1:a607cd9655d7 846 * @param[in] p_ble_evt Event received from the BLE stack.
yihui 1:a607cd9655d7 847 */
yihui 1:a607cd9655d7 848 static void on_connect(ble_evt_t * p_ble_evt)
yihui 1:a607cd9655d7 849 {
yihui 1:a607cd9655d7 850 m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
yihui 1:a607cd9655d7 851
yihui 1:a607cd9655d7 852 m_central.bond.central_handle = INVALID_CENTRAL_HANDLE;
yihui 1:a607cd9655d7 853 m_central.bond.central_addr = p_ble_evt->evt.gap_evt.params.connected.peer_addr;
yihui 1:a607cd9655d7 854 m_central.sys_attr.sys_attr_size = 0;
yihui 1:a607cd9655d7 855
yihui 1:a607cd9655d7 856 if (p_ble_evt->evt.gap_evt.params.connected.irk_match)
yihui 1:a607cd9655d7 857 {
yihui 1:a607cd9655d7 858 uint8_t irk_idx = p_ble_evt->evt.gap_evt.params.connected.irk_match_idx;
yihui 1:a607cd9655d7 859
yihui 1:a607cd9655d7 860 if ((irk_idx >= MAX_NUM_CENTRAL_WHITE_LIST) ||
yihui 1:a607cd9655d7 861 (m_whitelist_irk[irk_idx].central_handle >= BLE_BONDMNGR_MAX_BONDED_CENTRALS))
yihui 1:a607cd9655d7 862 {
yihui 1:a607cd9655d7 863 m_bondmngr_config.error_handler(NRF_ERROR_INTERNAL);
yihui 1:a607cd9655d7 864 }
yihui 1:a607cd9655d7 865 else
yihui 1:a607cd9655d7 866 {
yihui 1:a607cd9655d7 867 m_central = m_centrals_db[m_whitelist_irk[irk_idx].central_handle];
yihui 1:a607cd9655d7 868 }
yihui 1:a607cd9655d7 869 }
yihui 1:a607cd9655d7 870 else
yihui 1:a607cd9655d7 871 {
yihui 1:a607cd9655d7 872 int i;
yihui 1:a607cd9655d7 873
yihui 1:a607cd9655d7 874 for (i = 0; i < m_addr_count; i++)
yihui 1:a607cd9655d7 875 {
yihui 1:a607cd9655d7 876 ble_gap_addr_t * p_cur_addr = m_whitelist_addr[i].p_addr;
yihui 1:a607cd9655d7 877
yihui 1:a607cd9655d7 878 if (memcmp(p_cur_addr->addr, m_central.bond.central_addr.addr, BLE_GAP_ADDR_LEN) == 0)
yihui 1:a607cd9655d7 879 {
yihui 1:a607cd9655d7 880 m_central = m_centrals_db[m_whitelist_addr[i].central_handle];
yihui 1:a607cd9655d7 881 break;
yihui 1:a607cd9655d7 882 }
yihui 1:a607cd9655d7 883 }
yihui 1:a607cd9655d7 884 }
yihui 1:a607cd9655d7 885
yihui 1:a607cd9655d7 886 if (m_central.bond.central_handle != INVALID_CENTRAL_HANDLE)
yihui 1:a607cd9655d7 887 {
yihui 1:a607cd9655d7 888 // Reset bond and system attributes loaded variables.
yihui 1:a607cd9655d7 889 m_bond_loaded = false;
yihui 1:a607cd9655d7 890 m_sys_attr_loaded = false;
yihui 1:a607cd9655d7 891
yihui 1:a607cd9655d7 892 // Do not set the system attributes of the central on connection.
yihui 1:a607cd9655d7 893 if (m_bondmngr_config.evt_handler != NULL)
yihui 1:a607cd9655d7 894 {
yihui 1:a607cd9655d7 895 ble_bondmngr_evt_t evt;
yihui 1:a607cd9655d7 896
yihui 1:a607cd9655d7 897 evt.evt_type = BLE_BONDMNGR_EVT_CONN_TO_BONDED_CENTRAL;
yihui 1:a607cd9655d7 898 evt.central_handle = m_central.bond.central_handle;
yihui 1:a607cd9655d7 899 evt.central_id = m_central.bond.central_id_info.div;
yihui 1:a607cd9655d7 900
yihui 1:a607cd9655d7 901 m_bondmngr_config.evt_handler(&evt);
yihui 1:a607cd9655d7 902 }
yihui 1:a607cd9655d7 903 }
yihui 1:a607cd9655d7 904 }
yihui 1:a607cd9655d7 905
yihui 1:a607cd9655d7 906
yihui 1:a607cd9655d7 907 /**@brief Function for handling the 'System Attributes Missing' event received from the
yihui 1:a607cd9655d7 908 * SoftDevice.
yihui 1:a607cd9655d7 909 *
yihui 1:a607cd9655d7 910 * @param[in] p_ble_evt Event received from the BLE stack.
yihui 1:a607cd9655d7 911 */
yihui 1:a607cd9655d7 912 static void on_sys_attr_missing(ble_evt_t * p_ble_evt)
yihui 1:a607cd9655d7 913 {
yihui 1:a607cd9655d7 914 uint32_t err_code;
yihui 1:a607cd9655d7 915
yihui 1:a607cd9655d7 916 if (
yihui 1:a607cd9655d7 917 (m_central.bond.central_handle == INVALID_CENTRAL_HANDLE) ||
yihui 1:a607cd9655d7 918 !ENCRYPTION_STATUS_GET() ||
yihui 1:a607cd9655d7 919 BONDING_IN_PROGRESS_STATUS_GET()
yihui 1:a607cd9655d7 920 )
yihui 1:a607cd9655d7 921 {
yihui 1:a607cd9655d7 922 err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0);
yihui 1:a607cd9655d7 923 }
yihui 1:a607cd9655d7 924 else
yihui 1:a607cd9655d7 925 {
yihui 1:a607cd9655d7 926 // Current central is valid, use its data. Set the corresponding sys_attr.
yihui 1:a607cd9655d7 927 err_code = central_sys_attr_set(&m_central);
yihui 1:a607cd9655d7 928 if (err_code == NRF_SUCCESS)
yihui 1:a607cd9655d7 929 {
yihui 1:a607cd9655d7 930 // Set System Attributes loaded status variable.
yihui 1:a607cd9655d7 931 m_sys_attr_loaded = true;
yihui 1:a607cd9655d7 932 }
yihui 1:a607cd9655d7 933 }
yihui 1:a607cd9655d7 934
yihui 1:a607cd9655d7 935 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 936 {
yihui 1:a607cd9655d7 937 m_bondmngr_config.error_handler(err_code);
yihui 1:a607cd9655d7 938 }
yihui 1:a607cd9655d7 939 }
yihui 1:a607cd9655d7 940
yihui 1:a607cd9655d7 941
yihui 1:a607cd9655d7 942 /**@brief Function for handling the new authentication status event, received from the
yihui 1:a607cd9655d7 943 * SoftDevice, related to an already bonded central.
yihui 1:a607cd9655d7 944 *
yihui 1:a607cd9655d7 945 * @details This function also writes the updated Bonding Information to flash and notifies the
yihui 1:a607cd9655d7 946 * application.
yihui 1:a607cd9655d7 947 *
yihui 1:a607cd9655d7 948 * @param[in] p_auth_status Updated authentication status.
yihui 1:a607cd9655d7 949 */
yihui 1:a607cd9655d7 950 static void auth_status_update(ble_gap_evt_auth_status_t * p_auth_status)
yihui 1:a607cd9655d7 951 {
yihui 1:a607cd9655d7 952 uint32_t err_code;
yihui 1:a607cd9655d7 953
yihui 1:a607cd9655d7 954 // Authentication status changed, update Bonding Information.
yihui 1:a607cd9655d7 955 m_central.bond.auth_status = *p_auth_status;
yihui 1:a607cd9655d7 956 m_central.bond.central_id_info.div = p_auth_status->periph_keys.enc_info.div;
yihui 1:a607cd9655d7 957
yihui 1:a607cd9655d7 958 memset(&(m_centrals_db[m_central.bond.central_handle]), 0, sizeof(central_t));
yihui 1:a607cd9655d7 959 m_centrals_db[m_central.bond.central_handle] = m_central;
yihui 1:a607cd9655d7 960
yihui 1:a607cd9655d7 961 // Write updated Bonding Information to flash.
yihui 1:a607cd9655d7 962 err_code = bond_info_store(&m_central.bond);
yihui 1:a607cd9655d7 963 if ((err_code == NRF_ERROR_NO_MEM) && (m_bondmngr_config.evt_handler != NULL))
yihui 1:a607cd9655d7 964 {
yihui 1:a607cd9655d7 965 ble_bondmngr_evt_t evt;
yihui 1:a607cd9655d7 966
yihui 1:a607cd9655d7 967 evt.evt_type = BLE_BONDMNGR_EVT_BOND_FLASH_FULL;
yihui 1:a607cd9655d7 968 evt.central_handle = m_central.bond.central_handle;
yihui 1:a607cd9655d7 969 evt.central_id = m_central.bond.central_id_info.div;
yihui 1:a607cd9655d7 970
yihui 1:a607cd9655d7 971 m_bondmngr_config.evt_handler(&evt);
yihui 1:a607cd9655d7 972 }
yihui 1:a607cd9655d7 973 else if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 974 {
yihui 1:a607cd9655d7 975 m_bondmngr_config.error_handler(err_code);
yihui 1:a607cd9655d7 976 }
yihui 1:a607cd9655d7 977
yihui 1:a607cd9655d7 978 // Pass the event to the application.
yihui 1:a607cd9655d7 979 if (m_bondmngr_config.evt_handler != NULL)
yihui 1:a607cd9655d7 980 {
yihui 1:a607cd9655d7 981 ble_bondmngr_evt_t evt;
yihui 1:a607cd9655d7 982
yihui 1:a607cd9655d7 983 evt.evt_type = BLE_BONDMNGR_EVT_AUTH_STATUS_UPDATED;
yihui 1:a607cd9655d7 984 evt.central_handle = m_central.bond.central_handle;
yihui 1:a607cd9655d7 985 evt.central_id = m_central.bond.central_id_info.div;
yihui 1:a607cd9655d7 986
yihui 1:a607cd9655d7 987 m_bondmngr_config.evt_handler(&evt);
yihui 1:a607cd9655d7 988 }
yihui 1:a607cd9655d7 989 }
yihui 1:a607cd9655d7 990
yihui 1:a607cd9655d7 991
yihui 1:a607cd9655d7 992 /**@brief Function for handling the Authentication Status event received from the BLE stack.
yihui 1:a607cd9655d7 993 *
yihui 1:a607cd9655d7 994 * @param[in] p_ble_evt Event received from the BLE stack.
yihui 1:a607cd9655d7 995 */
yihui 1:a607cd9655d7 996 static void on_auth_status(ble_gap_evt_auth_status_t * p_auth_status)
yihui 1:a607cd9655d7 997 {
yihui 1:a607cd9655d7 998 if (p_auth_status->auth_status != BLE_GAP_SEC_STATUS_SUCCESS)
yihui 1:a607cd9655d7 999 {
yihui 1:a607cd9655d7 1000 return;
yihui 1:a607cd9655d7 1001 }
yihui 1:a607cd9655d7 1002
yihui 1:a607cd9655d7 1003 // Verify if its pairing and not bonding
yihui 1:a607cd9655d7 1004 if (!ENCRYPTION_STATUS_GET())
yihui 1:a607cd9655d7 1005 {
yihui 1:a607cd9655d7 1006 return;
yihui 1:a607cd9655d7 1007 }
yihui 1:a607cd9655d7 1008
yihui 1:a607cd9655d7 1009 if (m_central.bond.central_handle == INVALID_CENTRAL_HANDLE)
yihui 1:a607cd9655d7 1010 {
yihui 1:a607cd9655d7 1011 uint32_t err_code = central_find_in_db(p_auth_status->periph_keys.enc_info.div);
yihui 1:a607cd9655d7 1012
yihui 1:a607cd9655d7 1013 if (err_code == NRF_SUCCESS)
yihui 1:a607cd9655d7 1014 {
yihui 1:a607cd9655d7 1015 // Possible DIV Collision indicate error to application,
yihui 1:a607cd9655d7 1016 // not storing the new LTK
yihui 1:a607cd9655d7 1017 err_code = NRF_ERROR_FORBIDDEN;
yihui 1:a607cd9655d7 1018 }
yihui 1:a607cd9655d7 1019 else
yihui 1:a607cd9655d7 1020 {
yihui 1:a607cd9655d7 1021 // Add the new device to data base
yihui 1:a607cd9655d7 1022 err_code = on_auth_status_from_new_central(p_auth_status);
yihui 1:a607cd9655d7 1023 }
yihui 1:a607cd9655d7 1024
yihui 1:a607cd9655d7 1025 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1026 {
yihui 1:a607cd9655d7 1027 m_bondmngr_config.error_handler(err_code);
yihui 1:a607cd9655d7 1028 }
yihui 1:a607cd9655d7 1029 }
yihui 1:a607cd9655d7 1030 else
yihui 1:a607cd9655d7 1031 {
yihui 1:a607cd9655d7 1032 m_bond_loaded = true;
yihui 1:a607cd9655d7 1033
yihui 1:a607cd9655d7 1034 // Receiving a auth status again when already in have existing information!
yihui 1:a607cd9655d7 1035 auth_status_update(p_auth_status);
yihui 1:a607cd9655d7 1036 }
yihui 1:a607cd9655d7 1037 }
yihui 1:a607cd9655d7 1038
yihui 1:a607cd9655d7 1039
yihui 1:a607cd9655d7 1040 /**@brief Function for handling the Security Info Request event received from the BLE stack.
yihui 1:a607cd9655d7 1041 *
yihui 1:a607cd9655d7 1042 * @param[in] p_ble_evt Event received from the BLE stack.
yihui 1:a607cd9655d7 1043 */
yihui 1:a607cd9655d7 1044 static void on_sec_info_request(ble_evt_t * p_ble_evt)
yihui 1:a607cd9655d7 1045 {
yihui 1:a607cd9655d7 1046 uint32_t err_code;
yihui 1:a607cd9655d7 1047
yihui 1:a607cd9655d7 1048 err_code = central_find_in_db(p_ble_evt->evt.gap_evt.params.sec_info_request.div);
yihui 1:a607cd9655d7 1049 if (err_code == NRF_SUCCESS)
yihui 1:a607cd9655d7 1050 {
yihui 1:a607cd9655d7 1051 // Bond information has been found and loaded for security procedures. Reflect this in the
yihui 1:a607cd9655d7 1052 // status variable
yihui 1:a607cd9655d7 1053 m_bond_loaded = true;
yihui 1:a607cd9655d7 1054
yihui 1:a607cd9655d7 1055 // Central found in the list of bonded central. Use the encryption info for this central.
yihui 1:a607cd9655d7 1056 err_code = sd_ble_gap_sec_info_reply(m_conn_handle,
yihui 1:a607cd9655d7 1057 &m_central.bond.auth_status.periph_keys.enc_info,
yihui 1:a607cd9655d7 1058 NULL);
yihui 1:a607cd9655d7 1059 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1060 {
yihui 1:a607cd9655d7 1061 m_bondmngr_config.error_handler(err_code);
yihui 1:a607cd9655d7 1062 }
yihui 1:a607cd9655d7 1063
yihui 1:a607cd9655d7 1064 // Do not set the sys_attr yet, should be set only when sec_update is successful.
yihui 1:a607cd9655d7 1065 }
yihui 1:a607cd9655d7 1066 else if (err_code == NRF_ERROR_NOT_FOUND)
yihui 1:a607cd9655d7 1067 {
yihui 1:a607cd9655d7 1068 m_central.bond.central_id_info = p_ble_evt->evt.gap_evt.params.sec_info_request;
yihui 1:a607cd9655d7 1069
yihui 1:a607cd9655d7 1070 // New central.
yihui 1:a607cd9655d7 1071 err_code = sd_ble_gap_sec_info_reply(m_conn_handle, NULL, NULL);
yihui 1:a607cd9655d7 1072 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1073 {
yihui 1:a607cd9655d7 1074 m_bondmngr_config.error_handler(err_code);
yihui 1:a607cd9655d7 1075 }
yihui 1:a607cd9655d7 1076
yihui 1:a607cd9655d7 1077 // Initialize the sys_attr.
yihui 1:a607cd9655d7 1078 err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0);
yihui 1:a607cd9655d7 1079 }
yihui 1:a607cd9655d7 1080
yihui 1:a607cd9655d7 1081 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1082 {
yihui 1:a607cd9655d7 1083 m_bondmngr_config.error_handler(err_code);
yihui 1:a607cd9655d7 1084 }
yihui 1:a607cd9655d7 1085 }
yihui 1:a607cd9655d7 1086
yihui 1:a607cd9655d7 1087
yihui 1:a607cd9655d7 1088 /**@brief Function for handling the Connection Security Update event received from the BLE
yihui 1:a607cd9655d7 1089 * stack.
yihui 1:a607cd9655d7 1090 *
yihui 1:a607cd9655d7 1091 * @param[in] p_ble_evt Event received from the BLE stack.
yihui 1:a607cd9655d7 1092 */
yihui 1:a607cd9655d7 1093 static void on_sec_update(ble_gap_evt_conn_sec_update_t * p_sec_update)
yihui 1:a607cd9655d7 1094 {
yihui 1:a607cd9655d7 1095 uint8_t security_mode = p_sec_update->conn_sec.sec_mode.sm;
yihui 1:a607cd9655d7 1096 uint8_t security_level = p_sec_update->conn_sec.sec_mode.lv;
yihui 1:a607cd9655d7 1097
yihui 1:a607cd9655d7 1098 if (((security_mode == 1) && (security_level > 1)) ||
yihui 1:a607cd9655d7 1099 ((security_mode == 2) && (security_level != 0)))
yihui 1:a607cd9655d7 1100 {
yihui 1:a607cd9655d7 1101 ENCRYPTION_STATUS_SET();
yihui 1:a607cd9655d7 1102
yihui 1:a607cd9655d7 1103 uint32_t err_code = central_sys_attr_set(&m_central);
yihui 1:a607cd9655d7 1104
yihui 1:a607cd9655d7 1105 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1106 {
yihui 1:a607cd9655d7 1107 m_bondmngr_config.error_handler(err_code);
yihui 1:a607cd9655d7 1108 }
yihui 1:a607cd9655d7 1109 else
yihui 1:a607cd9655d7 1110 {
yihui 1:a607cd9655d7 1111 m_sys_attr_loaded = true;
yihui 1:a607cd9655d7 1112 }
yihui 1:a607cd9655d7 1113
yihui 1:a607cd9655d7 1114 if (m_bondmngr_config.evt_handler != NULL)
yihui 1:a607cd9655d7 1115 {
yihui 1:a607cd9655d7 1116 ble_bondmngr_evt_t evt;
yihui 1:a607cd9655d7 1117
yihui 1:a607cd9655d7 1118 evt.evt_type = BLE_BONDMNGR_EVT_ENCRYPTED;
yihui 1:a607cd9655d7 1119 evt.central_handle = m_central.bond.central_handle;
yihui 1:a607cd9655d7 1120 evt.central_id = m_central.bond.central_id_info.div;
yihui 1:a607cd9655d7 1121
yihui 1:a607cd9655d7 1122 m_bondmngr_config.evt_handler(&evt);
yihui 1:a607cd9655d7 1123 }
yihui 1:a607cd9655d7 1124 }
yihui 1:a607cd9655d7 1125 }
yihui 1:a607cd9655d7 1126
yihui 1:a607cd9655d7 1127
yihui 1:a607cd9655d7 1128 /**@brief Function for handling the Connection Security Parameters Request event received from
yihui 1:a607cd9655d7 1129 * the BLE stack.
yihui 1:a607cd9655d7 1130 *
yihui 1:a607cd9655d7 1131 * @param[in] p_ble_evt Event received from the BLE stack.
yihui 1:a607cd9655d7 1132 */
yihui 1:a607cd9655d7 1133 static void on_sec_param_request(ble_gap_evt_sec_params_request_t * p_sec_update)
yihui 1:a607cd9655d7 1134 {
yihui 1:a607cd9655d7 1135 if (p_sec_update->peer_params.bond)
yihui 1:a607cd9655d7 1136 {
yihui 1:a607cd9655d7 1137 BONDING_IN_PROGRESS_STATUS_SET();
yihui 1:a607cd9655d7 1138
yihui 1:a607cd9655d7 1139 if (m_central.bond.central_handle != INVALID_CENTRAL_HANDLE)
yihui 1:a607cd9655d7 1140 {
yihui 1:a607cd9655d7 1141 // Bonding request received from a bonded central, make all system attributes null
yihui 1:a607cd9655d7 1142 m_central.sys_attr.sys_attr_size = 0;
yihui 1:a607cd9655d7 1143 memset(m_central.sys_attr.sys_attr, 0, SYS_ATTR_BUFFER_MAX_LEN);
yihui 1:a607cd9655d7 1144 }
yihui 1:a607cd9655d7 1145 }
yihui 1:a607cd9655d7 1146 }
yihui 1:a607cd9655d7 1147
yihui 1:a607cd9655d7 1148
yihui 1:a607cd9655d7 1149 void ble_bondmngr_on_ble_evt(ble_evt_t * p_ble_evt)
yihui 1:a607cd9655d7 1150 {
yihui 1:a607cd9655d7 1151 if (!m_is_bondmngr_initialized)
yihui 1:a607cd9655d7 1152 {
yihui 1:a607cd9655d7 1153 m_bondmngr_config.error_handler(NRF_ERROR_INVALID_STATE);
yihui 1:a607cd9655d7 1154 }
yihui 1:a607cd9655d7 1155
yihui 1:a607cd9655d7 1156 switch (p_ble_evt->header.evt_id)
yihui 1:a607cd9655d7 1157 {
yihui 1:a607cd9655d7 1158 case BLE_GAP_EVT_CONNECTED:
yihui 1:a607cd9655d7 1159 on_connect(p_ble_evt);
yihui 1:a607cd9655d7 1160 break;
yihui 1:a607cd9655d7 1161
yihui 1:a607cd9655d7 1162 // NOTE: All actions to be taken on the Disconnected event are performed in
yihui 1:a607cd9655d7 1163 // ble_bondmngr_bonded_centrals_store(). This function must be called from the
yihui 1:a607cd9655d7 1164 // Disconnected handler of the application before advertising is restarted (to make
yihui 1:a607cd9655d7 1165 // sure the flash blocks are cleared while the radio is inactive).
yihui 1:a607cd9655d7 1166 case BLE_GAP_EVT_DISCONNECTED:
yihui 1:a607cd9655d7 1167 SECURITY_STATUS_RESET();
yihui 1:a607cd9655d7 1168 break;
yihui 1:a607cd9655d7 1169
yihui 1:a607cd9655d7 1170 case BLE_GATTS_EVT_SYS_ATTR_MISSING:
yihui 1:a607cd9655d7 1171 on_sys_attr_missing(p_ble_evt);
yihui 1:a607cd9655d7 1172 break;
yihui 1:a607cd9655d7 1173
yihui 1:a607cd9655d7 1174 case BLE_GAP_EVT_AUTH_STATUS:
yihui 1:a607cd9655d7 1175 on_auth_status(&p_ble_evt->evt.gap_evt.params.auth_status);
yihui 1:a607cd9655d7 1176 break;
yihui 1:a607cd9655d7 1177
yihui 1:a607cd9655d7 1178 case BLE_GAP_EVT_SEC_INFO_REQUEST:
yihui 1:a607cd9655d7 1179 on_sec_info_request(p_ble_evt);
yihui 1:a607cd9655d7 1180 break;
yihui 1:a607cd9655d7 1181
yihui 1:a607cd9655d7 1182 case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
yihui 1:a607cd9655d7 1183 on_sec_param_request(&p_ble_evt->evt.gap_evt.params.sec_params_request);
yihui 1:a607cd9655d7 1184 break;
yihui 1:a607cd9655d7 1185
yihui 1:a607cd9655d7 1186 case BLE_GAP_EVT_CONN_SEC_UPDATE:
yihui 1:a607cd9655d7 1187 on_sec_update(&p_ble_evt->evt.gap_evt.params.conn_sec_update);
yihui 1:a607cd9655d7 1188 break;
yihui 1:a607cd9655d7 1189
yihui 1:a607cd9655d7 1190 default:
yihui 1:a607cd9655d7 1191 // No implementation needed.
yihui 1:a607cd9655d7 1192 break;
yihui 1:a607cd9655d7 1193 }
yihui 1:a607cd9655d7 1194 }
yihui 1:a607cd9655d7 1195
yihui 1:a607cd9655d7 1196
yihui 1:a607cd9655d7 1197 uint32_t ble_bondmngr_bonded_centrals_store(void)
yihui 1:a607cd9655d7 1198 {
yihui 1:a607cd9655d7 1199 uint32_t err_code;
yihui 1:a607cd9655d7 1200 int i;
yihui 1:a607cd9655d7 1201
yihui 1:a607cd9655d7 1202 VERIFY_MODULE_INITIALIZED();
yihui 1:a607cd9655d7 1203
yihui 1:a607cd9655d7 1204 if (m_central.bond.central_handle != INVALID_CENTRAL_HANDLE)
yihui 1:a607cd9655d7 1205 {
yihui 1:a607cd9655d7 1206 // Fetch System Attributes from stack.
yihui 1:a607cd9655d7 1207 uint16_t sys_attr_size = SYS_ATTR_BUFFER_MAX_LEN;
yihui 1:a607cd9655d7 1208
yihui 1:a607cd9655d7 1209 err_code = sd_ble_gatts_sys_attr_get(m_conn_handle,
yihui 1:a607cd9655d7 1210 m_central.sys_attr.sys_attr,
yihui 1:a607cd9655d7 1211 &sys_attr_size);
yihui 1:a607cd9655d7 1212 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1213 {
yihui 1:a607cd9655d7 1214 return err_code;
yihui 1:a607cd9655d7 1215 }
yihui 1:a607cd9655d7 1216
yihui 1:a607cd9655d7 1217 m_central.sys_attr.central_handle = m_central.bond.central_handle;
yihui 1:a607cd9655d7 1218 m_central.sys_attr.sys_attr_size = (uint16_t)sys_attr_size;
yihui 1:a607cd9655d7 1219
yihui 1:a607cd9655d7 1220 // Update the current central.
yihui 1:a607cd9655d7 1221 err_code = central_update();
yihui 1:a607cd9655d7 1222 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1223 {
yihui 1:a607cd9655d7 1224 return err_code;
yihui 1:a607cd9655d7 1225 }
yihui 1:a607cd9655d7 1226 }
yihui 1:a607cd9655d7 1227
yihui 1:a607cd9655d7 1228 // Save Bonding Information if changed.
yihui 1:a607cd9655d7 1229 if (bond_info_changed())
yihui 1:a607cd9655d7 1230 {
yihui 1:a607cd9655d7 1231 // Erase flash page.
yihui 1:a607cd9655d7 1232 err_code = pstorage_clear(&mp_flash_bond_info,MAX_BONDS_IN_FLASH);
yihui 1:a607cd9655d7 1233 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1234 {
yihui 1:a607cd9655d7 1235 return err_code;
yihui 1:a607cd9655d7 1236 }
yihui 1:a607cd9655d7 1237
yihui 1:a607cd9655d7 1238 // Store bond information for all centrals.
yihui 1:a607cd9655d7 1239 m_bond_info_in_flash_count = 0;
yihui 1:a607cd9655d7 1240 for (i = 0; i < m_centrals_in_db_count; i++)
yihui 1:a607cd9655d7 1241 {
yihui 1:a607cd9655d7 1242 err_code = bond_info_store(&m_centrals_db[i].bond);
yihui 1:a607cd9655d7 1243 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1244 {
yihui 1:a607cd9655d7 1245 return err_code;
yihui 1:a607cd9655d7 1246 }
yihui 1:a607cd9655d7 1247 }
yihui 1:a607cd9655d7 1248 }
yihui 1:a607cd9655d7 1249
yihui 1:a607cd9655d7 1250 // Save System Attributes, if changed.
yihui 1:a607cd9655d7 1251 if (sys_attr_changed())
yihui 1:a607cd9655d7 1252 {
yihui 1:a607cd9655d7 1253 // Erase flash page.
yihui 1:a607cd9655d7 1254 err_code = pstorage_clear(&mp_flash_sys_attr, MAX_BONDS_IN_FLASH);
yihui 1:a607cd9655d7 1255 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1256 {
yihui 1:a607cd9655d7 1257 return err_code;
yihui 1:a607cd9655d7 1258 }
yihui 1:a607cd9655d7 1259
yihui 1:a607cd9655d7 1260 // Store System Attributes for all centrals.
yihui 1:a607cd9655d7 1261 m_sys_attr_in_flash_count = 0;
yihui 1:a607cd9655d7 1262 for (i = 0; i < m_centrals_in_db_count; i++)
yihui 1:a607cd9655d7 1263 {
yihui 1:a607cd9655d7 1264 err_code = sys_attr_store(&m_centrals_db[i].sys_attr);
yihui 1:a607cd9655d7 1265 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1266 {
yihui 1:a607cd9655d7 1267 return err_code;
yihui 1:a607cd9655d7 1268 }
yihui 1:a607cd9655d7 1269 }
yihui 1:a607cd9655d7 1270 }
yihui 1:a607cd9655d7 1271
yihui 1:a607cd9655d7 1272 m_conn_handle = BLE_CONN_HANDLE_INVALID;
yihui 1:a607cd9655d7 1273 m_central.bond.central_handle = INVALID_CENTRAL_HANDLE;
yihui 1:a607cd9655d7 1274 m_central.sys_attr.central_handle = INVALID_CENTRAL_HANDLE;
yihui 1:a607cd9655d7 1275 m_central.sys_attr.sys_attr_size = 0;
yihui 1:a607cd9655d7 1276 m_bond_loaded = false;
yihui 1:a607cd9655d7 1277 m_sys_attr_loaded = false;
yihui 1:a607cd9655d7 1278
yihui 1:a607cd9655d7 1279 return NRF_SUCCESS;
yihui 1:a607cd9655d7 1280 }
yihui 1:a607cd9655d7 1281
yihui 1:a607cd9655d7 1282
yihui 1:a607cd9655d7 1283 uint32_t ble_bondmngr_sys_attr_store(void)
yihui 1:a607cd9655d7 1284 {
yihui 1:a607cd9655d7 1285 uint32_t err_code;
yihui 1:a607cd9655d7 1286
yihui 1:a607cd9655d7 1287 if (m_central.sys_attr.sys_attr_size == 0)
yihui 1:a607cd9655d7 1288 {
yihui 1:a607cd9655d7 1289 // Connected to new central. So the flash block for System Attributes for this
yihui 1:a607cd9655d7 1290 // central is empty. Hence no erase is needed.
yihui 1:a607cd9655d7 1291
yihui 1:a607cd9655d7 1292 uint16_t sys_attr_size = SYS_ATTR_BUFFER_MAX_LEN;
yihui 1:a607cd9655d7 1293
yihui 1:a607cd9655d7 1294 // Fetch System Attributes from stack.
yihui 1:a607cd9655d7 1295 err_code = sd_ble_gatts_sys_attr_get(m_conn_handle,
yihui 1:a607cd9655d7 1296 m_central.sys_attr.sys_attr,
yihui 1:a607cd9655d7 1297 &sys_attr_size);
yihui 1:a607cd9655d7 1298
yihui 1:a607cd9655d7 1299 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1300 {
yihui 1:a607cd9655d7 1301 return err_code;
yihui 1:a607cd9655d7 1302 }
yihui 1:a607cd9655d7 1303
yihui 1:a607cd9655d7 1304 m_central.sys_attr.central_handle = m_central.bond.central_handle;
yihui 1:a607cd9655d7 1305 m_central.sys_attr.sys_attr_size = (uint16_t)sys_attr_size;
yihui 1:a607cd9655d7 1306
yihui 1:a607cd9655d7 1307 // Copy the System Attributes to database.
yihui 1:a607cd9655d7 1308 m_centrals_db[m_central.bond.central_handle].sys_attr = m_central.sys_attr;
yihui 1:a607cd9655d7 1309
yihui 1:a607cd9655d7 1310 // Write new central's System Attributes to flash.
yihui 1:a607cd9655d7 1311 return (sys_attr_store(&m_central.sys_attr));
yihui 1:a607cd9655d7 1312 }
yihui 1:a607cd9655d7 1313 else
yihui 1:a607cd9655d7 1314 {
yihui 1:a607cd9655d7 1315 // Will not write to flash because System Attributes of an old central would already be
yihui 1:a607cd9655d7 1316 // in flash and so this operation needs a flash erase operation.
yihui 1:a607cd9655d7 1317 return NRF_ERROR_INVALID_STATE;
yihui 1:a607cd9655d7 1318 }
yihui 1:a607cd9655d7 1319 }
yihui 1:a607cd9655d7 1320
yihui 1:a607cd9655d7 1321
yihui 1:a607cd9655d7 1322 uint32_t ble_bondmngr_bonded_centrals_delete(void)
yihui 1:a607cd9655d7 1323 {
yihui 1:a607cd9655d7 1324 VERIFY_MODULE_INITIALIZED();
yihui 1:a607cd9655d7 1325
yihui 1:a607cd9655d7 1326 m_centrals_in_db_count = 0;
yihui 1:a607cd9655d7 1327 m_bond_info_in_flash_count = 0;
yihui 1:a607cd9655d7 1328 m_sys_attr_in_flash_count = 0;
yihui 1:a607cd9655d7 1329
yihui 1:a607cd9655d7 1330 return flash_pages_erase();
yihui 1:a607cd9655d7 1331 }
yihui 1:a607cd9655d7 1332
yihui 1:a607cd9655d7 1333
yihui 1:a607cd9655d7 1334 uint32_t ble_bondmngr_central_addr_get(int8_t central_handle, ble_gap_addr_t * p_central_addr)
yihui 1:a607cd9655d7 1335 {
yihui 1:a607cd9655d7 1336 if (
yihui 1:a607cd9655d7 1337 (central_handle == INVALID_CENTRAL_HANDLE) ||
yihui 1:a607cd9655d7 1338 (central_handle >= m_centrals_in_db_count) ||
yihui 1:a607cd9655d7 1339 (p_central_addr == NULL) ||
yihui 1:a607cd9655d7 1340 (
yihui 1:a607cd9655d7 1341 m_centrals_db[central_handle].bond.central_addr.addr_type
yihui 1:a607cd9655d7 1342 ==
yihui 1:a607cd9655d7 1343 BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE
yihui 1:a607cd9655d7 1344 )
yihui 1:a607cd9655d7 1345 )
yihui 1:a607cd9655d7 1346 {
yihui 1:a607cd9655d7 1347 return NRF_ERROR_INVALID_PARAM;
yihui 1:a607cd9655d7 1348 }
yihui 1:a607cd9655d7 1349
yihui 1:a607cd9655d7 1350 *p_central_addr = m_centrals_db[central_handle].bond.central_addr;
yihui 1:a607cd9655d7 1351 return NRF_SUCCESS;
yihui 1:a607cd9655d7 1352 }
yihui 1:a607cd9655d7 1353
yihui 1:a607cd9655d7 1354
yihui 1:a607cd9655d7 1355 uint32_t ble_bondmngr_whitelist_get(ble_gap_whitelist_t * p_whitelist)
yihui 1:a607cd9655d7 1356 {
yihui 1:a607cd9655d7 1357 static ble_gap_addr_t * s_addr[MAX_NUM_CENTRAL_WHITE_LIST];
yihui 1:a607cd9655d7 1358 static ble_gap_irk_t * s_irk[MAX_NUM_CENTRAL_WHITE_LIST];
yihui 1:a607cd9655d7 1359
yihui 1:a607cd9655d7 1360 int i;
yihui 1:a607cd9655d7 1361
yihui 1:a607cd9655d7 1362 for (i = 0; i < m_irk_count; i++)
yihui 1:a607cd9655d7 1363 {
yihui 1:a607cd9655d7 1364 s_irk[i] = m_whitelist_irk[i].p_irk;
yihui 1:a607cd9655d7 1365 }
yihui 1:a607cd9655d7 1366 for (i = 0; i < m_addr_count; i++)
yihui 1:a607cd9655d7 1367 {
yihui 1:a607cd9655d7 1368 s_addr[i] = m_whitelist_addr[i].p_addr;
yihui 1:a607cd9655d7 1369 }
yihui 1:a607cd9655d7 1370
yihui 1:a607cd9655d7 1371 p_whitelist->addr_count = m_addr_count;
yihui 1:a607cd9655d7 1372 p_whitelist->pp_addrs = (m_addr_count != 0) ? s_addr : NULL;
yihui 1:a607cd9655d7 1373 p_whitelist->irk_count = m_irk_count;
yihui 1:a607cd9655d7 1374 p_whitelist->pp_irks = (m_irk_count != 0) ? s_irk : NULL;
yihui 1:a607cd9655d7 1375
yihui 1:a607cd9655d7 1376 return NRF_SUCCESS;
yihui 1:a607cd9655d7 1377 }
yihui 1:a607cd9655d7 1378
yihui 1:a607cd9655d7 1379
yihui 1:a607cd9655d7 1380 static void bm_pstorage_cb_handler(pstorage_handle_t * handle,
yihui 1:a607cd9655d7 1381 uint8_t op_code,
yihui 1:a607cd9655d7 1382 uint32_t result,
yihui 1:a607cd9655d7 1383 uint8_t * p_data,
yihui 1:a607cd9655d7 1384 uint32_t data_len)
yihui 1:a607cd9655d7 1385 {
yihui 1:a607cd9655d7 1386 if (result != NRF_SUCCESS)
yihui 1:a607cd9655d7 1387 {
yihui 1:a607cd9655d7 1388 m_bondmngr_config.error_handler(result);
yihui 1:a607cd9655d7 1389 }
yihui 1:a607cd9655d7 1390 }
yihui 1:a607cd9655d7 1391
yihui 1:a607cd9655d7 1392
yihui 1:a607cd9655d7 1393 uint32_t ble_bondmngr_init(ble_bondmngr_init_t * p_init)
yihui 1:a607cd9655d7 1394 {
yihui 1:a607cd9655d7 1395 pstorage_module_param_t param;
yihui 1:a607cd9655d7 1396 uint32_t err_code;
yihui 1:a607cd9655d7 1397
yihui 1:a607cd9655d7 1398 if (p_init->error_handler == NULL)
yihui 1:a607cd9655d7 1399 {
yihui 1:a607cd9655d7 1400 return NRF_ERROR_INVALID_PARAM;
yihui 1:a607cd9655d7 1401 }
yihui 1:a607cd9655d7 1402
yihui 1:a607cd9655d7 1403 if (BLE_BONDMNGR_MAX_BONDED_CENTRALS > MAX_BONDS_IN_FLASH)
yihui 1:a607cd9655d7 1404 {
yihui 1:a607cd9655d7 1405 return NRF_ERROR_DATA_SIZE;
yihui 1:a607cd9655d7 1406 }
yihui 1:a607cd9655d7 1407
yihui 1:a607cd9655d7 1408 param.block_size = sizeof (central_bond_t) + sizeof (uint32_t);
yihui 1:a607cd9655d7 1409 param.block_count = MAX_BONDS_IN_FLASH;
yihui 1:a607cd9655d7 1410 param.cb = bm_pstorage_cb_handler;
yihui 1:a607cd9655d7 1411
yihui 1:a607cd9655d7 1412 // Blocks are requested twice, once for bond information and once for system attributes.
yihui 1:a607cd9655d7 1413 // The number of blocks requested has to be the maximum number of bonded devices that
yihui 1:a607cd9655d7 1414 // need to be supported. However, the size of blocks can be different if the sizes of
yihui 1:a607cd9655d7 1415 // system attributes and bonds are not too close.
yihui 1:a607cd9655d7 1416 err_code = pstorage_register(&param, &mp_flash_bond_info);
yihui 1:a607cd9655d7 1417 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1418 {
yihui 1:a607cd9655d7 1419 return err_code;
yihui 1:a607cd9655d7 1420 }
yihui 1:a607cd9655d7 1421
yihui 1:a607cd9655d7 1422 param.block_size = sizeof(central_sys_attr_t) + sizeof(uint32_t);
yihui 1:a607cd9655d7 1423
yihui 1:a607cd9655d7 1424 err_code = pstorage_register(&param, &mp_flash_sys_attr);
yihui 1:a607cd9655d7 1425 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1426 {
yihui 1:a607cd9655d7 1427 return err_code;
yihui 1:a607cd9655d7 1428 }
yihui 1:a607cd9655d7 1429
yihui 1:a607cd9655d7 1430 m_bondmngr_config = *p_init;
yihui 1:a607cd9655d7 1431
yihui 1:a607cd9655d7 1432 memset(&m_central, 0, sizeof(central_t));
yihui 1:a607cd9655d7 1433
yihui 1:a607cd9655d7 1434 m_central.bond.central_handle = INVALID_CENTRAL_HANDLE;
yihui 1:a607cd9655d7 1435 m_conn_handle = BLE_CONN_HANDLE_INVALID;
yihui 1:a607cd9655d7 1436 m_centrals_in_db_count = 0;
yihui 1:a607cd9655d7 1437 m_bond_info_in_flash_count = 0;
yihui 1:a607cd9655d7 1438 m_sys_attr_in_flash_count = 0;
yihui 1:a607cd9655d7 1439
yihui 1:a607cd9655d7 1440 SECURITY_STATUS_RESET();
yihui 1:a607cd9655d7 1441
yihui 1:a607cd9655d7 1442 // Erase all stored centrals if specified.
yihui 1:a607cd9655d7 1443 if (m_bondmngr_config.bonds_delete)
yihui 1:a607cd9655d7 1444 {
yihui 1:a607cd9655d7 1445 err_code = flash_pages_erase();
yihui 1:a607cd9655d7 1446 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1447 {
yihui 1:a607cd9655d7 1448 return err_code;
yihui 1:a607cd9655d7 1449 }
yihui 1:a607cd9655d7 1450
yihui 1:a607cd9655d7 1451 m_centrals_in_db_count = 0;
yihui 1:a607cd9655d7 1452 int i;
yihui 1:a607cd9655d7 1453 for (i = m_centrals_in_db_count; i < BLE_BONDMNGR_MAX_BONDED_CENTRALS; i++)
yihui 1:a607cd9655d7 1454 {
yihui 1:a607cd9655d7 1455 m_centrals_db[i].bond.central_handle = INVALID_CENTRAL_HANDLE;
yihui 1:a607cd9655d7 1456 m_centrals_db[i].sys_attr.sys_attr_size = 0;
yihui 1:a607cd9655d7 1457 m_centrals_db[i].sys_attr.central_handle = INVALID_CENTRAL_HANDLE;
yihui 1:a607cd9655d7 1458 }
yihui 1:a607cd9655d7 1459 }
yihui 1:a607cd9655d7 1460 else
yihui 1:a607cd9655d7 1461 {
yihui 1:a607cd9655d7 1462 // Load bond manager data from flash.
yihui 1:a607cd9655d7 1463 err_code = load_all_from_flash();
yihui 1:a607cd9655d7 1464 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1465 {
yihui 1:a607cd9655d7 1466 return err_code;
yihui 1:a607cd9655d7 1467 }
yihui 1:a607cd9655d7 1468 }
yihui 1:a607cd9655d7 1469
yihui 1:a607cd9655d7 1470 m_is_bondmngr_initialized = true;
yihui 1:a607cd9655d7 1471
yihui 1:a607cd9655d7 1472 return NRF_SUCCESS;
yihui 1:a607cd9655d7 1473 }
yihui 1:a607cd9655d7 1474
yihui 1:a607cd9655d7 1475
yihui 1:a607cd9655d7 1476 uint32_t ble_bondmngr_central_ids_get(uint16_t * p_central_ids, uint16_t * p_length)
yihui 1:a607cd9655d7 1477 {
yihui 1:a607cd9655d7 1478 VERIFY_MODULE_INITIALIZED();
yihui 1:a607cd9655d7 1479 int i;
yihui 1:a607cd9655d7 1480 if (p_length == NULL)
yihui 1:a607cd9655d7 1481 {
yihui 1:a607cd9655d7 1482 return NRF_ERROR_NULL;
yihui 1:a607cd9655d7 1483 }
yihui 1:a607cd9655d7 1484
yihui 1:a607cd9655d7 1485 if (*p_length < m_centrals_in_db_count)
yihui 1:a607cd9655d7 1486 {
yihui 1:a607cd9655d7 1487 // Length of the input array is not enough to fit all known central identifiers.
yihui 1:a607cd9655d7 1488 return NRF_ERROR_DATA_SIZE;
yihui 1:a607cd9655d7 1489 }
yihui 1:a607cd9655d7 1490
yihui 1:a607cd9655d7 1491 *p_length = m_centrals_in_db_count;
yihui 1:a607cd9655d7 1492 if (p_central_ids == NULL)
yihui 1:a607cd9655d7 1493 {
yihui 1:a607cd9655d7 1494 // Only the length field was required to be filled.
yihui 1:a607cd9655d7 1495 return NRF_SUCCESS;
yihui 1:a607cd9655d7 1496 }
yihui 1:a607cd9655d7 1497
yihui 1:a607cd9655d7 1498 for (i = 0; i < m_centrals_in_db_count; i++)
yihui 1:a607cd9655d7 1499 {
yihui 1:a607cd9655d7 1500 p_central_ids[i] = m_centrals_db[i].bond.central_id_info.div;
yihui 1:a607cd9655d7 1501 }
yihui 1:a607cd9655d7 1502
yihui 1:a607cd9655d7 1503 return NRF_SUCCESS;
yihui 1:a607cd9655d7 1504 }
yihui 1:a607cd9655d7 1505
yihui 1:a607cd9655d7 1506
yihui 1:a607cd9655d7 1507 uint32_t ble_bondmngr_bonded_central_delete(uint16_t central_id)
yihui 1:a607cd9655d7 1508 {
yihui 1:a607cd9655d7 1509 VERIFY_MODULE_INITIALIZED();
yihui 1:a607cd9655d7 1510
yihui 1:a607cd9655d7 1511 int8_t central_handle_to_be_deleted = INVALID_CENTRAL_HANDLE;
yihui 1:a607cd9655d7 1512 uint8_t i;
yihui 1:a607cd9655d7 1513
yihui 1:a607cd9655d7 1514 // Search for the handle of the central.
yihui 1:a607cd9655d7 1515 for (i = 0; i < m_centrals_in_db_count; i++)
yihui 1:a607cd9655d7 1516 {
yihui 1:a607cd9655d7 1517 if (m_centrals_db[i].bond.central_id_info.div == central_id)
yihui 1:a607cd9655d7 1518 {
yihui 1:a607cd9655d7 1519 central_handle_to_be_deleted = i;
yihui 1:a607cd9655d7 1520 break;
yihui 1:a607cd9655d7 1521 }
yihui 1:a607cd9655d7 1522 }
yihui 1:a607cd9655d7 1523
yihui 1:a607cd9655d7 1524 if (central_handle_to_be_deleted == INVALID_CENTRAL_HANDLE)
yihui 1:a607cd9655d7 1525 {
yihui 1:a607cd9655d7 1526 // Central ID not found.
yihui 1:a607cd9655d7 1527 return NRF_ERROR_NOT_FOUND;
yihui 1:a607cd9655d7 1528 }
yihui 1:a607cd9655d7 1529
yihui 1:a607cd9655d7 1530 // Delete the central in RAM.
yihui 1:a607cd9655d7 1531 for (i = central_handle_to_be_deleted; i < (m_centrals_in_db_count - 1); i++)
yihui 1:a607cd9655d7 1532 {
yihui 1:a607cd9655d7 1533 // Overwrite the current central entry with the next one.
yihui 1:a607cd9655d7 1534 m_centrals_db[i] = m_centrals_db[i + 1];
yihui 1:a607cd9655d7 1535
yihui 1:a607cd9655d7 1536 // Decrement the value of handle.
yihui 1:a607cd9655d7 1537 m_centrals_db[i].bond.central_handle--;
yihui 1:a607cd9655d7 1538 if (INVALID_CENTRAL_HANDLE != m_centrals_db[i].sys_attr.central_handle)
yihui 1:a607cd9655d7 1539 {
yihui 1:a607cd9655d7 1540 m_centrals_db[i].sys_attr.central_handle--;
yihui 1:a607cd9655d7 1541 }
yihui 1:a607cd9655d7 1542 }
yihui 1:a607cd9655d7 1543
yihui 1:a607cd9655d7 1544 // Clear the last database entry.
yihui 1:a607cd9655d7 1545 memset(&(m_centrals_db[m_centrals_in_db_count - 1]), 0, sizeof(central_t));
yihui 1:a607cd9655d7 1546
yihui 1:a607cd9655d7 1547 m_centrals_in_db_count--;
yihui 1:a607cd9655d7 1548
yihui 1:a607cd9655d7 1549 uint32_t err_code;
yihui 1:a607cd9655d7 1550
yihui 1:a607cd9655d7 1551 // Reinitialize the pointers to the memory where bonding info and System Attributes are stored
yihui 1:a607cd9655d7 1552 // in flash.
yihui 1:a607cd9655d7 1553 // Refresh the data in the flash memory (both Bonding Information and System Attributes).
yihui 1:a607cd9655d7 1554 // Erase and rewrite bonding info and System Attributes.
yihui 1:a607cd9655d7 1555
yihui 1:a607cd9655d7 1556 err_code = flash_pages_erase();
yihui 1:a607cd9655d7 1557 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1558 {
yihui 1:a607cd9655d7 1559 return err_code;
yihui 1:a607cd9655d7 1560 }
yihui 1:a607cd9655d7 1561
yihui 1:a607cd9655d7 1562 m_bond_info_in_flash_count = 0;
yihui 1:a607cd9655d7 1563 m_sys_attr_in_flash_count = 0;
yihui 1:a607cd9655d7 1564
yihui 1:a607cd9655d7 1565 for (i = 0; i < m_centrals_in_db_count; i++)
yihui 1:a607cd9655d7 1566 {
yihui 1:a607cd9655d7 1567 err_code = bond_info_store(&(m_centrals_db[i].bond));
yihui 1:a607cd9655d7 1568 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1569 {
yihui 1:a607cd9655d7 1570 return err_code;
yihui 1:a607cd9655d7 1571 }
yihui 1:a607cd9655d7 1572 }
yihui 1:a607cd9655d7 1573
yihui 1:a607cd9655d7 1574 for (i = 0; i < m_centrals_in_db_count; i++)
yihui 1:a607cd9655d7 1575 {
yihui 1:a607cd9655d7 1576 err_code = sys_attr_store(&(m_centrals_db[i].sys_attr));
yihui 1:a607cd9655d7 1577 if (err_code != NRF_SUCCESS)
yihui 1:a607cd9655d7 1578 {
yihui 1:a607cd9655d7 1579 return err_code;
yihui 1:a607cd9655d7 1580 }
yihui 1:a607cd9655d7 1581 }
yihui 1:a607cd9655d7 1582
yihui 1:a607cd9655d7 1583 update_whitelist();
yihui 1:a607cd9655d7 1584
yihui 1:a607cd9655d7 1585 return NRF_SUCCESS;
yihui 1:a607cd9655d7 1586 }
yihui 1:a607cd9655d7 1587
yihui 1:a607cd9655d7 1588
yihui 1:a607cd9655d7 1589 uint32_t ble_bondmngr_is_link_encrypted (bool * status)
yihui 1:a607cd9655d7 1590 {
yihui 1:a607cd9655d7 1591 VERIFY_MODULE_INITIALIZED();
yihui 1:a607cd9655d7 1592
yihui 1:a607cd9655d7 1593 (*status) = ENCRYPTION_STATUS_GET();
yihui 1:a607cd9655d7 1594
yihui 1:a607cd9655d7 1595 return NRF_SUCCESS;
yihui 1:a607cd9655d7 1596 }
yihui 1:a607cd9655d7 1597
yihui 1:a607cd9655d7 1598 #endif /* #if NEED_BOND_MANAGER */