diff --git a/Kconfig b/Kconfig index abe3e1062..5b3ee339d 100644 --- a/Kconfig +++ b/Kconfig @@ -728,6 +728,15 @@ config BLUETOOTH_GATTS_MAX_CONNECTIONS config BLUETOOTH_GATTS_MAX_ATTRIBUTE_NUM int "GATT Server max number of attributes contained in a table" default 10 + +config BLUETOOTH_GATTS_CACHE_SUPPORT + bool "Enable GATT Server Cache Support" + default y + depends on BLUETOOTH_BLE_SUPPORT + help + Enable internal GATT attribute table hash comparison. + On reconnect, trusted devices may receive Service Changed indications + if attribute changes are detected. endif # BLUETOOTH_GATT_SERVER menuconfig BLUETOOTH_SPP diff --git a/service/common/bluetooth_define.h b/service/common/bluetooth_define.h index 3cbe8f4bb..62c68765e 100644 --- a/service/common/bluetooth_define.h +++ b/service/common/bluetooth_define.h @@ -21,6 +21,8 @@ #include "bt_uuid.h" // #define BLE_MAX_ADV_NUM 8 +#define BT_GATT_HASH_LEN 16 + #define SMP_KEYS_MAX_SIZE 80 #define BT_COMMON_KEY_LENGTH 16 @@ -91,6 +93,13 @@ typedef struct { uint8_t local_csrk[16]; } __attribute__((aligned(4))) remote_device_le_properties_v5_0_3_t; +typedef struct { + bt_address_t addr; + ble_addr_type_t addr_type; + // only can add member after "addr_type" if needed, see function bt_storage_save_le_remote_device for reasons. + uint8_t hash[BT_GATT_HASH_LEN]; +} __attribute__((aligned(4))) remote_device_gatt_properties_v5_0_3_t; + typedef struct { char name[BT_LOC_NAME_MAX_LEN + 1]; uint8_t pad[3]; @@ -103,6 +112,7 @@ typedef struct { typedef remote_device_properties_v5_0_3_t remote_device_properties_t; typedef remote_device_le_properties_v5_0_3_t remote_device_le_properties_t; +typedef remote_device_gatt_properties_v5_0_3_t remote_device_gatt_properties_t; typedef adapter_storage_v5_0_3_t adapter_storage_t; #endif /* __BLUETOOTH_DEFINE_H_ */ \ No newline at end of file diff --git a/service/common/storage.c b/service/common/storage.c index 28f2a701c..2f954a22c 100644 --- a/service/common/storage.c +++ b/service/common/storage.c @@ -36,6 +36,7 @@ #define BT_KEY_BLEBOND "BleBonded" #define BT_KEY_BLEWHITELIST "WhiteList" #define BT_KEY_BLERESOLVINGLIST "ResolvingList" +#define BT_KEY_BLEGATTHASH "BleGattDBHash" typedef struct { uint16_t items; @@ -146,6 +147,11 @@ static int bt_storage_save_remote_device(const char* key, void* value, uint16_t return ret; } +int bt_storage_save_gatt_cache_device(remote_device_gatt_properties_t* remote, uint16_t size) +{ + return bt_storage_save_remote_device(BT_KEY_BLEGATTHASH, remote, sizeof(*remote), size); +} + int bt_storage_save_bonded_device(remote_device_properties_t* remote, uint16_t size) { return bt_storage_save_remote_device(BT_KEY_BTBOND, remote, sizeof(*remote), size); @@ -161,6 +167,11 @@ int bt_storage_save_le_bonded_device(remote_device_le_properties_t* remote, uint return bt_storage_save_remote_device(BT_KEY_BLEBOND, remote, sizeof(*remote), size); } +int bt_storage_load_gatt_cache_device(load_storage_callback_t cb) +{ + return storage_get_key(BT_KEY_BLEGATTHASH, NULL, NULL, (void*)cb); +} + int bt_storage_load_bonded_device(load_storage_callback_t cb) { return storage_get_key(BT_KEY_BTBOND, NULL, NULL, (void*)cb); diff --git a/service/common/storage.h b/service/common/storage.h index c83891210..f1b4e1a74 100644 --- a/service/common/storage.h +++ b/service/common/storage.h @@ -28,9 +28,11 @@ int bt_storage_load_adapter_info(adapter_storage_t* adapter); int bt_storage_save_bonded_device(remote_device_properties_t* remote, uint16_t size); int bt_storage_save_whitelist(remote_device_le_properties_t* remote, uint16_t size); int bt_storage_save_le_bonded_device(remote_device_le_properties_t* remote, uint16_t size); +int bt_storage_save_gatt_cache_device(remote_device_gatt_properties_t* remote, uint16_t size); int bt_storage_load_bonded_device(load_storage_callback_t cb); int bt_storage_load_whitelist_device(load_storage_callback_t cb); int bt_storage_load_le_bonded_device(load_storage_callback_t cb); +int bt_storage_load_gatt_cache_device(load_storage_callback_t cb); #ifdef CONFIG_BLUETOOTH_STORAGE_PROPERTY_SUPPORT #define GEN_PROP_KEY(buf, key, address, len) snprintf((buf), (len), "%s%02X:%02X:%02X:%02X:%02X:%02X", \ @@ -57,6 +59,7 @@ int bt_storage_load_le_bonded_device(load_storage_callback_t cb); #define BT_KVDB_BTBOND "persist.bluetooth.btbonded." #define BT_KVDB_BLEBOND "persist.bluetooth.blebonded." #define BT_KVDB_BLEWHITELIST "persist.bluetooth.whitelist." +#define BT_KVDB_BLEGATTDBHASH "persist.bluetooth.blegattDBhash." int bt_storage_properties_destory(void); void bt_storage_delete(char* key, uint16_t items, char* prop_name); diff --git a/service/common/storage_property.c b/service/common/storage_property.c index 49e143c98..a4267ee92 100644 --- a/service/common/storage_property.c +++ b/service/common/storage_property.c @@ -295,6 +295,44 @@ static int bt_storage_save_le_remote_device(const char* key, void* value, uint16 return 0; } +/*BT_KVDB_BLEGATTDBHASH*/ +static int bt_storage_save_gatt_cache_remote_device(const char* key, void* value, uint16_t value_size, uint16_t items) +{ + size_t prop_vlen; + char* prop_name; + remote_device_gatt_properties_t* data; + bt_address_t* addr; + int i; + int ret; + + if (!key || !value) + return 0; + + prop_name = (char*)malloc(PROP_NAME_MAX); + if (!prop_name) { + BT_LOGE("property_name malloc failed!"); + return -ENOMEM; + } + data = (remote_device_gatt_properties_t*)value; + prop_vlen = value_size - offsetof(remote_device_gatt_properties_t, addr_type); + for (i = 0; i < items; i++) { + addr = &data->addr; + GEN_PROP_KEY(prop_name, key, addr, PROP_NAME_MAX); + /** + * Note: It should be ensured that "addr" is the first member of the struct remote_device_gatt_properties_t + * and "addr_type" is the second member. + * */ + ret = storage_set_key(prop_name, &data->addr_type, prop_vlen); + if (ret < 0) { + free(prop_name); + return ret; + } + data++; + } + free(prop_name); + return 0; +} + static void callback_bt_count(const char* name, const char* value, void* count_u16) { if (!strncmp(name, BT_KVDB_BTBOND, strlen(BT_KVDB_BTBOND))) { @@ -309,6 +347,13 @@ static void callback_le_count(const char* name, const char* value, void* count_u } } +static void callback_gatthash_count(const char* name, const char* value, void* count_u16) +{ + if (!strncmp(name, BT_KVDB_BLEGATTDBHASH, strlen(BT_KVDB_BLEGATTDBHASH))) { + (*(uint16_t*)count_u16)++; + } +} + static void callback_whitelist_count(const char* name, const char* value, void* count_u16) { if (!strncmp(name, BT_KVDB_BLEWHITELIST, strlen(BT_KVDB_BLEWHITELIST))) { @@ -422,6 +467,34 @@ int bt_storage_save_whitelist(remote_device_le_properties_t* remote, uint16_t si return ret; } +int bt_storage_save_gatt_cache_device(remote_device_gatt_properties_t* remote, uint16_t size) +{ + uint16_t items = 0; + char* prop_name; + int ret; + + prop_name = (char*)malloc(PROP_NAME_MAX); + if (!prop_name) { + BT_LOGE("property_name malloc failed!"); + return -ENOMEM; + } + + /* remove all BLE gatt cache device property before save new property*/ + property_list(callback_gatthash_count, &items); + bt_storage_delete(BT_KVDB_BLEGATTDBHASH, items, prop_name); + + ret = bt_storage_save_gatt_cache_remote_device(BT_KVDB_BLEGATTDBHASH, remote, sizeof(remote_device_gatt_properties_t), size); + if (ret < 0) { + BT_LOGE("save BLE gatt cache device failed!"); + items = 0; + property_list(callback_gatthash_count, &items); + bt_storage_delete(BT_KVDB_BLEGATTDBHASH, items, prop_name); + } + + free(prop_name); + return ret; +} + int bt_storage_save_le_bonded_device(remote_device_le_properties_t* remote, uint16_t size) { uint16_t items = 0; @@ -482,6 +555,38 @@ int bt_storage_load_bonded_device(load_storage_callback_t cb) return 0; } +int bt_storage_load_gatt_cache_device(load_storage_callback_t cb) +{ + uint16_t items; + bt_property_value_t* prop_value; + uint32_t total_length; + int ret; + + items = 0; + ret = property_list(callback_gatthash_count, &items); + if (ret < 0) { + BT_LOGE("property_list failed!"); + return ret; + } + + total_length = items * sizeof(remote_device_gatt_properties_t); + prop_value = malloc(sizeof(bt_property_value_t) + total_length); + if (!prop_value) { + BT_LOGE("property malloc failed!"); + return -ENOMEM; + } + + prop_value->key = BT_KVDB_BLEGATTDBHASH; + prop_value->items = items; + prop_value->offset = 0; + prop_value->value_length = total_length; + + storage_get_key(BT_KVDB_BLEGATTDBHASH, (void*)prop_value, sizeof(remote_device_gatt_properties_t), (void*)cb); + free(prop_value); + + return 0; +} + int bt_storage_load_whitelist_device(load_storage_callback_t cb) { uint16_t items; @@ -567,6 +672,11 @@ int bt_storage_properties_destory(void) property_list(callback_whitelist_count, &items); bt_storage_delete(BT_KVDB_BLEWHITELIST, items, prop_name); + /* remove all GATT cache device property */ + items = 0; + property_list(callback_gatthash_count, &items); + bt_storage_delete(BT_KVDB_BLEGATTDBHASH, items, prop_name); + /* remove all BREDR bond device property */ items = 0; property_list(callback_bt_count, &items); @@ -580,6 +690,7 @@ int bt_storage_properties_destory(void) ret |= property_delete(BT_KVDB_ADAPTERINFO_IOCAP); ret |= property_delete(BT_KVDB_ADAPTERINFO_SCAN); ret |= property_delete(BT_KVDB_ADAPTERINFO_BOND); + ret |= property_delete(BT_KVDB_ADAPTERINFO_IRK); if (ret) { BT_LOGE("property_delete failed!"); return ret; diff --git a/service/profiles/gatt/gatts_service.c b/service/profiles/gatt/gatts_service.c index 7915b2c04..9e0e38615 100644 --- a/service/profiles/gatt/gatts_service.c +++ b/service/profiles/gatt/gatts_service.c @@ -20,6 +20,7 @@ #include #include +#include "adapter_internel.h" #include "bt_list.h" #include "bt_profile.h" #include "gatts_event.h" @@ -236,6 +237,50 @@ static gatts_op_t* gatts_pendops_execute_out(gatts_manager_t* manager, gatts_req return NULL; } +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT +static void gatts_process_database_hash_evt(struct gatts_db_hash_evt_param* evt) +{ + bt_status_t status; + char addr_str[BT_ADDR_STR_LENGTH] = { 0 }; + uint8_t stored_hash[BT_GATT_HASH_LEN] = { 0 }; + + if (!evt) { + BT_LOGE("%s, invalid param", __func__); + return; + } + + bt_addr_ba2str(&evt->addr, addr_str); + BT_LOGD("GATTS-DB-HASH-EVENT from:%s, force_update:%d, hash:" + "%02X%02X%02X%02X%02X%02X%02X%02X" + "%02X%02X%02X%02X%02X%02X%02X%02X", + addr_str, evt->force_update, + evt->hash[0], evt->hash[1], evt->hash[2], evt->hash[3], + evt->hash[4], evt->hash[5], evt->hash[6], evt->hash[7], + evt->hash[8], evt->hash[9], evt->hash[10], evt->hash[11], + evt->hash[12], evt->hash[13], evt->hash[14], evt->hash[15]); + + status = adapter_get_device_gatt_hash(&evt->addr, evt->addr_type, stored_hash); + if (status != BT_STATUS_SUCCESS) { + BT_LOGD("No bonded, skip."); + return; + } + + if (!memcmp(stored_hash, evt->hash, sizeof(stored_hash))) { + BT_LOGD("DB Hash unchanged, no action."); + return; + } + + if (evt->force_update) { + BT_LOGI("Force update"); + } else { + BT_LOGI("Hash mismatch, trigger Service Changed: %s", addr_str); + bt_sal_gatt_server_change_indicate(PRIMARY_ADAPTER, 0x0001, 0xFFFF); + } + + adapter_set_device_gatt_hash((bt_address_t*)&evt->addr, evt->addr_type, evt->hash); +} +#endif + static void gatts_process_message(void* data) { gatts_service_t* service; @@ -265,6 +310,10 @@ static void gatts_process_message(void* data) profile_connection_state_t connect_state = msg->param.connect_change.state; BT_ADDR_LOG("GATTS-CONNECTION-STATE-EVENT from:%s, state:%d", &msg->param.connect_change.addr, connect_state); if (connect_state == PROFILE_STATE_CONNECTED) { +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT + /* Always fetch latest db hash when gatt connected */ + bt_sal_gatt_server_get_database_hash(PRIMARY_ADAPTER, &msg->param.connect_change.addr, false); +#endif GATTS_CALLBACK_FOREACH(g_gatts_manager.services, gatts_service_t, on_connected, &msg->param.connect_change.addr); } else if (connect_state == PROFILE_STATE_DISCONNECTED) { GATTS_CALLBACK_FOREACH(g_gatts_manager.services, gatts_service_t, on_disconnected, &msg->param.connect_change.addr); @@ -341,6 +390,12 @@ static void gatts_process_message(void* data) GATTS_CALLBACK_FOREACH(g_gatts_manager.services, gatts_service_t, on_conn_param_changed, &msg->param.conn_param.addr, msg->param.conn_param.interval, msg->param.conn_param.latency, msg->param.conn_param.timeout); break; +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT + case GATTS_EVENT_DB_HASH_AVAILABLE: + gatts_process_database_hash_evt(&msg->param.db_hash); + break; +#endif + default: { } break; @@ -428,6 +483,32 @@ static bt_status_t if_gatts_shutdown(profile_on_shutdown_t cb) return BT_STATUS_SUCCESS; } +static void if_gatts_process_msg(profile_msg_t* msg) +{ + if (!msg) { + return; + } + + switch (msg->event) { +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT + case PROFILE_EVT_GATTS_REQUEST_DB_HASH: { + bt_address_t* addr = (bt_address_t*)msg->data.data; + if (!addr) { + BT_LOGE("received null address"); + break; + } + + BT_ADDR_LOG("GATTS-DB-HASH-REQUEST to:%s, force_update:%d", addr, msg->data.valuebool); + bt_sal_gatt_server_get_database_hash(PRIMARY_ADAPTER, addr, msg->data.valuebool); + break; + } +#endif + + default: + break; + } +} + static void if_gatts_cleanup(void) { g_gatts_manager.started = false; @@ -832,6 +913,18 @@ void if_gatts_on_notification_sent(bt_address_t* addr, uint16_t element_id, gatt gatts_send_message(msg); } +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT +void if_gatts_on_database_hash(bt_address_t* addr, ble_addr_type_t addr_type, const uint8_t* hash, bool force_update) +{ + gatts_msg_t* msg = gatts_msg_new(GATTS_EVENT_DB_HASH_AVAILABLE, 0); + memcpy(&msg->param.db_hash.addr, addr, sizeof(bt_address_t)); + memcpy(msg->param.db_hash.hash, hash, BT_GATT_HASH_LEN); + msg->param.db_hash.addr_type = addr_type; + msg->param.db_hash.force_update = force_update; + gatts_send_message(msg); +} +#endif + void if_gatts_on_phy_read(bt_address_t* addr, ble_phy_type_t tx_phy, ble_phy_type_t rx_phy) { gatts_msg_t* msg = gatts_msg_new(GATTS_EVENT_PHY_READ, 0); @@ -880,7 +973,7 @@ static const profile_service_t gatts_service = { .init = if_gatts_init, .startup = if_gatts_startup, .shutdown = if_gatts_shutdown, - .process_msg = NULL, + .process_msg = if_gatts_process_msg, .get_state = if_gatts_get_state, .get_profile_interface = get_gatts_profile_interface, .cleanup = if_gatts_cleanup, diff --git a/service/profiles/include/gatts_event.h b/service/profiles/include/gatts_event.h index 5e9b17a58..9a9ce1549 100644 --- a/service/profiles/include/gatts_event.h +++ b/service/profiles/include/gatts_event.h @@ -20,6 +20,7 @@ * Included Files ****************************************************************************/ #include "bluetooth.h" +#include "bluetooth_define.h" #include "bt_addr.h" #include "gatt_define.h" #include @@ -38,6 +39,7 @@ typedef enum { GATTS_EVENT_PHY_READ, GATTS_EVENT_PHY_UPDATE, GATTS_EVENT_CONN_PARAM_CHANGE, + GATTS_EVENT_DB_HASH_AVAILABLE, } gatts_event_t; typedef enum { @@ -138,6 +140,18 @@ typedef struct uint16_t timeout; } conn_param; +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT + /** + * @brief GATTS_EVENT_DB_HASH_AVAILABLE + */ + struct gatts_db_hash_evt_param { + bt_address_t addr; + ble_addr_type_t addr_type; + uint8_t hash[BT_GATT_HASH_LEN]; + bool force_update; + } db_hash; +#endif + } param; } gatts_msg_t; diff --git a/service/profiles/include/gatts_service.h b/service/profiles/include/gatts_service.h index c1b099736..0ea4dcd1f 100644 --- a/service/profiles/include/gatts_service.h +++ b/service/profiles/include/gatts_service.h @@ -39,6 +39,9 @@ void if_gatts_on_phy_read(bt_address_t* addr, ble_phy_type_t tx_phy, ble_phy_typ void if_gatts_on_phy_updated(bt_address_t* addr, ble_phy_type_t tx_phy, ble_phy_type_t rx_phy, gatt_status_t status); void if_gatts_on_connection_parameter_changed(bt_address_t* addr, uint16_t connection_interval, uint16_t peripheral_latency, uint16_t supervision_timeout); +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT +void if_gatts_on_database_hash(bt_address_t* addr, ble_addr_type_t addr_type, const uint8_t* hash, bool force_update); +#endif /* * gatts remote diff --git a/service/profiles/service_manager.h b/service/profiles/service_manager.h index e9d4e3788..08ba261b9 100644 --- a/service/profiles/service_manager.h +++ b/service/profiles/service_manager.h @@ -36,6 +36,7 @@ typedef enum { PROFILE_EVT_HFP_OFFLOADING, PROFILE_EVT_LEA_OFFLOADING, PROFILE_EVT_REMOTE_DETACH, + PROFILE_EVT_GATTS_REQUEST_DB_HASH, } profile_event_t; typedef struct diff --git a/service/src/adapter_internel.h b/service/src/adapter_internel.h index a43f313c3..5c273cc63 100644 --- a/service/src/adapter_internel.h +++ b/service/src/adapter_internel.h @@ -360,6 +360,10 @@ bt_status_t adapter_switch_role(bt_address_t* addr, bt_link_role_t role); bt_status_t adapter_set_afh_channel_classification(uint16_t central_frequency, uint16_t band_width, uint16_t number); +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT +bt_status_t adapter_set_device_gatt_hash(bt_address_t* addr, ble_addr_type_t addr_type, const uint8_t* hash); +bt_status_t adapter_get_device_gatt_hash(bt_address_t* addr, ble_addr_type_t addr_type, uint8_t* out_hash); +#endif void* adapter_register_callback(void* remote, const adapter_callbacks_t* adapter_cbs); bool adapter_unregister_callback(void** remote, void* cookie); diff --git a/service/src/adapter_service.c b/service/src/adapter_service.c index b248daa72..1c6f9ce5b 100644 --- a/service/src/adapter_service.c +++ b/service/src/adapter_service.c @@ -549,6 +549,32 @@ static void whitelist_device_loaded(void* data, uint16_t length, uint16_t items) BT_LOGD("ble whitelist device cnt: %" PRIu16, items); } +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT +static void gatt_hash_device_loaded(void* data, uint16_t length, uint16_t items) +{ + if (data && items) { + char addr_str[BT_ADDR_STR_LENGTH] = { 0 }; + + remote_device_gatt_properties_t* remote = (remote_device_gatt_properties_t*)data; + + BT_LOGD("load GATT hash state successfully:"); + for (int i = 0; i < items; i++) { + bt_device_t* device = adapter_find_create_le_device(&remote->addr, remote->addr_type); + device_set_gatt_hash(device, remote->hash); + device_set_flags(device, DFLAG_GATT_HASH_VALID); + bt_addr_ba2str(&remote->addr, addr_str); + uint8_t* h = remote->hash; + BT_LOGD("GATT HASH[%d], Addr:[%s] Hash: [%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X]", + i, addr_str, + h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], + h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]); + remote++; + } + } + BT_LOGD("gatt hash device cnt: %" PRIu16, items); +} +#endif + static void le_bonded_device_loaded(void* data, uint16_t length, uint16_t items) { char addr_str[BT_ADDR_STR_LENGTH] = { 0 }; @@ -657,6 +683,36 @@ static void adapter_update_whitelist(void) bt_storage_save_whitelist(remotes, size); } + +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT +static void adapter_update_gatt_hash(void) +{ + bt_list_t* list = g_adapter_service.le_devices; + bt_list_node_t* node; + + int size = get_devices_cnt(DFLAG_GATT_HASH_VALID, BT_TRANSPORT_BLE); + if (!size) { + bt_storage_save_gatt_cache_device(NULL, 0); + return; + } + + BT_LOGD("%s", __func__); + + remote_device_gatt_properties_t remotes[size]; + size = 0; + + for (node = bt_list_head(list); node != NULL; node = bt_list_next(list, node)) { + bt_device_t* device = bt_list_node(node); + if (device_check_flag(device, DFLAG_GATT_HASH_VALID)) { + remote_device_gatt_properties_t* remote = &remotes[size]; + device_get_gatt_hash_property(device, remote); + size++; + } + } + + bt_storage_save_gatt_cache_device(remotes, size); +} +#endif #endif static void adapter_save_properties(void) @@ -798,6 +854,11 @@ static void process_bond_state_change_evt(bt_address_t* addr, bond_state_t state #endif // device_set_connection_state(device, CONNECTION_STATE_ENCRYPTED_LE); } else if (state == BOND_STATE_NONE) { +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT + device_clear_flag(device, DFLAG_GATT_HASH_VALID); + device_delete_gatt_hash(device); + adapter_update_gatt_hash(); +#endif device_delete_smp_key(device); } #else @@ -1155,6 +1216,23 @@ static void handle_discovery_event(void* data) free(data); } +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT +static void handle_adapter_to_profile_event(void* data) +{ + profile_msg_t* msg; + + if (!data) { + return; + } + + msg = (profile_msg_t*)data; + + service_manager_processmsg(msg); + + free(msg); +} +#endif + #ifdef CONFIG_BLUETOOTH_BLE_SUPPORT static void process_le_address_update_evt(bt_address_t* addr, ble_addr_type_t type) { @@ -1226,6 +1304,9 @@ static void process_le_whitelist_update_evt(bt_address_t* addr, bool is_add, bt_ static void process_le_bonded_device_update_evt(remote_device_le_properties_t* props, uint16_t bonded_devices_cnt) { +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT + profile_msg_t* msg; +#endif bt_device_t* device; remote_device_le_properties_t* prop = props; char addr_str[BT_ADDR_STR_LENGTH]; @@ -1247,6 +1328,21 @@ static void process_le_bonded_device_update_evt(remote_device_le_properties_t* p device_set_identity_address(device, (bt_address_t*)prop->smp_key); device_set_local_csrk(device, prop->local_csrk); +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT + if (device_is_connected(device) && !device_check_flag(device, DFLAG_GATT_HASH_VALID)) { + /* only first bonded request db hash to update gatt cache */ + msg = (profile_msg_t*)zalloc(sizeof(profile_msg_t)); + if (msg) { + msg->event = PROFILE_EVT_GATTS_REQUEST_DB_HASH; + msg->data.data = device_get_address(device); + msg->data.valuebool = true; /* force_update */ + do_in_service_loop(handle_adapter_to_profile_event, msg); + } else { + BT_LOGE("DB hash request allocate failed"); + } + } +#endif + bt_addr_ba2str(&prop->addr, addr_str); uint8_t* ltk = &prop->smp_key[12]; BT_LOGD("LE BOND DEVICE[%d]: Addr:[%s] Atype:[%d] LTK: [%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X]", @@ -1429,6 +1525,14 @@ void adapter_on_le_enabled(bool enablebt) whitelist_device_loaded(NULL, 0, 0); } +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT + /* set gatt db hash ? */ + ret = bt_storage_load_gatt_cache_device(gatt_hash_device_loaded); + if (ret < 0) { + gatt_hash_device_loaded(NULL, 0, 0); + } +#endif + /* set resolvinglist list ? */ /* enable cdtk */ // bt_sal_le_enable_key_derivation(true, true); @@ -3374,7 +3478,47 @@ bt_status_t adapter_set_afh_channel_classification(uint16_t central_frequency, return bt_sal_set_afh_channel_classification(PRIMARY_ADAPTER, central_frequency, band_width, number); } -void adapter_get_support_profiles(void) { } +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT +bt_status_t adapter_set_device_gatt_hash(bt_address_t* addr, ble_addr_type_t addr_type, const uint8_t* hash) +{ + bt_device_t* device = adapter_find_create_le_device(addr, addr_type); + + if (!device_is_bonded(device)) { + return BT_STATUS_FAIL; + } + + device_set_gatt_hash(device, hash); + device_set_flags(device, DFLAG_GATT_HASH_VALID); + adapter_update_gatt_hash(); + + return BT_STATUS_SUCCESS; +} + +bt_status_t adapter_get_device_gatt_hash(bt_address_t* addr, ble_addr_type_t addr_type, uint8_t* out_hash) +{ + uint8_t* hash; + bt_device_t* device = adapter_find_create_le_device(addr, addr_type); + + if (!device_is_bonded(device)) { + return BT_STATUS_FAIL; + } + + if (!device_check_flag(device, DFLAG_GATT_HASH_VALID)) { + /* No valid hash (OTA or first bond), return all zeros */ + memset(out_hash, 0, BT_GATT_HASH_LEN); + return BT_STATUS_SUCCESS; + } + + hash = device_get_gatt_hash(device); + memcpy(out_hash, hash, BT_GATT_HASH_LEN); + + return BT_STATUS_SUCCESS; +} +#endif + +void adapter_get_support_profiles(void) +{ +} void adapter_dump(void) { diff --git a/service/src/device.c b/service/src/device.c index beee03da0..1f446d149 100644 --- a/service/src/device.c +++ b/service/src/device.c @@ -67,6 +67,9 @@ typedef struct remote_device { uint8_t local_csrk[16]; ble_phy_type_t tx_phy; ble_phy_type_t rx_phy; +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT + uint8_t gatt_hash[BT_GATT_HASH_LEN]; +#endif // uint8_t scan_repetition_mode; // uint16_t clock_offset; } remote_device_t; @@ -385,6 +388,13 @@ uint8_t* device_get_link_key(bt_device_t* device) return device->remote.link_key; } +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT +uint8_t* device_get_gatt_hash(bt_device_t* device) +{ + return device->remote.gatt_hash; +} +#endif + void device_set_link_key(bt_device_t* device, bt_128key_t link_key) { memcpy(device->remote.link_key, link_key, sizeof(bt_128key_t)); @@ -571,6 +581,15 @@ void device_get_le_property(bt_device_t* device, remote_device_le_properties_t* memcpy(prop->local_csrk, device->remote.local_csrk, 16); } +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT +void device_get_gatt_hash_property(bt_device_t* device, remote_device_gatt_properties_t* prop) +{ + memcpy(&prop->addr, &device->remote.addr, sizeof(bt_address_t)); + prop->addr_type = device->remote.addr_type; + memcpy(prop->hash, device->remote.gatt_hash, sizeof(prop->hash)); +} +#endif + void device_set_flags(bt_device_t* device, uint32_t flags) { device->flags |= flags; @@ -603,6 +622,18 @@ void device_delete_smp_key(bt_device_t* device) memset(device->remote.smp_data, 0, sizeof(device->remote.smp_data)); } +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT +void device_set_gatt_hash(bt_device_t* device, const uint8_t* hash) +{ + memcpy(device->remote.gatt_hash, hash, sizeof(device->remote.gatt_hash)); +} + +void device_delete_gatt_hash(bt_device_t* device) +{ + memset(device->remote.gatt_hash, 0, sizeof(device->remote.gatt_hash)); +} +#endif + static int linkkey_dump(bt_device_t* device, char* str) { uint8_t* lk = device->remote.link_key; diff --git a/service/src/device.h b/service/src/device.h index e34788c5e..6f178c919 100644 --- a/service/src/device.h +++ b/service/src/device.h @@ -27,6 +27,7 @@ #define DFLAG_CONNECTED (1 << 5) #define DFLAG_BONDED (1 << 6) #define DFLAG_LE_KEY_SET (1 << 7) +#define DFLAG_GATT_HASH_VALID (1 << 8) typedef struct bt_device bt_device_t; @@ -85,7 +86,15 @@ bool device_check_flag(bt_device_t* device, uint32_t flag); uint8_t* device_get_smp_key(bt_device_t* device); void device_set_smp_key(bt_device_t* device, uint8_t* smp_key); void device_delete_smp_key(bt_device_t* device); +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT +void device_set_gatt_hash(bt_device_t* device, const uint8_t* hash); +void device_delete_gatt_hash(bt_device_t* device); +uint8_t* device_get_gatt_hash(bt_device_t* device); +#endif void device_get_le_property(bt_device_t* device, remote_device_le_properties_t* prop); +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT +void device_get_gatt_hash_property(bt_device_t* device, remote_device_gatt_properties_t* prop); +#endif void device_dump(bt_device_t* device); #endif /* __REMOTE_DEVICE_H__ */ \ No newline at end of file diff --git a/service/stacks/include/sal_gatt_server_interface.h b/service/stacks/include/sal_gatt_server_interface.h index 180e685bf..692ebf018 100644 --- a/service/stacks/include/sal_gatt_server_interface.h +++ b/service/stacks/include/sal_gatt_server_interface.h @@ -44,6 +44,10 @@ bt_status_t bt_sal_gatt_server_send_indication(bt_controller_id_t id, bt_address #endif bt_status_t bt_sal_gatt_server_read_phy(bt_controller_id_t id, bt_address_t* addr); bt_status_t bt_sal_gatt_server_set_phy(bt_controller_id_t id, bt_address_t* addr, ble_phy_type_t tx_phy, ble_phy_type_t rx_phy); +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT +bt_status_t bt_sal_gatt_server_get_database_hash(bt_controller_id_t id, bt_address_t* addr, bool force_update); +#endif +bt_status_t bt_sal_gatt_server_change_indicate(bt_controller_id_t id, uint16_t start_hdl, uint16_t end_hdl); void bt_sal_gatt_server_connection_changed_callback(bt_address_t* addr, uint16_t connection_interval, uint16_t peripheral_latency, uint16_t supervision_timeout); void bt_sal_gatt_server_connection_state_changed_callback(bt_controller_id_t id, bt_address_t* addr, profile_connection_state_t state); diff --git a/service/stacks/zephyr/sal_gatt_server_interface.c b/service/stacks/zephyr/sal_gatt_server_interface.c index 4bfdc054b..bb9e9ab07 100644 --- a/service/stacks/zephyr/sal_gatt_server_interface.c +++ b/service/stacks/zephyr/sal_gatt_server_interface.c @@ -1124,6 +1124,18 @@ bt_status_t bt_sal_gatt_server_set_phy(bt_controller_id_t id, bt_address_t* addr return bt_sal_le_set_phy(id, addr, tx_phy, rx_phy); } +#ifdef CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT +bt_status_t bt_sal_gatt_server_get_database_hash(bt_controller_id_t id, bt_address_t* addr, bool force_update) +{ + SAL_NOT_SUPPORT; +} +#endif + +bt_status_t bt_sal_gatt_server_change_indicate(bt_controller_id_t id, uint16_t start_hdl, uint16_t end_hdl) +{ + SAL_NOT_SUPPORT; +} + void bt_sal_gatt_server_connection_state_changed_callback(bt_controller_id_t id, bt_address_t* addr, profile_connection_state_t state) { if_gatts_on_connection_state_changed(addr, state); diff --git a/tools/storage_update/storage_update.c b/tools/storage_update/storage_update.c index 002c11418..318643923 100644 --- a/tools/storage_update/storage_update.c +++ b/tools/storage_update/storage_update.c @@ -53,6 +53,7 @@ static void callback_adapter_count(const char* name, const char* value, void* co static void callback_bt_count(const char* name, const char* value, void* count_u16); static void callback_le_count(const char* name, const char* value, void* count_u16); static void callback_whitelist_count(const char* name, const char* value, void* count_u16); +static void callback_gatt_dbhash_count(const char* name, const char* value, void* count_u16); static uv_db_t* storage_handle = NULL; @@ -62,28 +63,34 @@ static int bt_storage_update_item_size[BT_STORAGE_VERSION_MAX][BT_STORAGE_UPDATE { sizeof(adapter_storage_v4_0_0_t), sizeof(remote_device_properties_v4_0_0_t), sizeof(remote_device_le_properties_v4_0_0_t), - sizeof(remote_device_le_properties_v4_0_0_t) }, + sizeof(remote_device_le_properties_v4_0_0_t), + 0 }, #endif #ifdef BLUETOOTH_STORAGE_VERSION_5 { sizeof(adapter_storage_v5_0_0_t), sizeof(remote_device_properties_v5_0_0_t), sizeof(remote_device_le_properties_v5_0_0_t), - sizeof(remote_device_le_properties_v5_0_0_t) }, + sizeof(remote_device_le_properties_v5_0_0_t), + 0 }, /* version 5_0_1 */ { sizeof(adapter_storage_v5_0_1_t), sizeof(remote_device_properties_v5_0_1_t), sizeof(remote_device_le_properties_v5_0_1_t), - sizeof(remote_device_le_properties_v5_0_1_t) }, + sizeof(remote_device_le_properties_v5_0_1_t), + 0 }, /* version 5_0_2 */ { sizeof(adapter_storage_v5_0_2_t), sizeof(remote_device_properties_v5_0_2_t), sizeof(remote_device_le_properties_v5_0_2_t), - sizeof(remote_device_le_properties_v5_0_2_t) }, + sizeof(remote_device_le_properties_v5_0_2_t), + 0 }, /* version 5_0_3 */ - { sizeof(adapter_storage_v5_0_3_t), + { + sizeof(adapter_storage_v5_0_3_t), sizeof(remote_device_properties_v5_0_3_t), sizeof(remote_device_le_properties_v5_0_3_t), - sizeof(remote_device_le_properties_v5_0_3_t) }, + sizeof(remote_device_le_properties_v5_0_3_t), + sizeof(remote_device_gatt_properties_v5_0_3_t) }, #endif /* Reserve for future version */ }; @@ -93,6 +100,7 @@ const static bt_storage_update_kvdb_callback_t callback_cnt_list[BT_STORAGE_UPDA { BT_KVDB_BTBOND, callback_bt_count }, { BT_KVDB_BLEBOND, callback_le_count }, { BT_KVDB_BLEWHITELIST, callback_whitelist_count }, + { BT_KVDB_BLEGATTDBHASH, callback_gatt_dbhash_count }, }; const static char* unqlite_item_key[BT_STORAGE_UNQLITE_ITEM] = { @@ -310,6 +318,13 @@ static void callback_whitelist_count(const char* name, const char* value, void* } } +static void callback_gatt_dbhash_count(const char* name, const char* value, void* count_u16) +{ + if (!strncmp(name, BT_KVDB_BLEGATTDBHASH, strlen(BT_KVDB_BLEGATTDBHASH))) { + (*(uint16_t*)count_u16)++; + } +} + static void callback_load_addr(const char* name, const char* value, void* cookie) { bt_property_value_t* prop_value = (bt_property_value_t*)cookie; @@ -668,6 +683,9 @@ static int bt_storage_update_save_info(bt_storage_update_properties_t* storage_i bt_storage_save_le_bonded_device( (remote_device_le_properties_t*)storage_info->storage_info[BT_STORAGE_UPDATE_BLEBOND_INFO].value, storage_info->storage_info[BT_STORAGE_UPDATE_BLEBOND_INFO].items); + bt_storage_save_gatt_cache_device( + (remote_device_gatt_properties_t*)storage_info->storage_info[BT_STORAGE_UPDATE_GATT_HASH_INFO].value, + storage_info->storage_info[BT_STORAGE_UPDATE_GATT_HASH_INFO].items); return 0; } diff --git a/tools/storage_update/storage_update.h b/tools/storage_update/storage_update.h index f5a1497fa..a8d8c960b 100644 --- a/tools/storage_update/storage_update.h +++ b/tools/storage_update/storage_update.h @@ -39,6 +39,7 @@ enum { BT_STORAGE_UPDATE_BTBOND_INFO, BT_STORAGE_UPDATE_BLEBOND_INFO, BT_STORAGE_UPDATE_WHITELIST_INFO, + BT_STORAGE_UPDATE_GATT_HASH_INFO, BT_STORAGE_UPDATE_ITEM_MAX, }; diff --git a/tools/storage_update/storage_version_5.c b/tools/storage_update/storage_version_5.c index f7125a763..3d7ce0ae9 100644 --- a/tools/storage_update/storage_version_5.c +++ b/tools/storage_update/storage_version_5.c @@ -354,5 +354,7 @@ bt_storage_update_properties_t* bt_storage_update_v5_0_2_to_v5_0_3(bt_storage_up old_whitelist++; } + /* No raw material conversion GATT HASH */ + return new_storage; }