]> granicus.if.org Git - esp-idf/commitdiff
component/bt: Change the btc gattc callback function with the compile error.
authorYulong <huangyulong@espressif.com>
Mon, 12 Mar 2018 03:34:20 +0000 (23:34 -0400)
committeryulong <huangyulong@espressif.com>
Thu, 19 Apr 2018 04:05:13 +0000 (12:05 +0800)
1. Change all the gattc API && bta gattc layer.
2. Debug the code and change the btc_ble_gattc_get_db method.
3. Change the gatt read API interface.
4. Reconstruction the BTA_gattc_cache code.
5. Change back the bluedroid_get_status to marco.
6. Change the gattc docs format.
7. Change the docs format.
8. fix the read char value bug.
9. change the gattc_get_attr_count method.
10. Change back the bta_gattc write ccc code.
11. Change the gattc api docs format
12. Change the gattc API docs.
13. Change the prepare write descriptor method to avoid the exection.
14. modify gatt clinet demo with new API
15. Change the p_src_data->read.p_value to avoid exection.
16. Change the bugfix of gattc unreg for the notify.

    component/bt: Added the serch service res start_handle & end_handle to the result.

component/bt: Added the bta_gattc_cache_write when gatt discovery complete.

component/bt: Added the bta_gattc_cache_write declaration.

component/bt: Added the comments for esp_ble_gattc_cache_refresh API.

component/bt: Change the spelling errors & some comment error.

component/bt: fix bug of get gattc cache address list error.

1. Change the esp_bluedroid_get_status to macro;
2. added the malloc & free for the get_addr_list

component/bt: Added the addr_info->ass_addr == NULL Judgment to prevent crashes in the bta_gattc_co_cache_find_src_addr function.

component/bt: Fixed following gattc cache bugs

1. gattc can't refresh the gattc cache in the gatt discover state;
2. remove the nvs_get_blob in the cache address init function;
3. added the nvs_set_blob return value judgment in the cache address save function;
4. added the list_new when ass_address is NULL;
5. Change the ass_address list remove method to fix the ass address can't remove bug.

14 files changed:
components/bt/bluedroid/api/esp_gattc_api.c
components/bt/bluedroid/api/include/esp_gattc_api.h
components/bt/bluedroid/bta/dm/bta_dm_act.c
components/bt/bluedroid/bta/gatt/bta_gattc_act.c
components/bt/bluedroid/bta/gatt/bta_gattc_api.c
components/bt/bluedroid/bta/gatt/bta_gattc_cache.c
components/bt/bluedroid/bta/gatt/bta_gattc_main.c
components/bt/bluedroid/bta/include/bta_gatt_api.h
components/bt/bluedroid/bta/include/bta_gattc_ci.h
components/bt/bluedroid/bta/include/bta_gattc_co.h
components/bt/bluedroid/bta/include/bta_gattc_int.h
components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c
components/bt/bluedroid/btc/profile/std/include/btc_gattc.h
components/bt/bluedroid/btif/bta_gattc_co.c

index 83c93660801da2dfed37dac37e65329a9067846a..cb613f085c484ae2bc944ebd7eccffa7aa15d4a6 100644 (file)
@@ -547,5 +547,37 @@ esp_err_t esp_ble_gattc_cache_refresh(esp_bd_addr_t remote_bda)
     return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
 }
 
+esp_err_t esp_ble_gattc_cache_associa(esp_gatt_if_t gattc_if, esp_bd_addr_t src_addr, esp_bd_addr_t ass_addr, bool is_associa)
+{
+    btc_msg_t msg;
+    btc_ble_gattc_args_t arg;
+
+    ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
+
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_GATTC;
+    msg.act = BTC_GATTC_ACT_CACHE_ASSOCIAT;
+    arg.cache_associat.is_associa = is_associa;
+    arg.cache_associat.gattc_if = gattc_if;
+    memcpy(arg.cache_associat.src_addr, src_addr, sizeof(esp_bd_addr_t));
+    memcpy(arg.cache_associat.ass_addr, ass_addr, sizeof(esp_bd_addr_t));
+
+    return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+}
+
+esp_err_t esp_ble_gattc_cache_get_addr_list(esp_gatt_if_t gattc_if)
+{
+    btc_msg_t msg;
+    btc_ble_gattc_args_t arg;
+
+    ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
+
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_GATTC;
+    msg.act = BTC_GATTC_ATC_CACHE_GET_ADDR_LIST;
+    arg.get_addr_list.gattc_if = gattc_if;
+    return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+}
+
 #endif  ///GATTC_INCLUDED == TRUE
 
index 5f9ae198c7d90bbf94d58ead6d808a896feea001..577a4109d5c788845e8e23f47f4e073d830e810f 100644 (file)
@@ -65,6 +65,8 @@ typedef enum {
     ESP_GATTC_DISCONNECT_EVT          = 41,       /*!< When the ble physical connection disconnected, the event comes */
     ESP_GATTC_READ_MULTIPLE_EVT       = 42,       /*!< When the ble characteristic or descriptor multiple complete, the event comes */
     ESP_GATTC_QUEUE_FULL_EVT          = 43,       /*!< When the gattc command queue full, the event comes */
+    ESP_GATTC_SET_ASSOCIAT_EVT        = 44,       /*!< When the ble gattc set the associat address complete, the event comes */
+    ESP_GATTC_GET_ADDR_LIST_EVT       = 45,       /*!< When the ble get gattc address list in cache finish, the event comes */
 } esp_gattc_cb_event_t;
 
 
@@ -215,6 +217,20 @@ typedef union {
         uint16_t conn_id;               /*!< Connection id */
         esp_bd_addr_t remote_bda;       /*!< Remote bluetooth device address */
     } disconnect;                       /*!< Gatt client callback param of ESP_GATTC_DISCONNECT_EVT */
+    /**
+     * @brief ESP_GATTC_SET_ASSOCIAT_EVT
+     */
+    struct gattc_set_ass_addr_cmp_evt_param {
+        esp_gatt_status_t status;      /*!< Operation status */
+    } set_ass_cmp;                     /*!< Gatt client callback param of ESP_GATTC_SET_ASSOCIAT_EVT */
+    /**
+     * @brief ESP_GATTC_GET_ADDR_LIST_EVT
+     */
+    struct gattc_get_addr_list_evt_param {
+        esp_gatt_status_t status;      /*!< Operation status */
+        uint8_t num_addr;              /*!< The number of address in the gattc cache address list */
+        esp_bd_addr_t *addr_list;      /*!< The pointer to the address list which has been get from the gattc cache */
+    } get_addr_list;                   /*!< Gatt client callback param of ESP_GATTC_GET_ADDR_LIST_EVT */
 
     /**
      * @brief ESP_GATTC_QUEUE_FULL_EVT
@@ -784,6 +800,34 @@ esp_err_t esp_ble_gattc_unregister_for_notify (esp_gatt_if_t gattc_if,
 */
 esp_err_t esp_ble_gattc_cache_refresh(esp_bd_addr_t remote_bda);
 
+/**
+* @brief           Add or delete the associated address with the source address.
+*
+* @param[in]       gattc_if: Gatt client access interface.
+* @param[in]       src_addr: the source address which provide the attribute table.
+* @param[in]       ass_addr: the associated device address which went to share the attribute table with the source address.
+* @param[in]       is_associa: true add the associated device address, false remove the associated device address.
+* @return
+*                  - ESP_OK: success
+*                  - other: failed
+*
+*/
+esp_err_t esp_ble_gattc_cache_associa(esp_gatt_if_t gattc_if, esp_bd_addr_t src_addr, 
+                                      esp_bd_addr_t ass_addr, bool is_associa);
+/**
+* @brief           Get the address list which has store the attribute table in the gattc cache. There will
+*                  callback ESP_GATTC_GET_ADDR_LIST_EVT event when get address list complete.
+*
+* @param[in]       gattc_if: Gatt client access interface.
+* @return
+*                  - ESP_OK: success
+*                  - other: failed
+*
+*/
+esp_err_t esp_ble_gattc_cache_get_addr_list(esp_gatt_if_t gattc_if);
+
+
+
 #ifdef __cplusplus
 }
 #endif
