first commit

Dependencies:   mbed

Dependents:   ibeacon

Fork of BLE_WallbotBLE_Challenge by JKSoft

Committer:
jksoft
Date:
Wed Nov 12 02:40:34 2014 +0000
Revision:
0:76dfa9657d9d
????????

Who changed what in which revision?

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