/** ********************************************************************************************************* * Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. ********************************************************************************************************* * @file gap_storage_le.h * @brief key storage function. * @details * @author jane * @date 2016-02-18 * @version v1.0 * ********************************************************************************************************* */ /*============================================================================* * Define to prevent recursive inclusion *============================================================================*/ #ifndef FLASH_KEY_MGR_LE_H #define FLASH_KEY_MGR_LE_H #ifdef __cplusplus extern "C" { #endif /*============================================================================* * Header Files *============================================================================*/ #include "upperstack_config.h" #include "gap.h" #include "gap_le_types.h" /** @defgroup GAP_LE_STORAGE GAP LE Storage * @brief GAP LE Storage * @{ */ /*============================================================================* * Macros *============================================================================*/ /** @defgroup GAP_LE_STORAGE_Exported_Macros GAP LE Storage Exported Macros * @{ */ /** @defgroup GAP_LE_STORAGE_BITS LE Key Storage Bits * @{ */ #define LE_KEY_STORE_REMOTE_BD_BIT 0x01 #define LE_KEY_STORE_LOCAL_LTK_BIT 0x02 #define LE_KEY_STORE_REMOTE_LTK_BIT 0x04 #define LE_KEY_STORE_REMOTE_IRK_BIT 0x08 #define LE_KEY_STORE_LOCAL_CSRK_BIT 0x10 #define LE_KEY_STORE_REMOTE_CSRK_BIT 0x20 #define LE_KEY_STORE_CCCD_DATA_BIT 0x40 #define LE_KEY_STORE_LOCAL_IRK_BIT 0x80 #define LE_KEY_STORE_REMOTE_CLIENT_SUPPORTED_FEATURES_BIT 0x0100 #define LE_KEY_STORE_REMOTE_SRV_CHANGE_AWARE_STATE_BIT 0x0200 #define LE_KEY_STORE_LOCAL_BD_BIT 0x8000 /** * @} */ /** End of GAP_LE_STORAGE_Exported_Macros * @} */ /*============================================================================* * Types *============================================================================*/ /** @defgroup GAP_LE_STORAGE_Exported_Types GAP LE Storage Exported Types * @{ */ /** @brief Local Device Name */ typedef struct { uint8_t local_name[40]; } T_LOCAL_NAME; /** @brief Local Device Appearance */ typedef struct { uint16_t local_appearance; uint8_t padding[2]; } T_LOCAL_APPEARANCE; /** @brief Local IRK */ typedef struct { uint8_t local_irk[16]; } T_LOCAL_IRK; /** @brief Remote Bluetooth device address info */ typedef struct { uint8_t addr[6]; uint8_t remote_bd_type; uint8_t bond_flags; } T_LE_REMOTE_BD; #if F_BT_LE_PRIVACY_SUPPORT /** @brief LE privacy information */ typedef struct { bool is_discov; bool central_addr_resolv; bool resolv_addr_only; } T_LE_PRIVACY_INFO; #endif /** @brief LE CCCD info */ typedef struct { uint16_t handle; uint16_t ccc_bits; } T_LE_CCCD_ELEM; typedef struct { uint8_t data_length; uint8_t padding[3]; uint8_t data[1]; } T_LE_CCCD; /** @brief LE Key Type */ typedef enum { LE_KEY_UNAUTHEN = 0x04, /**< SSP generated link key without MITM protection. */ LE_KEY_AUTHEN = 0x05, /**< SSP generated link key with MITM protection. */ LE_KEY_UNAUTHEN_P256 = 0x07, /**< Security Connections generated link key without MITM protection. */ LE_KEY_AUTHEN_P256 = 0x08, /**< Security Connections link key with MITM protection. */ } T_LE_KEY_TYPE; /** @brief LE key entry */ typedef struct { bool is_used; uint8_t idx; uint16_t flags; uint8_t local_bd_type; uint8_t app_data; uint8_t reserved[2]; T_LE_REMOTE_BD remote_bd; T_LE_REMOTE_BD resolved_remote_bd; uint8_t local_bd_addr[6]; } T_LE_KEY_ENTRY; typedef struct { uint16_t flags; T_LE_REMOTE_BD remote_bd; uint8_t local_ltk[32]; uint8_t remote_ltk[32]; uint8_t remote_irk[24]; } T_LE_DEV_INFO; typedef struct { uint8_t link_key_length; uint8_t padding[3]; uint8_t key[28]; } T_LE_LTK; /** End of GAP_LE_STORAGE_Exported_Types * @} */ /*============================================================================* * Functions *============================================================================*/ /** * @defgroup GAP_LE_STORAGE_EXPORT_Functions GAP LE Storage Exported Functions * * @{ */ /** * @brief Save local device name to flash. * @param[in] p_data pointer to local device name * @return Operation result. * @retval 0 Operation success. * @retval Others Operation failure. * * Example usage * \code{.c} T_APP_RESULT gap_service_callback(T_SERVER_ID service_id, void *p_para) { T_APP_RESULT result = APP_RESULT_SUCCESS; T_GAPS_CALLBACK_DATA *p_gap_data = (T_GAPS_CALLBACK_DATA *)p_para; APP_PRINT_INFO2("gap_service_callback conn_id = %d msg_type = %d\n", p_gap_data->conn_id, p_gap_data->msg_type); if (p_gap_data->msg_type == SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE) { switch (p_gap_data->msg_data.opcode) { case GAPS_WRITE_DEVICE_NAME: { T_LOCAL_NAME device_name; memcpy(device_name.local_name, p_gap_data->msg_data.p_value, p_gap_data->msg_data.len); device_name.local_name[p_gap_data->msg_data.len] = 0; flash_save_local_name(&device_name); } break; case GAPS_WRITE_APPEARANCE: { uint16_t appearance_val; T_LOCAL_APPEARANCE appearance; LE_ARRAY_TO_UINT16(appearance_val, p_gap_data->msg_data.p_value); appearance.local_appearance = appearance_val; flash_save_local_appearance(&appearance); } break; default: break; } } else if (p_gap_data->msg_type == SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION) { if (p_gap_data->msg_data.opcode == GATT_SERVICE_CHANGE_CCCD_ENABLE) { APP_PRINT_INFO0("GATT_SERVICE_CHANGE_CCCD_ENABLE"); } } return result; } * \endcode */ uint32_t flash_save_local_name(T_LOCAL_NAME *p_data); /** * @brief Load local device name from flash. * @param[in] p_data pointer to local device name * @return Operation result. * @retval 0 Operation success. * @retval Others Operation failure. * * Example usage * \code{.c} void test() { uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BB3_GapTest"; uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; uint8_t appearance_prop = GAPS_PROPERTY_WRITE_ENABLE; uint8_t device_name_prop = GAPS_PROPERTY_WRITE_ENABLE; T_LOCAL_APPEARANCE appearance_local; T_LOCAL_NAME local_device_name; if (flash_load_local_appearance(&appearance_local) == 0) { if (appearance_local.local_appearance != 0xffff) { appearance = appearance_local.local_appearance; } } if (flash_load_local_name(&local_device_name) == 0) { if (local_device_name.local_name[0] != 0xff) { memcpy(device_name, local_device_name.local_name, GAP_DEVICE_NAME_LEN); } } } * \endcode */ uint32_t flash_load_local_name(T_LOCAL_NAME *p_data); /** * @brief Save local device appearance to flash. * @param[in] p_data Pointer to local device name * @return Operation result * @retval 0 Operation success. * @retval Others Operation failure. * * Example usage * \code{.c} T_APP_RESULT gap_service_callback(T_SERVER_ID service_id, void *p_para) { T_APP_RESULT result = APP_RESULT_SUCCESS; T_GAPS_CALLBACK_DATA *p_gap_data = (T_GAPS_CALLBACK_DATA *)p_para; APP_PRINT_INFO2("gap_service_callback conn_id = %d msg_type = %d\n", p_gap_data->conn_id, p_gap_data->msg_type); if (p_gap_data->msg_type == SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE) { switch (p_gap_data->msg_data.opcode) { case GAPS_WRITE_DEVICE_NAME: { T_LOCAL_NAME device_name; memcpy(device_name.local_name, p_gap_data->msg_data.p_value, p_gap_data->msg_data.len); device_name.local_name[p_gap_data->msg_data.len] = 0; flash_save_local_name(&device_name); } break; case GAPS_WRITE_APPEARANCE: { uint16_t appearance_val; T_LOCAL_APPEARANCE appearance; LE_ARRAY_TO_UINT16(appearance_val, p_gap_data->msg_data.p_value); appearance.local_appearance = appearance_val; flash_save_local_appearance(&appearance); } break; default: break; } } else if (p_gap_data->msg_type == SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION) { if (p_gap_data->msg_data.opcode == GATT_SERVICE_CHANGE_CCCD_ENABLE) { APP_PRINT_INFO0("GATT_SERVICE_CHANGE_CCCD_ENABLE"); } } return result; } * \endcode */ uint32_t flash_save_local_appearance(T_LOCAL_APPEARANCE *p_data); /** * @brief Load local device appearance from flash. * @param[in] p_data Pointer to local device name * @return Operation result * @retval 0 Operation success. * @retval Others Operation failure. * * Example usage * \code{.c} void test() { uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BB3_GapTest"; uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; uint8_t appearance_prop = GAPS_PROPERTY_WRITE_ENABLE; uint8_t device_name_prop = GAPS_PROPERTY_WRITE_ENABLE; T_LOCAL_APPEARANCE appearance_local; T_LOCAL_NAME local_device_name; if (flash_load_local_appearance(&appearance_local) == 0) { if (appearance_local.local_appearance != 0xffff) { appearance = appearance_local.local_appearance; } } if (flash_load_local_name(&local_device_name) == 0) { if (local_device_name.local_name[0] != 0xff) { memcpy(device_name, local_device_name.local_name, GAP_DEVICE_NAME_LEN); } } } * \endcode */ uint32_t flash_load_local_appearance(T_LOCAL_APPEARANCE *p_data); #if F_BT_LE_LOCAL_IRK_SETTING_SUPPORT /** * @brief Save local IRK to flash. * @param[in] p_data Pointer to local device name * @return Operation result * @retval 0 Operation success. * @retval Others Operation failure. * * Example usage * \code{.c} void test() { T_LOCAL_IRK irk = {0x01,0x02,0x03,}; flash_save_local_irk(&irk); } * \endcode */ uint32_t flash_save_local_irk(T_LOCAL_IRK *p_data); /** * @brief Load local IRK from flash. * @param[in] p_data Pointer to local device name * @return Operation result * @retval 0 Operation success. * @retval Others Operation failure. * * Example usage * \code{.c} void test() { T_LOCAL_IRK irk; flash_load_local_irk(&irk); } * \endcode */ uint32_t flash_load_local_irk(T_LOCAL_IRK *p_data); #endif /** * @brief Find key entry by bluetooth device address and address type. * * @param[in] bd_addr Remote bluetooth device address. * @param[in] bd_type Remote bluetooth device address type. * @return p_entry Pointer to the found key entry. * @retval null No entry found. * @retval others Pointer to the found key entry. */ T_LE_KEY_ENTRY *le_find_key_entry(uint8_t *bd_addr, T_GAP_REMOTE_ADDR_TYPE bd_type); /** * @brief Find key entry by bluetooth device address and address type. * * @param[in] remote_bd_addr Remote bluetooth device address. * @param[in] remote_bd_type Remote bluetooth device address type. * @param[in] local_bd_addr Local bluetooth device address. * @param[in] local_bd_type Local bluetooth device address type. * @return p_entry Pointer to the found key entry. * @retval null No entry found. * @retval others Pointer to the found key entry. */ T_LE_KEY_ENTRY *le_find_key_entry_v2(uint8_t *remote_bd_addr, T_GAP_REMOTE_ADDR_TYPE remote_bd_type, uint8_t *local_bd_addr, uint8_t local_bd_type); /** * @brief Find key entry by index. * * @param[in] idx Key entry index. * @return p_entry Pointer to the found key entry. * @retval null No entry found. * @retval Others Pointer to the found key entry. */ T_LE_KEY_ENTRY *le_find_key_entry_by_idx(uint8_t idx); /** * @brief Get the bonded device count. * * Note: You can call this function after @ref le_gap_init is invoked. * * @return num Bonded device count. */ uint8_t le_get_bond_dev_num(void); /** * @brief Get the low priority bond device key entry. * * Note: You can call this function after @ref le_gap_init is invoked. * * @return p_entry Pointer to the found key entry. * @retval null No entry found. * @retval Others Pointer to the found key entry. */ T_LE_KEY_ENTRY *le_get_low_priority_bond(void); /** * @brief Get the high priority bond device key entry. * * Note: You can call this function after @ref le_gap_init is invoked. * * @return p_entry Pointer to the found key entry. * @retval null No entry found. * @retval others Pointer to the found key entry. */ T_LE_KEY_ENTRY *le_get_high_priority_bond(void); /** * @brief Make the specified bonded device with the high priority. * * NOTE: When the default value of @ref gap_config_local_addr_storage is true * or @ref gap_config_local_addr_storage (true) has been configured, * this function cannot be used if local device uses different local * addresses to bond with the same remote device. In this situation, * @ref le_set_high_priority_bond_v2 shall be called. * * @param[in] bd_addr Remote bluetooth device address. * @param[in] bd_type Remote bluetooth device address type. * @return Operation result. * @retval true Operation success. * @retval false Operation failure. */ bool le_set_high_priority_bond(uint8_t *bd_addr, T_GAP_REMOTE_ADDR_TYPE bd_type); /** * @brief Make the specified bonded device with the high priority. * * @param[in] p_entry Pointer the key entry of the bonded device. * @return Operation result. * @retval true Operation success. * @retval false Operation failure. */ bool le_set_high_priority_bond_v2(T_LE_KEY_ENTRY *p_entry); /** * @brief Resolve the specified bonded device. * * @param[in] unresolved_addr Unresolved remote bluetooth device address. * @param[in,out] resolved_addr Resolved remote bluetooth device address. * @param[in,out] resolved_addr_type Resolved remote bluetooth device address type. * @return Operation result. * @retval true Operation success. * @retval false Operation failure. * * Example usage * \code{.c} void app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t status) { APP_PRINT_INFO1("app_handle_authen_state_evt:conn_id %d", conn_id); switch (new_state) { ... case GAP_AUTHEN_STATE_COMPLETE: { APP_PRINT_INFO1("GAP_MSG_LE_AUTHEN_STATE_CHANGE:(GAP_AUTHEN_STATE_COMPLETE) status 0x%x", status); if (status == 0) { APP_PRINT_INFO0("GAP_MSG_LE_AUTHEN_STATE_CHANGE pair success"); { uint8_t addr[6]; T_GAP_REMOTE_ADDR_TYPE bd_type; uint8_t resolved_addr[6]; T_GAP_IDENT_ADDR_TYPE resolved_bd_type; le_get_conn_addr(conn_id, addr, &bd_type); if (bd_type == GAP_REMOTE_ADDR_LE_RANDOM) { if (le_resolve_random_address(addr, resolved_addr, &resolved_bd_type)) { APP_PRINT_INFO2("GAP_AUTHEN_STATE_COMPLETE: resolved_addr %s, resolved_addr_type %d", TRACE_BDADDR(resolved_addr), resolved_bd_type); } else { APP_PRINT_INFO0("GAP_AUTHEN_STATE_COMPLETE: resolved addr failed"); } } } } else { APP_PRINT_INFO0("GAP_MSG_LE_AUTHEN_STATE_CHANGE pair failed"); } } break; ... } } * \endcode */ bool le_resolve_random_address(uint8_t *unresolved_addr, uint8_t *resolved_addr, T_GAP_IDENT_ADDR_TYPE *resolved_addr_type); /** * @brief Get the cccd information of the bonded device. * * @param[in] p_entry Pointer the key entry of the bonded device. * @param[out] p_data Pointer to ccccd data to read. * @return Operation result. * @retval true Operation success. * @retval false Operation failure. * * Example usage * \code{.c} void test(void) { T_GAP_REMOTE_ADDR_TYPE remote_addr_type; uint8_t bd_addr[6]; uint8_t conn_id = 0; uint8_t ccc_bits_count = 16; T_LE_CCCD *p_cccd_data = os_mem_alloc(RAM_TYPE_DATA_ON, 4 + ccc_bits_count * 4); T_LE_KEY_ENTRY *p_entry = NULL; if(le_get_conn_addr(conn_id, bd_addr, &remote_addr_type)) { p_entry = le_find_key_entry(bd_addr, remote_addr_type); if (p_entry) { if (le_get_cccd_data(p_entry, p_cccd_data)) { APP_PRINT_INFO2("Get cccd data: len %d, data %s", p_cccd_data->data_length, TRACE_BINARY(p_cccd_data->data_length, p_cccd_data->data)); } } } os_mem_free(p_cccd_data); } * \endcode */ bool le_get_cccd_data(T_LE_KEY_ENTRY *p_entry, T_LE_CCCD *p_data); /** * @brief Generate a new bonded device information by APP. * * NOTE: When the default value of @ref gap_config_local_addr_storage is true * or @ref gap_config_local_addr_storage (true) has been configured, this * function cannot be used. In this situation, @ref le_gen_bond_dev_v2 * shall be called. * * @param[in] bd_addr Remote bluetooth device address. * @param[in] bd_type Remote bluetooth device address type. * @param[in] local_bd_type Local bluetooth device address type. * @param[in] ltk_length LTK length. * @param[in] p_ltk Pointer to LTK to write. * @param[in] p_cccd Pointer to cccd data to write. * @return Operation result. * @retval true Operation success. * @retval false Operation failure. * * Example usage * \code{.c} void test(void) { T_GAP_REMOTE_ADDR_TYPE remote_addr_type = GAP_REMOTE_ADDR_LE_PUBLIC; uint8_t bd_addr[6] = {0x11,0x22,0x33,0x44,0x55,0x66}; uint8_t ltk_length = 16; uint8_t ltk[16] = {0x0, 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; T_LE_KEY_TYPE key_type = LE_KEY_UNAUTHEN; uint8_t ccc_bits_count = 16; T_LE_CCCD *p_cccd_data = os_mem_alloc(RAM_TYPE_DATA_ON, 4 + ccc_bits_count * 4); p_cccd_data->data_length = 4; p_cccd_data->data[0] = 0x04; p_cccd_data->data[1] = 0x00; p_cccd_data->data[2] = 0x02; p_cccd_data->data[3] = 0x00; if(le_gen_bond_dev(bd_addr, remote_addr_type, GAP_LOCAL_ADDR_LE_PUBLIC, ltk_length, ltk, key_type, p_cccd_data)) { APP_PRINT_INFO0("Generate bond device success"); } os_mem_free(p_cccd_data); } * \endcode */ bool le_gen_bond_dev(uint8_t *bd_addr, T_GAP_REMOTE_ADDR_TYPE bd_type, T_GAP_LOCAL_ADDR_TYPE local_bd_type, uint8_t ltk_length, uint8_t *p_ltk, T_LE_KEY_TYPE key_type, T_LE_CCCD *p_cccd); /** * @brief Generate a new bonded device information by APP. * * @param[in] remote_bd_addr Remote bluetooth device address. * @param[in] remote_bd_type Remote bluetooth device address type. * @param[in] local_bd_addr Local bluetooth device address. * @param[in] local_bd_type Local bluetooth device address type. * @param[in] ltk_length LTK length. * @param[in] p_ltk Pointer to LTK to write. * @param[in] p_cccd Pointer to cccd data to write. * @return Operation result. * @retval true Operation success. * @retval false Operation failure. * * Example usage * \code{.c} void test(void) { T_GAP_REMOTE_ADDR_TYPE remote_addr_type = GAP_REMOTE_ADDR_LE_PUBLIC; uint8_t remote_bd_addr[6] = {0x11,0x22,0x33,0x44,0x55,0x66}; uint8_t local_bd_addr[6] = {0x00,0x22,0x33,0x44,0x55,0x66}; uint8_t ltk_length = 16; uint8_t ltk[16] = {0x0, 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; T_LE_KEY_TYPE key_type = LE_KEY_UNAUTHEN; uint8_t ccc_bits_count = 16; T_LE_CCCD *p_cccd_data = os_mem_alloc(RAM_TYPE_DATA_ON, 4 + ccc_bits_count * 4); p_cccd_data->data_length = 4; p_cccd_data->data[0] = 0x04; p_cccd_data->data[1] = 0x00; p_cccd_data->data[2] = 0x02; p_cccd_data->data[3] = 0x00; if(le_gen_bond_dev_v2(remote_bd_addr, remote_addr_type, local_bd_addr, GAP_LOCAL_ADDR_LE_PUBLIC, ltk_length, ltk, key_type, p_cccd_data)) { APP_PRINT_INFO0("Generate bond device success"); } os_mem_free(p_cccd_data); } * \endcode */ bool le_gen_bond_dev_v2(uint8_t *remote_bd_addr, T_GAP_REMOTE_ADDR_TYPE remote_bd_type, uint8_t *local_bd_addr, T_GAP_LOCAL_ADDR_TYPE local_bd_type, uint8_t ltk_length, uint8_t *p_ltk, T_LE_KEY_TYPE key_type, T_LE_CCCD *p_cccd); #if F_BT_LE_PRIVACY_SUPPORT /** * @brief Save privacy information. * * @param[in] p_entry Pointer to the key entry of bonded device. * @param[in] p_privacy_info Pointer to privacy information to write. * @return Operation result. * @retval true Operation success. * @retval false Operation failure. */ bool le_set_privacy_info(T_LE_KEY_ENTRY *p_entry, T_LE_PRIVACY_INFO *p_privacy_info); /** * @brief Get privacy information. * * @param[in] p_entry Pointer to the key entry of bonded device. * @param[out] p_privacy_info Pointer to privacy information to read. * @return Operation result. * @retval true Operation success. * @retval false Operation failure. */ bool le_get_privacy_info(T_LE_KEY_ENTRY *p_entry, T_LE_PRIVACY_INFO *p_privacy_info); /** * @brief Check the bonded device whether it is a privacy device. * * @param[in] p_entry Pointer to the key entry of bonded device. * @return Operation result. * @retval true This bonded device is a privacy device. * @retval false This bonded device is not a privacy device. */ bool le_check_privacy_bond(T_LE_KEY_ENTRY *p_entry); #endif /** * @brief Get length of device bond information. * * @return Length of device bond information. */ uint16_t le_get_dev_bond_info_len(void); /** * @brief Get device bond information. * * @param[in] p_entry Pointer to the key entry of bonded device. * @param[in] p_data Pointer to bond information to read. * @return Operation result. * @retval true Operation success. * @retval false Operation failure. */ bool le_get_dev_bond_info(T_LE_KEY_ENTRY *p_entry, uint8_t *p_data); /** * @brief Set device bond information. * * @param[in] length Length of device bond information. * @param[in] p_data Pointer to bond information to write. * @param[in,out] exist Indicate whether bond information of the device is existed. * @return p_entry Pointer to the key entry. * @retval null No entry, operation failure. * @retval others Pointer to the key entry. If parameter exist is false, operation success. If parameter exist is true, bond information of the device is existed. */ T_LE_KEY_ENTRY *le_set_dev_bond_info(uint16_t length, uint8_t *p_data, bool *exist); /** * @brief Get maximum pairing information number that can be stored. * * NOTE: This function can be called after @ref le_gap_init is invoked. * * @return Maximum number of LE paired device information that can be stored. */ uint8_t le_get_max_le_paired_device_num(void); /** * @brief Get device information. * * @param[in] p_entry Pointer to the key entry of bonded device. * @param[out] p_data Pointer to bond information to read. * @return Operation result. * @retval true Operation success. * @retval false Operation failure. */ bool le_get_dev_info(T_LE_KEY_ENTRY *p_entry, T_LE_DEV_INFO *p_info); /** * @brief Modify local LTK. * * @param[in] p_entry Pointer to the key entry of bonded device. * @param[in] key_length key length, Range: 7 to 16. * @param[in] p_ltk Pointer to local ltk to save. * @return Operation result. * @retval true Operation success. * @retval false Operation failure. */ bool le_set_local_ltk(T_LE_KEY_ENTRY *p_entry, uint8_t key_length, uint8_t *p_ltk); /** * @brief Erase CCCD except specific attribute handle. * * NOTE: This function can only be used for standby state (i.e., no link, not initiating, etc.). * * @param[in] handle_num Number of attribute handle of CCCD which will not be erased * @param[in] p_handle Pointer to attribute handle of CCCD which will not be erased * @return Operation result. * @retval true Operation success. * @retval false Operation failure. */ bool le_clear_cccd_data(uint16_t handle_num, uint16_t *p_handle); /** * @brief Get remote device IRK information. * * @param[in] p_entry Pointer to the key entry of bonded device. * @param[in] remote Read the remote IRK or the local IRK. * @param[out] p_irk Pointer to IRK to read. * @return Operation result. * @retval true Operation success. * @retval false Operation failure. */ bool le_get_dev_irk(T_LE_KEY_ENTRY *p_entry, bool remote, uint8_t *p_irk); /** @} */ /* End of group GAP_LE_STORAGE_EXPORT_Functions */ /** @} */ /* End of group GAP_LE_STORAGE */ #ifdef __cplusplus } #endif #endif /* FLASH_KEY_MGR_LE_H */