Nordic stack and drivers for the mbed BLE API

Dependents:   idd_hw5_bleFanProto

Fork of nRF51822 by Nordic Semiconductor

Committer:
bogdanm
Date:
Wed Mar 26 14:38:17 2014 +0000
Revision:
0:eff01767de02
Child:
32:84dea0924a63
Initial import of the nRF51822 code

Who changed what in which revision?

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