mediCAL's first BLE project

Dependents:   BLE_mediCAL

Fork of nRF51822 by Nordic Semiconductor

Committer:
antoniorohit
Date:
Sun Nov 02 20:43:14 2014 +0000
Revision:
69:d9f51b65a3c8
Parent:
32:84dea0924a63
First rev of BLE program for nRF51822 which provides BLE connectivity for team mediCAL's PILLar;

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