index 7fb3ddac66a6d3e156367d81d701f53ef7e52abd..df1c4533390cb0f88716487363eaf09a1b9b25ca 100644 (file)
@@ -29,6 +29,7 @@
 #include "bta_api.h"
 #include "bta_dm_int.h"
 #include "bta_dm_co.h"
+#include "bta_gattc_co.h"
 #include "btm_api.h"
 #include "btm_int.h"
 #include "btu.h"
@@ -404,6 +405,10 @@ static void bta_dm_sys_hw_cback( tBTA_SYS_HW_EVT status )
         BTM_SetDeviceClass (dev_class);
 
 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
+#if (GATTC_INCLUDED == TRUE)
+        // load the gattc cache address list
+        bta_gattc_co_cache_addr_init();
+#endif /* #if (GATTC_INCLUDED = TRUE) */
         /* load BLE local information: ID keys, ER if available */
         bta_dm_co_ble_load_local_keys(&key_mask, er, &id_key);
 
index 1e7e32affd4561430d0f3990b41c53a67977dfd7..357d6b2ce330f95b97330032667bf97f254f6e04 100644 (file)
@@ -1754,6 +1754,7 @@ void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg)
             }
             if (found) {
                 bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
+                bta_gattc_cache_reset(p_msg->api_conn.remote_bda);
                 return;
             }
         }
@@ -1765,6 +1766,84 @@ void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg)
     }
     /* used to reset cache in application */
     bta_gattc_cache_reset(p_msg->api_conn.remote_bda);
+}
+
+void bta_gattc_process_api_cache_associat(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg)
+{
+    tBTA_GATTC gattc_cb = {0};
+    gattc_cb.set_associa.client_if = p_msg->api_associa.client_if;
+    BOOLEAN state = FALSE;
+    tBTA_GATTC_CLCB *p_ass_clcb = bta_gattc_find_clcb_by_cif(p_msg->api_associa.client_if, 
+                                                             p_msg->api_associa.ass_addr, BTA_TRANSPORT_LE);
+    tBTA_GATTC_RCB *p_clrcb = bta_gattc_cl_get_regcb(p_msg->api_associa.client_if);
+    if (p_ass_clcb != NULL) {
+        if (p_ass_clcb->state == BTA_GATTC_CONN_ST || p_ass_clcb->state == BTA_GATTC_DISCOVER_ST) {
+            gattc_cb.set_associa.status = BTA_GATT_BUSY;
+            if (p_clrcb != NULL) {
+                (*p_clrcb->p_cback)(BTA_GATTC_ASSOCIAT_EVT, &gattc_cb);
+                return;
+            }
+        }
+    }
+
+    if (p_msg->api_associa.is_associa) {
+        if ((state = bta_gattc_co_cache_append_ass_addr(p_msg->api_associa.src_addr, p_msg->api_associa.ass_addr)) == TRUE) {
+            gattc_cb.set_associa.status = BTA_GATT_OK;
+
+        } else {
+            gattc_cb.set_associa.status = BTA_GATT_ERROR;
+            if (p_clrcb != NULL) {
+                (*p_clrcb->p_cback)(BTA_GATTC_ASSOCIAT_EVT, &gattc_cb);
+                return;
+            }
+        }
+    } else {
+        if (( state = bta_gattc_co_cache_remove_ass_addr(p_msg->api_associa.src_addr, p_msg->api_associa.ass_addr)) == TRUE) {
+            gattc_cb.set_associa.status = BTA_GATT_OK;
+        } else {
+            gattc_cb.set_associa.status = BTA_GATT_ERROR;
+            if (p_clrcb != NULL) {
+                (*p_clrcb->p_cback)(BTA_GATTC_ASSOCIAT_EVT, &gattc_cb);
+                return;
+            }
+        }
+    }
+
+    if (p_clrcb != NULL) {
+        (*p_clrcb->p_cback)(BTA_GATTC_ASSOCIAT_EVT, &gattc_cb);
+    }
+
+    return;
+}
+void bta_gattc_process_api_cache_get_addr_list(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg)
+{
+    tBTA_GATTC gattc_cb = {0};
+    tBTA_GATTC_RCB *p_clrcb = bta_gattc_cl_get_regcb(p_msg->api_get_addr.client_if);
+    UINT8 num_addr = bta_gattc_co_get_addr_num();
+    gattc_cb.get_addr_list.client_if = p_msg->api_get_addr.client_if;
+
+    if (num_addr != 0) {
+        gattc_cb.get_addr_list.num_addr = num_addr;
+        gattc_cb.get_addr_list.bda_list = (BD_ADDR *)osi_malloc(sizeof(BD_ADDR)*num_addr);
+        if (gattc_cb.get_addr_list.bda_list != NULL) {
+            bta_gattc_co_get_addr_list(gattc_cb.get_addr_list.bda_list);
+            gattc_cb.get_addr_list.status = BTA_GATT_OK;
+        } else {
+            gattc_cb.get_addr_list.status = BTA_GATT_ERROR;
+        }
+    } else {
+        gattc_cb.get_addr_list.status = BTA_GATT_NOT_FOUND;
+    }
+
+    if (p_clrcb != NULL) {
+        (* p_clrcb->p_cback)(BTA_GATTC_GET_ADDR_LIST_EVT, &gattc_cb);
+    }
+
+    //release the address list buffer after used.
+    if (gattc_cb.get_addr_list.bda_list != NULL) {
+        osi_free((void *)gattc_cb.get_addr_list.bda_list);
+    }
 
 }
 /*******************************************************************************
index be633e4d07198efc5a199854386aee6bcf9c866b..b76c46bf83c2e756a353178ebb38fb7e6d50c31c 100644 (file)
@@ -929,6 +929,35 @@ void BTA_GATTC_Refresh(BD_ADDR remote_bda)
     return;
 }
 
+void BTA_GATTC_CacheAssociat(tBTA_GATTC_IF client_if, BD_ADDR src_addr, BD_ADDR ass_addr, BOOLEAN is_associa)
+{
+    tBTA_GATTC_API_CACHE_ASSO *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_CACHE_ASSO *)osi_malloc(sizeof(tBTA_GATTC_API_CACHE_ASSO))) != NULL) {
+        p_buf->hdr.event = BTA_GATTC_API_CACHE_ASSOCIAT_EVT;
+        p_buf->is_associa = is_associa;
+        p_buf->client_if  = client_if;
+        memcpy(p_buf->src_addr, src_addr, sizeof(BD_ADDR));
+        memcpy(p_buf->ass_addr, ass_addr, sizeof(BD_ADDR));
+
+        bta_sys_sendmsg(p_buf);
+        
+    }
+    return;
+}
+
+void BTA_GATTC_CacheGetAddrList(tBTA_GATTC_IF client_if)
+{
+    tBTA_GATTC_API_GET_ADDR *p_buf;
+    if ((p_buf = (tBTA_GATTC_API_GET_ADDR *)osi_malloc(sizeof(tBTA_GATTC_API_GET_ADDR))) != NULL) {
+        p_buf->hdr.event = BTA_GATTC_API_CACHE_GET_ADDR_LIST_EVT;
+        p_buf->client_if = client_if;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
 /*******************************************************************************
 **
 ** Function         BTA_GATTC_Listen
index f6fe9f1a8fff37093aa2a5defdfa12bc433dff77..9385fecec73dd63b65af5c9e07fbf8f8daf93469 100644 (file)
@@ -49,6 +49,8 @@ static size_t bta_gattc_get_db_size_with_type(list_t *services,
                                               bt_gatt_db_attribute_type_t type,
                                               tBT_UUID *char_uuid,
                                               UINT16 start_handle, UINT16 end_handle);
+static void bta_gattc_cache_write(BD_ADDR server_bda, UINT16 num_attr,
+                           tBTA_GATTC_NV_ATTR *attr);
 tBTA_GATTC_SERVICE*  bta_gattc_find_matching_service(const list_t *services, UINT16 handle);
 tBTA_GATTC_DESCRIPTOR*  bta_gattc_get_descriptor_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle);
 tBTA_GATTC_CHARACTERISTIC*  bta_gattc_get_characteristic_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle);
@@ -551,10 +553,7 @@ static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
     /* save cache to NV */
     p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
 
