BLE temperature profile using digital DS1820 or analog LM35 sensors

Dependencies:   DS1820

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