SG RFID nRF51822 fork

Fork of nRF51822 by Nordic Semiconductor

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ble_bondmngr.cpp Source File

ble_bondmngr.cpp

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