-    if (btm_sec_is_a_bonded_dev(p_srvc_cb->server_bda)) {
-        bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id);
-    }
-
+    bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id);
     bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK);
 }
 /*******************************************************************************
@@ -1217,6 +1216,7 @@ void bta_gattc_get_db_with_opration(UINT16 conn_id,
 
     tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
     if (!p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache)) {
+        APPL_TRACE_DEBUG("the service cache is empty.");
         *count = 0;
         *char_db = NULL;
         return;
@@ -1225,6 +1225,7 @@ void bta_gattc_get_db_with_opration(UINT16 conn_id,
     size_t db_size = ((end_handle - start_handle) < p_srcb->total_attr) ? (end_handle - start_handle) : p_srcb->total_attr;
 
     if (!db_size) {
+        APPL_TRACE_DEBUG("the db size is 0.");
         *count = 0;
         *char_db = NULL;
         return;
@@ -1233,6 +1234,7 @@ void bta_gattc_get_db_with_opration(UINT16 conn_id,
     void *buffer = osi_malloc(db_size*sizeof(btgatt_db_element_t));
 
     if (!buffer) {
+        APPL_TRACE_DEBUG("the buffer is NULL.");
         *count = 0;
         *char_db = NULL;
         return;
@@ -1303,6 +1305,7 @@ void bta_gattc_get_db_with_opration(UINT16 conn_id,
             }
             if ((op == GATT_OP_GET_ALL_CHAR || op == GATT_OP_GET_CHAR_BY_UUID) &&
                 (char_uuid == NULL || bta_gattc_uuid_compare(&p_char->uuid, char_uuid, TRUE))) {
+                APPL_TRACE_DEBUG("%s(), uuid match.", __func__);
                 bta_gattc_fill_gatt_db_el(curr_db_attr,
                                           BTGATT_DB_CHARACTERISTIC,
                                           p_char->handle,
@@ -1813,7 +1816,7 @@ void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr,
                              tBTA_GATTC_NV_ATTR *p_attr)
 {
     /* first attribute loading, initialize buffer */
-    APPL_TRACE_ERROR("%s: bta_gattc_rebuild_cache", __func__);
+    APPL_TRACE_DEBUG("%s: bta_gattc_rebuild_cache, num_attr = %d", __func__, num_attr);
 
     list_free(p_srvc_cb->p_srvc_cache);
     p_srvc_cb->p_srvc_cache = NULL;
@@ -1892,6 +1895,11 @@ void bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id)
     int i = 0;
     size_t db_size = bta_gattc_get_db_size(p_srvc_cb->p_srvc_cache, 0x0000, 0xFFFF);
     tBTA_GATTC_NV_ATTR *nv_attr = osi_malloc(db_size * sizeof(tBTA_GATTC_NV_ATTR));
+    // This step is very importent, if not clear the memory, the hasy key base on the attribute case will be not corret.
+    if (nv_attr != NULL) {
+        memset(nv_attr, 0, db_size * sizeof(tBTA_GATTC_NV_ATTR));
+    }
+
     if (!nv_attr) {
         APPL_TRACE_WARNING("%s(), no resource.", __func__);
         return;
@@ -1967,6 +1975,7 @@ void bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id)
     }
 
     /* TODO: Gattc cache write/read need to be added in IDF 3.1*/
+    bta_gattc_cache_write(p_srvc_cb->server_bda, db_size, nv_attr);
     osi_free(nv_attr);
 }
 
@@ -1983,56 +1992,56 @@ void bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id)
 *******************************************************************************/
 bool bta_gattc_cache_load(tBTA_GATTC_CLCB *p_clcb)
 {
-#if 0
-    char fname[255] = {0};
-    bta_gattc_generate_cache_file_name(fname, p_clcb->p_srcb->server_bda);
+    /* open NV cache and send call in */
+    tBTA_GATT_STATUS status = BTA_GATT_OK;
+    UINT8 index = 0;
+    tBTA_GATTC_NV_ATTR  *attr = NULL;
 
-    FILE *fd = fopen(fname, "rb");
-    if (!fd) {
-        APPL_TRACE_ERROR("%s: can't open GATT cache file %s for reading, error: %s",
-                         __func__, fname, strerror(errno));
+    if ((status = bta_gattc_co_cache_open(p_clcb->p_srcb->server_bda, true, &index)) != BTA_GATT_OK) {
+        APPL_TRACE_DEBUG("%s(), gattc cache open fail, index = %x", __func__, index);
         return false;
     }
 
-    UINT16 cache_ver = 0;
-    tBTA_GATTC_NV_ATTR  *attr = NULL;
-    bool success = false;
+    size_t num_attr = bta_gattc_get_cache_attr_length(index) / sizeof(tBTA_GATTC_NV_ATTR);
 
-    if (fread(&cache_ver, sizeof(UINT16), 1, fd) != 1) {
-        APPL_TRACE_ERROR("%s: can't read GATT cache version from: %s", __func__, fname);
-        goto done;
-    }
-
-    if (cache_ver != GATT_CACHE_VERSION) {
-        APPL_TRACE_ERROR("%s: wrong GATT cache version: %s", __func__, fname);
-        goto done;
+    if (!num_attr) {
+        return false;
     }
-
-    UINT16 num_attr = 0;
-
-    if (fread(&num_attr, sizeof(UINT16), 1, fd) != 1) {
-        APPL_TRACE_ERROR("%s: can't read number of GATT attributes: %s", __func__, fname);
-        goto done;
+    //don't forget to set the total attribute number.
+    p_clcb->p_srcb->total_attr = num_attr;
+    APPL_TRACE_DEBUG("%s(), index = %x, num_attr = %d", __func__, index, num_attr);
+    if ((attr = osi_malloc(sizeof(tBTA_GATTC_NV_ATTR) * num_attr)) == NULL) {
+        APPL_TRACE_ERROR("%s, No Memory.", __func__);
+        return false;
     }
-
-    attr = osi_malloc(sizeof(tBTA_GATTC_NV_ATTR) * num_attr);
-
-    if (fread(attr, sizeof(tBTA_GATTC_NV_ATTR), 0xFF, fd) != num_attr) {
-        APPL_TRACE_ERROR("%s: can't read GATT attributes: %s", __func__, fname);
-        goto done;
+    if ((status = bta_gattc_co_cache_load(attr, index)) != BTA_GATT_OK) {
+        APPL_TRACE_DEBUG("%s(), gattc cache load fail, status = %x", __func__, status);
+        return false;
     }
 
     bta_gattc_rebuild_cache(p_clcb->p_srcb, num_attr, attr);
-
-    success = true;
-
-done:
+    //free the attr buffer after used.
     osi_free(attr);
-    fclose(fd);
-    return success;
-#endif
-    bool success = false;
-    return success;
+    return true;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_cache_write
+**
+** Description      This callout function is executed by GATT when a server cache
+**                  is available to save.
+**
+** Parameter        server_bda: server bd address of this cache belongs to
+**                  num_attr: number of attribute to be save.
+**                  attr: pointer to the list of attributes to save.
+** Returns
+**
+*******************************************************************************/
+static void bta_gattc_cache_write(BD_ADDR server_bda, UINT16 num_attr,
+                           tBTA_GATTC_NV_ATTR *attr)
+{
+    bta_gattc_co_cache_save(server_bda, num_attr, attr);
 }
 
 /*******************************************************************************
@@ -2052,6 +2061,7 @@ void bta_gattc_cache_reset(BD_ADDR server_bda)
     BTIF_TRACE_DEBUG("%s", __func__);
     char fname[255] = {0};
     bta_gattc_generate_cache_file_name(fname, server_bda);
+    bta_gattc_co_cache_reset(server_bda);
     //unlink(fname);
 }
 #endif /* BTA_GATT_INCLUDED */
index ea041402496cb77bb1c5168251e1ab9ca46353f8..224f34e39d0cf1d95b30f093436b83dea2157f10 100644 (file)
@@ -356,7 +356,12 @@ BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg)
     case BTA_GATTC_API_REFRESH_EVT:
         bta_gattc_process_api_refresh(p_cb, (tBTA_GATTC_DATA *) p_msg);
         break;
-
+    case BTA_GATTC_API_CACHE_ASSOCIAT_EVT:
+        bta_gattc_process_api_cache_associat(p_cb, (tBTA_GATTC_DATA *)p_msg);
+        break;
+    case BTA_GATTC_API_CACHE_GET_ADDR_LIST_EVT:
+        bta_gattc_process_api_cache_get_addr_list(p_cb, (tBTA_GATTC_DATA *)p_msg);
+        break;
 #if BLE_INCLUDED == TRUE
     case BTA_GATTC_API_LISTEN_EVT:
         bta_gattc_listen(p_cb, (tBTA_GATTC_DATA *) p_msg);
index 3d36961b0bb846badcff8b70c26506fce9e60800..c866b05a3296f51a78b872ab3ceaf5cea39489fd 100644 (file)
@@ -183,6 +183,8 @@ typedef UINT8 tBTA_GATT_STATUS;
 #define BTA_GATTC_DISCONNECT_EVT        36 /* GATTC DISCONNECT  event */
 #define BTA_GATTC_READ_MULTIPLE_EVT     37 /* GATTC Read mutiple event */
 #define BTA_GATTC_QUEUE_FULL_EVT        38 /* GATTC queue full event */
+#define BTA_GATTC_ASSOCIAT_EVT          39 /* GATTC association address event */
+#define BTA_GATTC_GET_ADDR_LIST_EVT     40 /* GATTC get address list in the cache event */
 
 typedef UINT8 tBTA_GATTC_EVT;
 
@@ -364,12 +366,24 @@ typedef struct {
     BOOLEAN is_full;
 } tBTA_GATTC_QUEUE_FULL;
 
+typedef struct {
+    tBTA_GATT_STATUS   status;
+    tBTA_GATTC_IF      client_if;
+} tBTA_GATTC_SET_ASSOCIAT;
+
+typedef struct {
+    tBTA_GATT_STATUS    status;
+    tBTA_GATTC_IF       client_if;
+    UINT8               num_addr;
+    BD_ADDR             *bda_list;
+} tBTA_GATTC_GET_ADDR_LIST;
+
 typedef struct {
     tBTA_GATT_STATUS        status;
     tBTA_GATTC_IF           client_if;
     UINT16                  conn_id;
     BD_ADDR                 remote_bda;
-}tBTA_GATTC_OPEN_CLOSE;
+} tBTA_GATTC_OPEN_CLOSE;
 
 typedef struct {
     tBTA_GATTC_IF           client_if;
@@ -413,6 +427,8 @@ typedef union {
     tBTA_GATTC_CONGEST      congest;
     tBTA_GATTC_QUEUE_FULL   queue_full;
     tBTA_GATTC_SERVICE_CHANGE srvc_chg;     /* service change event */
+    tBTA_GATTC_SET_ASSOCIAT set_associa;
+    tBTA_GATTC_GET_ADDR_LIST get_addr_list;
 } tBTA_GATTC;
 
 /* GATTC enable callback function */
@@ -1085,6 +1101,10 @@ extern void BTA_GATTC_ReadMultiple(UINT16 conn_id, tBTA_GATTC_MULTI *p_read_mult
 *******************************************************************************/
 extern void BTA_GATTC_Refresh(BD_ADDR remote_bda);
 
+extern void BTA_GATTC_CacheAssociat(tBTA_GATTC_IF client_if, BD_ADDR src_addr, BD_ADDR ass_addr, BOOLEAN is_associa);
+
+extern void BTA_GATTC_CacheGetAddrList(tBTA_GATTC_IF client_if);
+
 
 /*******************************************************************************
 **
index 12b3a4217360844a8cbb873f16c35edaf1006781..c4caf14990069a95de02aa7222a4e37d41244ed0 100644 (file)
@@ -36,7 +36,7 @@ typedef struct {
     tBTA_GATT_STATUS  status;
 } tBTA_GATTC_CI_EVT;
 
-#define BTA_GATTC_NV_LOAD_MAX   10
+#define BTA_GATTC_NV_LOAD_MAX   100
 
 /* Read Ready Event */
 typedef struct {
index f84f9d354c1af0a2976daf63c2c1c5afb54dfc59..84415f0164d320ae41df8a0912838a24f0e524a6 100644 (file)
@@ -25,6 +25,7 @@
 #define BTA_GATTC_CO_H
 
 #include "bta_gatt_api.h"
+#include "hashkey.h"
 
 /*******************************************************************************
 **
@@ -41,8 +42,7 @@
 ** Returns          void.
 **
 *******************************************************************************/
-extern void bta_gattc_co_cache_open(BD_ADDR server_bda, UINT16 evt,
-                                    UINT16 conn_id, BOOLEAN to_save);
+extern tBTA_GATT_STATUS bta_gattc_co_cache_open(BD_ADDR server_bda, BOOLEAN to_save, UINT8 *index);
 
 /*******************************************************************************
 **
@@ -75,9 +75,8 @@ extern void bta_gattc_co_cache_close(BD_ADDR server_bda, UINT16 conn_id);
 ** Returns
 **
 *******************************************************************************/
-extern void bta_gattc_co_cache_save(BD_ADDR server_bda, UINT16 evt,
-                                    UINT16 num_attr, tBTA_GATTC_NV_ATTR *p_attr,
-                                    UINT16 attr_index, UINT16 conn_id);
+extern void bta_gattc_co_cache_save (BD_ADDR server_bda, UINT16 num_attr,
+                              tBTA_GATTC_NV_ATTR *p_attr_list);
 
 /*******************************************************************************
 **
@@ -94,8 +93,7 @@ extern void bta_gattc_co_cache_save(BD_ADDR server_bda, UINT16 evt,
 ** Returns
 **
 *******************************************************************************/
-extern void bta_gattc_co_cache_load(BD_ADDR server_bda, UINT16 evt,
-                                    UINT16 start_index, UINT16 conn_id);
+extern tBTA_GATT_STATUS bta_gattc_co_cache_load(tBTA_GATTC_NV_ATTR *attr, UINT8 index);
 
 /*******************************************************************************
 **
@@ -111,4 +109,30 @@ extern void bta_gattc_co_cache_load(BD_ADDR server_bda, UINT16 evt,
 *******************************************************************************/
 extern void bta_gattc_co_cache_reset(BD_ADDR server_bda);
 
+extern size_t bta_gattc_get_cache_attr_length(UINT8 index);
+
+extern void bta_gattc_co_cache_addr_init(void);
+
+extern BOOLEAN bta_gattc_co_addr_in_cache(BD_ADDR bda);
+
+extern uint8_t bta_gattc_co_find_addr_in_cache(BD_ADDR bda);
+
+extern uint8_t bta_gattc_co_find_hash_in_cache(coap_key_t hash_key);
+
+extern UINT8 bta_gattc_co_get_addr_num(void);
+
+extern void bta_gattc_co_get_addr_list(BD_ADDR *addr_list);
+
+extern void bta_gattc_co_cache_addr_save(BD_ADDR bd_addr, coap_key_t hash_key);
+
+extern BOOLEAN bta_gattc_co_cache_new_ass_list(BD_ADDR src_addr, uint8_t index);
+
+extern BOOLEAN bta_gattc_co_cache_append_ass_addr(BD_ADDR src_addr, BD_ADDR ass_addr);
+
+extern BOOLEAN bta_gattc_co_cache_remove_ass_addr(BD_ADDR src_addr, BD_ADDR ass_addr);
+
+uint8_t* bta_gattc_co_cache_find_src_addr(BD_ADDR ass_addr, uint8_t *index);
+
+extern BOOLEAN bta_gattc_co_cache_clear_ass_addr(BD_ADDR src_addr);
+
 #endif /* BTA_GATT_CO_H */
index 8ce71871699700bfb4547d03bd78a6f8f2cbdfa5..96b6e6f0d02f6dd6a6145e020191ada4f1ccc50d 100644 (file)
@@ -65,7 +65,9 @@ enum {
     BTA_GATTC_API_LISTEN_EVT,
     BTA_GATTC_API_BROADCAST_EVT,
     BTA_GATTC_API_DISABLE_EVT,
-    BTA_GATTC_ENC_CMPL_EVT
+    BTA_GATTC_ENC_CMPL_EVT,  
+    BTA_GATTC_API_CACHE_ASSOCIAT_EVT,
+    BTA_GATTC_API_CACHE_GET_ADDR_LIST_EVT,
 };
 typedef UINT16 tBTA_GATTC_INT_EVT;
 
@@ -186,6 +188,19 @@ typedef struct {
     BT_HDR              hdr;
 } tBTA_GATTC_API_CFG_MTU;
 
+typedef struct {
+    BT_HDR             hdr;
+    tBTA_GATTC_IF      client_if;
+    BD_ADDR            src_addr;
+    BD_ADDR            ass_addr;
+    BOOLEAN            is_associa;
+} tBTA_GATTC_API_CACHE_ASSO;
+
+typedef struct {
+    BT_HDR             hdr;
+    tBTA_GATTC_IF      client_if;
+} tBTA_GATTC_API_GET_ADDR;
+
 typedef struct {
     BT_HDR                  hdr;
     BD_ADDR                 remote_bda;
@@ -215,6 +230,8 @@ typedef union {
     tBTA_GATTC_API_EXEC         api_exec;
     tBTA_GATTC_API_READ_MULTI   api_read_multi;
     tBTA_GATTC_API_CFG_MTU      api_mtu;
+    tBTA_GATTC_API_CACHE_ASSO   api_associa;
+    tBTA_GATTC_API_GET_ADDR     api_get_addr;
     tBTA_GATTC_OP_CMPL          op_cmpl;
     tBTA_GATTC_INT_CONN         int_conn;
     tBTA_GATTC_ENC_CMPL         enc_cmpl;
@@ -447,6 +464,8 @@ extern void bta_gattc_send_connect_cback( tBTA_GATTC_RCB *p_clreg, BD_ADDR remot
 extern void bta_gattc_send_disconnect_cback( tBTA_GATTC_RCB *p_clreg, tGATT_DISCONN_REASON reason,
                                 BD_ADDR remote_bda, UINT16 conn_id);
 extern void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg);
+extern void bta_gattc_process_api_cache_associat(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg);
+extern void bta_gattc_process_api_cache_get_addr_list(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg);
 extern void bta_gattc_cfg_mtu(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
 #if BLE_INCLUDED == TRUE
 extern void bta_gattc_listen(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg);
index 79bff3b7e2393a6132681dc30c5245902e5b8540..c07ddc75e071ddac4c4a83d2086460515d884eeb 100644 (file)
@@ -142,6 +142,18 @@ static void btc_gattc_copy_req_data(btc_msg_t *msg, void *p_dest, void *p_src)
             }
             break;
         }
+        case BTA_GATTC_GET_ADDR_LIST_EVT: {
+            if (p_src_data->get_addr_list.bda_list != NULL) {
+                uint8_t num_addr = p_src_data->get_addr_list.num_addr;
+                p_dest_data->get_addr_list.bda_list = (BD_ADDR *)osi_malloc(sizeof(BD_ADDR) * num_addr);
+                if (p_dest_data->get_addr_list.bda_list) {
+                    memcpy(p_dest_data->get_addr_list.bda_list, p_src_data->get_addr_list.bda_list, sizeof(BD_ADDR) * num_addr);
+                } else {
+                    LOG_ERROR("%s %d no mem\n", __func__, msg->act);
+                }
+            }
+            break;
+        }
         default:
             break;
     }
@@ -159,6 +171,12 @@ static void btc_gattc_free_req_data(btc_msg_t *msg)
             }
             break;
         }
+        case BTA_GATTC_GET_ADDR_LIST_EVT: {
+            if (arg->get_addr_list.bda_list) {
+                osi_free(arg->get_addr_list.bda_list);
+            }
+            break;
+        }
         default:
             break;
     }
@@ -721,6 +739,15 @@ void btc_gattc_call_handler(btc_msg_t *msg)
     case BTC_GATTC_ACT_CACHE_REFRESH:
         BTA_GATTC_Refresh(arg->cache_refresh.remote_bda);
         break;
+    case BTC_GATTC_ACT_CACHE_ASSOCIAT:
+        BTA_GATTC_CacheAssociat(arg->cache_associat.gattc_if,
+                                arg->cache_associat.src_addr,
+                                arg->cache_associat.ass_addr,
+                                arg->cache_associat.is_associa);
+        break;
+    case BTC_GATTC_ATC_CACHE_GET_ADDR_LIST:
+        BTA_GATTC_CacheGetAddrList(arg->get_addr_list.gattc_if);
+        break;
     default:
         LOG_ERROR("%s: Unhandled event (%d)!\n", __FUNCTION__, msg->act);
         break;
@@ -928,6 +955,20 @@ void btc_gattc_cb_handler(btc_msg_t *msg)
         btc_gattc_cb_to_app(ESP_GATTC_QUEUE_FULL_EVT, gattc_if, &param);
         break;
     }
+    case BTA_GATTC_ASSOCIAT_EVT: {
+        gattc_if = arg->set_associa.client_if;
+        param.set_ass_cmp.status = arg->set_associa.status;
+        btc_gattc_cb_to_app(ESP_GATTC_SET_ASSOCIAT_EVT, gattc_if, &param);
+        break;
+    }
+    case BTA_GATTC_GET_ADDR_LIST_EVT: {
+        gattc_if = arg->get_addr_list.client_if;
+        param.get_addr_list.status = arg->get_addr_list.status;
+        param.get_addr_list.num_addr = arg->get_addr_list.num_addr;
+        param.get_addr_list.addr_list = arg->get_addr_list.bda_list;
+        btc_gattc_cb_to_app(ESP_GATTC_GET_ADDR_LIST_EVT, gattc_if, &param);
+        break;
+    }
     default:
         LOG_DEBUG("%s: Unhandled event (%d)!", __FUNCTION__, msg->act);
         break;
index 3391dd1c9f0cd1e29e01f4d449e21dc7a01066f9..f36bd5a0728ff1ac8a95f56f096a78a961ceed07 100644 (file)
@@ -38,6 +38,8 @@ typedef enum {
     BTC_GATTC_ACT_REG_FOR_NOTIFY,
     BTC_GATTC_ACT_UNREG_FOR_NOTIFY,
     BTC_GATTC_ACT_CACHE_REFRESH,
+    BTC_GATTC_ACT_CACHE_ASSOCIAT,
+    BTC_GATTC_ATC_CACHE_GET_ADDR_LIST,
 } btc_gattc_act_t;
 
 /* btc_ble_gattc_args_t */
@@ -167,6 +169,17 @@ typedef union {
     struct cache_refresh_arg {
         esp_bd_addr_t remote_bda;
     } cache_refresh;
+    //BTC_GATTC_ACT_CACHE_ASSOCIAT
+    struct cache_associat_arg {
+        esp_gatt_if_t gattc_if;
+        esp_bd_addr_t src_addr;
+        esp_bd_addr_t ass_addr;
+        bool is_associa;
+    } cache_associat;
+    //BTC_GATTC_ATC_CACHE_GET_ADDR_LIST
+    struct cache_get_addr_list_arg {
+        esp_gatt_if_t gattc_if;
+    }get_addr_list;
 } btc_ble_gattc_args_t;
 
 void btc_gattc_call_handler(btc_msg_t *msg);
index b716766a7f41a44783ee48b146d169e24646dba1..7cb215334e234fb9b5ea0293da3d9a4b52a639e2 100644 (file)
 #include "bta_gattc_ci.h"
 // #include "btif_util.h"
 #include "btm_int.h"
+#include "nvs.h"
+#include "nvs_flash.h"
+#include "list.h"
+#include "esp_err.h"
+#include "allocator.h"
 
 #if( defined BLE_INCLUDED ) && (BLE_INCLUDED == TRUE)
 #if( defined BTA_GATT_INCLUDED ) && (GATTC_INCLUDED == TRUE)
 
-#define GATT_CACHE_PREFIX "/data/misc/bluedroid/gatt_cache_"
+#define GATT_CACHE_PREFIX "gatt_"
+#define INVALID_ADDR_NUM 0xff
+#define MAX_DEVICE_IN_CACHE 50
+#define MAX_ADDR_LIST_CACHE_BUF 2048
 
 #ifdef BT_SUPPORT_NVM
 static FILE *sCacheFD = 0;
-
 static void getFilename(char *buffer, BD_ADDR bda)
 {
     sprintf(buffer, "%s%02x%02x%02x%02x%02x%02x", GATT_CACHE_PREFIX
@@ -65,6 +72,96 @@ static void cacheReset(BD_ADDR bda)
     unlink(fname);
 }
 
+#else
+
+static const char *cache_key = "gattc_cahe_key";
+static const char *cache_addr = "cache_addr_tab";
+nvs_handle nvs_fp;
+
+typedef struct {
+    //save the service data in the list according to the address
+    nvs_handle cache_fp;
+    BOOLEAN is_open;
+    BD_ADDR addr;
+    coap_key_t hash_key;
+    list_t *ass_addr;
+}cache_addr_info_t;
+
+typedef struct {
+    //save the address list in the cache
+    nvs_handle addr_fp;
+    BOOLEAN is_open;
+    UINT8 num_addr;
+    cache_addr_info_t cache_addr[MAX_DEVICE_IN_CACHE];
+}cache_env_t;
+
+cache_env_t cache_env;
+
+static void getFilename(char *buffer, coap_key_t hash)
+{
+    sprintf(buffer, "%s%02x%02x%02x%02x", GATT_CACHE_PREFIX,
+            hash[0], hash[1], hash[2], hash[3]);
+}
+
+static void cacheClose(BD_ADDR bda)
+{
+    UINT8 index = 0;
+    if ((index = bta_gattc_co_find_addr_in_cache(bda)) != INVALID_ADDR_NUM) {
+        if (cache_env.cache_addr[index].is_open) {
+            nvs_close(cache_env.cache_addr[index].cache_fp);
+            cache_env.cache_addr[index].is_open = FALSE;
+        }
+    }
+}
+
+static bool cacheOpen(BD_ADDR bda, bool to_save, UINT8 *index)
+{
+    UNUSED(to_save);
+    char fname[255] = {0};
+    UINT8 *ass_addr = NULL;
+    esp_err_t status = ESP_FAIL;
+    coap_key_t hash_key = {0};
+    if (((*index = bta_gattc_co_find_addr_in_cache(bda)) != INVALID_ADDR_NUM) ||
+        ((ass_addr = bta_gattc_co_cache_find_src_addr(bda, index)) != NULL)) {
+        if (cache_env.cache_addr[*index].is_open) {
+            return TRUE;
+        } else {
+            memcpy(hash_key, cache_env.cache_addr[*index].hash_key, sizeof(coap_key_t));
+            getFilename(fname, hash_key);
+            if ((status = nvs_open(fname, NVS_READWRITE, &cache_env.cache_addr[*index].cache_fp)) == ESP_OK) {
+                // Set the open flag to TRUE when success to open the hash file.
+                cache_env.cache_addr[*index].is_open = TRUE;
+            }
+        }
+    }
+    
+    return ((status == ESP_OK) ? true : false);
+}
+
+static void cacheReset(BD_ADDR bda)
+{
+    char fname[255] = {0};
+    getFilename(fname, bda);
+    UINT8 index = 0;
+      //cache_env.cache_addr
+    if ((index = bta_gattc_co_find_addr_in_cache(bda)) != INVALID_ADDR_NUM) {
+        //clear the association address pending in the source address.
+        bta_gattc_co_cache_clear_ass_addr(bda);
+        if (cache_env.cache_addr[index].is_open) {
+            nvs_erase_all(cache_env.cache_addr[index].cache_fp);
+            nvs_close(cache_env.cache_addr[index].cache_fp);
+            cache_env.cache_addr[index].is_open = FALSE;
+        }
+        UINT8 num = cache_env.num_addr;
+        //delete the server_bda in the addr_info list.
+        for(UINT8 i = index; i < (num - 1); i++) {
+            memcpy(&cache_env.cache_addr[i], &cache_env.cache_addr[i+1], sizeof(cache_addr_info_t));
+        }
+        //reduced the number address counter also
+        cache_env.num_addr--;
+    }
+}
+
 #endif /* BT_SUPPORT_NVM */
 /*****************************************************************************
 **  Function Declarations
@@ -85,20 +182,16 @@ static void cacheReset(BD_ADDR bda)
 ** Returns          void.
 **
 *******************************************************************************/
-void bta_gattc_co_cache_open(BD_ADDR server_bda, UINT16 evt, UINT16 conn_id, BOOLEAN to_save)
+tBTA_GATT_STATUS bta_gattc_co_cache_open(BD_ADDR server_bda, BOOLEAN to_save, UINT8 *index)
 {
-#ifdef BT_SUPPORT_NVM
     /* open NV cache and send call in */
-    tBTA_GATT_STATUS    status = BTA_GATT_OK;
-    if (!btm_sec_is_a_bonded_dev(server_bda) || !cacheOpen(server_bda, to_save)) {
+    tBTA_GATT_STATUS status = BTA_GATT_OK;
+    if (!cacheOpen(server_bda, to_save, index)) {
         status = BTA_GATT_ERROR;
     }
 
-    BTIF_TRACE_DEBUG("%s() - status=%d", __FUNCTION__, status);
-    bta_gattc_ci_cache_open(server_bda, evt, status, conn_id);
-#else
-    bta_gattc_ci_cache_open(server_bda, evt, BTA_GATT_ERROR, conn_id);
-#endif /* BT_SUPPORT_NVM */
+    APPL_TRACE_DEBUG("%s() - status=%d", __func__, status);
+    return status;
 }
 
 /*******************************************************************************
@@ -116,21 +209,33 @@ void bta_gattc_co_cache_open(BD_ADDR server_bda, UINT16 evt, UINT16 conn_id, BOO
 ** Returns
 **
 *******************************************************************************/
-void bta_gattc_co_cache_load(BD_ADDR server_bda, UINT16 evt, UINT16 start_index, UINT16 conn_id)
+tBTA_GATT_STATUS bta_gattc_co_cache_load(tBTA_GATTC_NV_ATTR *attr, UINT8 index)
 {
     UINT16              num_attr = 0;
-    tBTA_GATTC_NV_ATTR  attr[BTA_GATTC_NV_LOAD_MAX];
     tBTA_GATT_STATUS    status = BTA_GATT_ERROR;
-#ifdef BT_SUPPORT_NVM
-    if (sCacheFD && (0 == fseek(sCacheFD, start_index * sizeof(tBTA_GATTC_NV_ATTR), SEEK_SET))) {
-        num_attr = fread(attr, sizeof(tBTA_GATTC_NV_ATTR), BTA_GATTC_NV_LOAD_MAX, sCacheFD);
-        status = (num_attr < BTA_GATTC_NV_LOAD_MAX ? BTA_GATT_OK : BTA_GATT_MORE);
+    size_t length = 0;
+    // Read the size of memory space required for blob
+    nvs_get_blob(cache_env.cache_addr[index].cache_fp, cache_key, NULL, &length);
+    // Read previously saved blob if available
+    esp_err_t err_code = nvs_get_blob(cache_env.cache_addr[index].cache_fp, cache_key, attr, &length);
+    num_attr = length / sizeof(tBTA_GATTC_NV_ATTR);
+    status = (err_code == ESP_OK && length != 0) ? BTA_GATT_OK : BTA_GATT_ERROR;
+    APPL_TRACE_DEBUG("%s() - read=%d, status=%d, err_code = %d",
+                     __func__, num_attr, status, err_code);
+
+    return status;
+ }
+
+size_t bta_gattc_get_cache_attr_length(UINT8 index)
+{
+    size_t length = 0;
+    if (index == INVALID_ADDR_NUM) {
+        return 0;
     }
-    BTIF_TRACE_DEBUG("%s() - sCacheFD=%p, start_index=%d, read=%d, status=%d",
-                     __FUNCTION__, sCacheFD, start_index, num_attr, status);
-#endif /* BT_SUPPORT_NVM */
 
-    bta_gattc_ci_cache_load(server_bda, evt, num_attr, attr, status, conn_id);
+    // Read the size of memory space required for blob
+    nvs_get_blob(cache_env.cache_addr[index].cache_fp, cache_key, NULL, &length);
+    return length;
 }
 
 /*******************************************************************************
@@ -149,18 +254,26 @@ void bta_gattc_co_cache_load(BD_ADDR server_bda, UINT16 evt, UINT16 start_index,
 ** Returns
 **
 *******************************************************************************/
-void bta_gattc_co_cache_save (BD_ADDR server_bda, UINT16 evt, UINT16 num_attr,
-                              tBTA_GATTC_NV_ATTR *p_attr_list, UINT16 attr_index, UINT16 conn_id)
+void bta_gattc_co_cache_save (BD_ADDR server_bda, UINT16 num_attr,
+                              tBTA_GATTC_NV_ATTR *p_attr_list)
 {
     tBTA_GATT_STATUS    status = BTA_GATT_OK;
-    UNUSED(attr_index);
-#ifdef BT_SUPPORT_NVM
-    if (sCacheFD != 0) {
-        int num = fwrite(p_attr_list, sizeof(tBTA_GATTC_NV_ATTR), num_attr, sCacheFD);
-        BTIF_TRACE_DEBUG("%s() wrote %d", __FUNCTION__, num);
+    coap_key_t hash_key = {0};
+    UINT8 index = INVALID_ADDR_NUM;
+    //calculate  the hash value of the attribute table which should be added to the nvs flash.
+    coap_hash_impl((unsigned char *)p_attr_list, sizeof(tBTA_GATTC_NV_ATTR)*num_attr, hash_key);
+    //save the address list to the nvs flash
+    bta_gattc_co_cache_addr_save(server_bda, hash_key);
+
+    if (cacheOpen(server_bda, TRUE, &index)) {
+        esp_err_t err_code = nvs_set_blob(cache_env.cache_addr[index].cache_fp, cache_key,
+                                          p_attr_list, sizeof(tBTA_GATTC_NV_ATTR)*num_attr);
+        status = (err_code == ESP_OK) ? BTA_GATT_OK : BTA_GATT_ERROR;
+    } else {
+        status = BTA_GATT_ERROR;
     }
-#endif /* BT_SUPPORT_NVM */
-    bta_gattc_ci_cache_save(server_bda, evt, status, conn_id);
+
+    APPL_TRACE_DEBUG("%s() wrote hash_key = %x%x%x%x, num_attr = %d, status = %d.", __func__, hash_key[0], hash_key[1], hash_key[2], hash_key[3], num_attr, status);
 }
 
 /*******************************************************************************
@@ -178,11 +291,10 @@ void bta_gattc_co_cache_save (BD_ADDR server_bda, UINT16 evt, UINT16 num_attr,
 *******************************************************************************/
 void bta_gattc_co_cache_close(BD_ADDR server_bda, UINT16 conn_id)
 {
-    UNUSED(server_bda);
     UNUSED(conn_id);
-#ifdef BT_SUPPORT_NVM
-    cacheClose();
-#endif /* BT_SUPPORT_NVM */
+//#ifdef BT_SUPPORT_NVM
+    cacheClose(server_bda);
+//#endif /* BT_SUPPORT_NVM */
     /* close NV when server cache is done saving or loading,
        does not need to do anything for now on Insight */
 
@@ -203,10 +315,256 @@ void bta_gattc_co_cache_close(BD_ADDR server_bda, UINT16 conn_id)
 *******************************************************************************/
 void bta_gattc_co_cache_reset(BD_ADDR server_bda)
 {
-    BTIF_TRACE_DEBUG("%s()", __FUNCTION__);
-#ifdef BT_SUPPORT_NVM
     cacheReset(server_bda);
-#endif /* BT_SUPPORT_NVM */
+}
+
+void bta_gattc_co_cache_addr_init(void)
+{
+    nvs_handle fp;
+    esp_err_t err_code;
+    UINT8 num_addr;
+    UINT8 *p_buf = osi_malloc(MAX_ADDR_LIST_CACHE_BUF);
+    size_t length = 0;
+
+    if ((err_code = nvs_open(cache_addr, NVS_READWRITE, &fp)) == ESP_OK) {
+        cache_env.addr_fp = fp;
+        // Read previously saved blob if available
+        if ((err_code = nvs_get_blob(fp, cache_key, p_buf, &length)) != ESP_OK) {
+            APPL_TRACE_ERROR("%s, Line = %d, nvs flash get blob data fail, err_code = %x", __func__, __LINE__, err_code);
+            osi_free(p_buf);
+            return;
+        }
+        num_addr = length / (sizeof(BD_ADDR) + sizeof(coap_key_t));
+        cache_env.num_addr = num_addr;
+        //read the address from nvs flash to cache address list.
+        for (UINT8 i = 0; i < num_addr; i++) {
+            memcpy(cache_env.cache_addr[i].addr, p_buf + i*(sizeof(BD_ADDR) + sizeof(coap_key_t)), sizeof(BD_ADDR));
+            memcpy(cache_env.cache_addr[i].hash_key,
+                    p_buf + i*(sizeof(BD_ADDR) + sizeof(coap_key_t)) + sizeof(BD_ADDR), sizeof(coap_key_t));
+
+            APPL_TRACE_DEBUG("cache_addr[%x] = %x:%x:%x:%x:%x:%x", i, cache_env.cache_addr[i].addr[0], cache_env.cache_addr[i].addr[1], cache_env.cache_addr[i].addr[2],
+                             cache_env.cache_addr[i].addr[3], cache_env.cache_addr[i].addr[4], cache_env.cache_addr[i].addr[5]);
+            APPL_TRACE_DEBUG("hash_key[%x] = %x%x%x%x", i, cache_env.cache_addr[i].hash_key[0], cache_env.cache_addr[i].hash_key[1],
+                             cache_env.cache_addr[i].hash_key[2], cache_env.cache_addr[i].hash_key[3]);
+            bta_gattc_co_cache_new_ass_list(cache_env.cache_addr[i].addr, i);
+        }
+    } else {
+        APPL_TRACE_ERROR("%s, Line = %d, nvs flash open fail, err_code = %x", __func__, __LINE__, err_code);
+        osi_free(p_buf);
+        return;
+    }
+
+    osi_free(p_buf);
+    return;
+}
+
+BOOLEAN bta_gattc_co_addr_in_cache(BD_ADDR bda)
+{
+    UINT8 addr_index = 0;
+    UINT8 num = cache_env.num_addr;
+    cache_addr_info_t *addr_info = &cache_env.cache_addr[0];
+    for (addr_index = 0; addr_index < num; addr_index++) {
+        if (!memcmp(addr_info->addr, bda, sizeof(BD_ADDR))) {
+            return TRUE;
+        }
+    }
+
+    return FALSE;
+}
+
+UINT8 bta_gattc_co_find_addr_in_cache(BD_ADDR bda)
+{
+    UINT8 addr_index = 0;
+    UINT8 num = cache_env.num_addr;
+    cache_addr_info_t *addr_info = &cache_env.cache_addr[0];
+
+    for (addr_index = 0; addr_index < num; addr_index++, addr_info++) {
+        if (!memcmp(addr_info->addr, bda, sizeof(BD_ADDR))) {
+            return addr_index;
+        }
+    }
+
+    return INVALID_ADDR_NUM;
+}
+
+UINT8 bta_gattc_co_find_hash_in_cache(coap_key_t hash_key)
+{
+    UINT8 index = 0;
+    UINT8 num = cache_env.num_addr;
+    cache_addr_info_t *addr_info = &cache_env.cache_addr[0];
+    for (index = 0; index < num; index++) {
+        if (!memcmp(addr_info->hash_key, hash_key, sizeof(coap_key_t))) {
+            return index;
+        }
+    }
+
+    return INVALID_ADDR_NUM;
+}
+
+UINT8 bta_gattc_co_get_addr_num(void)
+{
+    return cache_env.num_addr;
+}
+
+void bta_gattc_co_get_addr_list(BD_ADDR *addr_list)
+{
+    UINT8 num = cache_env.num_addr;
+    for (UINT8 i = 0; i < num; i++) {
+        memcpy(addr_list[i], cache_env.cache_addr[i].addr, sizeof(BD_ADDR));
+    }
+}
+
+void bta_gattc_co_cache_addr_save(BD_ADDR bd_addr, coap_key_t hash_key)
+{
+    esp_err_t err_code;
+    UINT8 num = ++cache_env.num_addr;
+    UINT8 index = 0;
+    UINT8 *p_buf = osi_malloc(MAX_ADDR_LIST_CACHE_BUF);
+    // check the address list has the same hash key or not
+    if (bta_gattc_co_find_hash_in_cache(hash_key) != INVALID_ADDR_NUM) {
+        APPL_TRACE_DEBUG("%s(), the hash key already in the cache list.", __func__);
+        if ((index = bta_gattc_co_find_addr_in_cache(bd_addr)) != INVALID_ADDR_NUM) {
+            APPL_TRACE_DEBUG("%s(), the hash bd_addr already in the cache list, index = %x", __func__, index);
+            //if the bd_addr already in the address list, update the hash key in it.
+            memcpy(cache_env.cache_addr[index].addr, bd_addr, sizeof(BD_ADDR));
+            memcpy(cache_env.cache_addr[index].hash_key, hash_key, sizeof(coap_key_t));
+        } else {
+            //if the bd_addr didn't in the address list, added the bd_addr to the last of the address list.
+            memcpy(cache_env.cache_addr[num - 1].hash_key, hash_key, sizeof(coap_key_t));
+            memcpy(cache_env.cache_addr[num - 1].addr, bd_addr, sizeof(BD_ADDR));
+        }
+
+    } else {
+        APPL_TRACE_DEBUG("%s(), num = %d", __func__, num);
+        memcpy(cache_env.cache_addr[num - 1].addr, bd_addr, sizeof(BD_ADDR));
+        memcpy(cache_env.cache_addr[num - 1].hash_key, hash_key, sizeof(coap_key_t));
+    }
+
+    nvs_handle *fp = &cache_env.addr_fp;
+    UINT16 length = num*(sizeof(BD_ADDR) + sizeof(coap_key_t));
+
+    for (UINT8 i = 0; i < num; i++) {
+        //copy the address to the buffer.
+        memcpy(p_buf + i*(sizeof(BD_ADDR) + sizeof(coap_key_t)), cache_env.cache_addr[i].addr, sizeof(BD_ADDR));
+        //copy the hash key to the buffer.
+        memcpy(p_buf + i*(sizeof(BD_ADDR) + sizeof(coap_key_t)) + sizeof(BD_ADDR),
+                cache_env.cache_addr[i].hash_key, sizeof(coap_key_t));
+    }
+
+    if (cache_env.is_open) {
+        if ((err_code = nvs_set_blob(cache_env.addr_fp, cache_key, p_buf, length)) != ESP_OK) {
+            APPL_TRACE_WARNING("%s(), nvs set blob fail, err %d", __func__, err_code);
+        }
+    } else {
+        if ((err_code = nvs_open(cache_addr, NVS_READWRITE , fp)) == ESP_OK) {
+            cache_env.is_open = true;
+            if (( err_code = nvs_set_blob(cache_env.addr_fp, cache_key, p_buf, length)) != ESP_OK) {
+                APPL_TRACE_WARNING("%s(), nvs set blob fail, err %d", __func__, err_code);
+            }
+        } else {
+            APPL_TRACE_ERROR("%s, Line = %d, nvs flash open fail, err_code = %x", __func__, __LINE__, err_code);
+        }
+    }
+    //free the buffer after used.
+    osi_free(p_buf);
+    return;
+
+}
+
+BOOLEAN bta_gattc_co_cache_new_ass_list(BD_ADDR src_addr, UINT8 index)
+{
+    cache_addr_info_t *addr_info = &cache_env.cache_addr[index];
+    addr_info->ass_addr = list_new(osi_free_func);
+    return (addr_info->ass_addr != NULL ? TRUE : FALSE);
+}
+
+BOOLEAN bta_gattc_co_cache_append_ass_addr(BD_ADDR src_addr, BD_ADDR ass_addr)
+{
+    UINT8 addr_index = 0;
+    cache_addr_info_t *addr_info;
+    UINT8 *p_ass_buf = osi_malloc(sizeof(BD_ADDR));
+    memcpy(p_ass_buf, ass_addr, sizeof(BD_ADDR));
+    if ((addr_index = bta_gattc_co_find_addr_in_cache(src_addr)) != INVALID_ADDR_NUM) {
+        addr_info = &cache_env.cache_addr[addr_index];
+        if (addr_info->ass_addr == NULL) {
+            addr_info->ass_addr =list_new(NULL);
+        }
+        return list_append(addr_info->ass_addr, p_ass_buf);
+    }
+
+    return FALSE;
+}
+
+BOOLEAN bta_gattc_co_cache_remove_ass_addr(BD_ADDR src_addr, BD_ADDR ass_addr)
+{
+    UINT8 addr_index = 0;
+    cache_addr_info_t *addr_info;
+    if ((addr_index = bta_gattc_co_find_addr_in_cache(src_addr)) != INVALID_ADDR_NUM) {
+        addr_info = &cache_env.cache_addr[addr_index];
+        if (addr_info->ass_addr != NULL) {
+            for (list_node_t *sn = list_begin(addr_info->ass_addr);
+             sn != list_end(addr_info->ass_addr); sn = list_next(sn)) {
+                void *addr = list_node(sn);
+                if (!memcmp(addr, ass_addr, sizeof(BD_ADDR))) {
+                    return list_remove(addr_info->ass_addr, addr);
+                }
+            }
+            //return list_remove(addr_info->ass_addr, ass_addr);
+        } else {
+            return FALSE;
+        }
+    }
+
+    return FALSE;
+}
+
+UINT8* bta_gattc_co_cache_find_src_addr(BD_ADDR ass_addr, UINT8 *index)
+{
+    UINT8 num = cache_env.num_addr;
+    cache_addr_info_t *addr_info = &cache_env.cache_addr[0];
+    UINT8 *addr_data;
+    //Check the ass_addr list is NULL or not
+    if (addr_info->ass_addr == NULL) {
+        *index = INVALID_ADDR_NUM;
+        return NULL;
+    }
+
+    for (int i = 0; i < num; i++) {
+       for (const list_node_t *node = list_begin(addr_info->ass_addr); node != list_end(addr_info->ass_addr); 
+            node = list_next(node)) {
+            addr_data = (UINT8 *)list_node(node);
+           if (!memcmp(addr_data, ass_addr, sizeof(BD_ADDR))) {
+               *index = i;
+               return (UINT8 *)addr_info->addr;
+           }
+       }
+       addr_info++;
+
+       if (addr_info->ass_addr == NULL) {
+           *index = INVALID_ADDR_NUM;
+           return NULL;
+       }
+    }
+
+    *index = INVALID_ADDR_NUM;
+    return NULL;
+}
+
+BOOLEAN bta_gattc_co_cache_clear_ass_addr(BD_ADDR src_addr)
+{
+    UINT8 addr_index = 0;
+    cache_addr_info_t *addr_info;
+    if ((addr_index = bta_gattc_co_find_addr_in_cache(src_addr)) != INVALID_ADDR_NUM) {
+        addr_info = &cache_env.cache_addr[addr_index];
+        if (addr_info->ass_addr != NULL) {
+            list_clear(addr_info->ass_addr);
+        } else {
+            return FALSE;
+        }
+        return TRUE;
+    }
+
+    return FALSE;
 }
 
 #endif /* #if( defined BLE_INCLUDED ) && (BLE_INCLUDED == TRUE) */