]> granicus.if.org Git - esp-idf/commitdiff
This is a combination of 4 commits.
authorYulong <huangyulong@espressif.com>
Thu, 24 Aug 2017 06:24:04 +0000 (02:24 -0400)
committerYulong <huangyulong@espressif.com>
Tue, 12 Sep 2017 11:36:02 +0000 (07:36 -0400)
squash again all the commit.

component/bt: Change all the gattc API && bta gattc layer.

component/bt: Debug the code and change the btc_ble_gattc_get_db method.

component/bt: Change the gatt read API interface.

component/bt: Reconstruction the BTA_gattc_cache code.

component/bt: Change back the bluedroid_get_status to marco.

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

component/bt: Change the gattc docs format.

component/bt: Change the docs format.

component/bt: fix the read char value bug.

component/bt: change the gattc_get_attr_count method.

component/bt: Change back the bta_gattc write ccc code.

component/bt: Change the gattc api docs format

component/bt: Change the gattc API docs.

component/bt: Change the prepare write descriptor method to avoid the exection.

Component/bt: modify gatt clinet demo with new API

component/bt: Change the p_src_data->read.p_value to avoid exection.

compoent/bt: Change the bugfix of gattc unreg for the notify.

Modify gattc security demo

component/bt: Change the log error.

Component/bt: modify gattc_multi_connect demo

componnet/bt: Change the bta_gattc_cache sdp include.

component/bt: Change the start_handle & end_handle not from the service.

component/bt: Change the gattc API docs.

component/bt: Change the return issues.

component/bt: Fixed the include service bug.

component/bt: Modify gattc_multi_connect demo , add scan log

component/bt: Fixed the BTA_GATTC_GetIncludeService start handle & end handle error bug.

component/bt: Fix the invalid handle of the get all char issues.

component/bt: Fix the bug with get_db_size_with_type of the start handle & end_handle not correted issue.

component/bt: Fixed the get secondly service num not correct issue.

component/bt: Fixed the last service handle not correted issue.

20 files changed:
components/bt/bluedroid/api/esp_gattc_api.c
components/bt/bluedroid/api/include/esp_gatt_defs.h
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/gatt/bta_gattc_utils.c
components/bt/bluedroid/bta/include/bta_gatt_api.h
components/bt/bluedroid/bta/include/bta_gattc_int.h
components/bt/bluedroid/btc/profile/esp/blufi/blufi_protocol.c
components/bt/bluedroid/btc/profile/std/gatt/btc_gatt_util.c
components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c
components/bt/bluedroid/btc/profile/std/include/btc_gattc.h
components/bt/bluedroid/stack/gatt/gatt_utils.c
examples/bluetooth/gatt_client/main/gattc_demo.c
examples/bluetooth/gatt_security_client/main/example_ble_sec_gattc_demo.c
examples/bluetooth/gatt_security_server/main/example_ble_sec_gatts_demo.c
examples/bluetooth/gattc_multi_connect/main/gattc_multi_connect.c

index 75970ad3f121c26e740a6b927056abb595d9f43f..d486c14c6a99df4fef40447863e0ea825f97aad1 100644 (file)
@@ -24,7 +24,7 @@
 esp_err_t esp_ble_gattc_register_callback(esp_gattc_cb_t callback)
 {
     ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
-    
+
     if (callback == NULL) {
         return ESP_FAIL;
     }
@@ -39,7 +39,7 @@ esp_err_t esp_ble_gattc_app_register(uint16_t app_id)
     btc_ble_gattc_args_t arg;
 
     ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
-    
+
     if (app_id > ESP_APP_ID_MAX) {
         return ESP_ERR_INVALID_ARG;
     }
@@ -57,8 +57,8 @@ esp_err_t esp_ble_gattc_app_unregister(esp_gatt_if_t gattc_if)
     btc_msg_t msg;
     btc_ble_gattc_args_t arg;
 
-   ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
-    
+    ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
+
     msg.sig = BTC_SIG_API_CALL;
     msg.pid = BTC_PID_GATTC;
     msg.act = BTC_GATTC_ACT_APP_UNREGISTER;
@@ -73,7 +73,7 @@ esp_err_t esp_ble_gattc_open(esp_gatt_if_t gattc_if, esp_bd_addr_t remote_bda, b
     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_OPEN;
@@ -90,7 +90,7 @@ esp_err_t esp_ble_gattc_close (esp_gatt_if_t gattc_if, uint16_t conn_id)
     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_CLOSE;
@@ -120,7 +120,7 @@ esp_err_t esp_ble_gattc_search_service(esp_gatt_if_t gattc_if, uint16_t conn_id,
     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_SEARCH_SERVICE;
@@ -136,155 +136,264 @@ esp_err_t esp_ble_gattc_search_service(esp_gatt_if_t gattc_if, uint16_t conn_id,
     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_get_characteristic(esp_gatt_if_t gattc_if,
-                                            uint16_t conn_id,
-                                            esp_gatt_srvc_id_t *srvc_id,
-                                            esp_gatt_id_t *start_char_id)
+esp_gatt_status_t esp_ble_gattc_get_service(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_bt_uuid_t *svc_uuid,
+                                            esp_gattc_service_elem_t *result, uint16_t *count, uint16_t offset)
 {
-    btc_msg_t msg;
-    btc_ble_gattc_args_t arg;
+    ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
 
+    if (result == NULL || count == NULL || *count == 0) {
+        return ESP_GATT_INVALID_PDU;
+    }
+
+    uint16_t conn_hdl = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
+    return btc_ble_gattc_get_service(conn_hdl, svc_uuid, result, count, offset);
+}
+
+
+esp_gatt_status_t esp_ble_gattc_get_all_char(esp_gatt_if_t gattc_if,
+                                             uint16_t conn_id,
+                                             uint16_t start_handle,
+                                             uint16_t end_handle,
+                                             esp_gattc_char_elem_t *result,
+                                             uint16_t *count, uint16_t offset)
+{
     ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
-    
-    msg.sig = BTC_SIG_API_CALL;
-    msg.pid = BTC_PID_GATTC;
-    if (start_char_id) {
-        arg.get_next_char.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
-        memcpy(&arg.get_next_char.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
-        memcpy(&arg.get_next_char.char_id, start_char_id, sizeof(esp_gatt_id_t));
-        msg.act = BTC_GATTC_ACT_GET_NEXT_CHAR;
-    } else {
-        arg.get_first_char.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
-        memcpy(&arg.get_first_char.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
-        msg.act = BTC_GATTC_ACT_GET_FIRST_CHAR;
+
+    if ((start_handle == 0) && (end_handle == 0)) {
+        return ESP_GATT_INVALID_HANDLE;
     }
 
-    return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+    if (result == NULL || count == NULL || *count == 0) {
+        return ESP_GATT_INVALID_PDU;
+    }
+
+    uint16_t conn_hdl = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
+    return btc_ble_gattc_get_all_char(conn_hdl, start_handle, end_handle, result, count, offset);
 }
 
-esp_err_t esp_ble_gattc_get_descriptor(esp_gatt_if_t gattc_if,
-                                       uint16_t conn_id,
-                                       esp_gatt_srvc_id_t *srvc_id,
-                                       esp_gatt_id_t *char_id,
-                                       esp_gatt_id_t *start_descr_id)
+esp_gatt_status_t esp_ble_gattc_get_all_descr(esp_gatt_if_t gattc_if,
+                                              uint16_t conn_id,
+                                              uint16_t char_handle,                                            
+                                              esp_gattc_descr_elem_t *result,
+                                              uint16_t *count, uint16_t offset)
 {
-    btc_msg_t msg;
-    btc_ble_gattc_args_t arg;
+    ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
+
+    if (char_handle == 0) {
+        return ESP_GATT_INVALID_HANDLE;
+    }
+
+    if (result == NULL || count == NULL || *count == 0) {
+        return ESP_GATT_INVALID_PDU;
+    }
+
+    uint16_t conn_hdl = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
+    return btc_ble_gattc_get_all_descr(conn_hdl, char_handle, result, count, offset);
+}
 
+esp_gatt_status_t esp_ble_gattc_get_char_by_uuid(esp_gatt_if_t gattc_if, 
+                                                 uint16_t conn_id,
+                                                 uint16_t start_handle,
+                                                 uint16_t end_handle,
+                                                 esp_bt_uuid_t char_uuid,
+                                                 esp_gattc_char_elem_t *result,
+                                                 uint16_t *count)
+{
     ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
-    
-    msg.sig = BTC_SIG_API_CALL;
-    msg.pid = BTC_PID_GATTC;
 
-    if (start_descr_id) {
-        arg.get_next_descr.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
-        memcpy(&arg.get_next_descr.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
-        memcpy(&arg.get_next_descr.char_id, char_id, sizeof(esp_gatt_id_t));
-        memcpy(&arg.get_next_descr.descr_id, start_descr_id, sizeof(esp_gatt_id_t));
-        msg.act = BTC_GATTC_ACT_GET_NEXT_DESCR;
-    } else {
-        arg.get_first_descr.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
-        memcpy(&arg.get_first_descr.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
-        memcpy(&arg.get_first_descr.char_id, char_id, sizeof(esp_gatt_id_t));
-        msg.act = BTC_GATTC_ACT_GET_FIRST_DESCR;
+    if (start_handle == 0 && end_handle == 0) {
+        return ESP_GATT_INVALID_HANDLE;
     }
 
-    return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+    if (result == NULL || count == NULL || *count == 0) {
+        return ESP_GATT_INVALID_PDU;
+    }
+
+    uint16_t conn_hdl = BTC_GATT_CREATE_CONN_ID(gattc_if,conn_id);
+    return btc_ble_gattc_get_char_by_uuid(conn_hdl, start_handle, end_handle, char_uuid, result, count);
 }
 
-esp_err_t esp_ble_gattc_get_included_service(esp_gatt_if_t gattc_if, 
-                                            uint16_t conn_id,
-                                            esp_gatt_srvc_id_t *srvc_id,
-                                            esp_gatt_srvc_id_t *start_incl_srvc_id)
+
+esp_gatt_status_t esp_ble_gattc_get_descr_by_uuid(esp_gatt_if_t gattc_if,
+                                                  uint16_t conn_id,
+                                                  uint16_t start_handle,
+                                                  uint16_t end_handle,
+                                                  esp_bt_uuid_t char_uuid,
+                                                  esp_bt_uuid_t descr_uuid,
+                                                  esp_gattc_descr_elem_t *result,
+                                                  uint16_t *count)
 {
-    btc_msg_t msg;
-    btc_ble_gattc_args_t arg;
+    ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
+
+    if (result == NULL || count == NULL || *count == 0) {
+        return ESP_GATT_INVALID_PDU;
+    }
 
+    uint16_t conn_hdl = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
+    return btc_ble_gattc_get_descr_by_uuid(conn_hdl, start_handle, end_handle, char_uuid, descr_uuid, result, count);
+}
+
+esp_gatt_status_t esp_ble_gattc_get_descr_by_char_handle(esp_gatt_if_t gattc_if,
+                                                         uint16_t conn_id,
+                                                         uint16_t char_handle,
+                                                         esp_bt_uuid_t descr_uuid,
+                                                         esp_gattc_descr_elem_t *result,
+                                                         uint16_t *count)
+{
     ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
+
+    if (char_handle == 0) {
+        return ESP_GATT_INVALID_HANDLE;
+    }
     
-    msg.sig = BTC_SIG_API_CALL;
-    msg.pid = BTC_PID_GATTC;
+    if (result == NULL || count == NULL || *count == 0) {
+        return ESP_GATT_INVALID_PDU;
+    }
 
-    if (start_incl_srvc_id) {
-        arg.get_next_incl_srvc.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
-        memcpy(&arg.get_next_incl_srvc.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
-        memcpy(&arg.get_next_incl_srvc.start_service_id, start_incl_srvc_id, sizeof(esp_gatt_srvc_id_t));
-        msg.act = BTC_GATTC_ACT_GET_NEXT_INCL_SERVICE;
-    } else {
-        arg.get_first_incl_srvc.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
-        memcpy(&arg.get_first_incl_srvc.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
-        msg.act = BTC_GATTC_ACT_GET_FIRST_INCL_SERVICE;
+    uint16_t conn_hdl = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
+    return btc_ble_gattc_get_descr_by_char_handle(conn_hdl, char_handle, descr_uuid, result, count);
+}
+
+esp_gatt_status_t esp_ble_gattc_get_include_service(esp_gatt_if_t gattc_if,
+                                                    uint16_t conn_id,
+                                                    uint16_t start_handle,
+                                                    uint16_t end_handle,
+                                                    esp_bt_uuid_t *incl_uuid,
+                                                    esp_gattc_incl_svc_elem_t *result,
+                                                    uint16_t *count)
+{
+    ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
+
+    if (start_handle == 0 && end_handle == 0) {
+        return ESP_GATT_INVALID_HANDLE;
     }
 
-    return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+    if (result == NULL || count == NULL || *count == 0) {
+        return ESP_GATT_INVALID_PDU;
+    }
+
+    uint16_t conn_hdl = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
+    return btc_ble_gattc_get_include_service(conn_hdl, start_handle, end_handle, incl_uuid, result, count);
 }
 
+esp_gatt_status_t esp_ble_gattc_get_attr_count(esp_gatt_if_t gattc_if,
+                                               uint16_t conn_id,
+                                               esp_gatt_db_attr_type_t type,
+                                               uint16_t start_handle,
+                                               uint16_t end_handle,
+                                               uint16_t char_handle,
+                                               uint16_t *count)
+{
+    ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
+
+    if ((start_handle == 0 && end_handle == 0) && (type != ESP_GATT_DB_DESCRIPTOR)) {
+        return ESP_GATT_INVALID_HANDLE;
+    }
+
+    if (count == NULL) {
+        return ESP_GATT_INVALID_PDU;
+    }
+
+    uint16_t conn_hdl = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
+    return btc_ble_gattc_get_attr_count(conn_hdl, type, start_handle, end_handle, char_handle, count);
+}
+
+esp_gatt_status_t esp_ble_gattc_get_db(esp_gatt_if_t gattc_if, uint16_t conn_id, uint16_t start_handle, uint16_t end_handle,
+                                       esp_gattc_db_elem_t *db, uint16_t *count)
+{
+    ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
+
+    if (start_handle == 0 && end_handle == 0) {
+        return ESP_GATT_INVALID_HANDLE;
+    }
+
+    if (db == NULL || count == NULL || *count == 0) {
+        return ESP_GATT_INVALID_PDU;
+    }
+
+    uint16_t conn_hdl = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
+    return btc_ble_gattc_get_db(conn_hdl, start_handle, end_handle, db, count);
+}
+
+
 esp_err_t esp_ble_gattc_read_char (esp_gatt_if_t gattc_if, 
-                                uint16_t conn_id,
-                                esp_gatt_srvc_id_t *srvc_id,
-                                esp_gatt_id_t *char_id,
-                                esp_gatt_auth_req_t auth_req)
+                                   uint16_t conn_id, uint16_t handle,
+                                   esp_gatt_auth_req_t auth_req)
 {
     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_READ_CHAR;
     arg.read_char.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
-    memcpy(&arg.read_char.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
-    memcpy(&arg.read_char.char_id, char_id, sizeof(esp_gatt_id_t));
+    arg.read_char.handle = handle;
     arg.read_char.auth_req = auth_req;
 
     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_read_multiple(esp_gatt_if_t gattc_if,
+                                      uint16_t conn_id, esp_gattc_multi_t *read_multi,
+                                      esp_gatt_auth_req_t auth_req)
+{
+    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_READ_MULTIPLE_CHAR;
+    arg.read_multiple.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
+    if (read_multi->num_attr > 0) {
+        memcpy(arg.read_multiple.handles, read_multi->handles, sizeof(uint16_t)*read_multi->num_attr);
+    } else {
+        LOG_ERROR("%s(), the num_attr should not be 0.", __func__);
+        return ESP_FAIL;
+    }
+    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_read_char_descr (esp_gatt_if_t gattc_if,
-                                        uint16_t conn_id,
-                                        esp_gatt_srvc_id_t *srvc_id,
-                                        esp_gatt_id_t  *char_id,
-                                        esp_gatt_id_t  *descr_id,
-                                        esp_gatt_auth_req_t auth_req)
+                                         uint16_t conn_id, uint16_t handle,
+                                         esp_gatt_auth_req_t auth_req)
 {
     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_READ_CHAR_DESCR;
     arg.read_descr.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
-    memcpy(&arg.read_descr.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
-    memcpy(&arg.read_descr.char_id, char_id, sizeof(esp_gatt_id_t));
-    memcpy(&arg.read_descr.descr_id, descr_id, sizeof(esp_gatt_id_t));
+    arg.read_descr.handle = handle;
     arg.read_descr.auth_req = auth_req;
 
     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_write_char( esp_gatt_if_t gattc_if,
-                                    uint16_t conn_id,
-                                    esp_gatt_srvc_id_t *srvc_id,
-                                    esp_gatt_id_t *char_id,
-                                    uint16_t value_len,
-                                    uint8_t *value,
-                                    esp_gatt_write_type_t write_type,
-                                    esp_gatt_auth_req_t auth_req)
+esp_err_t esp_ble_gattc_write_char(esp_gatt_if_t gattc_if,
+                                   uint16_t conn_id, uint16_t handle,
+                                   uint16_t value_len,
+                                   uint8_t *value,
+                                   esp_gatt_write_type_t write_type,
+                                   esp_gatt_auth_req_t auth_req)
 {
     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_WRITE_CHAR;
     arg.write_char.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
-    memcpy(&arg.write_char.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
-    memcpy(&arg.write_char.char_id, char_id, sizeof(esp_gatt_id_t));
+    arg.write_char.handle = handle;
     arg.write_char.value_len = value_len > ESP_GATT_MAX_ATTR_LEN ? ESP_GATT_MAX_ATTR_LEN : value_len;
     arg.write_char.value = value;
     arg.write_char.write_type = write_type;
@@ -294,14 +403,11 @@ esp_err_t esp_ble_gattc_write_char( esp_gatt_if_t gattc_if,
 }
 
 esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if,
-                                         uint16_t conn_id,
-                                         esp_gatt_srvc_id_t *srvc_id,
-                                         esp_gatt_id_t *char_id,
-                                         esp_gatt_id_t *descr_id,
-                                         uint16_t value_len,
-                                         uint8_t *value,
-                                         esp_gatt_write_type_t write_type,
-                                         esp_gatt_auth_req_t auth_req)
+                                          uint16_t conn_id, uint16_t handle,
+                                          uint16_t value_len,
+                                          uint8_t *value,
+                                          esp_gatt_write_type_t write_type,
+                                          esp_gatt_auth_req_t auth_req)
 {
     btc_msg_t msg;
     btc_ble_gattc_args_t arg;
@@ -312,9 +418,7 @@ esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if,
     msg.pid = BTC_PID_GATTC;
     msg.act = BTC_GATTC_ACT_WRITE_CHAR_DESCR;
     arg.write_descr.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
-    memcpy(&arg.write_descr.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
-    memcpy(&arg.write_descr.char_id, char_id, sizeof(esp_gatt_id_t));
-    memcpy(&arg.write_descr.descr_id, descr_id, sizeof(esp_gatt_id_t));
+    arg.write_descr.handle = handle;
     arg.write_descr.value_len = value_len > ESP_GATT_MAX_ATTR_LEN ? ESP_GATT_MAX_ATTR_LEN : value_len;
     arg.write_descr.value = value;
     arg.write_descr.write_type = write_type;
@@ -324,9 +428,7 @@ esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if,
 }
 
 esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if, 
-                                      uint16_t conn_id,
-                                      esp_gatt_srvc_id_t *srvc_id,
-                                      esp_gatt_id_t *char_id,
+                                      uint16_t conn_id, uint16_t handle,
                                       uint16_t offset,
                                       uint16_t value_len,
                                       uint8_t *value,
@@ -341,8 +443,7 @@ esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if,
     msg.pid = BTC_PID_GATTC;
     msg.act = BTC_GATTC_ACT_PREPARE_WRITE;
     arg.prep_write.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
-    memcpy(&arg.prep_write.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
-    memcpy(&arg.prep_write.char_id, char_id, sizeof(esp_gatt_id_t));
+    arg.prep_write.handle = handle;
     arg.prep_write.offset = offset;
     arg.prep_write.value_len = value_len > ESP_GATT_MAX_ATTR_LEN ? ESP_GATT_MAX_ATTR_LEN : value_len; // length check ?
     arg.prep_write.value = value;
@@ -352,10 +453,7 @@ esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if,
 }
 
 esp_err_t esp_ble_gattc_prepare_write_char_descr(esp_gatt_if_t gattc_if,
-                                                 uint16_t conn_id,
-                                                 esp_gatt_srvc_id_t *srvc_id,
-                                                 esp_gatt_id_t *char_id,
-                                                 esp_gatt_id_t *descr_id,
+                                                 uint16_t conn_id, uint16_t handle,
                                                  uint16_t offset,
                                                  uint16_t value_len,
                                                  uint8_t *value,
@@ -370,9 +468,7 @@ esp_err_t esp_ble_gattc_prepare_write_char_descr(esp_gatt_if_t gattc_if,
     msg.pid = BTC_PID_GATTC;
     msg.act = BTC_GATTC_ACT_PREPARE_WRITE_CHAR_DESCR;
     arg.prep_write_descr.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
-    memcpy(&arg.prep_write_descr.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
-    memcpy(&arg.prep_write_descr.char_id, char_id, sizeof(esp_gatt_id_t));
-    memcpy(&arg.prep_write_descr.descr_id, descr_id, sizeof(esp_gatt_id_t));
+    arg.prep_write_descr.handle = handle;
     arg.prep_write_descr.offset = offset;
     arg.prep_write_descr.value_len = value_len > ESP_GATT_MAX_ATTR_LEN ? ESP_GATT_MAX_ATTR_LEN : value_len; // length check ?
     arg.prep_write_descr.value = value;
@@ -387,7 +483,7 @@ esp_err_t esp_ble_gattc_execute_write (esp_gatt_if_t gattc_if, uint16_t conn_id,
     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_EXECUTE_WRITE;
@@ -398,44 +494,37 @@ esp_err_t esp_ble_gattc_execute_write (esp_gatt_if_t gattc_if, uint16_t conn_id,
 }
 
 esp_err_t esp_ble_gattc_register_for_notify (esp_gatt_if_t gattc_if,
-        esp_bd_addr_t server_bda,
-        esp_gatt_srvc_id_t *srvc_id,
-        esp_gatt_id_t *char_id)
+                                             esp_bd_addr_t server_bda, uint16_t handle)
 {
     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_REG_FOR_NOTIFY;
     arg.reg_for_notify.gattc_if = gattc_if;
     memcpy(arg.reg_for_notify.remote_bda, server_bda, sizeof(esp_bd_addr_t));
-    memcpy(&arg.reg_for_notify.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
-    memcpy(&arg.reg_for_notify.char_id, char_id, sizeof(esp_gatt_id_t));
+    arg.reg_for_notify.handle = handle;
 
     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_unregister_for_notify (esp_gatt_if_t gattc_if,
-        esp_bd_addr_t server_bda,
-        esp_gatt_srvc_id_t *srvc_id,
-        esp_gatt_id_t *char_id)
+                                               esp_bd_addr_t server_bda, uint16_t handle)
 {
     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_UNREG_FOR_NOTIFY;
     arg.unreg_for_notify.gattc_if = gattc_if;
+    arg.unreg_for_notify.handle = handle;
     memcpy(arg.unreg_for_notify.remote_bda, server_bda, sizeof(esp_bd_addr_t));
-    memcpy(&arg.unreg_for_notify.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
-    memcpy(&arg.unreg_for_notify.char_id, char_id, sizeof(esp_gatt_id_t));
-
     return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
 }
 
index d0f73dd32cd56fc4ee53b8a73f27a871972a58cb..a98069eadb515ea47234b5201b5d7aca7c6a7f49 100644 (file)
@@ -27,6 +27,7 @@ extern "C" {
 #define ESP_GATT_ILLEGAL_HANDLE             0
 /// GATT attribute max handle
 #define ESP_GATT_ATTR_HANDLE_MAX            100
+#define ESP_GATT_MAX_READ_MULTI_HANDLES     10           /* Max attributes to read in one request */
 
 
 /**@{
@@ -294,12 +295,12 @@ typedef uint8_t esp_gatt_char_prop_t;
  */
  typedef struct
  {   
-     uint16_t uuid_length;              /*!< UUID length */  
-     uint8_t  *uuid_p;                  /*!< UUID value */  
-     uint16_t perm;                     /*!< Attribute permission */        
-     uint16_t max_length;               /*!< Maximum length of the element*/    
-     uint16_t length;                   /*!< Current length of the element*/    
-     uint8_t  *value;                   /*!< Element value array*/  
+     uint16_t uuid_length;              /*!< UUID length */
+     uint8_t  *uuid_p;                  /*!< UUID value */
+     uint16_t perm;                     /*!< Attribute permission */
+     uint16_t max_length;               /*!< Maximum length of the element*/
+     uint16_t length;                   /*!< Current length of the element*/
+     uint8_t  *value;                   /*!< Element value array*/
  } esp_attr_desc_t;
 
 
@@ -313,8 +314,8 @@ typedef struct
     /**
      * @brief if auto_rsp set to ESP_GATT_RSP_BY_APP, means the response of Write/Read operation will by replied by application.
               if auto_rsp set to ESP_GATT_AUTO_RSP, means the response of Write/Read operation will be replied by GATT stack automatically.
-     */  
-    uint8_t auto_rsp;                   
+     */
+    uint8_t auto_rsp;
 } esp_attr_control_t;
 
 
@@ -323,8 +324,8 @@ typedef struct
  */
 typedef struct
 {
-    esp_attr_control_t      attr_control;       /*!< The attribute control type*/
-    esp_attr_desc_t         att_desc;           /*!< The attribute type*/
+    esp_attr_control_t      attr_control;                   /*!< The attribute control type */
+    esp_attr_desc_t         att_desc;                       /*!< The attribute type */
 } esp_gatts_attr_db_t;
 
 
@@ -333,9 +334,9 @@ typedef struct
   */
 typedef struct
 {
-    uint16_t attr_max_len;                      /*!<  attribute max value length */     
-    uint16_t attr_len;                          /*!<  attribute current value length */ 
-    uint8_t  *attr_value;                       /*!<  the pointer to attribute value */
+    uint16_t attr_max_len;                                  /*!<  attribute max value length */
+    uint16_t attr_len;                                      /*!<  attribute current value length */
+    uint8_t  *attr_value;                                   /*!<  the pointer to attribute value */
 } esp_attr_value_t;
 
 
@@ -344,22 +345,19 @@ typedef struct
   */
 typedef struct 
 {
-    uint16_t start_hdl;                             /*!< Gatt  start handle value of included service */
-    uint16_t end_hdl;                               /*!< Gatt  end handle value of included service */
-    uint16_t uuid;                                  /*!< Gatt  attribute value UUID of included service */
-} esp_gatts_incl_svc_desc_t;                        /*!< Gatt  include service entry element */
+    uint16_t start_hdl;                                     /*!< Gatt  start handle value of included service */
+    uint16_t end_hdl;                                       /*!< Gatt  end handle value of included service */
+    uint16_t uuid;                                          /*!< Gatt  attribute value UUID of included service */
+} esp_gatts_incl_svc_desc_t;                                /*!< Gatt include service entry element */
 
 /**
   * @brief Gatt  include 128 bit service entry element
   */
 typedef struct 
 {
-    uint16_t start_hdl;                             /*!< Gatt  start handle value of included 128 bit service */
-    uint16_t end_hdl;                               /*!< Gatt  end handle value of included 128 bit service */
-} esp_gatts_incl128_svc_desc_t;                     /*!< Gatt  include 128 bit service entry element */
-
-
-
+    uint16_t start_hdl;                                     /*!< Gatt  start handle value of included 128 bit service */
+    uint16_t end_hdl;                                       /*!< Gatt  end handle value of included 128 bit service */
+} esp_gatts_incl128_svc_desc_t;                             /*!< Gatt  include 128 bit service entry element */
 
 /// Gatt attribute value 
 typedef struct {
@@ -388,6 +386,75 @@ typedef enum {
 
 typedef uint8_t    esp_gatt_if_t;                           /*!< Gatt interface type, different application on GATT client use different gatt_if */
 
+/**
+  * @brief the type of attribute element
+  */
+typedef enum {
+    ESP_GATT_DB_PRIMARY_SERVICE,                            /*!< Gattc primary service attribute type in the cache */
+    ESP_GATT_DB_SECONDARY_SERVICE,                          /*!< Gattc secondary service attribute type in the cache */
+    ESP_GATT_DB_CHARACTERISTIC,                             /*!< Gattc characteristic attribute type in the cache */
+    ESP_GATT_DB_DESCRIPTOR,                                 /*!< Gattc characteristic descriptor attribute type in the cache */
+    ESP_GATT_DB_INCLUDED_SERVICE,                           /*!< Gattc include service attribute type in the cache */
+    ESP_GATT_DB_ALL,                                        /*!< Gattc all the attribute (primary service & secondary service & include service & char & descriptor) type in the cache */
+} esp_gatt_db_attr_type_t;                                  /*!< Gattc attribute type element */
+
+/**
+  * @brief read multiple attribute
+  */
+typedef struct {
+    uint8_t  num_attr;                                      /*!< The number of the attribute */
+    uint16_t handles[ESP_GATT_MAX_READ_MULTI_HANDLES];      /*!< The handles list */
+} esp_gattc_multi_t;                                        /*!< The gattc multiple read element */
+
+/**
+  * @brief data base attribute element
+  */
+typedef struct {
+    esp_gatt_db_attr_type_t     type;                       /*!< The attribute type */
+    uint16_t                    attribute_handle;           /*!< The attribute handle, it's valid for all of the type */
+    uint16_t                    start_handle;               /*!< The service start handle, it's valid only when the type = ESP_GATT_DB_PRIMARY_SERVICE or ESP_GATT_DB_SECONDARY_SERVICE */
+    uint16_t                    end_handle;                 /*!< The service end handle, it's valid only when the type = ESP_GATT_DB_PRIMARY_SERVICE or ESP_GATT_DB_SECONDARY_SERVICE */
+    esp_gatt_char_prop_t        properties;                 /*!< The characteristic properties, it's valid only when the type = ESP_GATT_DB_CHARACTERISTIC */
+    esp_bt_uuid_t               uuid;                       /*!< The attribute uuid, it's valid for all of the type */
+} esp_gattc_db_elem_t;                                      /*!< The gattc service data base element in the cache */
+
+/**
+  * @brief service element
+  */
+typedef struct { 
+    bool                        is_primary;                 /*!< The service flag, ture if the service is primary service, else is secondly service */
+    uint16_t                    start_handle;               /*!< The start handle of the service */
+    uint16_t                    end_handle;                 /*!< The end handle of the service */
+    esp_bt_uuid_t               uuid;                       /*!< The uuid of the service */
+} esp_gattc_service_elem_t;                                 /*!< The gattc service element */
+
+/**
+  * @brief characteristic element
+  */
+typedef struct {
+    uint16_t                    char_handle;                /*!< The characteristic handle */
+    esp_gatt_char_prop_t        properties;                 /*!< The characteristic properties */
+    esp_bt_uuid_t               uuid;                       /*!< The characteristic uuid */
+} esp_gattc_char_elem_t;                                    /*!< The gattc characteristic element */
+
+/**
+  * @brief descriptor element
+  */
+typedef struct {
+    uint16_t                   handle;                      /*!< The characteristic descriptor handle */
+    esp_bt_uuid_t              uuid;                        /*!< The characteristic descriptor uuid */
+} esp_gattc_descr_elem_t;                                   /*!< The gattc descriptor type element */
+
+/**
+  * @brief include service element
+  */
+typedef struct {
+    uint16_t                   handle;                      /*!< The include service current attribute handle */
+    uint16_t                   incl_srvc_s_handle;          /*!< The start hanlde of the service which has been included */
+    esp_bt_uuid_t              uuid;                        /*!< The include service uuid */
+} esp_gattc_incl_svc_elem_t;                                /*!< The gattc inclue service element */
+
+
 #ifdef __cplusplus
 }
 #endif
index b950d438f087f0733e58d90a8e9f1ae0e5c68a2f..ba5cfffac0898359a31d52b5cfef3c16028ae68a 100644 (file)
@@ -59,9 +59,6 @@ typedef enum {
     ESP_GATTC_SCAN_FLT_PARAM_EVT      = 32,       /*!< When Scan filter parameters are set, the event comes */
     ESP_GATTC_SCAN_FLT_STATUS_EVT     = 33,       /*!< When Scan filter status is reported, the event comes */
     ESP_GATTC_ADV_VSC_EVT             = 34,       /*!< When advertising vendor spec content event is reported, the event comes */
-    ESP_GATTC_GET_CHAR_EVT            = 35,       /*!< When characteristic is got from GATT server, the event comes */
-    ESP_GATTC_GET_DESCR_EVT           = 36,       /*!< When characteristic descriptor is got from GATT server, the event comes */
-    ESP_GATTC_GET_INCL_SRVC_EVT       = 37,       /*!< When included service is got from GATT server, the event comes */
     ESP_GATTC_REG_FOR_NOTIFY_EVT      = 38,       /*!< When register for notification of a service completes, the event comes */
     ESP_GATTC_UNREG_FOR_NOTIFY_EVT    = 39,       /*!< When unregister for notification of a service completes, the event comes */
     ESP_GATTC_CONNECT_EVT             = 40,       /*!< When the ble physical connection is set up, the event comes */
@@ -74,57 +71,59 @@ typedef enum {
  */
 typedef union {
     /**
-        * @brief ESP_GATTC_REG_EVT
-        */
-    struct gattc_reg_evt_param {               
-        esp_gatt_status_t status;              /*!< Operation status */
-        uint16_t app_id;                               /*!< Application id which input in register API */
-    } reg;                                                             /*!< Gatt client callback param of ESP_GATTC_REG_EVT */
+     * @brief ESP_GATTC_REG_EVT
+     */
+    struct gattc_reg_evt_param {
+        esp_gatt_status_t status;       /*!< Operation status */
+        uint16_t app_id;                /*!< Application id which input in register API */
+    } reg;                              /*!< Gatt client callback param of ESP_GATTC_REG_EVT */
 
     /**
      * @brief ESP_GATTC_OPEN_EVT
      */
     struct gattc_open_evt_param {
-        esp_gatt_status_t status;              /*!< Operation status */
-        uint16_t conn_id;                              /*!< Connection id */
-        esp_bd_addr_t remote_bda;              /*!< Remote bluetooth device address */
-        uint16_t mtu;                                  /*!< MTU size */
-    } open;                                                            /*!< Gatt client callback param of ESP_GATTC_OPEN_EVT */
+        esp_gatt_status_t status;       /*!< Operation status */
+        uint16_t conn_id;               /*!< Connection id */
+        esp_bd_addr_t remote_bda;       /*!< Remote bluetooth device address */
+        uint16_t mtu;                   /*!< MTU size */
+    } open;                             /*!< Gatt client callback param of ESP_GATTC_OPEN_EVT */
 
     /**
      * @brief ESP_GATTC_CLOSE_EVT
      */
     struct gattc_close_evt_param {
-        esp_gatt_status_t status;              /*!< Operation status */
-        uint16_t conn_id;                              /*!< Connection id */
-        esp_bd_addr_t remote_bda;              /*!< Remote bluetooth device address */
-        esp_gatt_conn_reason_t reason; /*!< The reason of gatt connection close */
-    } close;                                                   /*!< Gatt client callback param of ESP_GATTC_CLOSE_EVT */
+        esp_gatt_status_t status;       /*!< Operation status */
+        uint16_t conn_id;               /*!< Connection id */
+        esp_bd_addr_t remote_bda;       /*!< Remote bluetooth device address */
+        esp_gatt_conn_reason_t reason;  /*!< The reason of gatt connection close */
+    } close;                            /*!< Gatt client callback param of ESP_GATTC_CLOSE_EVT */
 
     /**
      * @brief ESP_GATTC_CFG_MTU_EVT
      */
     struct gattc_cfg_mtu_evt_param {
-        esp_gatt_status_t status;              /*!< Operation status */
-        uint16_t conn_id;                              /*!< Connection id */
-        uint16_t mtu;                                  /*!< MTU size */
-    } cfg_mtu;                                                 /*!< Gatt client callback param of ESP_GATTC_CFG_MTU_EVT */
+        esp_gatt_status_t status;       /*!< Operation status */
+        uint16_t conn_id;               /*!< Connection id */
+        uint16_t mtu;                   /*!< MTU size */
+    } cfg_mtu;                          /*!< Gatt client callback param of ESP_GATTC_CFG_MTU_EVT */
 
     /**
      * @brief ESP_GATTC_SEARCH_CMPL_EVT
      */
     struct gattc_search_cmpl_evt_param {
-        esp_gatt_status_t status;              /*!< Operation status */
-        uint16_t conn_id;                              /*!< Connection id */
-    } search_cmpl;                                             /*!< Gatt client callback param of ESP_GATTC_SEARCH_CMPL_EVT */
+        esp_gatt_status_t status;       /*!< Operation status */
+        uint16_t conn_id;               /*!< Connection id */
+    } search_cmpl;                      /*!< Gatt client callback param of ESP_GATTC_SEARCH_CMPL_EVT */
 
     /**
      * @brief ESP_GATTC_SEARCH_RES_EVT
      */
     struct gattc_search_res_evt_param {
-        uint16_t conn_id;                              /*!< Connection id */
-        esp_gatt_srvc_id_t srvc_id;    /*!< Service id, include service uuid and other information */
-    } search_res;                                              /*!< Gatt client callback param of ESP_GATTC_SEARCH_RES_EVT */
+        uint16_t conn_id;               /*!< Connection id */
+        uint16_t start_handle;          /*!< Service start handle */
+        uint16_t end_handle;            /*!< Service end handle */
+        esp_gatt_id_t srvc_id;          /*!< Service id, include service uuid and other information */
+    } search_res;                       /*!< Gatt client callback param of ESP_GATTC_SEARCH_RES_EVT */
 
     /**
      * @brief ESP_GATTC_READ_CHAR_EVT,  ESP_GATTC_READ_DESCR_EVT
@@ -133,17 +132,8 @@ typedef union {
 
         esp_gatt_status_t status;       /*!< Operation status */
         uint16_t conn_id;               /*!< Connection id */
-        esp_gatt_srvc_id_t srvc_id;     /*!< Service id, include service uuid and other information */
-        esp_gatt_id_t char_id;          /*!< Characteristic id, include characteristic uuid and other information */
-        esp_gatt_id_t descr_id;         /*!< Descriptor id, include descriptor uuid and other information */
+        uint16_t handle;                /*!< Characteristic handle */
         uint8_t *value;                 /*!< Characteristic value */
-        uint16_t value_type;            /*!< Characteristic value type, there is two value for this type:
-                                             ESP_GATTC_READ_VALUE_TYPE_VALUE(0x0000) and 
-                                             ESP_GATTC_READ_VALUE_TYPE_AGG_FORMAT(0x2905).
-                                             If the value is ESP_GATTC_READ_VALUE_TYPE_VALUE means it is a generally
-                                             value type, and if is the type of ESP_GATTC_READ_VALUE_TYPE_AGG_FORMAT,
-                                             the unit of the value will indicate in the Characteristic 
-                                             aggregate format descriptor */
         uint16_t value_len;             /*!< Characteristic value length */
     } read;                             /*!< Gatt client callback param of ESP_GATTC_READ_CHAR_EVT */
 
@@ -151,99 +141,60 @@ typedef union {
      * @brief ESP_GATTC_WRITE_CHAR_EVT, ESP_GATTC_PREP_WRITE_EVT, ESP_GATTC_WRITE_DESCR_EVT
      */
     struct gattc_write_evt_param {
-        esp_gatt_status_t status;              /*!< Operation status */
-        uint16_t conn_id;                              /*!< Connection id */
-        esp_gatt_srvc_id_t srvc_id;    /*!< Service id, include service uuid and other information */
-        esp_gatt_id_t char_id;                 /*!< Characteristic id, include characteristic uuid and other information */
-        esp_gatt_id_t descr_id;                        /*!< Descriptor id, include descriptor uuid and other information */
-    } write;                                                   /*!< Gatt client callback param of ESP_GATTC_WRITE_DESCR_EVT */
+        esp_gatt_status_t status;       /*!< Operation status */
+        uint16_t conn_id;               /*!< Connection id */
+        uint16_t handle;                /*!< The Characteristic or descriptor handle */
+    } write;                            /*!< Gatt client callback param of ESP_GATTC_WRITE_DESCR_EVT */
 
     /**
      * @brief ESP_GATTC_EXEC_EVT
      */
     struct gattc_exec_cmpl_evt_param {
-        esp_gatt_status_t status;              /*!< Operation status */
-        uint16_t conn_id;                              /*!< Connection id */
-    } exec_cmpl;                                               /*!< Gatt client callback param of ESP_GATTC_EXEC_EVT */
+        esp_gatt_status_t status;       /*!< Operation status */
+        uint16_t conn_id;               /*!< Connection id */
+    } exec_cmpl;                        /*!< Gatt client callback param of ESP_GATTC_EXEC_EVT */
 
     /**
      * @brief ESP_GATTC_NOTIFY_EVT
      */
     struct gattc_notify_evt_param {
-        uint16_t conn_id;                              /*!< Connection id */
-        esp_bd_addr_t remote_bda;              /*!< Remote bluetooth device address */
-        esp_gatt_srvc_id_t srvc_id;    /*!< Service id, include service uuid and other information */
-        esp_gatt_id_t char_id;                 /*!< Characteristic id, include characteristic uuid and other information */
-        esp_gatt_id_t descr_id;                        /*!< Descriptor id, include descriptor uuid and other information */
-        uint16_t value_len;                            /*!< Notify attribute value */
-        uint8_t *value;                                        /*!< Notify attribute value */
-        bool is_notify;                                        /*!< True means notify, false means indicate */
-    } notify;                                                  /*!< Gatt client callback param of ESP_GATTC_NOTIFY_EVT */
+        uint16_t conn_id;               /*!< Connection id */
+        esp_bd_addr_t remote_bda;       /*!< Remote bluetooth device address */
+        uint16_t handle;                /*!< The Characteristic or descriptor handle */
+        uint16_t value_len;             /*!< Notify attribute value */
+        uint8_t *value;                 /*!< Notify attribute value */
+        bool is_notify;                 /*!< True means notify, false means indicate */
+    } notify;                           /*!< Gatt client callback param of ESP_GATTC_NOTIFY_EVT */
 
     /**
      * @brief ESP_GATTC_SRVC_CHG_EVT
         */
     struct gattc_srvc_chg_evt_param {
-        esp_bd_addr_t remote_bda;              /*!< Remote bluetooth device address */
-    } srvc_chg;                                                        /*!< Gatt client callback param of ESP_GATTC_SRVC_CHG_EVT */
+        esp_bd_addr_t remote_bda;       /*!< Remote bluetooth device address */
+    } srvc_chg;                         /*!< Gatt client callback param of ESP_GATTC_SRVC_CHG_EVT */
 
     /**
      * @brief ESP_GATTC_CONGEST_EVT
      */
     struct gattc_congest_evt_param {
-        uint16_t conn_id;                              /*!< Connection id */
-        bool congested;                                        /*!< Congested or not */
-    } congest;                                                 /*!< Gatt client callback param of ESP_GATTC_CONGEST_EVT */
-
-    /**
-     * @brief ESP_GATTC_GET_CHAR_EVT
-     */
-    struct gattc_get_char_evt_param {
-        esp_gatt_status_t status;              /*!< Operation status */
-        uint16_t conn_id;                              /*!< Connection id */
-        esp_gatt_srvc_id_t srvc_id;    /*!< Service id, include service uuid and other information */
-        esp_gatt_id_t char_id;                 /*!< Characteristic id, include characteristic uuid and other information */
-        esp_gatt_char_prop_t char_prop; /*!< Characteristic property */
-    } get_char;                                                        /*!< Gatt client callback param of ESP_GATTC_GET_CHAR_EVT */
-
-    /**
-     * @brief ESP_GATTC_GET_DESCR_EVT
-     */
-    struct gattc_get_descr_evt_param {
-        esp_gatt_status_t status;              /*!< Operation status */
-        uint16_t conn_id;                              /*!< Connection id */
-        esp_gatt_srvc_id_t srvc_id;    /*!< Service id, include service uuid and other information */
-        esp_gatt_id_t char_id;                 /*!< Characteristic id, include characteristic uuid and other information */
-        esp_gatt_id_t descr_id;                        /*!< Descriptor id, include descriptor uuid and other information */
-    } get_descr;                                               /*!< Gatt client callback param of ESP_GATTC_GET_DESCR_EVT */
-
-    /**
-     * @brief ESP_GATTC_GET_INCL_SRVC_EVT
-     */
-    struct gattc_get_incl_srvc_evt_param {
-        esp_gatt_status_t status;              /*!< Operation status */
-        uint16_t conn_id;                              /*!< Connection id */
-        esp_gatt_srvc_id_t srvc_id;    /*!< Service id, include service uuid and other information */
-        esp_gatt_srvc_id_t incl_srvc_id;/*!< Included service id, include service uuid and other information */
-    } get_incl_srvc;                                   /*!< Gatt client callback param of ESP_GATTC_GET_INCL_SRVC_EVT */
-
+        uint16_t conn_id;               /*!< Connection id */
+        bool congested;                 /*!< Congested or not */
+    } congest;                          /*!< Gatt client callback param of ESP_GATTC_CONGEST_EVT */
     /**
      * @brief ESP_GATTC_REG_FOR_NOTIFY_EVT
      */
     struct gattc_reg_for_notify_evt_param {
-        esp_gatt_status_t status;              /*!< Operation status */
-        esp_gatt_srvc_id_t srvc_id;    /*!< Service id, include service uuid and other information */
-        esp_gatt_id_t char_id;                 /*!< Characteristic id, include characteristic uuid and other information */
-    } reg_for_notify;                                  /*!< Gatt client callback param of ESP_GATTC_REG_FOR_NOTIFY_EVT */
+        esp_gatt_status_t status;       /*!< Operation status */
+        uint16_t handle;                /*!< The characteristic or descriptor handle */
+    } reg_for_notify;                   /*!< Gatt client callback param of ESP_GATTC_REG_FOR_NOTIFY_EVT */
 
-       /**
+    /**
      * @brief ESP_GATTC_UNREG_FOR_NOTIFY_EVT
      */
     struct gattc_unreg_for_notify_evt_param {
-        esp_gatt_status_t status;              /*!< Operation status */
-        esp_gatt_srvc_id_t srvc_id;    /*!< Service id, include service uuid and other information */
-        esp_gatt_id_t char_id;                 /*!< Characteristic id, include characteristic uuid and other information */
-    } unreg_for_notify;                                        /*!< Gatt client callback param of ESP_GATTC_UNREG_FOR_NOTIFY_EVT */
+        esp_gatt_status_t status;       /*!< Operation status */
+        uint16_t handle;                /*!< The characteristic or descriptor handle */
+    } unreg_for_notify;                 /*!< Gatt client callback param of ESP_GATTC_UNREG_FOR_NOTIFY_EVT */
 
     /**
      * @brief ESP_GATTC_CONNECT_EVT
@@ -263,7 +214,7 @@ typedef union {
         esp_bd_addr_t remote_bda;       /*!< Remote bluetooth device address */
     } disconnect;                       /*!< Gatt client callback param of ESP_GATTC_DISCONNECT_EVT */
 
-} esp_ble_gattc_cb_param_t;                            /*!< GATT client callback parameter union type */
+} esp_ble_gattc_cb_param_t;             /*!< GATT client callback parameter union type */
 
 /**
  * @brief GATT Client callback function type
@@ -383,76 +334,233 @@ esp_err_t esp_ble_gattc_send_mtu_req (esp_gatt_if_t gattc_if, uint16_t conn_id);
  */
 esp_err_t esp_ble_gattc_search_service(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_bt_uuid_t *filter_uuid);
 
+/**
+ * @brief           Find all the service with the given service uuid in the gattc cache, if the svc_uuid is NULL, find all the service.
+ *                  Note: It just get service from local cache, won't get from remote devices. If want to get it from remote device, need
+ *                  to used the esp_ble_gattc_search_service.
+ *
+ * @param[in]       gattc_if: Gatt client access interface.
+ * @param[in]       conn_id: connection ID which identify the server.
+ * @param[in]       svc_uuid: the pointer to the service uuid.
+ * @param[out]      result: The pointer to the service whith has been found in the gattc cache.
+ * @param[inout]   count: input the number of service want to find,
+ *                         it will output the number of service has been found in the gattc cache with the given service uuid.
+ * @param[in]       offset: Offset of the service position to get.
+ *
+ * @return
+ *                  - ESP_OK: success
+ *                  - other: failed
+ *
+ */
+esp_gatt_status_t esp_ble_gattc_get_service(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_bt_uuid_t *svc_uuid,
+                                            esp_gattc_service_elem_t *result, uint16_t *count, uint16_t offset);
 
 /**
- * @brief           This function is called to find the first characteristic of the
- *                  service on the given server.
+ * @brief           Find all the characteristic with the given service in the gattc cache
+ *                  Note: It just get characteristic from local cache, won't get from remote devices.
  *
  * @param[in]       gattc_if: Gatt client access interface.
  * @param[in]       conn_id: connection ID which identify the server.
- * @param[in]       srvc_id: service ID
- * @param[in]       start_char_id:  the start characteristic ID
+ * @param[in]       start_handle: the attribute start handle.
+ * @param[in]       end_handle: the attribute end handle
+ * @param[out]      result: The pointer to the charateristic in the service.
+ * @param[inout]   count: input the number of characteristic want to find,
+ *                         it will output the number of characteristic has been found in the gattc cache with the given service.
+ * @param[in]       offset: Offset of the characteristic position to get.
+ *
  * @return
  *                  - ESP_OK: success
  *                  - other: failed
  *
  */
-esp_err_t esp_ble_gattc_get_characteristic(esp_gatt_if_t gattc_if,
-                                            uint16_t conn_id,
-                                            esp_gatt_srvc_id_t *srvc_id,
-                                            esp_gatt_id_t *start_char_id);
+esp_gatt_status_t esp_ble_gattc_get_all_char(esp_gatt_if_t gattc_if,
+                                             uint16_t conn_id,
+                                             uint16_t start_handle,
+                                             uint16_t end_handle,
+                                             esp_gattc_char_elem_t *result,
+                                             uint16_t *count, uint16_t offset);
 
 /**
- * @brief           This function is called to find the descriptor of the
- *                  service on the given server.
+ * @brief           Find all the descriptor with the given characteristic in the gattc cache
+ *                  Note: It just get descriptor from local cache, won't get from remote devices.
  *
  * @param[in]       gattc_if: Gatt client access interface.
  * @param[in]       conn_id: connection ID which identify the server.
- * @param[in]       srvc_id: the service ID of which the characteristic is belonged to.
- * @param[in]       char_id: Characteristic ID, if NULL find the first available
- *                  characteristic.
- * @param[in]       start_descr_id:  the start descriptor id
+ * @param[in]       char_handle: the given characteristic handle
+ * @param[out]      result: The pointer to the descriptor in the characteristic.
+ * @param[inout]    count: input the number of descriptor want to find,
+ *                         it will output the number of descriptor has been found in the gattc cache with the given characteristic.
+ * @param[in]       offset: Offset of the descriptor position to get.
  *
  * @return
  *                  - ESP_OK: success
  *                  - other: failed
  *
  */
-esp_err_t esp_ble_gattc_get_descriptor(esp_gatt_if_t gattc_if,
-                                       uint16_t conn_id,
-                                       esp_gatt_srvc_id_t *srvc_id,
-                                       esp_gatt_id_t *char_id,
-                                       esp_gatt_id_t *start_descr_id);
+esp_gatt_status_t esp_ble_gattc_get_all_descr(esp_gatt_if_t gattc_if,
+                                              uint16_t conn_id,
+                                              uint16_t char_handle,
+                                              esp_gattc_descr_elem_t *result,
+                                              uint16_t *count, uint16_t offset);
 
 
 /**
- * @brief           This function is called to find the first characteristic of the
- *                  service on the given server.
+ * @brief           Find the characteristic with the given characteristic uuid in the gattc cache
+ *                  Note: It just get characteristic from local cache, won't get from remote devices.
  *
  * @param[in]       gattc_if: Gatt client access interface.
  * @param[in]       conn_id: connection ID which identify the server.
- * @param[in]       srvc_id: the service ID of which the characteristic is belonged to.
- * @param[in]       start_incl_srvc_id: the start include service id
+ * @param[in]       start_handle: the attribute start handle
+ * @param[in]       end_handle: the attribute end handle
+ * @param[in]       char_uuid: the characteristic uuid
+ * @param[out]      result: The pointer to the characteristic in the service.
+ * @param[inout]   count: input the number of characteristic want to find,
+ *                         it will output the number of characteristic has been found in the gattc cache with the given service.
  *
  * @return
  *                  - ESP_OK: success
  *                  - other: failed
  *
  */
-esp_err_t esp_ble_gattc_get_included_service(esp_gatt_if_t gattc_if, 
-                                            uint16_t conn_id,
-                                            esp_gatt_srvc_id_t *srvc_id,
-                                            esp_gatt_srvc_id_t *start_incl_srvc_id);
+esp_gatt_status_t esp_ble_gattc_get_char_by_uuid(esp_gatt_if_t gattc_if,
+                                                 uint16_t conn_id,
+                                                 uint16_t start_handle,
+                                                 uint16_t end_handle,
+                                                 esp_bt_uuid_t char_uuid,
+                                                 esp_gattc_char_elem_t *result,
+                                                 uint16_t *count);
 
+/**
+ * @brief           Find the descriptor with the given characteristic uuid in the gattc cache
+ *                  Note: It just get descriptor from local cache, won't get from remote devices.
+ *
+ * @param[in]       gattc_if: Gatt client access interface.
+ * @param[in]       conn_id: connection ID which identify the server.
+ * @param[in]       start_handle: the attribute start handle
+ * @param[in]       end_handle: the attribute end handle
+ * @param[in]       char_uuid: the characteristic uuid.
+ * @param[in]       descr_uuid: the descriptor uuid.
+ * @param[out]      result: The pointer to the descriptor in the given characteristic.
+ * @param[inout]   count: input the number of descriptor want to find,
+ *                         it will output the number of descriptor has been found in the gattc cache with the given characteristic.
+ *
+ * @return
+ *                  - ESP_OK: success
+ *                  - other: failed
+ *
+ */
+esp_gatt_status_t esp_ble_gattc_get_descr_by_uuid(esp_gatt_if_t gattc_if,
+                                                  uint16_t conn_id,
+                                                  uint16_t start_handle,
+                                                  uint16_t end_handle,
+                                                  esp_bt_uuid_t char_uuid,
+                                                  esp_bt_uuid_t descr_uuid,
+                                                  esp_gattc_descr_elem_t *result,
+                                                  uint16_t *count);
+
+/**
+ * @brief           Find the descriptor with the given characteristic handle in the gattc cache
+ *                  Note: It just get descriptor from local cache, won't get from remote devices.
+ *
+ * @param[in]       gattc_if: Gatt client access interface.
+ * @param[in]       conn_id: connection ID which identify the server.
+ * @param[in]       char_handle: the characteristic handle.
+ * @param[in]       descr_uuid: the descriptor uuid.
+ * @param[out]      result: The pointer to the descriptor in the given characteristic.
+ * @param[inout]   count: input the number of descriptor want to find,
+ *                         it will output the number of descriptor has been found in the gattc cache with the given characteristic.
+ *
+ * @return
+ *                  - ESP_OK: success
+ *                  - other: failed
+ *
+ */
+esp_gatt_status_t esp_ble_gattc_get_descr_by_char_handle(esp_gatt_if_t gattc_if,
+                                                         uint16_t conn_id,
+                                                         uint16_t char_handle,
+                                                         esp_bt_uuid_t descr_uuid,
+                                                         esp_gattc_descr_elem_t *result,
+                                                         uint16_t *count);
+
+/**
+ * @brief           Find the include service with the given service handle in the gattc cache
+ *                  Note: It just get include service from local cache, won't get from remote devices.
+ *
+ * @param[in]       gattc_if: Gatt client access interface.
+ * @param[in]       conn_id: connection ID which identify the server.
+ * @param[in]       start_handle: the attribute start handle
+ * @param[in]       end_handle: the attribute end handle
+ * @param[in]       incl_uuid: the include service uuid
+ * @param[out]      result: The pointer to the include service in the given service.
+ * @param[inout]   count: input the number of include service want to find,
+ *                         it will output the number of include service has been found in the gattc cache with the given service.
+ *
+ * @return
+ *                  - ESP_OK: success
+ *                  - other: failed
+ *
+ */
+esp_gatt_status_t esp_ble_gattc_get_include_service(esp_gatt_if_t gattc_if,
+                                                    uint16_t conn_id,
+                                                    uint16_t start_handle,
+                                                    uint16_t end_handle,
+                                                    esp_bt_uuid_t *incl_uuid,
+                                                    esp_gattc_incl_svc_elem_t *result,
+                                                    uint16_t *count);
+
+
+/**
+ * @brief           Find the attribute count with the given service or characteristic in the gattc cache
+ *
+ * @param[in]       gattc_if: Gatt client access interface.
+ * @param[in]       conn_id: connection ID which identify the server.
+ * @param[in]       type: the attribute type.
+ * @param[in]       start_handle: the attribute start handle, if the type is ESP_GATT_DB_DESCRIPTOR, this parameter should be ignore
+ * @param[in]       end_handle: the attribute end handle, if the type is ESP_GATT_DB_DESCRIPTOR, this parameter should be ignore
+ * @param[in]       char_handle: the characteristic handle, this parameter valid when the type is ESP_GATT_DB_DESCRIPTOR. If the type
+ *                               isn't ESP_GATT_DB_DESCRIPTOR, this parameter should be ignore.
+ * @param[out]      count: output the number of attribute has been found in the gattc cache with the given attribute type.
+ *
+ * @return
+ *                  - ESP_OK: success
+ *                  - other: failed
+ *
+ */
+esp_gatt_status_t esp_ble_gattc_get_attr_count(esp_gatt_if_t gattc_if,
+                                               uint16_t conn_id,
+                                               esp_gatt_db_attr_type_t type,
+                                               uint16_t start_handle,
+                                               uint16_t end_handle,
+                                               uint16_t char_handle,
+                                               uint16_t *count);
+
+/**
+ * @brief           This function is called to get the GATT database.
+ *                  Note: It just get attribute data base from local cache, won't get from remote devices.
+ *
+ * @param[in]       gattc_if: Gatt client access interface.
+ * @param[in]       start_handle: the attribute start handle
+ * @param[in]       end_handle: the attribute end handle
+ * @param[in]       conn_id: connection ID which identify the server.
+ * @param[in]       db: output parameter which will contain the GATT database copy.
+ *                      Caller is responsible for freeing it.
+ * @param[in]       count: number of elements in database.
+ *
+ * @return
+ *                  - ESP_OK: success
+ *                  - other: failed
+ *
+ */
+esp_gatt_status_t esp_ble_gattc_get_db(esp_gatt_if_t gattc_if, uint16_t conn_id, uint16_t start_handle, uint16_t end_handle,
+                                        esp_gattc_db_elem_t *db, uint16_t *count);
 
 /**
  * @brief           This function is called to read a service's characteristics of
- *                  the given characteristic ID
+ *                  the given characteristic handle
  *
  * @param[in]       gattc_if: Gatt client access interface.
  * @param[in]       conn_id : connection ID.
- * @param[in]       srvc_id : service ID.
- * @param[in]       char_id : characteristic ID to read.
+ * @param[in]       handle : characteritic handle to read.
  * @param[in]       auth_req : authenticate request type
  *
  * @return
@@ -460,11 +568,28 @@ esp_err_t esp_ble_gattc_get_included_service(esp_gatt_if_t gattc_if,
  *                  - other: failed
  *
  */
-esp_err_t esp_ble_gattc_read_char (esp_gatt_if_t gattc_if, 
-                                uint16_t conn_id,
-                                esp_gatt_srvc_id_t *srvc_id,
-                                esp_gatt_id_t *char_id,
-                                esp_gatt_auth_req_t auth_req);
+esp_err_t esp_ble_gattc_read_char (esp_gatt_if_t gattc_if,
+                                   uint16_t conn_id,
+                                   uint16_t handle,
+                                   esp_gatt_auth_req_t auth_req);
+
+/**
+ * @brief           This function is called to read multiple characteristic or
+ *                  characteristic descriptors.
+ *
+ * @param[in]       gattc_if: Gatt client access interface.
+ * @param[in]       conn_id : connection ID.
+ * @param[in]       read_multi : pointer to the read multiple parameter.
+ * @param[in]       auth_req : authenticate request type
+ *
+ * @return
+ *                  - ESP_OK: success
+ *                  - other: failed
+ *
+ */
+esp_err_t esp_ble_gattc_read_multiple(esp_gatt_if_t gattc_if,
+                                      uint16_t conn_id, esp_gattc_multi_t *read_multi,
+                                      esp_gatt_auth_req_t auth_req);
 
 
 /**
@@ -472,9 +597,7 @@ esp_err_t esp_ble_gattc_read_char (esp_gatt_if_t gattc_if,
  *
  * @param[in]       gattc_if: Gatt client access interface.
  * @param[in]       conn_id : connection ID.
- * @param[in]       srvc_id : service ID.
- * @param[in]       char_id : characteristic ID to read.
- * @param[in]       descr_id : characteristic descriptor ID to read.
+ * @param[in]       handle : descriptor handle to read.
  * @param[in]       auth_req : authenticate request type
  *
  * @return
@@ -483,11 +606,9 @@ esp_err_t esp_ble_gattc_read_char (esp_gatt_if_t gattc_if,
  *
  */
 esp_err_t esp_ble_gattc_read_char_descr (esp_gatt_if_t gattc_if,
-                                        uint16_t conn_id,
-                                        esp_gatt_srvc_id_t *srvc_id,
-                                        esp_gatt_id_t  *char_id,
-                                        esp_gatt_id_t  *descr_id,
-                                        esp_gatt_auth_req_t auth_req);
+                                         uint16_t conn_id,
+                                         uint16_t handle,
+                                         esp_gatt_auth_req_t auth_req);
 
 
 /**
@@ -495,8 +616,7 @@ esp_err_t esp_ble_gattc_read_char_descr (esp_gatt_if_t gattc_if,
  *
  * @param[in]       gattc_if: Gatt client access interface.
  * @param[in]       conn_id : connection ID.
- * @param[in]       srvc_id : service ID.
- * @param[in]       char_id : characteristic ID to write.
+ * @param[in]       handle : characteristic handle to write.
  * @param[in]       value_len: length of the value to be written.
  * @param[in]       value : the value to be written.
  * @param[in]       write_type : the type of attribute write operation.
@@ -509,11 +629,10 @@ esp_err_t esp_ble_gattc_read_char_descr (esp_gatt_if_t gattc_if,
  */
 esp_err_t esp_ble_gattc_write_char( esp_gatt_if_t gattc_if,
                                     uint16_t conn_id,
-                                    esp_gatt_srvc_id_t *srvc_id,
-                                    esp_gatt_id_t *char_id,
+                                    uint16_t handle,
                                     uint16_t value_len,
                                     uint8_t *value,
-                                                                       esp_gatt_write_type_t write_type,
+                                    esp_gatt_write_type_t write_type,
                                     esp_gatt_auth_req_t auth_req);
 
 
@@ -522,9 +641,7 @@ esp_err_t esp_ble_gattc_write_char( esp_gatt_if_t gattc_if,
  *
  * @param[in]       gattc_if: Gatt client access interface.
  * @param[in]       conn_id : connection ID
- * @param[in]       srvc_id : service ID.
- * @param[in]       char_id : characteristic ID.
- * @param[in]       descr_id : characteristic descriptor ID to write.
+ * @param[in]       handle : descriptor hadle to write.
  * @param[in]       value_len: length of the value to be written.
  * @param[in]       value : the value to be written.
  * @param[in]       write_type : the type of attribute write operation.
@@ -537,9 +654,7 @@ esp_err_t esp_ble_gattc_write_char( esp_gatt_if_t gattc_if,
  */
 esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if,
                                          uint16_t conn_id,
-                                         esp_gatt_srvc_id_t *srvc_id,
-                                         esp_gatt_id_t *char_id,
-                                         esp_gatt_id_t *descr_id,
+                                         uint16_t handle,
                                          uint16_t value_len,
                                          uint8_t *value,
                                          esp_gatt_write_type_t write_type,
@@ -551,8 +666,7 @@ esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if,
  *
  * @param[in]       gattc_if: Gatt client access interface.
  * @param[in]       conn_id : connection ID.
- * @param[in]       srvc_id : service ID.
- * @param[in]       char_id : GATT characteristic ID of the service.
+ * @param[in]       handle : charateristic handle to prepare write.
  * @param[in]       offset : offset of the write value.
  * @param[in]       value_len: length of the value to be written.
  * @param[in]       value : the value to be written.
@@ -563,10 +677,9 @@ esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if,
  *                  - other: failed
  *
  */
-esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if, 
+esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if,
                                       uint16_t conn_id,
-                                      esp_gatt_srvc_id_t *srvc_id,
-                                      esp_gatt_id_t *char_id,
+                                      uint16_t handle,
                                       uint16_t offset,
                                       uint16_t value_len,
                                       uint8_t *value,
@@ -578,9 +691,7 @@ esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if,
  *
  * @param[in]       gattc_if: Gatt client access interface.
  * @param[in]       conn_id : connection ID.
- * @param[in]       srvc_id : service ID.
- * @param[in]       char_id : GATT characteristic ID of the service.
- * @param[in]       descr_id : characteristic descriptor ID to write.
+ * @param[in]       handle : characteristic descriptor hanlde to prepare write.
  * @param[in]       offset : offset of the write value.
  * @param[in]       value_len: length of the value to be written.
  * @param[in]       value : the value to be written.
@@ -593,9 +704,7 @@ esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if,
  */
 esp_err_t esp_ble_gattc_prepare_write_char_descr(esp_gatt_if_t gattc_if,
                                                  uint16_t conn_id,
-                                                 esp_gatt_srvc_id_t *srvc_id,
-                                                 esp_gatt_id_t *char_id,
-                                                 esp_gatt_id_t *descr_id,
+                                                 uint16_t handle,
                                                  uint16_t offset,
                                                  uint16_t value_len,
                                                  uint8_t *value,
@@ -622,8 +731,7 @@ esp_err_t esp_ble_gattc_execute_write (esp_gatt_if_t gattc_if, uint16_t conn_id,
  *
  * @param[in]       gattc_if: Gatt client access interface.
  * @param[in]       server_bda : target GATT server.
- * @param[in]       srvc_id : pointer to GATT service ID.
- * @param[in]       char_id : pointer to GATT characteristic ID.
+ * @param[in]       handle : GATT characteristic handle.
  *
  * @return
  *                  - ESP_OK: registration succeeds
@@ -631,9 +739,8 @@ esp_err_t esp_ble_gattc_execute_write (esp_gatt_if_t gattc_if, uint16_t conn_id,
  *
  */
 esp_err_t esp_ble_gattc_register_for_notify (esp_gatt_if_t gattc_if,
-                                                    esp_bd_addr_t server_bda,
-                                                    esp_gatt_srvc_id_t *srvc_id,
-                                                    esp_gatt_id_t *char_id);
+                                             esp_bd_addr_t server_bda,
+                                             uint16_t handle);
 
 
 /**
@@ -641,8 +748,7 @@ esp_err_t esp_ble_gattc_register_for_notify (esp_gatt_if_t gattc_if,
  *
  * @param[in]       gattc_if: Gatt client access interface.
  * @param[in]       server_bda : target GATT server.
- * @param[in]       srvc_id : pointer to GATT service ID.
- * @param[in]       char_id : pointer to GATT characteristic ID.
+ * @param[in]       handle : GATT characteristic handle.
  *
  * @return
  *                  - ESP_OK: unregister succeeds
@@ -650,9 +756,8 @@ esp_err_t esp_ble_gattc_register_for_notify (esp_gatt_if_t gattc_if,
  *
  */
 esp_err_t esp_ble_gattc_unregister_for_notify (esp_gatt_if_t gattc_if,
-                                                      esp_bd_addr_t server_bda,
-                                                      esp_gatt_srvc_id_t *srvc_id,
-                                                      esp_gatt_id_t *char_id);
+                                               esp_bd_addr_t server_bda,
+                                               uint16_t handle);
 
 
 /**
index 12ceef36cc7acbe32dbf78d4315a91738673dff5..eed5241a5a0246e6f65d67b7d5300e4b1faf0806 100644 (file)
@@ -5608,7 +5608,7 @@ static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
         break;
 
     case BTA_GATTC_SEARCH_RES_EVT:
-        bta_dm_gatt_disc_result(p_data->srvc_res.service_uuid.id);
+        bta_dm_gatt_disc_result(p_data->srvc_res.service_uuid);
         break;
 
     case BTA_GATTC_SEARCH_CMPL_EVT:
index 2738b52ad0e1e2bba2d08617aa2d781d9fc82e5c..159baa0632d462aeb55d0115266d6817b1287d2c 100644 (file)
@@ -102,6 +102,9 @@ static const char *bta_gattc_op_code_name[] = {
 **  Action Functions
 *****************************************************************************/
 
+
+void bta_gattc_reset_discover_st(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_STATUS status);
+
 /*******************************************************************************
 **
 ** Function         bta_gattc_enable
@@ -659,13 +662,18 @@ void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
             p_clcb->p_srcb->state != BTA_GATTC_SERV_IDLE) {
         if (p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE) {
             p_clcb->p_srcb->state = BTA_GATTC_SERV_LOAD;
-            bta_gattc_sm_execute(p_clcb, BTA_GATTC_START_CACHE_EVT, NULL);
+            if (bta_gattc_cache_load(p_clcb)) {
+                p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
+                bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK);
         } else { /* cache is building */
-            p_clcb->state = BTA_GATTC_DISCOVER_ST;
+                p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC;
+                /* cache load failure, start discovery */
+                bta_gattc_start_discover(p_clcb, NULL);
         }
+    } else { /* cache is building */
+        p_clcb->state = BTA_GATTC_DISCOVER_ST;
     }
-
-    else {
+    } else {
         /* a pending service handle change indication */
         if (p_clcb->p_srcb->srvc_hdl_chg) {
             p_clcb->p_srcb->srvc_hdl_chg = FALSE;
@@ -932,9 +940,8 @@ void bta_gattc_start_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
 
     if (((p_clcb->p_q_cmd == NULL || p_clcb->auto_update == BTA_GATTC_REQ_WAITING) &&
             p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE) ||
-            p_clcb->p_srcb->state == BTA_GATTC_SERV_DISC)
+            p_clcb->p_srcb->state == BTA_GATTC_SERV_DISC) {
         /* no pending operation, start discovery right away */
-    {
         p_clcb->auto_update = BTA_GATTC_NO_SCHEDULE;
 
         if (p_clcb->p_srcb != NULL) {
@@ -988,7 +995,7 @@ void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
     tBTA_GATTC_DATA *p_q_cmd = p_clcb->p_q_cmd;
     UNUSED(p_data);
 
-    APPL_TRACE_DEBUG("bta_gattc_disc_cmpl conn_id=%d", p_clcb->bta_conn_id);
+    APPL_TRACE_DEBUG("bta_gattc_disc_cmpl conn_id=%d, status = %d", p_clcb->bta_conn_id, p_clcb->status);
 
     p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
     p_clcb->disc_active = FALSE;
@@ -996,30 +1003,30 @@ void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
     if (p_clcb->status != GATT_SUCCESS) {
         /* clean up cache */
         if (p_clcb->p_srcb && p_clcb->p_srcb->p_srvc_cache) {
-            while (!fixed_queue_is_empty(p_clcb->p_srcb->cache_buffer)) {
-                osi_free(fixed_queue_try_dequeue(p_clcb->p_srcb->cache_buffer));
-            }
-            //fixed_queue_free(p_clcb->p_srcb->cache_buffer, NULL);
+            list_free(p_clcb->p_srcb->p_srvc_cache);
             p_clcb->p_srcb->p_srvc_cache = NULL;
         }
 
         /* used to reset cache in application */
-        bta_gattc_co_cache_reset(p_clcb->p_srcb->server_bda);
+        bta_gattc_cache_reset(p_clcb->p_srcb->server_bda);
+    }
+    if (p_clcb->p_srcb && p_clcb->p_srcb->p_srvc_list) {
+        /* release pending attribute list buffer */
+        APPL_TRACE_DEBUG("+++++++++++++++++++++++++++++++++++++++++++++++++++++++= %p", p_clcb->p_srcb->p_srvc_list);
+        osi_free(p_clcb->p_srcb->p_srvc_list);
+        p_clcb->p_srcb->p_srvc_list = NULL;
+        //osi_free_and_reset((void **)&p_clcb->p_srcb->p_srvc_list);
     }
-    /* release pending attribute list buffer */
-    utl_freebuf((void **)&p_clcb->p_srcb->p_srvc_list);
 
     if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING) {
         /* start discovery again */
-        p_clcb->auto_update = BTA_GATTC_REQ_WAITING;
         bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
     }
     /* get any queued command to proceed */
     else if (p_q_cmd != NULL) {
         p_clcb->p_q_cmd = NULL;
-         /* execute pending operation of link block still present */
-        if (l2cu_find_lcb_by_bd_addr(p_clcb->p_srcb->server_bda,
-            BT_TRANSPORT_LE) != NULL) {
+        /* execute pending operation of link block still present */
+        if (l2cu_find_lcb_by_bd_addr(p_clcb->p_srcb->server_bda, BT_TRANSPORT_LE) != NULL) {
             bta_gattc_sm_execute(p_clcb, p_q_cmd->hdr.event, p_q_cmd);
         }
         /* if the command executed requeued the cmd, we don't
@@ -1027,8 +1034,11 @@ void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
          * referenced by p_clcb->p_q_cmd
          */
         if (p_q_cmd != p_clcb->p_q_cmd) {
-            utl_freebuf((void **)&p_q_cmd);
+            APPL_TRACE_DEBUG("====================================================================");
+            osi_free(p_q_cmd);
+            p_q_cmd = NULL;
         }
+            //osi_free_and_reset((void **)&p_q_cmd);
     }
 }
 /*******************************************************************************
@@ -1042,24 +1052,15 @@ void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
 *******************************************************************************/
 void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
 {
-    UINT16 handle = 0;
-    tGATT_READ_PARAM    read_param;
-    tBTA_GATT_STATUS    status;
-
-    memset (&read_param, 0 , sizeof(tGATT_READ_PARAM));
+    if (!bta_gattc_enqueue(p_clcb, p_data))
+        return;
 
-    if (bta_gattc_enqueue(p_clcb, p_data)) {
-        if ((handle = bta_gattc_id2handle(p_clcb->p_srcb,
-                                          &p_data->api_read.srvc_id,
-                                          &p_data->api_read.char_id,
-                                          p_data->api_read.p_descr_type)) == 0) {
-            status = BTA_GATT_ERROR;
-        } else {
-            read_param.by_handle.handle = handle;
-            read_param.by_handle.auth_req = p_data->api_read.auth_req;
+    tGATT_READ_PARAM    read_param;
+    memset (&read_param, 0 ,sizeof(tGATT_READ_PARAM));
+    read_param.by_handle.handle = p_data->api_read.handle;
+    read_param.by_handle.auth_req = p_data->api_read.auth_req;
 
-            status = GATTC_Read(p_clcb->bta_conn_id, GATT_READ_BY_HANDLE, &read_param);
-        }
+    tBTA_GATT_STATUS status = GATTC_Read(p_clcb->bta_conn_id, GATT_READ_BY_HANDLE, &read_param);
 
         /* read fail */
         if (status != BTA_GATT_OK) {
@@ -1070,7 +1071,6 @@ void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
 
             bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_READ, status, NULL);
         }
-    }
 }
 /*******************************************************************************
 **
@@ -1082,41 +1082,17 @@ void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
 *********************************************************************************/
 void bta_gattc_read_multi(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
 {
-    UINT16              i, handle;
     tBTA_GATT_STATUS    status = BTA_GATT_OK;
     tGATT_READ_PARAM    read_param;
-    tBTA_GATTC_ATTR_ID  *p_id;
 
     if (bta_gattc_enqueue(p_clcb, p_data)) {
         memset(&read_param, 0, sizeof(tGATT_READ_PARAM));
 
-        p_id = p_data->api_read_multi.p_id_list;
-
-        for (i = 0; i < p_data->api_read_multi.num_attr && p_id; i ++, p_id ++) {
-            handle = 0;
-
-            if (p_id->id_type == BTA_GATT_TYPE_CHAR) {
-                handle = bta_gattc_id2handle(p_clcb->p_srcb,
-                                             &p_id->id_value.char_id.srvc_id,
-                                             &p_id->id_value.char_id.char_id,
-                                             NULL);
-            } else if (p_id->id_type == BTA_GATT_TYPE_CHAR_DESCR) {
-                handle = bta_gattc_id2handle(p_clcb->p_srcb,
-                                             &p_id->id_value.char_descr_id.char_id.srvc_id,
-                                             &p_id->id_value.char_descr_id.char_id.char_id,
-                                             &p_id->id_value.char_descr_id.descr_id);
-            } else {
-                APPL_TRACE_ERROR("invalud ID type: %d", p_id->id_type);
-            }
-
-            if (handle == 0) {
-                status = BTA_GATT_ERROR;
-                break;
-            }
-        }
         if (status == BTA_GATT_OK) {
             read_param.read_multiple.num_handles = p_data->api_read_multi.num_attr;
             read_param.read_multiple.auth_req = p_data->api_read_multi.auth_req;
+            memcpy(&read_param.read_multiple.handles, p_data->api_read_multi.handles,
+                                        sizeof(UINT16) * p_data->api_read_multi.num_attr);
 
             status = GATTC_Read(p_clcb->bta_conn_id, GATT_READ_MULTIPLE, &read_param);
         }
@@ -1143,38 +1119,32 @@ void bta_gattc_read_multi(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
 *******************************************************************************/
 void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
 {
-    UINT16              handle = 0;
-    tGATT_VALUE         attr = {0};
-    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+    if (!bta_gattc_enqueue(p_clcb, p_data))
+        return;
 
-    if (bta_gattc_enqueue(p_clcb, p_data)) {
-        if ((handle = bta_gattc_id2handle(p_clcb->p_srcb,
-                                          &p_data->api_write.srvc_id,
-                                          &p_data->api_write.char_id,
-                                          p_data->api_write.p_descr_type)) == 0) {
-            status = BTA_GATT_ERROR;
-        } else {
-            attr.handle = handle;
-            attr.offset = p_data->api_write.offset;
-            attr.len    = p_data->api_write.len;
-            attr.auth_req = p_data->api_write.auth_req;
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+    tGATT_VALUE attr;
 
-            if (p_data->api_write.p_value) {
-                memcpy(attr.value, p_data->api_write.p_value, p_data->api_write.len);
-            }
+    attr.conn_id = p_clcb->bta_conn_id;
+    attr.handle = p_data->api_write.handle;
+    attr.offset = p_data->api_write.offset;
+    attr.len    = p_data->api_write.len;
+    attr.auth_req = p_data->api_write.auth_req;
 
-            status = GATTC_Write(p_clcb->bta_conn_id, p_data->api_write.write_type, &attr);
-        }
+    if (p_data->api_write.p_value) {
+        memcpy(attr.value, p_data->api_write.p_value, p_data->api_write.len);
+    }
 
-        /* write fail */
-        if (status != BTA_GATT_OK) {
-            /* Dequeue the data, if it was enqueued */
-            if (p_clcb->p_q_cmd == p_data) {
-                p_clcb->p_q_cmd = NULL;
-            }
+    status = GATTC_Write(p_clcb->bta_conn_id, p_data->api_write.write_type, &attr);
 
-            bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_WRITE, status, NULL);
+    /* write fail */
+    if (status != BTA_GATT_OK) {
+        /* Dequeue the data, if it was enqueued */
+        if (p_clcb->p_q_cmd == p_data) {
+            p_clcb->p_q_cmd = NULL;
         }
+
+        bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_WRITE, status, NULL);
     }
 }
 /*******************************************************************************
@@ -1213,23 +1183,16 @@ void bta_gattc_execute(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
 *******************************************************************************/
 void bta_gattc_confirm(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
 {
-    UINT16 handle;
+    UINT16 handle = p_data->api_confirm.handle;
 
-    if ((handle = bta_gattc_id2handle(p_clcb->p_srcb,
-                                      &p_data->api_confirm.srvc_id,
-                                      &p_data->api_confirm.char_id,
-                                      NULL)) == 0) {
-        APPL_TRACE_ERROR("Can not map service/char ID into valid handle");
-    } else {
-        if (GATTC_SendHandleValueConfirm(p_data->api_confirm.hdr.layer_specific, handle)
-                != GATT_SUCCESS) {
+    if (GATTC_SendHandleValueConfirm(p_data->api_confirm.hdr.layer_specific, handle)
+        != GATT_SUCCESS) {
             APPL_TRACE_ERROR("bta_gattc_confirm to handle [0x%04x] failed", handle);
-        } else {
-            /* if over BR_EDR, inform PM for mode change */
-            if (p_clcb->transport == BTA_TRANSPORT_BR_EDR) {
-                bta_sys_busy(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
-                bta_sys_idle(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
-            }
+    } else {
+        /* if over BR_EDR, inform PM for mode change */
+        if (p_clcb->transport == BTA_TRANSPORT_BR_EDR) {
+            bta_sys_busy(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
+            bta_sys_idle(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
         }
     }
 }
@@ -1246,42 +1209,28 @@ void bta_gattc_read_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
 {
     UINT8               event;
     tBTA_GATTC          cb_data;
-    tBTA_GATT_READ_VAL  read_value;
+    tBTA_GATT_UNFMT     read_value;
 
     memset(&cb_data, 0, sizeof(tBTA_GATTC));
-    memset(&read_value, 0, sizeof(tBTA_GATT_READ_VAL));
+    memset(&read_value, 0, sizeof(tBTA_GATT_UNFMT));
 
     cb_data.read.status     = p_data->status;
 
     if (p_data->p_cmpl != NULL && p_data->status == BTA_GATT_OK) {
-        if (bta_gattc_handle2id(p_clcb->p_srcb,
-                                p_data->p_cmpl->att_value.handle,
-                                &cb_data.read.srvc_id,
-                                &cb_data.read.char_id,
-                                &cb_data.read.descr_type) == FALSE) {
-            cb_data.read.status = BTA_GATT_INTERNAL_ERROR;
-            APPL_TRACE_ERROR("can not map to GATT ID. handle = 0x%04x",
-                             p_data->p_cmpl->att_value.handle);
-        } else {
-            cb_data.read.status = bta_gattc_pack_read_cb_data(p_clcb->p_srcb,
-                                  &cb_data.read.descr_type.uuid,
-                                  &p_data->p_cmpl->att_value,
-                                  &read_value);
-            cb_data.read.p_value = &read_value;
-        }
+        cb_data.read.handle = p_data->p_cmpl->att_value.handle;
+
+        read_value.len = p_data->p_cmpl->att_value.len;
+        read_value.p_value = p_data->p_cmpl->att_value.value;
+        cb_data.read.p_value = &read_value;
     } else {
-        cb_data.read.srvc_id = p_clcb->p_q_cmd->api_read.srvc_id;
-        cb_data.read.char_id = p_clcb->p_q_cmd->api_read.char_id;
-        if (p_clcb->p_q_cmd->api_read.p_descr_type)
-            memcpy(&cb_data.read.descr_type, p_clcb->p_q_cmd->api_read.p_descr_type,
-                   sizeof(tBTA_GATT_ID));
+        cb_data.read.handle = p_clcb->p_q_cmd->api_read.handle;
     }
 
-    event = (p_clcb->p_q_cmd->api_read.p_descr_type == NULL) ?
-            BTA_GATTC_READ_CHAR_EVT : BTA_GATTC_READ_DESCR_EVT;
+    event = p_clcb->p_q_cmd->api_read.cmpl_evt;
     cb_data.read.conn_id = p_clcb->bta_conn_id;
-
-    utl_freebuf((void **)&p_clcb->p_q_cmd);
+    osi_free(p_clcb->p_q_cmd);
+    p_clcb->p_q_cmd = NULL;
+    //osi_free_and_reset((void **)&p_clcb->p_q_cmd);
     /* read complete, callback */
     ( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data);
 
@@ -1303,39 +1252,18 @@ void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
     memset(&cb_data, 0, sizeof(tBTA_GATTC));
 
     cb_data.write.status     = p_data->status;
-
-    if (p_data->p_cmpl != NULL) {
-        bta_gattc_handle2id(p_clcb->p_srcb, p_data->p_cmpl->att_value.handle,
-                            &cb_data.write.srvc_id, &cb_data.write.char_id,
-                            &cb_data.write.descr_type);
-    } else {
-        memcpy(&cb_data.write.srvc_id, &p_clcb->p_q_cmd->api_write.srvc_id,
-               sizeof(tBTA_GATT_SRVC_ID));
-        memcpy(&cb_data.write.char_id, &p_clcb->p_q_cmd->api_write.char_id,
-               sizeof(tBTA_GATT_ID));
-        if (p_clcb->p_q_cmd->api_write.p_descr_type)
-            memcpy(&cb_data.write.descr_type, p_clcb->p_q_cmd->api_write.p_descr_type,
-                   sizeof(tBTA_GATT_ID));
-    }
+    cb_data.write.handle = p_data->p_cmpl->att_value.handle;
 
     if (p_clcb->p_q_cmd->api_write.hdr.event == BTA_GATTC_API_WRITE_EVT &&
-            p_clcb->p_q_cmd->api_write.write_type == BTA_GATTC_WRITE_PREPARE)
+        p_clcb->p_q_cmd->api_write.write_type == BTA_GATTC_WRITE_PREPARE) {
 
-    {
         event = BTA_GATTC_PREP_WRITE_EVT;
-    }
-
-    else if (p_clcb->p_q_cmd->api_write.p_descr_type == NULL)
-
-    {
-        event = BTA_GATTC_WRITE_CHAR_EVT;
-    }
-
-    else {
-        event = BTA_GATTC_WRITE_DESCR_EVT;
-    }
-
-    utl_freebuf((void **)&p_clcb->p_q_cmd);
+               } else {
+        event = p_clcb->p_q_cmd->api_write.cmpl_evt;
+       }
+    osi_free(p_clcb->p_q_cmd);
+    p_clcb->p_q_cmd = NULL;
+    //osi_free_and_reset((void **)&p_clcb->p_q_cmd);
     cb_data.write.conn_id = p_clcb->bta_conn_id;
     /* write complete, callback */
     ( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data);
@@ -1353,9 +1281,9 @@ void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
 void bta_gattc_exec_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
 {
     tBTA_GATTC          cb_data;
-
-    utl_freebuf((void **)&p_clcb->p_q_cmd);
-
+    osi_free(p_clcb->p_q_cmd);
+    p_clcb->p_q_cmd = NULL;
+    //osi_free_and_reset((void **)&p_clcb->p_q_cmd);
     p_clcb->status      = BTA_GATT_OK;
 
     /* execute complete, callback */
@@ -1378,8 +1306,9 @@ void bta_gattc_exec_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
 void bta_gattc_cfg_mtu_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
 {
     tBTA_GATTC          cb_data;
-
-    utl_freebuf((void **)&p_clcb->p_q_cmd);
+    osi_free(p_clcb->p_q_cmd);
+    p_clcb->p_q_cmd = NULL;
+    //osi_free_and_reset((void **)&p_clcb->p_q_cmd);
 
 
     if (p_data->p_cmpl  &&  p_data->status == BTA_GATT_OK) {
@@ -1521,128 +1450,7 @@ void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
 {
     bta_gattc_enqueue(p_clcb, p_data);
 }
-/*******************************************************************************
-**
-** Function         bta_gattc_cache_open
-**
-** Description      open a NV cache for loading
-**
-** Returns          void
-**
-*******************************************************************************/
-void bta_gattc_cache_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
-{
-    UNUSED(p_data);
-
-    bta_gattc_set_discover_st(p_clcb->p_srcb);
-
-    APPL_TRACE_DEBUG("bta_gattc_cache_open conn_id=%d", p_clcb->bta_conn_id);
-    bta_gattc_co_cache_open(p_clcb->p_srcb->server_bda, BTA_GATTC_CI_CACHE_OPEN_EVT,
-                            p_clcb->bta_conn_id, FALSE);
-}
-/*******************************************************************************
-**
-** Function         bta_gattc_start_load
-**
-** Description      start cache loading by sending callout open cache
-**
-** Returns          None.
-**
-*******************************************************************************/
-void bta_gattc_ci_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
-{
-    APPL_TRACE_DEBUG("bta_gattc_ci_open conn_id=%d server state=%d" ,
-                     p_clcb->bta_conn_id, p_clcb->p_srcb->state);
-    if (p_clcb->p_srcb->state == BTA_GATTC_SERV_LOAD) {
-        if (p_data->ci_open.status == BTA_GATT_OK) {
-            p_clcb->p_srcb->attr_index = 0;
-            bta_gattc_co_cache_load(p_clcb->p_srcb->server_bda,
-                                    BTA_GATTC_CI_CACHE_LOAD_EVT,
-                                    p_clcb->p_srcb->attr_index,
-                                    p_clcb->bta_conn_id);
-        } else {
-            p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC;
-            /* cache open failure, start discovery */
-            bta_gattc_start_discover(p_clcb, NULL);
-        }
-    }
-    if (p_clcb->p_srcb->state == BTA_GATTC_SERV_SAVE) {
-        if (p_data->ci_open.status == BTA_GATT_OK) {
-            if (!bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id)) {
-                p_data->ci_open.status = BTA_GATT_ERROR;
-            }
-        }
-        if (p_data->ci_open.status != BTA_GATT_OK) {
-            p_clcb->p_srcb->attr_index = 0;
-            bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, p_clcb->bta_conn_id);
-            bta_gattc_reset_discover_st(p_clcb->p_srcb, p_clcb->status);
-
-        }
-    }
-}
-/*******************************************************************************
-**
-** Function         bta_gattc_ci_load
-**
-** Description      cache loading received.
-**
-** Returns          None.
-**
-*******************************************************************************/
-void bta_gattc_ci_load(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
-{
-
-    APPL_TRACE_DEBUG("bta_gattc_ci_load conn_id=%d load status=%d",
-                     p_clcb->bta_conn_id, p_data->ci_load.status);
-
-    if (p_data->ci_load.status == BTA_GATT_OK ||
-            p_data->ci_load.status == BTA_GATT_MORE) {
-        if (p_data->ci_load.num_attr != 0)
-            bta_gattc_rebuild_cache(p_clcb->p_srcb, p_data->ci_load.num_attr,
-                                    p_data->ci_load.attr, p_clcb->p_srcb->attr_index);
-
-        if (p_data->ci_load.status == BTA_GATT_OK) {
-            p_clcb->p_srcb->attr_index = 0;
-            bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK);
-            bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, 0);
-        } else { /* load more */
-            p_clcb->p_srcb->attr_index += p_data->ci_load.num_attr;
-
-            bta_gattc_co_cache_load(p_clcb->p_srcb->server_bda,
-                                    BTA_GATTC_CI_CACHE_LOAD_EVT,
-                                    p_clcb->p_srcb->attr_index,
-                                    p_clcb->bta_conn_id);
-        }
-    } else {
-        bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, 0);
-        p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC;
-        p_clcb->p_srcb->attr_index = 0;
-        /* cache load failure, start discovery */
-        bta_gattc_start_discover(p_clcb, NULL);
-    }
-}
-/*******************************************************************************
-**
-** Function         bta_gattc_ci_save
-**
-** Description      cache loading received.
-**
-** Returns          None.
-**
-*******************************************************************************/
-void bta_gattc_ci_save(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
-{
-    UNUSED(p_data);
-
-    APPL_TRACE_DEBUG("bta_gattc_ci_save conn_id=%d  " ,
-                     p_clcb->bta_conn_id   );
 
-    if (!bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id)) {
-        p_clcb->p_srcb->attr_index = 0;
-        bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, 0);
-        bta_gattc_reset_discover_st(p_clcb->p_srcb, p_clcb->status);
-    }
-}
 /*******************************************************************************
 **
 ** Function         bta_gattc_fail
@@ -1731,9 +1539,9 @@ static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id,
     }
 
     if ((transport == BT_TRANSPORT_LE) && (connected == TRUE) && (p_conn != NULL) \
-         && (p_conn->service_change_ccc_written == FALSE) && (p_conn->ccc_timer_used == FALSE)){
+         && (p_conn->service_change_ccc_written == FALSE) && (p_conn->ccc_timer_used == FALSE)) {
         result = bta_gattc_register_service_change_notify(conn_id, bda, &start_ccc_timer);
-        if (start_ccc_timer == TRUE){
+        if (start_ccc_timer == TRUE) {
             TIMER_LIST_ENT *ccc_timer = &(p_conn->service_change_ccc_timer);
             /* start a 1000ms timer to wait for service discovery finished */
             bta_gattc_start_service_change_ccc_timer(conn_id, bda, 1000, 0, result, ccc_timer);
@@ -1804,6 +1612,8 @@ static void bta_gattc_enc_cmpl_cback(tGATT_IF gattc_if, BD_ADDR bda)
     APPL_TRACE_DEBUG("bta_gattc_enc_cmpl_cback: cif = %d", gattc_if);
 
     if ((p_buf = (tBTA_GATTC_DATA *) osi_calloc(sizeof(tBTA_GATTC_DATA))) != NULL) {
+        memset(p_buf, 0, sizeof(tBTA_GATTC_DATA));
+
         p_buf->enc_cmpl.hdr.event            = BTA_GATTC_ENC_CMPL_EVT;
         p_buf->enc_cmpl.hdr.layer_specific   = p_clcb->bta_conn_id;
         p_buf->enc_cmpl.client_if            = gattc_if;
@@ -1847,15 +1657,12 @@ void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg)
         }
         /* in all other cases, mark it and delete the cache */
         if (p_srvc_cb->p_srvc_cache != NULL) {
-            while (!fixed_queue_is_empty(p_clcb->p_srcb->cache_buffer)) {
-                osi_free(fixed_queue_try_dequeue(p_clcb->p_srcb->cache_buffer));
-            }
-            //fixed_queue_free(p_clcb->p_srcb->cache_buffer, NULL);
+            list_free(p_srvc_cb->p_srvc_cache);
             p_srvc_cb->p_srvc_cache = NULL;
         }
     }
     /* used to reset cache in application */
-    bta_gattc_co_cache_reset(p_msg->api_conn.remote_bda);
+    bta_gattc_cache_reset(p_msg->api_conn.remote_bda);
 
 }
 /*******************************************************************************
@@ -1872,7 +1679,7 @@ BOOLEAN bta_gattc_process_srvc_chg_ind(UINT16 conn_id,
                                        tBTA_GATTC_SERV     *p_srcb,
                                        tBTA_GATTC_CLCB      *p_clcb,
                                        tBTA_GATTC_NOTIFY    *p_notify,
-                                       UINT16 handle)
+                                       tGATT_VALUE *att_value)
 {
     tBT_UUID        gattp_uuid, srvc_chg_uuid;
     BOOLEAN         processed = FALSE;
@@ -1884,13 +1691,26 @@ BOOLEAN bta_gattc_process_srvc_chg_ind(UINT16 conn_id,
     srvc_chg_uuid.len = 2;
     srvc_chg_uuid.uu.uuid16 = GATT_UUID_GATT_SRV_CHGD;
 
-    if (bta_gattc_uuid_compare(&p_notify->char_id.srvc_id.id.uuid, &gattp_uuid, TRUE) &&
-            bta_gattc_uuid_compare(&p_notify->char_id.char_id.uuid, &srvc_chg_uuid, TRUE)) {
+    const tBTA_GATTC_CHARACTERISTIC *p_char = bta_gattc_get_characteristic_srcb(p_srcb, p_notify->handle);
+    if (p_char && bta_gattc_uuid_compare(&p_char->service->uuid, &gattp_uuid, TRUE) &&
+        bta_gattc_uuid_compare(&p_char->uuid, &srvc_chg_uuid, TRUE)) {
+        if (att_value->len != BTA_GATTC_SERVICE_CHANGED_LEN) {
+            APPL_TRACE_ERROR("%s: received malformed service changed indication, skipping", __func__);
+            return FALSE;
+        }
+
+        UINT8 *p = att_value->value;
+        UINT16 s_handle = ((UINT16)(*(p    )) + (((UINT16)(*(p + 1))) << 8));
+        UINT16 e_handle = ((UINT16)(*(p + 2)) + (((UINT16)(*(p + 3))) << 8));
+
+        APPL_TRACE_ERROR("%s: service changed s_handle:0x%04x e_handle:0x%04x",
+                         __func__, s_handle, e_handle);
+
         processed = TRUE;
         /* mark service handle change pending */
         p_srcb->srvc_hdl_chg = TRUE;
         /* clear up all notification/indication registration */
-        bta_gattc_clear_notif_registration(conn_id);
+        bta_gattc_clear_notif_registration(p_srcb, conn_id, s_handle, e_handle);
         /* service change indication all received, do discovery update */
         if ( ++ p_srcb->update_count == bta_gattc_num_reg_app()) {
             /* not an opened connection; or connection busy */
@@ -1906,7 +1726,7 @@ BOOLEAN bta_gattc_process_srvc_chg_ind(UINT16 conn_id,
                 }
             }
             /* send confirmation here if this is an indication, it should always be */
-            GATTC_SendHandleValueConfirm(conn_id, handle);
+            GATTC_SendHandleValueConfirm(conn_id, att_value->handle);
 
             /* if connection available, refresh cache by doing discovery now */
             if (p_clcb != NULL) {
@@ -1936,9 +1756,8 @@ void bta_gattc_proc_other_indication(tBTA_GATTC_CLCB *p_clcb, UINT8 op,
                                      tGATT_CL_COMPLETE *p_data,
                                      tBTA_GATTC_NOTIFY *p_notify)
 {
-    APPL_TRACE_DEBUG("bta_gattc_proc_other_indication check \
-                       p_data->att_value.handle=%d p_data->handle=%d",
-                     p_data->att_value.handle, p_data->handle);
+    APPL_TRACE_DEBUG("bta_gattc_proc_other_indication check p_data->att_value.handle=%d p_data->handle=%d",
+                       p_data->att_value.handle, p_data->handle);
     APPL_TRACE_DEBUG("is_notify %d", p_notify->is_notify);
 
     p_notify->is_notify = (op == GATTC_OPTYPE_INDICATION) ? FALSE : TRUE;
@@ -1998,40 +1817,32 @@ void bta_gattc_process_indicate(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_CL_COMPL
 
     p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
 
-    if (bta_gattc_handle2id(p_srcb, handle,
-                            &notify.char_id.srvc_id,
-                            &notify.char_id.char_id,
-                            &notify.descr_type)) {
-        /* if non-service change indication/notification, forward to application */
-        if (!bta_gattc_process_srvc_chg_ind(conn_id, p_clrcb, p_srcb, p_clcb, &notify, handle)) {
-            /* if app registered for the notification */
-            if (bta_gattc_check_notif_registry(p_clrcb, p_srcb, &notify)) {
-                /* connection not open yet */
-                if (p_clcb == NULL) {
-                    if ((p_clcb = bta_gattc_clcb_alloc(gatt_if, remote_bda, transport)) != NULL) {
-                        p_clcb->bta_conn_id = conn_id;
-                        p_clcb->transport   = transport;
+    notify.handle = handle;
+    /* if non-service change indication/notification, forward to application */
+    if (!bta_gattc_process_srvc_chg_ind(conn_id, p_clrcb, p_srcb, p_clcb, &notify, &p_data->att_value)) {
+        /* if app registered for the notification */
+        if (bta_gattc_check_notif_registry(p_clrcb, p_srcb, &notify)) {
+            /* connection not open yet */
+            if (p_clcb == NULL) {
+                p_clcb = bta_gattc_clcb_alloc(gatt_if, remote_bda, transport);
 
-                        bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, NULL);
-                    } else {
-                        APPL_TRACE_ERROR("No resources");
-                    }
+                if (p_clcb == NULL) {
+                    APPL_TRACE_ERROR("No resources");
+                    return;
                 }
 
-                if (p_clcb != NULL) {
-                    bta_gattc_proc_other_indication(p_clcb, op, p_data, &notify);
-                }
+                p_clcb->bta_conn_id = conn_id;
+                p_clcb->transport   = transport;
+
+                bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, NULL);
             }
-            /* no one intersted and need ack? */
-            else if (op == GATTC_OPTYPE_INDICATION) {
-                APPL_TRACE_DEBUG("%s no one interested, ack now", __func__);
-                GATTC_SendHandleValueConfirm(conn_id, handle);
+
+            if (p_clcb != NULL) {
+                bta_gattc_proc_other_indication(p_clcb, op, p_data, &notify);
             }
-        }
-    } else {
-        APPL_TRACE_ERROR("%s Indi/Notif for Unknown handle[0x%04x], can not find in local cache.",
-                         __func__, handle);
-        if (op == GATTC_OPTYPE_INDICATION) {
+        } else if (op == GATTC_OPTYPE_INDICATION) {
+            /* no one intersted and need ack? */
+            APPL_TRACE_DEBUG("%s no one interested, ack now", __func__);
             GATTC_SendHandleValueConfirm(conn_id, handle);
         }
     }
@@ -2287,7 +2098,7 @@ void bta_gattc_start_service_change_ccc_timer(UINT16 conn_id, BD_ADDR bda,UINT32
                                               UINT8 timer_cnt, UINT8 last_status, TIMER_LIST_ENT *ccc_timer)
 {
     tBTA_GATTC_WAIT_CCC_TIMER *p_timer_param = (tBTA_GATTC_WAIT_CCC_TIMER*) osi_malloc(sizeof(tBTA_GATTC_WAIT_CCC_TIMER));
-    if (p_timer_param != NULL){
+    if (p_timer_param != NULL) {
         p_timer_param->conn_id = conn_id;
         memcpy(p_timer_param->remote_bda, bda, sizeof(BD_ADDR));
         p_timer_param->count = timer_cnt;
@@ -2311,12 +2122,13 @@ void bta_gattc_start_service_change_ccc_timer(UINT16 conn_id, BD_ADDR bda,UINT32
 ** Returns          Return result of service change ccc service discovery result result and written operate result
 **
 *******************************************************************************/
-tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_id, BD_ADDR remote_bda, BOOLEAN *need_timer){
+tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_id, BD_ADDR remote_bda, BOOLEAN *need_timer)
+{
     tBTA_GATTC_SERV     *p_srcb = NULL;
-    tBTA_GATTC_CACHE    *p_cache = NULL;
-    tBTA_GATT_ID        result_id;
-    tBTA_GATT_ID        *p_result = &result_id;
-    tBTA_GATTC_CACHE_ATTR   *p_attr = NULL;
+    list_t              *p_cache = NULL;
+    tBTA_GATTC_SERVICE *p_service = NULL;
+    tBTA_GATTC_CHARACTERISTIC *p_char = NULL;
+    tBTA_GATTC_DESCRIPTOR *p_desc = NULL;
     tGATT_STATUS        write_status;
     tGATT_VALUE         ccc_value;
     tBTA_GATTC_FIND_SERVICE_CB    result;
@@ -2331,7 +2143,7 @@ tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_
     tBT_UUID gatt_ccc_uuid = {LEN_UUID_16, {GATT_UUID_CHAR_CLIENT_CONFIG}};
 
     p_srcb = bta_gattc_find_srcb(remote_bda);
-    if ((p_srcb != NULL) && (p_srcb->p_srvc_cache != NULL)){
+    if ((p_srcb != NULL) && (p_srcb->p_srvc_cache != NULL)) {
         p_cache = p_srcb->p_srvc_cache;
         gatt_cache_found = TRUE;
     }
@@ -2339,15 +2151,15 @@ tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_
         start_find_ccc_timer = TRUE;
         result = SERVICE_CHANGE_CACHE_NOT_FOUND;
     }
-
     /* start to find gatt service */
-    if (gatt_cache_found == TRUE){
-        while (p_cache) {
-            if (bta_gattc_uuid_compare(&gatt_service_uuid, &p_cache->service_uuid.id.uuid, TRUE)) {
+    if (gatt_cache_found == TRUE) {
+        for (list_node_t *sn = list_begin(p_cache);
+             sn != list_end(p_cache); sn = list_next(sn)) {
+            p_service = list_node(sn);
+            if (bta_gattc_uuid_compare(&gatt_service_uuid, &p_service->uuid, TRUE)) {
                 gatt_service_found = TRUE;
                 break;
             }
-            p_cache = p_cache->p_next;
         }
     }
     else {
@@ -2356,38 +2168,37 @@ tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_
     }
 
     /* start to find gatt service change characteristic */
-    if (gatt_service_found == TRUE){
-        p_attr = p_cache->p_attr;
-
-        while(p_attr){
-            bta_gattc_pack_attr_uuid(p_attr, &p_result->uuid);
-            if (bta_gattc_uuid_compare(&gatt_service_change_uuid, &p_result->uuid, TRUE)){
-                gatt_service_change_found = TRUE;
-                break;
+    if (gatt_service_found == TRUE) {
+        if (p_service->characteristics) {
+            for (list_node_t *cn = list_begin(p_service->characteristics);
+                 cn != list_end(p_service->characteristics); cn = list_next(cn)) {
+                p_char = list_node(cn);
+                if (bta_gattc_uuid_compare(&gatt_service_change_uuid, &p_char->uuid, TRUE)) {
+                    gatt_service_change_found = TRUE;
+                    break;
+                }
             }
-            p_attr = p_attr->p_next;
         }
     }
-    else if (gatt_cache_found == TRUE){
+    else if (gatt_cache_found == TRUE) {
         /* Gatt service not found, start a timer to wait for service discovery */
         start_find_ccc_timer = TRUE;
         result = SERVICE_CHANGE_SERVICE_NOT_FOUND;
     }
-
     /* start to find gatt service change characteristic ccc */
-    if (gatt_service_change_found == TRUE){
-        p_attr = p_attr->p_next;
-
-        while(p_attr && p_attr->attr_type != BTA_GATTC_ATTR_TYPE_CHAR){
-            bta_gattc_pack_attr_uuid(p_attr, &p_result->uuid);
-            if (bta_gattc_uuid_compare(&gatt_ccc_uuid, &p_result->uuid, TRUE)){
-                gatt_ccc_found = TRUE;
-                break;
+    if (gatt_service_change_found == TRUE) {
+        if (p_char->descriptors) {
+            for (list_node_t *dn = list_begin(p_char->descriptors);
+                 dn != list_end(p_char->descriptors); dn = list_next(dn)) {
+                p_desc = list_node(dn);
+                if (bta_gattc_uuid_compare(&gatt_ccc_uuid, &p_desc->uuid, TRUE)) {
+                    gatt_ccc_found = TRUE;
+                    break;
+                }
             }
-            p_attr = p_attr->p_next;
         }
     }
-    else if (gatt_service_found ==TRUE){
+    else if (gatt_service_found ==TRUE) {
         /* Gatt service found, but service change char not found,
          * Case1: remote device doesn't have service change char, we don't need to start a timer here to
          * wait for service discovery
@@ -2398,7 +2209,7 @@ tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_
     }
 
     if (gatt_ccc_found == TRUE){
-        ccc_value.handle = p_attr->attr_handle;
+        ccc_value.handle = p_desc->handle;
         ccc_value.len = 2;
         ccc_value.value[0] = GATT_CLT_CONFIG_INDICATION;
         ccc_value.auth_req = GATT_AUTH_REQ_NONE;
@@ -2417,17 +2228,17 @@ tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_
             result = SERVICE_CHANGE_CCC_WRITTEN_SUCCESS;
         }
     }
-    else if (gatt_service_change_found == TRUE){
+    else if (gatt_service_change_found == TRUE) {
         /* Gatt service char found, but service change char ccc not found,
          * Case1: remote device doesn't have service change char ccc, we don't need to start a timer here to
          * wait for service discovery
          * Case2: remote device exist service change char ccc, we have found gatt service change char, but have not found
-         * service change char ccc, we need to start a timer here*/
+         * service change char ccc, we need to start a timer here */
         start_find_ccc_timer = TRUE;
         result = SERVICE_CHANGE_CCC_NOT_FOUND;
     }
 
-    if (need_timer != NULL){
+    if (need_timer != NULL) {
         *need_timer = start_find_ccc_timer;
     }
 
index eaaf77cccfb1e43342e4129f8f8c932d81e4fb0b..802310b901bbb5a5c03de4a802c3510f3e389390 100644 (file)
@@ -282,272 +282,194 @@ void BTA_GATTC_ServiceSearchRequest (UINT16 conn_id, tBT_UUID *p_srvc_uuid)
 
 /*******************************************************************************
 **
-** Function         BTA_GATTC_GetFirstChar
+** Function         BTA_GATTC_GetServices
 **
-** Description      This function is called to find the first characteristic of the
-**                  service on the given server.
+** Description      This function is called to find the services on the given server.
 **
 ** Parameters       conn_id: connection ID which identify the server.
-**                  p_srvc_id: the service ID of which the characteristic is belonged to.
-**                  p_char_uuid_cond: Characteristic UUID, if NULL find the first available
-**                               characteristic.
-**                  p_char_result: output parameter which will store the GATT
-**                                  characteristic ID.
-**                  p_property: output parameter to carry the characteristic property.
 **
-** Returns          returns status.
+** Returns          returns list_t of tBTA_GATTC_SERVICE or NULL.
 **
 *******************************************************************************/
-tBTA_GATT_STATUS  BTA_GATTC_GetFirstChar (UINT16 conn_id, tBTA_GATT_SRVC_ID *p_srvc_id,
-        tBT_UUID *p_char_uuid_cond,
-        tBTA_GATTC_CHAR_ID *p_char_result,
-        tBTA_GATT_CHAR_PROP *p_property)
+const list_t* BTA_GATTC_GetServices(UINT16 conn_id) 
 {
-    tBTA_GATT_STATUS    status;
-
-    if (!p_srvc_id || !p_char_result) {
-        return BTA_GATT_ILLEGAL_PARAMETER;
-    }
-
-    if ((status = bta_gattc_query_cache(conn_id, BTA_GATTC_ATTR_TYPE_CHAR, p_srvc_id, NULL,
-                                        p_char_uuid_cond, &p_char_result->char_id, (void *)p_property))
-            == BTA_GATT_OK) {
-        memcpy(&p_char_result->srvc_id, p_srvc_id, sizeof(tBTA_GATT_SRVC_ID));
-    }
-
-    return status;
-
+    return bta_gattc_get_services(conn_id);
 }
+
 /*******************************************************************************
 **
-** Function         BTA_GATTC_GetNextChar
+** Function         BTA_GATTC_GetCharacteristic
 **
-** Description      This function is called to find the next characteristic of the
-**                  service on the given server.
+** Description      This function is called to find the characteristic on the given server.
 **
-** Parameters       conn_id: connection ID which identify the server.
-**                  p_start_char_id: start the characteristic search from the next record
-**                           after the one identified by char_id.
-**                  p_char_uuid_cond: Characteristic UUID, if NULL find the first available
-**                               characteristic.
-**                  p_char_result: output parameter which will store the GATT
-**                                  characteristic ID.
-**                  p_property: output parameter to carry the characteristic property.
+** Parameters       conn_id - connection ID which identify the server.
+**                  handle - characteristic handle
 **
-** Returns          returns status.
+** Returns          returns pointer to tBTA_GATTC_CHARACTERISTIC or NULL.
 **
 *******************************************************************************/
-tBTA_GATT_STATUS  BTA_GATTC_GetNextChar (UINT16 conn_id,
-        tBTA_GATTC_CHAR_ID *p_start_char_id,
-        tBT_UUID           *p_char_uuid_cond,
-        tBTA_GATTC_CHAR_ID *p_char_result,
-        tBTA_GATT_CHAR_PROP    *p_property)
+const tBTA_GATTC_CHARACTERISTIC* BTA_GATTC_GetCharacteristic(UINT16 conn_id, UINT16 handle) 
 {
-    tBTA_GATT_STATUS    status;
-
-    if (!p_start_char_id || !p_char_result) {
-        return BTA_GATT_ILLEGAL_PARAMETER;
-    }
-
-    if ((status = bta_gattc_query_cache(conn_id, BTA_GATTC_ATTR_TYPE_CHAR,
-                                        &p_start_char_id->srvc_id,
-                                        &p_start_char_id->char_id,
-                                        p_char_uuid_cond,
-                                        &p_char_result->char_id,
-                                        (void *) p_property))
-            == BTA_GATT_OK) {
-        memcpy(&p_char_result->srvc_id, &p_start_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
-    }
-
-    return status;
+    return bta_gattc_get_characteristic(conn_id, handle);
 }
 
 /*******************************************************************************
 **
-** Function         BTA_GATTC_GetFirstCharDescr
+** Function         BTA_GATTC_GetDescriptor
 **
-** Description      This function is called to find the first characteristic descriptor of the
-**                  characteristic on the given server.
+** Description      This function is called to find the characteristic on the given server.
 **
-** Parameters       conn_id: connection ID which identify the server.
-**                  p_char_id: the characteristic ID of which the descriptor is belonged to.
-**                  p_descr_uuid_cond: Characteristic Descr UUID, if NULL find the first available
-**                               characteristic.
-**                  p_descr_result: output parameter which will store the GATT
-**                                  characteristic descriptor ID.
+** Parameters       conn_id - connection ID which identify the server.
+**                  handle - descriptor handle
 **
-** Returns          returns status.
+** Returns          returns pointer to tBTA_GATTC_DESCRIPTOR or NULL.
 **
 *******************************************************************************/
-tBTA_GATT_STATUS  BTA_GATTC_GetFirstCharDescr (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
-        tBT_UUID *p_descr_uuid_cond,
-        tBTA_GATTC_CHAR_DESCR_ID *p_descr_result)
+const tBTA_GATTC_DESCRIPTOR* BTA_GATTC_GetDescriptor(UINT16 conn_id, UINT16 handle)
 {
-    tBTA_GATT_STATUS    status;
-
-    if (!p_char_id || !p_descr_result) {
-        return BTA_GATT_ILLEGAL_PARAMETER;
-    }
+    return bta_gattc_get_descriptor(conn_id, handle);
+}
 
-    memset(p_descr_result, 0, sizeof(tBTA_GATTC_CHAR_DESCR_ID));
-
-    if ((status = bta_gattc_query_cache(conn_id,
-                                        BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
-                                        &p_char_id->srvc_id,
-                                        &p_char_id->char_id,
-                                        p_descr_uuid_cond,
-                                        &p_descr_result->char_id.char_id,
-                                        NULL))
-            == BTA_GATT_OK) {
-        memcpy(&p_descr_result->descr_id, &p_descr_result->char_id.char_id, sizeof(tBTA_GATT_ID));
-        memcpy(&p_descr_result->char_id, p_char_id, sizeof(tBTA_GATTC_CHAR_ID));
-    }
-    return status;
+void BTA_GATTC_GetServiceWithUUID(UINT16 conn_id, tBT_UUID *svc_uuid,
+                                  btgatt_db_element_t **db, int *count)
+{
+    bta_gattc_get_service_with_uuid(conn_id, svc_uuid, db, count);
+}
 
+void BTA_GATTC_GetAllChar(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle,
+                          btgatt_db_element_t **db, int *count)
+{
+    bta_gattc_get_db_with_opration(conn_id,
+                                   GATT_OP_GET_ALL_CHAR,
+                                   0,
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   start_handle,
+                                   end_handle,
+                                   db,
+                                   count);
 }
-/*******************************************************************************
-**
-** Function         BTA_GATTC_GetNextCharDescr
-**
-** Description      This function is called to find the next characteristic descriptor
-**                  of the characterisctic.
-**
-** Parameters       conn_id: connection ID which identify the server.
-**                  p_start_descr_id: start the descriptor search from the next record
-**                           after the one identified by p_start_descr_id.
-**                  p_descr_uuid_cond: Characteristic descriptor UUID, if NULL find
-**                               the first available characteristic descriptor.
-**                  p_descr_result: output parameter which will store the GATT
-**                                  characteristic descriptor ID.
-**
-** Returns          returns status.
-**
-*******************************************************************************/
-tBTA_GATT_STATUS  BTA_GATTC_GetNextCharDescr (UINT16 conn_id,
-        tBTA_GATTC_CHAR_DESCR_ID *p_start_descr_id,
-        tBT_UUID           *p_descr_uuid_cond,
-        tBTA_GATTC_CHAR_DESCR_ID *p_descr_result)
+
+void BTA_GATTC_GetAllDescriptor(UINT16 conn_id, UINT16 char_handle,
+                                btgatt_db_element_t **db, int *count)
 {
-    tBTA_GATT_STATUS    status;
+    bta_gattc_get_db_with_opration(conn_id,
+                                   GATT_OP_GET_ALL_DESCRI,
+                                   char_handle,
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   0,
+                                   0xFFFF,
+                                   db,
+                                   count);
+}
 
-    if (!p_start_descr_id || !p_descr_result) {
-        return BTA_GATT_ILLEGAL_PARAMETER;
-    }
+void BTA_GATTC_GetCharByUUID(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle, tBT_UUID char_uuid,
+                             btgatt_db_element_t **db, int *count)
+{
+    bta_gattc_get_db_with_opration(conn_id,
+                                   GATT_OP_GET_CHAR_BY_UUID,
+                                   0,
+                                   NULL,
+                                   &char_uuid,
+                                   NULL,
+                                   start_handle,
+                                   end_handle,
+                                   db,
+                                   count);
+}
 
-    memset(p_descr_result, 0, sizeof(tBTA_GATTC_CHAR_DESCR_ID));
-
-    if ((status = bta_gattc_query_cache(conn_id, BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
-                                        &p_start_descr_id->char_id.srvc_id,
-                                        &p_start_descr_id->char_id.char_id,
-                                        p_descr_uuid_cond,
-                                        &p_descr_result->char_id.char_id,
-                                        (void *)&p_start_descr_id->descr_id))
-            == BTA_GATT_OK) {
-        memcpy(&p_descr_result->descr_id, &p_descr_result->char_id.char_id, sizeof(tBTA_GATT_ID));
-        memcpy(&p_descr_result->char_id, p_start_descr_id, sizeof(tBTA_GATTC_CHAR_ID));
-    }
+void BTA_GATTC_GetDescrByUUID(UINT16 conn_id, uint16_t start_handle, uint16_t end_handle,
+                              tBT_UUID char_uuid, tBT_UUID descr_uuid,
+                              btgatt_db_element_t **db, int *count)
+{
+    bta_gattc_get_db_with_opration(conn_id,
+                                   GATT_OP_GET_DESCRI_BY_UUID,
+                                   0,
+                                   NULL,
+                                   &char_uuid,
+                                   &descr_uuid,
+                                   start_handle,
+                                   end_handle,
+                                   db,
+                                   count);
+}
 
-    return status;
+void BTA_GATTC_GetDescrByCharHandle(UINT16 conn_id, UINT16 char_handle, tBT_UUID descr_uuid,
+                                    btgatt_db_element_t **db, int *count)
+{
+    bta_gattc_get_db_with_opration(conn_id,
+                                   GATT_OP_GET_DESCRI_BY_HANDLE,
+                                   char_handle,
+                                   NULL,
+                                   NULL,
+                                   &descr_uuid,
+                                   0,
+                                   0xFFFF,
+                                   db,
+                                   count);
 }
 
+void BTA_GATTC_GetIncludeService(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle,
+                                 tBT_UUID *incl_uuid, btgatt_db_element_t **db, int *count)
+{
+    bta_gattc_get_db_with_opration(conn_id,
+                                   GATT_OP_GET_INCLUDE_SVC,
+                                   0,
+                                   incl_uuid,
+                                   NULL,
+                                   NULL,
+                                   start_handle,
+                                   end_handle,
+                                   db,
+                                   count);
+}
 
-/*******************************************************************************
-**
-** Function         BTA_GATTC_GetFirstIncludedService
-**
-** Description      This function is called to find the first included service of the
-**                  service on the given server.
-**
-** Parameters       conn_id: connection ID which identify the server.
-**                  p_srvc_id: the service ID of which the characteristic is belonged to.
-**                  p_uuid_cond: Characteristic UUID, if NULL find the first available
-**                               characteristic.
-**                  p_result: output parameter which will store the GATT ID
-**                              of the included service found.
-**
-** Returns          returns status.
-**
-*******************************************************************************/
-tBTA_GATT_STATUS  BTA_GATTC_GetFirstIncludedService(UINT16 conn_id, tBTA_GATT_SRVC_ID *p_srvc_id,
-        tBT_UUID *p_uuid_cond, tBTA_GATTC_INCL_SVC_ID *p_result)
+void BTA_GATTC_GetDBSize(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle, int *count)
 {
-    tBTA_GATT_STATUS    status;
+    bta_gattc_get_db_size_handle(conn_id, start_handle, end_handle, count);
+}
 
-    if (!p_srvc_id || !p_result) {
-        return BTA_GATT_ILLEGAL_PARAMETER;
-    }
+void BTA_GATTC_GetDBSizeByType(UINT16 conn_id, bt_gatt_db_attribute_type_t type,
+                               UINT16 start_handle, UINT16 end_handle, UINT16 char_handle, int *count)
+{
+    bta_gattc_get_db_size_with_type_handle(conn_id, type, start_handle, end_handle, char_handle, count);
+}
 
-    if ((status = bta_gattc_query_cache(conn_id,
-                                        BTA_GATTC_ATTR_TYPE_INCL_SRVC,
-                                        p_srvc_id,
-                                        NULL,
-                                        p_uuid_cond,
-                                        &p_result->incl_svc_id.id,
-                                        (void *)&p_result->incl_svc_id.is_primary))
-            == BTA_GATT_OK) {
-        memcpy(&p_result->srvc_id, p_srvc_id, sizeof(tBTA_GATT_SRVC_ID));
-    }
 
-    return status;
-}
 /*******************************************************************************
 **
-** Function         BTA_GATTC_GetNextIncludedService
+** Function         BTA_GATTC_GetGattDb
 **
-** Description      This function is called to find the next included service of the
-**                  service on the given server.
+** Description      This function is called to get the GATT database.
 **
 ** Parameters       conn_id: connection ID which identify the server.
-**                  p_start_id: start the search from the next record
-**                                  after the one identified by p_start_id.
-**                  p_uuid_cond: Included service UUID, if NULL find the first available
-**                               included service.
-**                  p_result: output parameter which will store the GATT ID
-**                              of the included service found.
-**
-** Returns          returns status.
+**                  db: output parameter which will contain the GATT database copy.
+**                      Caller is responsible for freeing it.
+**                  count: number of elements in database.
 **
 *******************************************************************************/
-tBTA_GATT_STATUS  BTA_GATTC_GetNextIncludedService(UINT16 conn_id,
-        tBTA_GATTC_INCL_SVC_ID *p_start_id,
-        tBT_UUID               *p_uuid_cond,
-        tBTA_GATTC_INCL_SVC_ID *p_result)
+void  BTA_GATTC_GetGattDb(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle,
+                          btgatt_db_element_t **db, int *count)
 {
-    tBTA_GATT_STATUS    status;
-
-    if (!p_start_id || !p_result) {
-        return BTA_GATT_ILLEGAL_PARAMETER;
-    }
-
-    if ((status = bta_gattc_query_cache(conn_id,
-                                        BTA_GATTC_ATTR_TYPE_INCL_SRVC,
-                                        &p_start_id->srvc_id,
-                                        &p_start_id->incl_svc_id.id,
-                                        p_uuid_cond,
-                                        &p_result->incl_svc_id.id,
-                                        (void *)&p_result->incl_svc_id.is_primary))
-            == BTA_GATT_OK) {
-        memcpy(&p_result->srvc_id, &p_start_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
-    }
-
-    return status;
+    bta_gattc_get_gatt_db(conn_id, start_handle, end_handle, db, count);
 }
 
 /*******************************************************************************
 **
 ** Function         BTA_GATTC_ReadCharacteristic
 **
-** Description      This function is called to read a service's characteristics of
-**                    the given characteritisc ID.
+** Description      This function is called to read a characteristics value
 **
 ** Parameters       conn_id - connection ID.
-**                    p_char_id - characteritic ID to read.
+**                  handle - characteritic handle to read.
 **
 ** Returns          None
 **
 *******************************************************************************/
-void BTA_GATTC_ReadCharacteristic(UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
-                                  tBTA_GATT_AUTH_REQ auth_req)
+void BTA_GATTC_ReadCharacteristic(UINT16 conn_id, UINT16 handle, tBTA_GATT_AUTH_REQ auth_req)
 {
     tBTA_GATTC_API_READ  *p_buf;
 
@@ -557,10 +479,8 @@ void BTA_GATTC_ReadCharacteristic(UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
         p_buf->hdr.event = BTA_GATTC_API_READ_EVT;
         p_buf->hdr.layer_specific = conn_id;
         p_buf->auth_req = auth_req;
-
-        memcpy(&p_buf->srvc_id, &p_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
-        memcpy(&p_buf->char_id, &p_char_id->char_id, sizeof(tBTA_GATT_ID));
-        p_buf->p_descr_type = NULL;
+        p_buf->handle = handle;
+        p_buf->cmpl_evt = BTA_GATTC_READ_CHAR_EVT;
 
         bta_sys_sendmsg(p_buf);
     }
@@ -571,17 +491,15 @@ void BTA_GATTC_ReadCharacteristic(UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
 **
 ** Function         BTA_GATTC_ReadCharDescr
 **
-** Description      This function is called to read a characteristics descriptor.
+** Description      This function is called to read a descriptor value.
 **
 ** Parameters       conn_id - connection ID.
-**                    p_char_descr_id - characteritic descriptor ID to read.
+**                  handle - descriptor handle to read.
 **
 ** Returns          None
 **
 *******************************************************************************/
-void BTA_GATTC_ReadCharDescr (UINT16 conn_id,
-                              tBTA_GATTC_CHAR_DESCR_ID  *p_descr_id,
-                              tBTA_GATT_AUTH_REQ auth_req)
+void BTA_GATTC_ReadCharDescr (UINT16 conn_id, UINT16 handle, tBTA_GATT_AUTH_REQ auth_req)
 {
     tBTA_GATTC_API_READ  *p_buf;
     UINT16  len = (UINT16)(sizeof(tBTA_GATT_ID) + sizeof(tBTA_GATTC_API_READ));
@@ -592,12 +510,8 @@ void BTA_GATTC_ReadCharDescr (UINT16 conn_id,
         p_buf->hdr.event = BTA_GATTC_API_READ_EVT;
         p_buf->hdr.layer_specific = conn_id;
         p_buf->auth_req = auth_req;
-
-        memcpy(&p_buf->srvc_id, &p_descr_id->char_id.srvc_id, sizeof(tBTA_GATT_SRVC_ID));
-        memcpy(&p_buf->char_id, &p_descr_id->char_id.char_id, sizeof(tBTA_GATT_ID));
-        p_buf->p_descr_type  = (tBTA_GATT_ID *)(p_buf + 1);
-
-        memcpy(p_buf->p_descr_type, &p_descr_id->descr_id, sizeof(tBTA_GATT_ID));
+        p_buf->handle = handle;
+        p_buf->cmpl_evt = BTA_GATTC_READ_DESCR_EVT;
 
         bta_sys_sendmsg(p_buf);
     }
@@ -621,10 +535,8 @@ void BTA_GATTC_ReadMultiple(UINT16 conn_id, tBTA_GATTC_MULTI *p_read_multi,
                             tBTA_GATT_AUTH_REQ auth_req)
 {
     tBTA_GATTC_API_READ_MULTI  *p_buf;
-    tBTA_GATTC_ATTR_ID          *p_value;
-    UINT16      len = (UINT16)(sizeof(tBTA_GATTC_API_READ_MULTI) +
-                               p_read_multi->num_attr * sizeof(tBTA_GATTC_ATTR_ID));
-    UINT8       i;
+    //tBTA_GATTC_API_READ_MULTI          *p_value;
+    UINT16      len = (UINT16)(sizeof(tBTA_GATTC_API_READ_MULTI));
 
     if ((p_buf = (tBTA_GATTC_API_READ_MULTI *) osi_malloc(len)) != NULL) {
         memset(p_buf, 0, len);
@@ -632,16 +544,12 @@ void BTA_GATTC_ReadMultiple(UINT16 conn_id, tBTA_GATTC_MULTI *p_read_multi,
         p_buf->hdr.event = BTA_GATTC_API_READ_MULTI_EVT;
         p_buf->hdr.layer_specific = conn_id;
         p_buf->auth_req = auth_req;
-
         p_buf->num_attr = p_read_multi->num_attr;
 
         if (p_buf->num_attr > 0) {
-            p_buf->p_id_list = p_value = (tBTA_GATTC_ATTR_ID *)(p_buf + 1);
+            memcpy(p_buf->handles, p_read_multi->handles, sizeof(UINT16) * p_read_multi->num_attr);
+           }
 
-            for (i = 0; i < p_buf->num_attr; i ++, p_value ++) {
-                memcpy(p_value, &p_read_multi->id_list[i], sizeof(tBTA_GATTC_ATTR_ID));
-            }
-        }
         bta_sys_sendmsg(p_buf);
     }
     return;
@@ -655,8 +563,8 @@ void BTA_GATTC_ReadMultiple(UINT16 conn_id, tBTA_GATTC_MULTI *p_read_multi,
 ** Description      This function is called to write characteristic value.
 **
 ** Parameters       conn_id - connection ID.
-**                    p_char_id - characteristic ID to write.
-**                    write_type - type of write.
+**                  handle - characteristic handle to write.
+**                  write_type - type of write.
 **                  len: length of the data to be written.
 **                  p_value - the value to be written.
 **
@@ -664,7 +572,7 @@ void BTA_GATTC_ReadMultiple(UINT16 conn_id, tBTA_GATTC_MULTI *p_read_multi,
 **
 *******************************************************************************/
 void BTA_GATTC_WriteCharValue ( UINT16 conn_id,
-                                tBTA_GATTC_CHAR_ID *p_char_id,
+                                UINT16 handle,
                                 tBTA_GATTC_WRITE_TYPE  write_type,
                                 UINT16 len,
                                 UINT8 *p_value,
@@ -678,10 +586,8 @@ void BTA_GATTC_WriteCharValue ( UINT16 conn_id,
         p_buf->hdr.event = BTA_GATTC_API_WRITE_EVT;
         p_buf->hdr.layer_specific = conn_id;
         p_buf->auth_req = auth_req;
-
-        memcpy(&p_buf->srvc_id, &p_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
-        memcpy(&p_buf->char_id, &p_char_id->char_id, sizeof(tBTA_GATT_ID));
-
+        p_buf->handle = handle;
+        p_buf->cmpl_evt = BTA_GATTC_WRITE_CHAR_EVT;
         p_buf->write_type = write_type;
         p_buf->len = len;
 
@@ -698,10 +604,10 @@ void BTA_GATTC_WriteCharValue ( UINT16 conn_id,
 **
 ** Function         BTA_GATTC_WriteCharDescr
 **
-** Description      This function is called to write characteristic descriptor value.
+** Description      This function is called to write descriptor value.
 **
 ** Parameters       conn_id - connection ID
-**                    p_char_descr_id - characteristic descriptor ID to write.
+**                  handle - descriptor hadle to write.
 **                  write_type - write type.
 **                  p_value - the value to be written.
 **
@@ -709,14 +615,13 @@ void BTA_GATTC_WriteCharValue ( UINT16 conn_id,
 **
 *******************************************************************************/
 void BTA_GATTC_WriteCharDescr (UINT16 conn_id,
-                               tBTA_GATTC_CHAR_DESCR_ID *p_char_descr_id,
+                               UINT16 handle,
                                tBTA_GATTC_WRITE_TYPE  write_type,
                                tBTA_GATT_UNFMT      *p_data,
                                tBTA_GATT_AUTH_REQ auth_req)
 {
-    tBTA_GATTC_API_WRITE  *p_buf;
-    UINT16  len = sizeof(tBTA_GATTC_API_WRITE) + sizeof(tBTA_GATT_ID);
-
+    size_t len = sizeof(tBTA_GATTC_API_WRITE);
+    tBTA_GATTC_API_WRITE *p_buf;
     if (p_data != NULL) {
         len += p_data->len;
     }
@@ -727,15 +632,12 @@ void BTA_GATTC_WriteCharDescr (UINT16 conn_id,
         p_buf->hdr.event = BTA_GATTC_API_WRITE_EVT;
         p_buf->hdr.layer_specific = conn_id;
         p_buf->auth_req = auth_req;
-
-        memcpy(&p_buf->srvc_id, &p_char_descr_id->char_id.srvc_id, sizeof(tBTA_GATT_SRVC_ID));
-        memcpy(&p_buf->char_id, &p_char_descr_id->char_id.char_id, sizeof(tBTA_GATT_ID));
-        p_buf->p_descr_type = (tBTA_GATT_ID *)(p_buf + 1);
-        memcpy(p_buf->p_descr_type, &p_char_descr_id->descr_id, sizeof(tBTA_GATT_ID));
+        p_buf->handle = handle;
+        p_buf->cmpl_evt = BTA_GATTC_WRITE_DESCR_EVT;
         p_buf->write_type = write_type;
 
         if (p_data && p_data->len != 0) {
-            p_buf->p_value  = (UINT8 *)(p_buf->p_descr_type + 1);
+            p_buf->p_value  = (UINT8 *)(p_buf + 1);
             p_buf->len      = p_data->len;
             /* pack the descr data */
             memcpy(p_buf->p_value, p_data->p_value, p_data->len);
@@ -761,7 +663,7 @@ void BTA_GATTC_WriteCharDescr (UINT16 conn_id,
 ** Returns          None
 **
 *******************************************************************************/
-void BTA_GATTC_PrepareWrite  (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
+void BTA_GATTC_PrepareWrite  (UINT16 conn_id, UINT16 handle,
                               UINT16 offset, UINT16 len, UINT8 *p_value,
                               tBTA_GATT_AUTH_REQ auth_req)
 {
@@ -773,9 +675,7 @@ void BTA_GATTC_PrepareWrite  (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
         p_buf->hdr.event = BTA_GATTC_API_WRITE_EVT;
         p_buf->hdr.layer_specific = conn_id;
         p_buf->auth_req = auth_req;
-
-        memcpy(&p_buf->srvc_id, &p_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
-        memcpy(&p_buf->char_id, &p_char_id->char_id, sizeof(tBTA_GATT_ID));
+        p_buf->handle = handle;
 
         p_buf->write_type = BTA_GATTC_WRITE_PREPARE;
         p_buf->offset   = offset;
@@ -806,12 +706,12 @@ void BTA_GATTC_PrepareWrite  (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
 ** Returns          None
 **
 *******************************************************************************/
-void BTA_GATTC_PrepareWriteCharDescr  (UINT16 conn_id, tBTA_GATTC_CHAR_DESCR_ID *p_char_descr_id,
+void BTA_GATTC_PrepareWriteCharDescr  (UINT16 conn_id, UINT16 handle,
                                        UINT16 offset,tBTA_GATT_UNFMT *p_data,
                                        tBTA_GATT_AUTH_REQ auth_req)
 {
     tBTA_GATTC_API_WRITE  *p_buf;
-    UINT16  len = sizeof(tBTA_GATTC_API_WRITE) + sizeof(tBTA_GATT_ID);
+    UINT16  len = sizeof(tBTA_GATTC_API_WRITE) + p_data->len;
 
     if (p_data != NULL) {
         len += p_data->len;
@@ -823,17 +723,13 @@ void BTA_GATTC_PrepareWriteCharDescr  (UINT16 conn_id, tBTA_GATTC_CHAR_DESCR_ID
         p_buf->hdr.event = BTA_GATTC_API_WRITE_EVT;
         p_buf->hdr.layer_specific = conn_id;
         p_buf->auth_req = auth_req;
-
-        memcpy(&p_buf->srvc_id, &p_char_descr_id->char_id.srvc_id, sizeof(tBTA_GATT_SRVC_ID));
-        memcpy(&p_buf->char_id, &p_char_descr_id->char_id.char_id, sizeof(tBTA_GATT_ID));
-        p_buf->p_descr_type = (tBTA_GATT_ID *)(p_buf + 1);
-        memcpy(p_buf->p_descr_type, &p_char_descr_id->descr_id, sizeof(tBTA_GATT_ID));
+        p_buf->handle = handle;
         p_buf->write_type = BTA_GATTC_WRITE_PREPARE;
         p_buf->offset = offset;
 
         if (p_data && p_data->len != 0) {
-            p_buf->p_value  = (UINT8 *)(p_buf->p_descr_type + 1);
             p_buf->len      = p_data->len;
+            p_buf->p_value = (UINT8 *)(p_buf + 1);
             /* pack the descr data */
             memcpy(p_buf->p_value, p_data->p_value, p_data->len);
         }
@@ -861,7 +757,6 @@ void BTA_GATTC_ExecuteWrite  (UINT16 conn_id, BOOLEAN is_execute)
 
     if ((p_buf = (tBTA_GATTC_API_EXEC *) osi_malloc((UINT16)sizeof(tBTA_GATTC_API_EXEC))) != NULL) {
         memset(p_buf, 0, sizeof(tBTA_GATTC_API_EXEC));
-
         p_buf->hdr.event = BTA_GATTC_API_EXEC_EVT;
         p_buf->hdr.layer_specific = conn_id;
 
@@ -884,21 +779,18 @@ void BTA_GATTC_ExecuteWrite  (UINT16 conn_id, BOOLEAN is_execute)
 ** Returns          None
 **
 *******************************************************************************/
-void BTA_GATTC_SendIndConfirm (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id)
+void BTA_GATTC_SendIndConfirm (UINT16 conn_id, UINT16 handle)
 {
     tBTA_GATTC_API_CONFIRM  *p_buf;
 
-    APPL_TRACE_API("BTA_GATTC_SendIndConfirm conn_id=%d service uuid1=0x%x char uuid=0x%x",
-                   conn_id, p_char_id->srvc_id.id.uuid.uu.uuid16, p_char_id->char_id.uuid.uu.uuid16);
+    APPL_TRACE_API("BTA_GATTC_SendIndConfirm conn_id=%d handle =0x%x",
+                   conn_id, handle);
 
     if ((p_buf = (tBTA_GATTC_API_CONFIRM *) osi_malloc(sizeof(tBTA_GATTC_API_CONFIRM))) != NULL) {
         memset(p_buf, 0, sizeof(tBTA_GATTC_API_CONFIRM));
-
         p_buf->hdr.event = BTA_GATTC_API_CONFIRM_EVT;
         p_buf->hdr.layer_specific = conn_id;
-
-        memcpy(&p_buf->srvc_id, &p_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
-        memcpy(&p_buf->char_id, &p_char_id->char_id, sizeof(tBTA_GATT_ID));
+        p_buf->handle = handle;
 
         bta_sys_sendmsg(p_buf);
     }
@@ -914,21 +806,21 @@ void BTA_GATTC_SendIndConfirm (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id)
 **
 ** Parameters       client_if - client interface.
 **                  bda - target GATT server.
-**                  p_char_id - pointer to GATT characteristic ID.
+**                  handle - GATT characteristic handle.
 **
 ** Returns          OK if registration succeed, otherwise failed.
 **
 *******************************************************************************/
 tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF client_if,
-        BD_ADDR bda,
-        tBTA_GATTC_CHAR_ID *p_char_id)
+                                                     BD_ADDR bda, UINT16 handle)
 {
     tBTA_GATTC_RCB      *p_clreg;
     tBTA_GATT_STATUS    status = BTA_GATT_ILLEGAL_PARAMETER;
     UINT8               i;
 
-    if (!p_char_id) {
-        APPL_TRACE_ERROR("deregistration failed, unknow char id");
+    if (!handle)
+    {
+        APPL_TRACE_ERROR("deregistration failed, handle is 0");
         return status;
     }
 
@@ -936,7 +828,7 @@ tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF client_if,
         for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++) {
             if ( p_clreg->notif_reg[i].in_use &&
                     !memcmp(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN) &&
-                    bta_gattc_charid_compare(&p_clreg->notif_reg[i].char_id, p_char_id)) {
+                  p_clreg->notif_reg[i].handle == handle) {
                 APPL_TRACE_WARNING("notification already registered");
                 status = BTA_GATT_OK;
                 break;
@@ -950,10 +842,7 @@ tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF client_if,
                     p_clreg->notif_reg[i].in_use = TRUE;
                     memcpy(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN);
 
-                    p_clreg->notif_reg[i].char_id.srvc_id.is_primary = p_char_id->srvc_id.is_primary;
-                    bta_gattc_cpygattid(&p_clreg->notif_reg[i].char_id.srvc_id.id, &p_char_id->srvc_id.id);
-                    bta_gattc_cpygattid(&p_clreg->notif_reg[i].char_id.char_id, &p_char_id->char_id);
-
+                    p_clreg->notif_reg[i].handle = handle;
                     status = BTA_GATT_OK;
                     break;
                 }
@@ -977,48 +866,41 @@ tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF client_if,
 ** Description      This function is called to de-register for notification of a service.
 **
 ** Parameters       client_if - client interface.
-**                  bda - target GATT server.
-**                  p_char_id - pointer to GATT characteristic ID.
+**                  remote_bda - target GATT server.
+**                  handle - GATT characteristic handle.
 **
 ** Returns          OK if deregistration succeed, otherwise failed.
 **
 *******************************************************************************/
 tBTA_GATT_STATUS BTA_GATTC_DeregisterForNotifications (tBTA_GATTC_IF client_if,
-        BD_ADDR bda,
-        tBTA_GATTC_CHAR_ID *p_char_id)
+                                                       BD_ADDR bda, UINT16 handle)
 {
-    tBTA_GATTC_RCB      *p_clreg;
-    tBTA_GATT_STATUS    status = BTA_GATT_ILLEGAL_PARAMETER;
-    UINT8               i;
+    if (!handle) {
+        APPL_TRACE_ERROR("%s: deregistration failed, handle is 0", __func__);
+        return BTA_GATT_ILLEGAL_PARAMETER;
+    }
 
-    if (!p_char_id) {
-        APPL_TRACE_ERROR("%s deregistration failed, unknown char id", __func__);
-        return status;
+    tBTA_GATTC_RCB *p_clreg = bta_gattc_cl_get_regcb(client_if);
+    if (p_clreg == NULL) {
+        APPL_TRACE_ERROR("%s client_if: %d not registered bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
+            __func__, client_if, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
+        return BTA_GATT_ILLEGAL_PARAMETER;
     }
 
-    if ((p_clreg = bta_gattc_cl_get_regcb(client_if)) != NULL) {
-        for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++) {
-            if (p_clreg->notif_reg[i].in_use &&
-                    !memcmp(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN) &&
-                    bta_gattc_charid_compare(&p_clreg->notif_reg[i].char_id, p_char_id)) {
-                APPL_TRACE_DEBUG("%s deregistered bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
-                                 __func__, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
-                memset(&p_clreg->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
-                status = BTA_GATT_OK;
-                break;
-            }
-        }
-        if (i == BTA_GATTC_NOTIF_REG_MAX) {
-            status = BTA_GATT_ERROR;
-            APPL_TRACE_ERROR("%s registration not found bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
-                             __func__, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
+    for (int i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++) {
+        if (p_clreg->notif_reg[i].in_use &&
+            !memcmp(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN) &&
+            p_clreg->notif_reg[i].handle == handle) {
+            APPL_TRACE_DEBUG("%s deregistered bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
+                __func__, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
+            memset(&p_clreg->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
+            return BTA_GATT_OK;
         }
-    } else {
-        APPL_TRACE_ERROR("%s client_if: %d not registered bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
-                         __func__, client_if, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
     }
 
-    return status;
+    APPL_TRACE_ERROR("%s registration not found bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
+        __func__, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
+    return BTA_GATT_ERROR;
 }
 
 /*******************************************************************************
@@ -1038,10 +920,8 @@ void BTA_GATTC_Refresh(BD_ADDR remote_bda)
 
     if ((p_buf = (tBTA_GATTC_API_OPEN *) osi_malloc(sizeof(tBTA_GATTC_API_OPEN))) != NULL) {
         p_buf->hdr.event = BTA_GATTC_API_REFRESH_EVT;
-
         memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
 
-
         bta_sys_sendmsg(p_buf);
     }
     return;
@@ -1108,5 +988,5 @@ void BTA_GATTC_Broadcast(tBTA_GATTC_IF client_if, BOOLEAN start)
     return;
 }
 
-#endif /* BTA_GATT_INCLUDED */
+#endif /* defined(GATTC_INCLUDED) && (GATTC_INCLUDED == TRUE) */
 
index 506fd9e1405f406c686729aadcd0399bf214d71e..5e0943a9bb80955f5812882aab44f6389f44bb45 100644 (file)
 #include "btm_ble_api.h"
 #include "allocator.h"
 #include "l2c_api.h"
+#include "btm_int.h"
+#include "errno.h"
 
 #define LOG_TAG "bt_bta_gattc"
 // #include "osi/include/log.h"
 
+static void bta_gattc_cache_write(BD_ADDR server_bda, UINT16 num_attr, tBTA_GATTC_NV_ATTR *attr);
 static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb);
+extern void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src);
+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);
+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);
+void bta_gattc_fill_gatt_db_el(btgatt_db_element_t *p_attr,
+                               bt_gatt_db_attribute_type_t type,
+                               UINT16 att_handle,
+                               UINT16 s_handle, UINT16 e_handle,
+                               UINT16 id, tBT_UUID uuid, UINT8 prop);
+
+
 #if (SDP_INCLUDED == TRUE)
 static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb);
 #define BTA_GATT_SDP_DB_SIZE 4096
 #endif  ///SDP_INCLUDED == TRUE
+#define GATT_CACHE_PREFIX "/data/misc/bluetooth/gatt_cache_"
+#define GATT_CACHE_VERSION 2
+
+static void bta_gattc_generate_cache_file_name(char *buffer, BD_ADDR bda)
+{
+    sprintf(buffer, "%s%02x%02x%02x%02x%02x%02x", GATT_CACHE_PREFIX,
+            bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
+}
 
 /*****************************************************************************
-**  Constants
+**  Constants and data types
 *****************************************************************************/
+#if (SDP_INCLUDED == TRUE)
+typedef struct
+{
+    tSDP_DISCOVERY_DB   *p_sdp_db;
+    UINT16              sdp_conn_id;
+} tBTA_GATTC_CB_DATA;
+#endif  ///SDP_INCLUDED == TRUE
+
 
 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
 static char *bta_gattc_attr_type[] = {
@@ -59,6 +93,31 @@ static char *bta_gattc_attr_type[] = {
 };
 /* utility functions */
 
+bool display_cache_attribute(void *data, void *context) 
+{
+    //tBTA_GATTC_CACHE_ATTR *p_attr = data;
+    //APPL_TRACE_ERROR("\t Attr handle[%d] uuid[0x%04x] type[%s] prop[0x%1x]",
+    //                  p_attr->handle, p_attr->uuid.uu.uuid16,
+    //                  bta_gattc_attr_type[p_attr->attr_type], p_attr->property);
+    return true;
+}
+
+bool display_cache_service(void *data, void *context) 
+{
+    tBTA_GATTC_SERVICE    *p_cur_srvc = data;
+    LOG_INFO("Service: handle[%d ~ %d] %s[0x%04x] inst[%d]",
+              p_cur_srvc->s_handle, p_cur_srvc->e_handle,
+              ((p_cur_srvc->uuid.len == 2) ? "uuid16" : "uuid128"),
+              p_cur_srvc->uuid.uu.uuid16,
+              p_cur_srvc->handle);
+
+    if (p_cur_srvc->characteristics != NULL) {
+        list_foreach(p_cur_srvc->characteristics, display_cache_attribute, NULL);
+    }
+
+    return true;
+}
+
 /*******************************************************************************
 **
 ** Function         bta_gattc_display_cache_server
@@ -68,34 +127,10 @@ static char *bta_gattc_attr_type[] = {
 ** Returns          none.
 **
 *******************************************************************************/
-static void bta_gattc_display_cache_server(tBTA_GATTC_CACHE *p_cache)
+static void bta_gattc_display_cache_server(list_t *p_cache)
 {
-    UINT8 i = 0, j;
-    tBTA_GATTC_CACHE    *p_cur_srvc = p_cache;
-    tBTA_GATTC_CACHE_ATTR   *p_attr;
-
     APPL_TRACE_ERROR("<================Start Server Cache =============>");
-
-    while (p_cur_srvc) {
-        APPL_TRACE_ERROR("Service[%d]: handle[%d ~ %d] %s[0x%04x] inst[%d]",
-                         i, p_cur_srvc->s_handle, p_cur_srvc->e_handle,
-                         ((p_cur_srvc->service_uuid.id.uuid.len == 2) ? "uuid16" : "uuid128"),
-                         p_cur_srvc->service_uuid.id.uuid.uu.uuid16,
-                         p_cur_srvc->service_uuid.id.inst_id);
-        i ++;
-
-        p_attr = p_cur_srvc->p_attr;
-
-        for (j = 0; p_attr; j ++ ) {
-            APPL_TRACE_ERROR("\t Attr[0x%04x] handle[%d] uuid[0x%04x] inst[%d] type[%s] prop[0x%1x]",
-                             j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16, p_attr->inst_id,
-                             bta_gattc_attr_type[p_attr->attr_type], p_attr->property);
-
-            p_attr = p_attr->p_next;
-        }
-        p_cur_srvc = p_cur_srvc->p_next;
-    }
-
+    list_foreach(p_cache, display_cache_service, NULL);
     APPL_TRACE_ERROR("<================End Server Cache =============>");
     APPL_TRACE_ERROR(" ");
 }
@@ -126,35 +161,6 @@ static void bta_gattc_display_explore_record(tBTA_GATTC_ATTR_REC *p_rec, UINT8 n
 #endif  /* BTA_GATT_DEBUG == TRUE */
 
 
-/*******************************************************************************
-**
-** Function         bta_gattc_alloc_cache_buf
-**
-** Description      Allocate a buffer for database cache.
-**
-** Returns          status
-**
-*******************************************************************************/
-BT_HDR *bta_gattc_alloc_cache_buf(tBTA_GATTC_SERV *p_srvc_cb)
-{
-    BT_HDR  *p_buf;
-
-    if ((p_buf = (BT_HDR *)osi_calloc(GATT_DB_BUF_SIZE)) == NULL) {
-        APPL_TRACE_DEBUG("No resources: buffer allocation failed.");
-        utl_freebuf((void **)&p_srvc_cb->p_srvc_list);
-        p_srvc_cb->free_byte = 0;
-    } else {
-        p_srvc_cb->p_free = (UINT8 *) p_buf;
-        p_srvc_cb->free_byte = GATT_DB_BUF_SIZE;
-
-        /* link into buffer queue */
-        fixed_queue_enqueue(p_srvc_cb->cache_buffer, p_buf);
-    }
-#if BTA_GATT_DEBUG== TRUE
-    APPL_TRACE_DEBUG("allocating new buffer: free byte = %d", p_srvc_cb->free_byte);
-#endif
-    return p_buf;
-}
 /*******************************************************************************
 **
 ** Function         bta_gattc_init_cache
@@ -166,115 +172,44 @@ BT_HDR *bta_gattc_alloc_cache_buf(tBTA_GATTC_SERV *p_srvc_cb)
 *******************************************************************************/
 tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb)
 {
-    tBTA_GATT_STATUS    status = BTA_GATT_OK;
-
-    while (!fixed_queue_is_empty(p_srvc_cb->cache_buffer)) {
-        osi_free (fixed_queue_dequeue(p_srvc_cb->cache_buffer));
+    if (p_srvc_cb->p_srvc_cache != NULL) {
+        list_free(p_srvc_cb->p_srvc_cache);
+        p_srvc_cb->p_srvc_cache = NULL;
     }
 
-    utl_freebuf((void **)&p_srvc_cb->p_srvc_list);
+    osi_free(p_srvc_cb->p_srvc_list);
 
     if ((p_srvc_cb->p_srvc_list = (tBTA_GATTC_ATTR_REC *)osi_malloc(BTA_GATTC_ATTR_LIST_SIZE)) == NULL) {
-        APPL_TRACE_DEBUG("No resources: buffer allocation failed.");
-        status = GATT_NO_RESOURCES;
+        APPL_TRACE_DEBUG("No resources: GKI buffer allocation failed.");
+        return BTA_GATT_NO_RESOURCES;
     } else {
         p_srvc_cb->total_srvc = 0;
-        p_srvc_cb->cur_srvc_idx =
-            p_srvc_cb->cur_char_idx =
-                p_srvc_cb->next_avail_idx = 0;
-
-        if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL) {
-            status = GATT_NO_RESOURCES;
-        } else {
-            p_srvc_cb->p_cur_srvc = p_srvc_cb->p_srvc_cache = NULL;
-        }
+        p_srvc_cb->cur_srvc_idx = 0;
+        p_srvc_cb->cur_char_idx = 0;
+        p_srvc_cb->next_avail_idx = 0;
     }
 
-    return status;
+    return BTA_GATT_OK;
 }
-/*******************************************************************************
-**
-** Function         bta_gattc_get_srvc_inst_id
-**
-** Description      get service instance number
-**
-** Returns          instance ID of the service.
-**
-*******************************************************************************/
-static UINT8 bta_gattc_get_srvc_inst_id(tBTA_GATTC_SERV *p_srvc_cb, tBT_UUID uuid)
-{
-    UINT8 i = 0, inst = 0;
-    tBTA_GATTC_ATTR_REC   *p_srvc_rec;
 
-    for (i = 0; i < p_srvc_cb->total_srvc; i ++)
-        /*
-        for (; i < p_srvc_cb->cur_srvc_idx; i ++)*/
-    {
-        p_srvc_rec = p_srvc_cb->p_srvc_list + i;
-
-        if (bta_gattc_uuid_compare(&p_srvc_rec->uuid, &uuid, TRUE)) {
-            inst ++;
-        }
-    }
-    return inst ;
-}
-/*******************************************************************************
-**
-** Function         bta_gattc_get_char_inst_id
-**
-** Description      get characteristic instance number
-**
-** Returns          characteristic instance ID.
-**
-*******************************************************************************/
-static UINT8 bta_gattc_get_char_inst_id(tBTA_GATTC_CACHE *p_service_cache, tBT_UUID *p_uuid)
+static void characteristic_free(void *ptr)
 {
-    UINT8 inst = 0;
-    tBTA_GATTC_CACHE_ATTR   *p_attr;
-    tBT_UUID    attr_uuid;
-
-    p_attr = p_service_cache->p_attr;
-
-    while (p_attr) {
-        bta_gattc_pack_attr_uuid(p_attr, &attr_uuid);
-
-        if (bta_gattc_uuid_compare(&attr_uuid, p_uuid, TRUE)) {
-            inst ++;
-        }
-
-        p_attr = p_attr->p_next;
-    }
-
-    return inst ;
+  tBTA_GATTC_CHARACTERISTIC *p_char = ptr;
+  list_free(p_char->descriptors);
+  osi_free(p_char);
 }
-/*******************************************************************************
-**
-** Function         bta_gattc_get_char_descr_inst_id
-**
-** Description      get characteristic descriptor instance number
-**
-** Returns          characteristic instance ID.
-**
-*******************************************************************************/
-static UINT8 bta_gattc_get_char_descr_inst_id(tBTA_GATTC_CACHE_ATTR *p_char_attr, tBT_UUID *p_uuid)
-{
-    UINT8 inst = 0;
-    tBT_UUID    attr_uuid;
-
-    if (p_char_attr != NULL) {
-        p_char_attr = p_char_attr->p_next;
-    }
-
-    while (p_char_attr) {
-        bta_gattc_pack_attr_uuid(p_char_attr, &attr_uuid);
 
-        if (bta_gattc_uuid_compare(&attr_uuid, p_uuid, TRUE)) {
-            inst ++;
-        }
+static void service_free(void *ptr)
+{
+  tBTA_GATTC_SERVICE *srvc = ptr;
+  list_free(srvc->characteristics);
+  list_free(srvc->included_svc);
+  osi_free(srvc);
+}
 
-        p_char_attr = p_char_attr->p_next;
-    }
-    return inst ;
+static void bta_gattc_free(void *ptr)
+{
+    osi_free(ptr);
 }
 
 /*******************************************************************************
@@ -287,50 +222,75 @@ static UINT8 bta_gattc_get_char_descr_inst_id(tBTA_GATTC_CACHE_ATTR *p_char_attr
 **
 *******************************************************************************/
 static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
-        UINT16 s_handle, UINT16 e_handle,
-        tBT_UUID *p_uuid,
-        BOOLEAN is_primary, UINT8 srvc_inst)
+                                                    UINT16 s_handle, UINT16 e_handle,
+                                                    tBT_UUID *p_uuid,
+                                                    BOOLEAN is_primary)
 {
-    tBTA_GATTC_CACHE    *p_new_srvc = NULL;
-    tBTA_GATT_STATUS    status = BTA_GATT_OK;
-
 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
     APPL_TRACE_DEBUG("Add a service into Service");
-    APPL_TRACE_DEBUG("free byte = %d,  req %d bytes.", p_srvc_cb->free_byte, sizeof(tBTA_GATTC_CACHE))
 #endif
 
-    if (p_srvc_cb->free_byte < sizeof(tBTA_GATTC_CACHE)) {
-        if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL) {
-            return GATT_NO_RESOURCES;
-        }
+    tBTA_GATTC_SERVICE *p_new_srvc = osi_malloc(sizeof(tBTA_GATTC_SERVICE));
+    if (!p_new_srvc) {
+        APPL_TRACE_WARNING("%s(), no resource.", __func__);
+        return BTA_GATT_NO_RESOURCES;
     }
 
-    p_new_srvc = (tBTA_GATTC_CACHE *)p_srvc_cb->p_free;
     /* update service information */
     p_new_srvc->s_handle = s_handle;
     p_new_srvc->e_handle = e_handle;
-    p_new_srvc->service_uuid.is_primary = is_primary;
-    memcpy(&p_new_srvc->service_uuid.id.uuid, p_uuid, sizeof(tBT_UUID));
-    p_new_srvc->service_uuid.id.inst_id = srvc_inst;
-    p_new_srvc->p_next  = NULL;
+    p_new_srvc->is_primary = is_primary;
+    memcpy(&p_new_srvc->uuid, p_uuid, sizeof(tBT_UUID));
+    p_new_srvc->handle = s_handle;
+    p_new_srvc->characteristics = list_new(characteristic_free);
+    p_new_srvc->included_svc = list_new(bta_gattc_free);
 
-    if (p_srvc_cb->p_cur_srvc != NULL) {
-        p_srvc_cb->p_cur_srvc->p_next = p_new_srvc;
+    if (p_srvc_cb->p_srvc_cache == NULL) {
+        p_srvc_cb->p_srvc_cache = list_new(service_free);
     }
-    p_srvc_cb->p_cur_srvc = p_new_srvc;
-    p_srvc_cb->p_cur_srvc->p_cur_char = NULL;
 
-    /* first service */
-    if (p_srvc_cb->p_srvc_cache == NULL) {
-        p_srvc_cb->p_srvc_cache = p_new_srvc;
+    list_append(p_srvc_cb->p_srvc_cache, p_new_srvc);
+    return BTA_GATT_OK;
+}
+
+static tBTA_GATT_STATUS bta_gattc_add_char_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
+                                                    UINT16 attr_handle,
+                                                    UINT16 value_handle,
+                                                    tBT_UUID *p_uuid,
+                                                    UINT8 property)
+{
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+    APPL_TRACE_DEBUG("%s: Add a characteristic into Service", __func__);
+    APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x",
+                      value_handle, p_uuid->uu.uuid16, property);
+#endif
+
+    tBTA_GATTC_SERVICE *service = bta_gattc_find_matching_service(p_srvc_cb->p_srvc_cache, attr_handle);
+    if (!service) {
+        APPL_TRACE_ERROR("Illegal action to add char/descr/incl srvc for non-existing service!");
+        return GATT_WRONG_STATE;
     }
 
-    /* update buffer managament info */
-    p_srvc_cb->p_free += sizeof(tBTA_GATTC_CACHE);
-    p_srvc_cb->free_byte -= sizeof(tBTA_GATTC_CACHE);
+    /* TODO(jpawlowski): We should use attribute handle, not value handle to refer to characteristic.
+       This is just a temporary workaround.
+    */
+    if (service->e_handle < value_handle)
+        service->e_handle = value_handle;
+
+    tBTA_GATTC_CHARACTERISTIC *characteristic = osi_malloc(sizeof(tBTA_GATTC_CHARACTERISTIC));
+    if (!characteristic) {
+        APPL_TRACE_WARNING("%s(), no resource.", __func__);
+        return BTA_GATT_NO_RESOURCES;
+    }
+    characteristic->handle = value_handle;
+    characteristic->properties = property;
+    characteristic->descriptors = list_new(bta_gattc_free);
+    memcpy(&characteristic->uuid, p_uuid, sizeof(tBT_UUID));
 
+    characteristic->service = service;
+    list_append(service->characteristics, characteristic);
 
-    return status;
+    return BTA_GATT_OK;
 }
 /*******************************************************************************
 **
@@ -342,74 +302,68 @@ static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
 **
 *******************************************************************************/
 static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
-        UINT16 handle,
-        tBT_UUID *p_uuid,
-        UINT8 property,
-        tBTA_GATTC_ATTR_TYPE type)
+                                                    UINT16 handle,
+                                                    tBT_UUID *p_uuid,
+                                                    UINT8 property,
+                                                    UINT16 incl_srvc_s_handle,
+                                                    tBTA_GATTC_ATTR_TYPE type)
 {
-    tBTA_GATTC_CACHE_ATTR *p_attr;
-    tBTA_GATT_STATUS    status = BTA_GATT_OK;
-    UINT16  len = sizeof(tBTA_GATTC_CACHE_ATTR) + p_uuid->len;
-    UINT8   *pp;
-
 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-    APPL_TRACE_DEBUG("bta_gattc_add_attr_to_cache: Add a [%s] into Service", bta_gattc_attr_type[type]);
-    APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x type=%d", handle, p_uuid->uu.uuid16, property, type);
-    APPL_TRACE_DEBUG("free byte = %d,  req %d bytes.", p_srvc_cb->free_byte, len);
+    APPL_TRACE_DEBUG("%s: Add a [%s] into Service", __func__, bta_gattc_attr_type[type]);
+    APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x type=%d",
+                      handle, p_uuid->uu.uuid16, property, type);
 #endif
 
-    if (p_srvc_cb->p_cur_srvc == NULL) {
-        APPL_TRACE_ERROR("Illegal action to add char/descr/incl srvc before adding a service!");
+    tBTA_GATTC_SERVICE *service = bta_gattc_find_matching_service(p_srvc_cb->p_srvc_cache, handle);
+    if (!service) {
+        APPL_TRACE_ERROR("Illegal action to add char/descr/incl srvc for non-existing service!");
         return GATT_WRONG_STATE;
     }
 
-    if (p_srvc_cb->free_byte < len) {
-        if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL) {
-            return GATT_NO_RESOURCES;
+    if (type == BTA_GATTC_ATTR_TYPE_INCL_SRVC) {
+        tBTA_GATTC_INCLUDED_SVC *isvc =
+            osi_malloc(sizeof(tBTA_GATTC_INCLUDED_SVC));
+        if (!isvc) {
+            APPL_TRACE_WARNING("%s(), no resource.", __func__);
+            return BTA_GATT_NO_RESOURCES;
+        }
+        isvc->handle = handle;
+        memcpy(&isvc->uuid, p_uuid, sizeof(tBT_UUID));
+        isvc->incl_srvc_s_handle = incl_srvc_s_handle;
+        isvc->owning_service = service;
+        isvc->included_service = bta_gattc_find_matching_service(
+                                    p_srvc_cb->p_srvc_cache, incl_srvc_s_handle);
+        if (!isvc->included_service) {
+            APPL_TRACE_ERROR("%s: Illegal action to add non-existing included service!", __func__);
+            osi_free(isvc);
+            return GATT_WRONG_STATE;
         }
-    }
-
-    p_attr = (tBTA_GATTC_CACHE_ATTR *)p_srvc_cb->p_free;
-
-    p_attr->attr_handle = handle;
-    p_attr->attr_type   = type;
-    p_attr->property    = property;
-    p_attr->uuid_len    = p_uuid->len;
-    p_attr->p_uuid      = (tBTA_GATTC_UUID *)(p_attr + 1);
-    p_attr->p_next      = NULL;
-
-    pp = (UINT8 *)p_attr->p_uuid;
-
-    if (p_uuid->len == LEN_UUID_16) {
-        UINT16_TO_STREAM(pp, p_uuid->uu.uuid16);
-    } else if (p_uuid->len == LEN_UUID_128) {
-        memcpy(pp, p_uuid->uu.uuid128, LEN_UUID_128);
-    }
 
-    if (type == BTA_GATTC_ATTR_TYPE_CHAR) {
-        p_attr->inst_id = bta_gattc_get_char_inst_id(p_srvc_cb->p_cur_srvc, p_uuid);
-        p_srvc_cb->p_cur_srvc->p_cur_char = p_attr;
+        list_append(service->included_svc, isvc);
     } else if (type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) {
-        p_attr->inst_id = bta_gattc_get_char_descr_inst_id(p_srvc_cb->p_cur_srvc->p_cur_char, p_uuid);
-    } else { /* TODO: --->> temp treat included service as single instance */
-        p_attr->inst_id = 0;
-    }
+        tBTA_GATTC_DESCRIPTOR *descriptor =
+            osi_malloc(sizeof(tBTA_GATTC_DESCRIPTOR));
+        if (!descriptor) {
+            APPL_TRACE_WARNING("%s(), no resource.", __func__);
+            return BTA_GATT_NO_RESOURCES;
+        }
+        descriptor->handle = handle;
+        memcpy(&descriptor->uuid, p_uuid, sizeof(tBT_UUID));
+
+        if (service->characteristics == NULL ||
+            list_is_empty(service->characteristics)) {
+            APPL_TRACE_ERROR("%s: Illegal action to add descriptor before adding a characteristic!",
+                             __func__);
+            osi_free(descriptor);
+            return GATT_WRONG_STATE;
+        }
 
-    /* update service information */
-    p_srvc_cb->p_free += len;
-    p_srvc_cb->free_byte -= len;
+        tBTA_GATTC_CHARACTERISTIC *char_node = list_back(service->characteristics);
 
-    /* first attribute within the service, update the attribute pointer */
-    if (p_srvc_cb->p_cur_srvc->p_attr == NULL) {
-        p_srvc_cb->p_cur_srvc->p_attr = p_attr;
+        descriptor->characteristic = char_node;
+        list_append(char_node->descriptors, descriptor);
     }
-    if (p_srvc_cb->p_cur_srvc->p_last_attr != NULL) {
-        p_srvc_cb->p_cur_srvc->p_last_attr->p_next = p_attr;
-    }
-
-    p_srvc_cb->p_cur_srvc->p_last_attr = p_attr;
-
-    return status;
+    return BTA_GATT_OK;
 }
 
 /*******************************************************************************
@@ -476,7 +430,7 @@ tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV
 **
 *******************************************************************************/
 tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb,
-        UINT8 disc_type)
+                                              UINT8 disc_type)
 {
     tGATT_DISC_PARAM param;
     BOOLEAN is_service = TRUE;
@@ -575,8 +529,7 @@ static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
                                          p_rec->s_handle,
                                          p_rec->e_handle,
                                          &p_rec->uuid,
-                                         p_rec->is_primary,
-                                         p_rec->srvc_inst_id) == 0) {
+                                         p_rec->is_primary) == 0) {
             /* start discovering included services */
             bta_gattc_start_disc_include_srvc(conn_id, p_srvc_cb);
             return;
@@ -597,8 +550,12 @@ static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
 #endif
     /* save cache to NV */
     p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
-    bta_gattc_co_cache_open(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_OPEN_EVT,
-                            conn_id, TRUE);
+
+    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_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK);
 }
 /*******************************************************************************
 **
@@ -632,13 +589,13 @@ static void bta_gattc_char_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
     /* if there are characteristic needs to be explored */
     if (p_srvc_cb->total_char > 0) {
         /* add the first characteristic into cache */
-        bta_gattc_add_attr_to_cache (p_srvc_cb,
+        bta_gattc_add_char_to_cache (p_srvc_cb,
+                                     p_rec->char_decl_handle,
                                      p_rec->s_handle,
                                      &p_rec->uuid,
-                                     p_rec->property,
-                                     BTA_GATTC_ATTR_TYPE_CHAR);
+                                     p_rec->property);
 
-        /* start discoverying characteristic descriptor , if failed, disc for next char*/
+        /* start discoverying characteristic descriptor , if failed, disc for next char */
         bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
     } else { /* otherwise start with next service */
         p_srvc_cb->cur_srvc_idx ++;
@@ -659,14 +616,14 @@ static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_sr
 {
     tBTA_GATTC_ATTR_REC *p_rec = NULL;
 
-    if (-- p_srvc_cb->total_char > 0) {
+    if (--p_srvc_cb->total_char > 0) {
         p_rec = p_srvc_cb->p_srvc_list + (++ p_srvc_cb->cur_char_idx);
         /* add the next characteristic into cache */
-        bta_gattc_add_attr_to_cache (p_srvc_cb,
+        bta_gattc_add_char_to_cache (p_srvc_cb,
+                                     p_rec->char_decl_handle,
                                      p_rec->s_handle,
                                      &p_rec->uuid,
-                                     p_rec->property,
-                                     BTA_GATTC_ATTR_TYPE_CHAR);
+                                     p_rec->property);
 
         /* start discoverying next characteristic for char descriptor */
         bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
@@ -715,8 +672,8 @@ static BOOLEAN bta_gattc_srvc_in_list(tBTA_GATTC_SERV *p_srvc_cb, UINT16 s_handl
 **
 *******************************************************************************/
 static tBTA_GATT_STATUS bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV *p_srvc_cb,
-        UINT16 s_handle, UINT16 e_handle,
-        tBT_UUID uuid, BOOLEAN is_primary)
+                                                   UINT16 s_handle, UINT16 e_handle,
+                                                   tBT_UUID uuid, BOOLEAN is_primary)
 {
     tBTA_GATTC_ATTR_REC *p_rec = NULL;
     tBTA_GATT_STATUS    status = BTA_GATT_OK;
@@ -730,7 +687,6 @@ static tBTA_GATT_STATUS bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV *p_srvc_cb,
         p_rec->s_handle     = s_handle;
         p_rec->e_handle     = e_handle;
         p_rec->is_primary   = is_primary;
-        p_rec->srvc_inst_id = bta_gattc_get_srvc_inst_id(p_srvc_cb, uuid);
         memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
 
         p_srvc_cb->total_srvc ++;
@@ -753,8 +709,8 @@ static tBTA_GATT_STATUS bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV *p_srvc_cb,
 **
 *******************************************************************************/
 static tBTA_GATT_STATUS bta_gattc_add_char_to_list(tBTA_GATTC_SERV *p_srvc_cb,
-        UINT16 decl_handle, UINT16 value_handle,
-        tBT_UUID uuid, UINT8 property)
+                                                   UINT16 decl_handle, UINT16 value_handle,
+                                                   tBT_UUID uuid, UINT8 property)
 {
     tBTA_GATTC_ATTR_REC *p_rec = NULL;
     tBTA_GATT_STATUS    status = BTA_GATT_OK;
@@ -769,6 +725,7 @@ static tBTA_GATT_STATUS bta_gattc_add_char_to_list(tBTA_GATTC_SERV *p_srvc_cb,
         p_srvc_cb->total_char ++;
 
         p_rec->s_handle = value_handle;
+        p_rec->char_decl_handle = decl_handle;
         p_rec->property = property;
         p_rec->e_handle = (p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx)->e_handle;
         memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
@@ -797,19 +754,19 @@ static tBTA_GATT_STATUS bta_gattc_add_char_to_list(tBTA_GATTC_SERV *p_srvc_cb,
 **
 *******************************************************************************/
 #if (SDP_INCLUDED == TRUE)
-void bta_gattc_sdp_callback (UINT16 sdp_status)
+void bta_gattc_sdp_callback(UINT16 sdp_status, void* user_data)
 {
     tSDP_DISC_REC       *p_sdp_rec = NULL;
     tBT_UUID            service_uuid;
     tSDP_PROTOCOL_ELEM  pe;
     UINT16              start_handle = 0, end_handle = 0;
-    tBTA_GATTC_SERV     *p_srvc_cb = bta_gattc_find_scb_by_cid(bta_gattc_cb.sdp_conn_id);
+    tBTA_GATTC_CB_DATA  *cb_data = user_data;
+    tBTA_GATTC_SERV     *p_srvc_cb = bta_gattc_find_scb_by_cid(cb_data->sdp_conn_id);
 
     if (((sdp_status == SDP_SUCCESS) || (sdp_status == SDP_DB_FULL)) && p_srvc_cb != NULL) {
         do {
             /* find a service record, report it */
-            p_sdp_rec = SDP_FindServiceInDb(bta_gattc_cb.p_sdp_db,
-                                            0, p_sdp_rec);
+            p_sdp_rec = SDP_FindServiceInDb(cb_data->p_sdp_db, 0, p_sdp_rec);
             if (p_sdp_rec) {
                 if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid)) {
 
@@ -843,16 +800,18 @@ void bta_gattc_sdp_callback (UINT16 sdp_status)
     }
 
     if ( p_srvc_cb != NULL)
+    {
         /* start discover primary service */
+        bta_gattc_explore_srvc(cb_data->sdp_conn_id, p_srvc_cb);
+    }
+    else
     {
-        bta_gattc_explore_srvc(bta_gattc_cb.sdp_conn_id, p_srvc_cb);
-    } else {
         APPL_TRACE_ERROR("GATT service discovery is done on unknown connection");
     }
 
-    osi_free(bta_gattc_cb.p_sdp_db);
-    bta_gattc_cb.p_sdp_db  = NULL;
-    bta_gattc_cb.sdp_conn_id = 0;
+    /* both were allocated in bta_gattc_sdp_service_disc */
+    osi_free(cb_data->p_sdp_db);
+    osi_free(cb_data);
 }
 #endif  ///SDP_INCLUDED == TRUE
 
@@ -871,30 +830,39 @@ static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SE
     tSDP_UUID       uuid;
     UINT16          num_attrs = 2;
     UINT16          attr_list[2];
-    tBTA_GATT_STATUS    status = BTA_GATT_ERROR;
 
     memset (&uuid, 0, sizeof(tSDP_UUID));
 
     uuid.len = LEN_UUID_16;
     uuid.uu.uuid16 = UUID_PROTOCOL_ATT;
 
-    if ((bta_gattc_cb.p_sdp_db = (tSDP_DISCOVERY_DB *)osi_malloc(BTA_GATT_SDP_DB_SIZE)) != NULL) {
-        attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
-        attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
+    /*
+     * On success, cb_data will be freed inside bta_gattc_sdp_callback,
+     * otherwise it will be freed within this function.
+     */
+    tBTA_GATTC_CB_DATA *cb_data =
+        (tBTA_GATTC_CB_DATA *)osi_malloc(sizeof(tBTA_GATTC_CB_DATA));
+    cb_data->p_sdp_db = (tSDP_DISCOVERY_DB *)osi_malloc(BTA_GATT_SDP_DB_SIZE);
+    if (!cb_data || cb_data->p_sdp_db) {
+        APPL_TRACE_WARNING("%s(), no resource.", __func__);
+        return BTA_GATT_NO_RESOURCES;
+    }
+    attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
+    attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
 
-        SDP_InitDiscoveryDb (bta_gattc_cb.p_sdp_db, BTA_GATT_SDP_DB_SIZE, 1,
-                             &uuid, num_attrs, attr_list);
+    SDP_InitDiscoveryDb(cb_data->p_sdp_db, BTA_GATT_SDP_DB_SIZE, 1,
+                         &uuid, num_attrs, attr_list);
 
-        if (!SDP_ServiceSearchAttributeRequest (p_server_cb->server_bda,
-                                                bta_gattc_cb.p_sdp_db, &bta_gattc_sdp_callback)) {
-            osi_free(bta_gattc_cb.p_sdp_db);
-            bta_gattc_cb.p_sdp_db = NULL;
-        } else {
-            bta_gattc_cb.sdp_conn_id = conn_id;
-            status = BTA_GATT_OK;
-        }
+    if (!SDP_ServiceSearchAttributeRequest2(p_server_cb->server_bda,
+                                          cb_data->p_sdp_db, &bta_gattc_sdp_callback, cb_data))
+    {
+        osi_free(cb_data->p_sdp_db);
+        osi_free(cb_data);
+        return BTA_GATT_ERROR;
     }
-    return status;
+
+    cb_data->sdp_conn_id = conn_id;
+    return BTA_GATT_OK;
 }
 #endif  ///SDP_INCLUDED == TRUE
 
@@ -917,6 +885,7 @@ void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_
     p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
 
     if (p_srvc_cb != NULL && p_clcb != NULL && p_clcb->state == BTA_GATTC_DISCOVER_ST) {
+        p_srvc_cb->total_attr++;
         switch (disc_type) {
         case GATT_DISC_SRVC_ALL:
             /* discover services result, add services into a service list */
@@ -954,6 +923,7 @@ void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_
                                         p_data->handle,
                                         &p_data->value.incl_service.service_type,
                                         pri_srvc,
+                                        p_data->value.incl_service.s_handle,
                                         BTA_GATTC_ATTR_TYPE_INCL_SRVC);
             break;
 
@@ -968,8 +938,9 @@ void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_
 
         case GATT_DISC_CHAR_DSCPT:
             bta_gattc_add_attr_to_cache(p_srvc_cb, p_data->handle, &p_data->type, 0,
+                                        0 /* incl_srvc_handle */,
                                         BTA_GATTC_ATTR_TYPE_CHAR_DESCR);
-            break;
+                break;
         }
     }
 }
@@ -979,9 +950,8 @@ void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT
     tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
 
     if ( p_clcb && (status != GATT_SUCCESS || p_clcb->status != GATT_SUCCESS) ) {
-        if (p_clcb->status == GATT_SUCCESS) {
+        if (status == GATT_SUCCESS)
             p_clcb->status = status;
-        }
         bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
         return;
     }
@@ -1017,367 +987,815 @@ void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT
 }
 /*******************************************************************************
 **
-** Function         bta_gattc_id2handle
+** Function         bta_gattc_search_service
 **
-** Description      map GATT ID to handle in a given cache.
+** Description      search local cache for matching service record.
 **
-** Returns          the handle mapped. 0 if not found.
+** Returns          FALSE if map can not be found.
 **
 *******************************************************************************/
-UINT16 bta_gattc_id2handle(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_SRVC_ID *p_service_id,
-                           tBTA_GATT_ID *p_char_id, tBTA_GATT_ID *p_descr_uuid)
+void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid)
 {
-    tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
-    tBTA_GATTC_CACHE_ATTR   *p_attr;
-    UINT8       j;
-    UINT16      handle = 0;
-    tBT_UUID    attr_uuid;
-    BOOLEAN     char_map = FALSE, done = FALSE;
-
-    while (p_service_id && p_cache && !done) {
-#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-        APPL_TRACE_DEBUG("Service: handle[%d] uuid[0x%04x] inst[%d]",
-                         p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16,
-                         p_cache->service_uuid.id.inst_id);
-#endif
-        p_attr = p_cache->p_attr;
+    tBTA_GATTC          cb_data;
 
-        if (bta_gattc_srvcid_compare(p_service_id, &p_cache->service_uuid)) {
-            for (j = 0; p_attr; j ++) {
-#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-                APPL_TRACE_DEBUG("\t Attr[0x%04x] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
-                                 j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16,
-                                 p_attr->inst_id, p_attr->attr_type);
-#endif
-                bta_gattc_pack_attr_uuid(p_attr, &attr_uuid);
-
-                if (bta_gattc_uuid_compare(&p_char_id->uuid, &attr_uuid, TRUE) &&
-                        p_char_id->inst_id == p_attr->inst_id) {
-                    if (p_descr_uuid == NULL) {
-                        handle = p_attr->attr_handle;
-                        done = TRUE;
-                        break;
-                    } else {
-#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-                        APPL_TRACE_DEBUG("found matching characteristic for the descriptor");
-#endif
-                        char_map = TRUE;
-                    }
-                } else if (char_map == TRUE) {
-                    if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) {
+    if (!p_clcb->p_srcb->p_srvc_cache || list_is_empty(p_clcb->p_srcb->p_srvc_cache))
+        return;
+
+    for (list_node_t *sn = list_begin(p_clcb->p_srcb->p_srvc_cache);
+         sn != list_end(p_clcb->p_srcb->p_srvc_cache); sn = list_next(sn)) {
+        tBTA_GATTC_SERVICE *p_cache = list_node(sn);
+
+        if (!bta_gattc_uuid_compare(p_uuid, &p_cache->uuid, FALSE))
+            continue;
 
-                        if (p_descr_uuid != NULL &&
-                                bta_gattc_uuid_compare(&p_descr_uuid->uuid, &attr_uuid, TRUE) &&
-                                p_descr_uuid->inst_id == p_attr->inst_id) {
-#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-                            APPL_TRACE_DEBUG("found descriptor!!");
-#endif
-                            handle = p_attr->attr_handle;
-                            done = TRUE;
-                            break;
-                        } else {
-#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-                            APPL_TRACE_DEBUG("descriptor UUID not matching");
-#endif
-                        }
-                    } else { /* another char */
 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-                        APPL_TRACE_DEBUG("no matching descptr found!!start of next characteristic");
+        APPL_TRACE_DEBUG("found service [0x%04x], inst[%d] handle [%d]",
+                          p_cache->uuid.uu.uuid16,
+                          p_cache->handle,
+                          p_cache->s_handle);
 #endif
-                        char_map = FALSE;
-                        done = TRUE;
-                        break;
-                    }
-                }
-                p_attr = p_attr->p_next;
-            }
+        if (!p_clcb->p_rcb->p_cback)
+            continue;
+
+        memset(&cb_data, 0, sizeof(tBTA_GATTC));
+
+        cb_data.srvc_res.conn_id = p_clcb->bta_conn_id;
+        cb_data.srvc_res.service_uuid.inst_id = p_cache->handle;
+        cb_data.srvc_res.start_handle = p_cache->s_handle;
+        cb_data.srvc_res.end_handle = p_cache->e_handle;
+        memcpy(&cb_data.srvc_res.service_uuid.uuid, &p_cache->uuid, sizeof(tBTA_GATT_ID));
+
+        (* p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data);
+    }
+}
+
+list_t* bta_gattc_get_services_srcb(tBTA_GATTC_SERV *p_srcb) {
+    if (!p_srcb || !p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache))
+        return NULL;
+
+    return p_srcb->p_srvc_cache;
+}
+
+const list_t* bta_gattc_get_services(UINT16 conn_id) {
+    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+
+    if (p_clcb == NULL )
+        return NULL;
+
+    tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
+
+    return bta_gattc_get_services_srcb(p_srcb);
+}
+
+tBTA_GATTC_SERVICE*  bta_gattc_find_matching_service(const list_t *services, UINT16 handle) {
+    if (!services || list_is_empty(services))
+        return NULL;
+
+    for (list_node_t *sn = list_begin(services);
+         sn != list_end(services); sn = list_next(sn)) {
+        tBTA_GATTC_SERVICE *service = list_node(sn);
+
+        if (handle >= service->s_handle && handle <= service->e_handle)
+            return service;
+    }
+
+    return NULL;
+}
+
+const tBTA_GATTC_SERVICE*  bta_gattc_get_service_for_handle_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle) 
+{
+    const list_t *services = bta_gattc_get_services_srcb(p_srcb);
+
+    return bta_gattc_find_matching_service(services, handle);
+}
+
+const tBTA_GATTC_SERVICE*  bta_gattc_get_service_for_handle(UINT16 conn_id, UINT16 handle) 
+{
+    const list_t *services = bta_gattc_get_services(conn_id);
+
+    return bta_gattc_find_matching_service(services, handle);
+}
+
+tBTA_GATTC_CHARACTERISTIC*  bta_gattc_get_characteristic_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle) 
+{
+    const tBTA_GATTC_SERVICE* service = bta_gattc_get_service_for_handle_srcb(p_srcb, handle);
+
+    if (!service)
+        return NULL;
+
+    for (list_node_t *cn = list_begin(service->characteristics);
+         cn != list_end(service->characteristics); cn = list_next(cn)) {
+        tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
+        if (handle == p_char->handle)
+            return p_char;
+    }
+
+    return NULL;
+}
+
+tBTA_GATTC_CHARACTERISTIC*  bta_gattc_get_characteristic(UINT16 conn_id, UINT16 handle) 
+{
+   tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+
+    if (p_clcb == NULL )
+        return NULL;
+
+    tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
+    return bta_gattc_get_characteristic_srcb(p_srcb, handle);
+}
+
+tBTA_GATTC_DESCRIPTOR*  bta_gattc_get_descriptor_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle) 
+{
+    const tBTA_GATTC_SERVICE* service = bta_gattc_get_service_for_handle_srcb(p_srcb, handle);
+
+    if (!service) {
+        return NULL;
+    }
+
+    for (list_node_t *cn = list_begin(service->characteristics);
+         cn != list_end(service->characteristics); cn = list_next(cn)) {
+        tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
+        for (list_node_t *dn = list_begin(p_char->descriptors);
+             dn != list_end(p_char->descriptors); dn = list_next(dn)) {
+            tBTA_GATTC_DESCRIPTOR *p_desc = list_node(dn);
+            if (handle == p_desc->handle)
+                return p_desc;
+        }
+    }
+
+    return NULL;
+}
+
+tBTA_GATTC_DESCRIPTOR*  bta_gattc_get_descriptor(UINT16 conn_id, UINT16 handle) 
+{
+    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+
+    if (p_clcb == NULL )
+        return NULL;
+
+    tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
+    return bta_gattc_get_descriptor_srcb(p_srcb, handle);
+}
+
+void bta_gattc_get_service_with_uuid(UINT16 conn_id, tBT_UUID *svc_uuid,
+                                     btgatt_db_element_t **svc_db,
+                                     int *count)
+{
+    const list_t* svc = bta_gattc_get_services(conn_id);
+    size_t db_size = list_length(svc);
+    void *buffer = osi_malloc(db_size*sizeof(btgatt_db_element_t));
+    if (!buffer) {
+        APPL_TRACE_WARNING("%s(), no resource.", __func__);
+        *svc_db = NULL;
+        *count = 0;
+        return;
+    }
+    btgatt_db_element_t *curr_db_attr = buffer;
+    db_size = 0;
+    for (list_node_t *sn = list_begin(svc);
+         sn != list_end(svc); sn = list_next(sn)) {
+        tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn);
+        if (svc_uuid == NULL || bta_gattc_uuid_compare(svc_uuid, &p_cur_srvc->uuid, TRUE)) {
+            bta_gattc_fill_gatt_db_el(curr_db_attr,
+                                      p_cur_srvc->is_primary ?
+                                      BTGATT_DB_PRIMARY_SERVICE :
+                                      BTGATT_DB_SECONDARY_SERVICE,
+                                      0 /* att_handle */,
+                                      p_cur_srvc->s_handle /* s_handle */,
+                                      p_cur_srvc->e_handle /* e_handle */,
+                                      p_cur_srvc->s_handle,
+                                      p_cur_srvc->uuid,
+                                      0 /* prop */);
+            db_size++;
+            curr_db_attr++;
         }
-        p_cache = p_cache->p_next;
     }
 
-    return handle;
+    *svc_db = buffer;
+    *count = db_size;
 }
+
 /*******************************************************************************
 **
-** Function         bta_gattc_handle2id
+** Function         bta_gattc_fill_gatt_db_el
 **
-** Description      map a handle to GATT ID in a given cache.
+** Description      fill a btgatt_db_element_t value
 **
-** Returns          FALSE if map can not be found.
+** Returns          None.
 **
 *******************************************************************************/
+void bta_gattc_fill_gatt_db_el(btgatt_db_element_t *p_attr,
+                               bt_gatt_db_attribute_type_t type,
+                               UINT16 att_handle,
+                               UINT16 s_handle, UINT16 e_handle,
+                               UINT16 id, tBT_UUID uuid, UINT8 prop)
+{
+    p_attr->type             = type;
+    p_attr->attribute_handle = att_handle;
+    p_attr->start_handle     = s_handle;
+    p_attr->end_handle       = e_handle;
+    p_attr->id               = id;
+    p_attr->properties       = prop;
+    bta_to_btif_uuid(&p_attr->uuid, &uuid);
+}
 
-BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SRVC_ID *p_service_id,
-                            tBTA_GATT_ID *p_char_id, tBTA_GATT_ID *p_descr_type)
+void bta_gattc_get_db_with_opration(UINT16 conn_id,
+                                                      bt_gatt_get_db_op_t op,
+                                                      UINT16 char_handle,
+                                                      tBT_UUID *incl_uuid,
+                                                      tBT_UUID *char_uuid,
+                                                      tBT_UUID *descr_uuid,
+                                                      UINT16 start_handle, UINT16 end_handle,
+                                                      btgatt_db_element_t **char_db,
+                                                      int *count)
 {
-    tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
-    tBTA_GATTC_CACHE_ATTR   *p_attr, *p_char = NULL;
-    UINT8       j;
+    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
 
-    memset(p_service_id, 0, sizeof(tBTA_GATT_SRVC_ID));
-    memset(p_char_id, 0, sizeof(tBTA_GATT_ID));
-    memset(p_descr_type, 0, sizeof(tBTA_GATT_ID));
+    if (p_clcb == NULL) {
+        return NULL;
+    }
 
-    while (p_cache) {
-#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-        APPL_TRACE_DEBUG("Service: handle[%d] uuid[0x%04x] inst[%d]",
-                         p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16,
-                         p_cache->service_uuid.id.inst_id);
-#endif
-        /* a service found */
-        if (p_cache->s_handle == handle) {
-            memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
+    tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
+    if (!p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache)) {
+        *count = 0;
+        *char_db = NULL;
+        return;
+    }
 
-            return TRUE;
-        } else { /* start looking for attributes within the service */
-            p_attr = p_cache->p_attr;
+    size_t db_size = ((end_handle - start_handle) < p_srcb->total_attr) ? (end_handle - start_handle) : p_srcb->total_attr;
 
-            for (j = 0; p_attr; j ++) {
-#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-                APPL_TRACE_DEBUG("\t Attr[0x%04x] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
-                                 j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16,
-                                 p_attr->inst_id, p_attr->attr_type);
-#endif
-                if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR) {
-                    p_char = p_attr;
+    if (!db_size) {
+        *count = 0;
+        *char_db = NULL;
+        return;
+    }
+
+    void *buffer = osi_malloc(db_size*sizeof(btgatt_db_element_t));
+
+    if (!buffer) {
+        *count = 0;
+        *char_db = NULL;
+        return;
+    }
+    btgatt_db_element_t *curr_db_attr = buffer;
+    db_size = 0;
+    for (list_node_t *sn = list_begin(p_srcb->p_srvc_cache);
+         sn != list_end(p_srcb->p_srvc_cache); sn = list_next(sn)) {
+        tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn);
+
+        if (p_cur_srvc->e_handle < start_handle) {
+            continue;
+        }
+
+        if (p_cur_srvc->s_handle > end_handle) {
+            break;
+        }
+
+        if (op == GATT_OP_GET_INCLUDE_SVC) {
+            if (!p_cur_srvc->included_svc || list_is_empty(p_cur_srvc->included_svc))
+                continue;
+
+            for (list_node_t *isn = list_begin(p_cur_srvc->included_svc);
+                 isn != list_end(p_cur_srvc->included_svc); isn = list_next(isn)) {
+                tBTA_GATTC_INCLUDED_SVC *p_isvc = list_node(isn);
+
+                if (p_isvc->handle < start_handle) {
+                    continue;
                 }
 
-                if (handle == p_attr->attr_handle) {
-                    memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
+                if (p_isvc->handle > end_handle) {
+                    *char_db = buffer;
+                    *count = db_size;
+                    return;
+                }
+                if (!incl_uuid || bta_gattc_uuid_compare(&p_isvc->uuid, incl_uuid, TRUE)) {
+                    bta_gattc_fill_gatt_db_el(curr_db_attr,
+                                              BTGATT_DB_INCLUDED_SERVICE,
+                                              p_isvc->handle,
+                                              p_isvc->incl_srvc_s_handle /* s_handle */,
+                                              0 /* e_handle */,
+                                              p_isvc->handle,
+                                              p_isvc->uuid,
+                                              0 /* property */);
+                    curr_db_attr++;
+                    db_size++;
+                }
+            }
+            continue;
+        }
 
-                    if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) {
-                        bta_gattc_pack_attr_uuid(p_attr, &p_descr_type->uuid);
-                        p_descr_type->inst_id = p_attr->inst_id;
+        if (!p_cur_srvc->characteristics || list_is_empty(p_cur_srvc->characteristics)) {
+            continue;
+        }
 
-                        if (p_char != NULL) {
-                            bta_gattc_pack_attr_uuid(p_char, &p_char_id->uuid);
-                            p_char_id->inst_id = p_char->inst_id;
-                        } else {
-                            APPL_TRACE_ERROR("descptr does not belong to any chracteristic");
+        for (list_node_t *cn = list_begin(p_cur_srvc->characteristics);
+             cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
+            tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
+
+            if (p_char->handle < start_handle) {
+                continue;
+            }
+
+            if (p_char->handle > end_handle) {
+                *char_db = buffer;
+                *count = db_size;
+                return;
+            }
+            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))) {
+                bta_gattc_fill_gatt_db_el(curr_db_attr,
+                                          BTGATT_DB_CHARACTERISTIC,
+                                          p_char->handle,
+                                          0 /* s_handle */,
+                                          0 /* e_handle */,
+                                          p_char->handle,
+                                          p_char->uuid,
+                                          p_char->properties);
+                curr_db_attr++;
+                db_size++;
+                continue;
+            }
+
+            if (!p_char->descriptors || list_is_empty(p_char->descriptors)) {
+                continue;
+            }
+
+            if ((op == GATT_OP_GET_DESCRI_BY_HANDLE || op == GATT_OP_GET_ALL_DESCRI) && (p_char->handle != char_handle)) {
+                continue;
+            }
+
+            if ((op == GATT_OP_GET_DESCRI_BY_UUID) &&
+                !bta_gattc_uuid_compare(&p_char->uuid, char_uuid, TRUE)) {
+                continue;
+            }
+
+            if (op == GATT_OP_GET_ALL_DESCRI || op == GATT_OP_GET_DESCRI_BY_UUID || op == GATT_OP_GET_DESCRI_BY_HANDLE) {
+                for (list_node_t *dn = list_begin(p_char->descriptors);
+                     dn != list_end(p_char->descriptors); dn = list_next(dn)) {
+                    tBTA_GATTC_DESCRIPTOR *p_desc = list_node(dn);
+
+                    if (p_desc->handle < start_handle) {
+                        continue;
+                    }
+                    if (p_desc->handle > end_handle) {
+                        *char_db = buffer;
+                        *count = db_size;
+                        return;
+                    }
+                    if (((op == GATT_OP_GET_ALL_DESCRI || op == GATT_OP_GET_DESCRI_BY_UUID) &&
+                        (descr_uuid == NULL || bta_gattc_uuid_compare(&p_desc->uuid, descr_uuid, TRUE))) ||
+                        (op == GATT_OP_GET_DESCRI_BY_HANDLE && bta_gattc_uuid_compare(&p_desc->uuid, descr_uuid, TRUE))) {
+                        bta_gattc_fill_gatt_db_el(curr_db_attr,
+                                                  BTGATT_DB_DESCRIPTOR,
+                                                  p_desc->handle,
+                                                  0 /* s_handle */,
+                                                  0 /* e_handle */,
+                                                  p_desc->handle,
+                                                  p_desc->uuid,
+                                                  0 /* property */);
+                        curr_db_attr++;
+                        db_size++;
+                    }
+                }
+            }
+            
+        }
+    }
+
+    *char_db = buffer;
+    *count = db_size;
+}
+
+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)
+{
+    if (!services || list_is_empty(services)) {
+        return 0;
+    }
+
+    size_t db_size = 0;
+    UINT16 svc_length = list_length(services) - 1;
+
+    for (list_node_t *sn = list_begin(services);
+         sn != list_end(services); sn = list_next(sn), svc_length--) {
+        tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn);
+
+        if (p_cur_srvc->e_handle < start_handle) {
+            continue;
+        }
+
+        if (p_cur_srvc->s_handle > end_handle) {
+            break;
+        }
+
+        if (type == BTGATT_DB_PRIMARY_SERVICE || type == BTGATT_DB_SECONDARY_SERVICE) {
+            if ((type == BTGATT_DB_PRIMARY_SERVICE && p_cur_srvc->is_primary) || 
+                (type == BTGATT_DB_SECONDARY_SERVICE && !p_cur_srvc->is_primary)) {
+                // if the current service is the last service in the db, need to ensure the current service start handle is not less than the start_handle.
+                if (!svc_length) {
+                    if (p_cur_srvc->s_handle >= start_handle) {
+                        db_size++;
+                    }
+                } else {
+                    db_size++;
+                }
+            }
+            continue;
+        }
+
+        if (p_cur_srvc->included_svc && (type == BTGATT_DB_INCLUDED_SERVICE)) {
+            for (list_node_t *isn = list_begin(p_cur_srvc->included_svc);
+                 isn != list_end(p_cur_srvc->included_svc); isn = list_next(isn)) {
+                tBTA_GATTC_INCLUDED_SVC *p_isvc = list_node(isn);
+
+                if (p_isvc->handle < start_handle) {
+                    continue;
+                }
+
+                if (p_isvc->handle > end_handle) {
+                    return db_size;
+                }
+                db_size++;
+            }
+            continue;
+        }
+
+        if (!p_cur_srvc->characteristics || list_is_empty(p_cur_srvc->characteristics)) {
+            continue;
+        }
+
+        if (char_uuid != NULL) {
+            for (list_node_t *cn = list_begin(p_cur_srvc->characteristics);
+                cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
+                tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
+
+                if (p_char->handle < start_handle) {
+                    continue;
+                }
+
+                if (p_char->handle > end_handle) {
+                    return db_size;
+                }
+
+                if ((type == BTGATT_DB_CHARACTERISTIC) && bta_gattc_uuid_compare(&p_char->uuid, char_uuid, TRUE)) {
+                    db_size++;
+                    continue;
+                }
+
+                if (p_char->descriptors && (type == BTGATT_DB_DESCRIPTOR) && bta_gattc_uuid_compare(&p_char->uuid, char_uuid, TRUE)) {
+                    for (list_node_t *dn = list_begin(p_char->descriptors);
+                         dn != list_end(p_char->descriptors); dn = list_next(dn)) {
+                        tBTA_GATTC_DESCRIPTOR *p_desc = list_node(dn);
+
+                        if (p_desc->handle < start_handle) {
+                            continue;
+                        }
+
+                        if (p_desc->handle > end_handle) {
+                            return db_size;
                         }
-                    } else
-                        /* is a characterisitc value or included service */
-                    {
-                        bta_gattc_pack_attr_uuid(p_attr, &p_char_id->uuid);
-                        p_char_id->inst_id = p_attr->inst_id;
+                        db_size++;
+                    }
+                }
+            }
+        } else {
+            if (type == BTGATT_DB_CHARACTERISTIC) {
+                for (list_node_t *cn = list_begin(p_cur_srvc->characteristics);
+                     cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
+                    tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
+
+                    if (p_char->handle < start_handle) {
+                        continue;
+                    }
+
+                    if (p_char->handle > end_handle) {
+                        return db_size;
                     }
-                    return TRUE;
+                    db_size++;
                 }
-                p_attr = p_attr->p_next;
             }
         }
-        p_cache = p_cache->p_next;
+
     }
 
-    return FALSE;
+    return db_size;
 }
 
 /*******************************************************************************
-**
-** Function         bta_gattc_search_service
-**
-** Description      search local cache for matching service record.
-**
-** Returns          FALSE if map can not be found.
-**
+** Returns          number of elements inside db from start_handle to end_handle
 *******************************************************************************/
-void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid)
+static size_t bta_gattc_get_db_size(list_t *services,
+                                    UINT16 start_handle, UINT16 end_handle) 
 {
-    tBTA_GATTC_SERV     *p_srcb = p_clcb->p_srcb;
-    tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
-    tBTA_GATTC          cb_data;
+    if (!services || list_is_empty(services))
+        return 0;
 
-    while (p_cache) {
-        if (bta_gattc_uuid_compare(p_uuid, &p_cache->service_uuid.id.uuid, FALSE)) {
-#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-            APPL_TRACE_DEBUG("found service [0x%04x], inst[%d] handle [%d]",
-                             p_cache->service_uuid.id.uuid.uu.uuid16,
-                             p_cache->service_uuid.id.inst_id,
-                             p_cache->s_handle);
-#endif
-            if (p_clcb->p_rcb->p_cback) {
-                memset(&cb_data, 0, sizeof(tBTA_GATTC));
+    size_t db_size = 0;
+    UINT16 svc_length = list_length(services) - 1;
+    for (list_node_t *sn = list_begin(services);
+         sn != list_end(services); sn = list_next(sn), svc_length--) {
+        tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn);
+
+        if (p_cur_srvc->e_handle < start_handle) {
+            continue;
+        }
+
+        if (p_cur_srvc->s_handle > end_handle) {
+            break;
+        }
+
+        if (!svc_length) {
+            if (p_cur_srvc->s_handle >= start_handle) {
+                db_size++;
+            }
+        } else {
+            db_size++;
+        }
+        
+        if (!p_cur_srvc->characteristics || list_is_empty(p_cur_srvc->characteristics))
+            continue;
+
+        for (list_node_t *cn = list_begin(p_cur_srvc->characteristics);
+             cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
+            tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
+
+            if (p_char->handle < start_handle) {
+                continue;
+            }
+            if (p_char->handle > end_handle) {
+                return db_size;
+            }
+            db_size++;
+
+            if (p_char->descriptors) {
+                for (list_node_t *dn = list_begin(p_char->descriptors);
+                     dn != list_end(p_char->descriptors); dn = list_next(dn)) {
+                    tBTA_GATTC_DESCRIPTOR *p_desc = list_node(dn);
+                    if (p_desc->handle < start_handle) {
+                        continue;
+                    }
+                    if (p_desc->handle > end_handle) {
+                        return db_size;
+                    }
+                    db_size++;
+                }
+            }
+        }
 
-                cb_data.srvc_res.conn_id = p_clcb->bta_conn_id;
-                memcpy(&cb_data.srvc_res.service_uuid, &p_cache->service_uuid,
-                       sizeof(tBTA_GATT_SRVC_ID));
+        if (p_cur_srvc->included_svc) {
+            for (list_node_t *isn = list_begin(p_cur_srvc->included_svc);
+                 isn != list_end(p_cur_srvc->included_svc); isn = list_next(isn)) {
+                tBTA_GATTC_INCLUDED_SVC *p_isvc = list_node(isn);
+
+                if (p_isvc->handle < start_handle) {
+                    continue;
+                }
 
-                (* p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data);
+                if (p_isvc->handle > end_handle) {
+                    return db_size;
+                }
+                db_size++;
             }
         }
-        p_cache = p_cache->p_next;
     }
+
+    return db_size;
+}
+
+void bta_gattc_get_db_size_handle(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle, int *count)
+{
+    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+
+    if (p_clcb == NULL) {
+        return NULL;
+    }
+    
+    tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
+    if (!p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache)) {
+        *count = 0;
+        return;
+    }
+
+    *count = bta_gattc_get_db_size(p_srcb->p_srvc_cache, start_handle, end_handle);
+}
+
+void bta_gattc_get_db_size_with_type_handle(UINT16 conn_id, bt_gatt_db_attribute_type_t type,
+                                            UINT16 start_handle, UINT16 end_handle, UINT16 char_handle, int *count)
+{
+    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+
+    if (p_clcb == NULL) {
+        return NULL;
+    }
+    
+    tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
+    if (!p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache)) {
+        *count = 0;
+        return;
+    }
+
+    if (type == BTGATT_DB_DESCRIPTOR) {
+        if (char_handle == BTA_GATTC_INVALID_HANDLE) {
+            *count = 0;
+            return;
+        } else {
+            tBTA_GATTC_CHARACTERISTIC *char_db = bta_gattc_get_characteristic(conn_id, char_handle);
+            *count = char_db ? list_length(char_db->descriptors) : 0;
+            return;
+        }
+    }
+    *count = bta_gattc_get_db_size_with_type(p_srcb->p_srvc_cache, type, NULL, start_handle, end_handle);
+    
 }
+
 /*******************************************************************************
 **
-** Function         bta_gattc_find_record
+** Function         bta_gattc_get_gatt_db_impl
 **
-** Description      search local cache for matching attribute record.
+** Description      copy the server GATT database into db parameter.
 **
-** Parameter        p_result: output parameter to store the characteristic/
-**                            included service GATT ID.
+** Parameters       p_srvc_cb: server.
+**                  db: output parameter which will contain GATT database copy.
+**                      Caller is responsible for freeing it.
+**                  count: output parameter which will contain number of
+**                  elements in database.
 **
-** Returns          GATT_ERROR is no recording found. BTA_GATT_OK if record found.
+** Returns          None.
 **
 *******************************************************************************/
-static tBTA_GATT_STATUS bta_gattc_find_record(tBTA_GATTC_SERV *p_srcb,
-        tBTA_GATTC_ATTR_TYPE attr_type,
-        tBTA_GATT_SRVC_ID *p_service_id,
-        tBTA_GATT_ID  *p_start_rec,
-        tBT_UUID       *p_uuid_cond,
-        tBTA_GATT_ID  *p_result,
-        void *p_param)
+static void bta_gattc_get_gatt_db_impl(tBTA_GATTC_SERV *p_srvc_cb,
+                                       UINT16 start_handle, UINT16 end_handle,
+                                       btgatt_db_element_t **db,
+                                       int *count)
 {
-    tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
-    tBTA_GATT_STATUS    status = BTA_GATT_ERROR;
-    UINT8               i, j;
-    tBTA_GATTC_CACHE_ATTR   *p_attr;
-    BOOLEAN             char_found = FALSE, descr_found = FALSE;
-    tBTA_GATT_ID        *p_descr_id = (tBTA_GATT_ID *)p_param;;
-
-    for (i = 0; p_cache && status != BTA_GATT_OK; i ++) {
-        if (bta_gattc_srvcid_compare(p_service_id, &p_cache->service_uuid)) {
-#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-            APPL_TRACE_DEBUG("found matching service [0x%04x], inst[%d]",
-                             p_cache->service_uuid.id.uuid.uu.uuid16,
-                             p_cache->service_uuid.id.inst_id);
-#endif
-            p_attr = p_cache->p_attr;
+    APPL_TRACE_DEBUG("%s: start_handle 0x%04x, end_handle 0x%04x",
+                     __func__, start_handle, end_handle);
 
-            for (j = 0; p_attr; j ++) {
-#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-                APPL_TRACE_DEBUG("\t Attr[%d] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
-                                 j + 1, p_attr->attr_handle,
-                                 p_attr->p_uuid->uuid16,
-                                 p_attr->inst_id,
-                                 p_attr->attr_type);
-#endif
-                bta_gattc_pack_attr_uuid(p_attr, &p_result->uuid);
-
-                if (p_start_rec != NULL && char_found == FALSE) {
-                    /* find the starting record first */
-                    if (bta_gattc_uuid_compare(&p_start_rec->uuid, &p_result->uuid, FALSE) &&
-                            p_start_rec->inst_id  == p_attr->inst_id &&
-                            (attr_type == p_attr->attr_type ||
-                             /* find descriptor would look for characteristic first */
-                             (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR &&
-                              p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR))) {
-                        char_found = TRUE;
-                    }
-                } else {
-                    /* if looking for descriptor, here is the where the descrptor to be found */
-                    if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) {
-                        /* next characeteristic already, return error */
-                        if (p_attr->attr_type != BTA_GATTC_ATTR_TYPE_CHAR_DESCR) {
-                            break;
-                        } else {
-                            /* find starting descriptor */
-                            if (p_descr_id != NULL && !descr_found) {
-                                if (bta_gattc_uuid_compare(&p_descr_id->uuid, &p_result->uuid, TRUE)
-                                        && p_descr_id->inst_id == p_attr->inst_id) {
-                                    descr_found = TRUE;
-                                }
-                            } else {
-                                /* with matching descriptor */
-                                if (bta_gattc_uuid_compare(p_uuid_cond, &p_result->uuid, FALSE)) {
-                                    p_result->inst_id = p_attr->inst_id;
-                                    status = BTA_GATT_OK;
-                                    break;
-                                }
-                            }
-                        }
-                    } else {
-                        if (bta_gattc_uuid_compare(p_uuid_cond, &p_result->uuid, FALSE) &&
-                                attr_type == p_attr->attr_type) {
+    if (!p_srvc_cb->p_srvc_cache || list_is_empty(p_srvc_cb->p_srvc_cache)) {
+        *count = 0;
+        *db = NULL;
+        return;
+    }
 
-#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-                            APPL_TRACE_DEBUG("found char handle mapping characteristic");
-#endif
-                            p_result->inst_id = p_attr->inst_id;
+    size_t db_size = bta_gattc_get_db_size(p_srvc_cb->p_srvc_cache, start_handle, end_handle);
 
-                            if (p_param != NULL) {
-                                if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR ||
-                                        attr_type == BTA_GATTC_ATTR_TYPE_INCL_SRVC) {
-                                    *(tBTA_GATT_CHAR_PROP *)p_param = p_attr->property;
-                                }
-                            }
+    void* buffer = osi_malloc(db_size * sizeof(btgatt_db_element_t));
+    if (!buffer) {
+        APPL_TRACE_WARNING("%s(), no resource.", __func__);
+        *db = NULL;
+        *count = 0;
+        return;
+    }
+    btgatt_db_element_t *curr_db_attr = buffer;
 
-                            status = BTA_GATT_OK;
-                            break;
-                        }
+    for (list_node_t *sn = list_begin(p_srvc_cb->p_srvc_cache);
+         sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
+        tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn);
+
+        if (p_cur_srvc->e_handle < start_handle) {
+            continue;
+        }
+
+        if (p_cur_srvc->s_handle > end_handle) {
+            break;
+        }
+
+        bta_gattc_fill_gatt_db_el(curr_db_attr,
+                                  p_cur_srvc->is_primary ?
+                                  BTGATT_DB_PRIMARY_SERVICE :
+                                  BTGATT_DB_SECONDARY_SERVICE,
+                                  0 /* att_handle */,
+                                  p_cur_srvc->s_handle,
+                                  p_cur_srvc->e_handle,
+                                  p_cur_srvc->s_handle,
+                                  p_cur_srvc->uuid,
+                                  0 /* prop */);
+        curr_db_attr++;
+
+        if (p_cur_srvc->characteristics && !list_is_empty(p_cur_srvc->characteristics)) {
+
+            for (list_node_t *cn = list_begin(p_cur_srvc->characteristics);
+                 cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
+                tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
+
+                if (p_char->handle < start_handle) {
+                    continue;
+                }
+
+                if (p_char->handle > end_handle) {
+                    *db = buffer;
+                    *count = db_size;
+                    return;
+                }
+                bta_gattc_fill_gatt_db_el(curr_db_attr,
+                                          BTGATT_DB_CHARACTERISTIC,
+                                          p_char->handle,
+                                          0 /* s_handle */,
+                                          0 /* e_handle */,
+                                          p_char->handle,
+                                          p_char->uuid,
+                                          p_char->properties);
+                curr_db_attr++;
+
+                if (!p_char->descriptors || list_is_empty(p_char->descriptors))
+                    continue;
+
+                for (list_node_t *dn = list_begin(p_char->descriptors);
+                     dn != list_end(p_char->descriptors); dn = list_next(dn)) {
+                    tBTA_GATTC_DESCRIPTOR *p_desc = list_node(dn);
+
+                    if (p_desc->handle < start_handle) {
+                        continue;
+                    }
+
+                    if (p_desc->handle > end_handle) {
+                        *db = buffer;
+                        *count = db_size;
+                        return;
                     }
+                    bta_gattc_fill_gatt_db_el(curr_db_attr,
+                                              BTGATT_DB_DESCRIPTOR,
+                                              p_desc->handle,
+                                              0 /* s_handle */,
+                                              0 /* e_handle */,
+                                              p_desc->handle,
+                                              p_desc->uuid,
+                                              0 /* property */);
+                    curr_db_attr++;
                 }
-                p_attr = p_attr->p_next;
-            }
-#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-            if (status) {
-                APPL_TRACE_ERROR("In the given service, can not find matching record");
             }
-#endif
-            break;
         }
 
-        p_cache = p_cache->p_next;
+        if (!p_cur_srvc->included_svc || list_is_empty(p_cur_srvc->included_svc))
+            continue;
+
+        for (list_node_t *isn = list_begin(p_cur_srvc->included_svc);
+             isn != list_end(p_cur_srvc->included_svc); isn = list_next(isn)) {
+            tBTA_GATTC_INCLUDED_SVC *p_isvc = list_node(isn);
+
+            if (p_isvc->handle < start_handle) {
+                continue;
+            }
+
+            if (p_isvc->handle > end_handle) {
+                *db = buffer;
+                *count = db_size;
+                return;
+            }
+            bta_gattc_fill_gatt_db_el(curr_db_attr,
+                                      BTGATT_DB_INCLUDED_SERVICE,
+                                      p_isvc->handle,
+                                      0 /* s_handle */,
+                                      0 /* e_handle */,
+                                      p_isvc->handle,
+                                      p_isvc->uuid,
+                                      0 /* property */);
+            curr_db_attr++;
+        }
     }
-    return status;
 
+    *db = buffer;
+    *count = db_size;
 }
 
 /*******************************************************************************
 **
-** Function         bta_gattc_query_cache
+** Function         bta_gattc_get_gatt_db
 **
-** Description      search local cache for matching attribute record.
+** Description      copy the server GATT database into db parameter.
 **
 ** Parameters       conn_id: connection ID which identify the server.
-**                  p_srvc_id: the service ID of which the characteristic is belonged to.
-**                  *p_start_rec: start the search from the next record
-**                                  after the one identified by *p_start_rec.
-**                  p_uuid_cond: UUID, if NULL find the first available
-**                               characteristic/included service.
-**                  p_output:   output parameter which will store the GATT ID
-**                              of the characteristic /included service found.
+**                  db: output parameter which will contain GATT database copy.
+**                      Caller is responsible for freeing it.
+**                  count: number of elements in database.
 **
-** Returns          BTA_GATT_ERROR is no recording found. BTA_GATT_OK if record found.
+** Returns          None.
 **
 *******************************************************************************/
-tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id,
-                                       tBTA_GATTC_ATTR_TYPE query_type,
-                                       tBTA_GATT_SRVC_ID *p_srvc_id,
-                                       tBTA_GATT_ID *p_start_rec,
-                                       tBT_UUID *p_uuid_cond,
-                                       tBTA_GATT_ID *p_output,
-                                       void *p_param)
+void bta_gattc_get_gatt_db(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle, btgatt_db_element_t **db, int *count)
 {
     tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
-    tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER;
-
-    if (p_clcb != NULL ) {
-        if (p_clcb->state == BTA_GATTC_CONN_ST) {
-            if (p_clcb->p_srcb &&
-                    !p_clcb->p_srcb->p_srvc_list && /* no active discovery */
-                    p_clcb->p_srcb->p_srvc_cache) {
-                status = bta_gattc_find_record(p_clcb->p_srcb,
-                                               query_type,
-                                               p_srvc_id,
-                                               p_start_rec,
-                                               p_uuid_cond,
-                                               p_output,
-                                               p_param);
-            } else {
-                status = BTA_GATT_ERROR;
-                APPL_TRACE_ERROR("No server cache available");
-            }
-        } else {
-            APPL_TRACE_ERROR("server cache not available, CLCB state = %d", p_clcb->state);
 
-            status = (p_clcb->state == BTA_GATTC_DISCOVER_ST) ? BTA_GATT_BUSY : BTA_GATT_ERROR;
-        }
-    } else {
+    if (p_clcb == NULL) {
         APPL_TRACE_ERROR("Unknown conn ID: %d", conn_id);
+        return;
     }
 
-    return status;
+    if (p_clcb->state != BTA_GATTC_CONN_ST) {
+        APPL_TRACE_ERROR("server cache not available, CLCB state = %d",
+                         p_clcb->state);
+        return;
+    }
+
+    if (!p_clcb->p_srcb || p_clcb->p_srcb->p_srvc_list || /* no active discovery */
+        !p_clcb->p_srcb->p_srvc_cache) {
+        APPL_TRACE_ERROR("No server cache available");
+        return;
+    }
+
+    bta_gattc_get_gatt_db_impl(p_clcb->p_srcb, start_handle, end_handle, db, count);
 }
 
 /*******************************************************************************
@@ -1392,42 +1810,42 @@ tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id,
 **
 *******************************************************************************/
 void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr,
-                             tBTA_GATTC_NV_ATTR *p_attr, UINT16 attr_index)
+                             tBTA_GATTC_NV_ATTR *p_attr)
 {
     /* first attribute loading, initialize buffer */
-    APPL_TRACE_ERROR("bta_gattc_rebuild_cache");
-    if (attr_index == 0) {
-        while (!fixed_queue_is_empty(p_srvc_cb->cache_buffer)) {
-            osi_free(fixed_queue_dequeue(p_srvc_cb->cache_buffer));
-        }
+    APPL_TRACE_ERROR("%s: bta_gattc_rebuild_cache", __func__);
 
-        if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL) {
-            APPL_TRACE_ERROR("allocate cache buffer failed, no resources");
-        } else {
-            p_srvc_cb->p_cur_srvc = p_srvc_cb->p_srvc_cache = NULL;
-        }
-    }
+    list_free(p_srvc_cb->p_srvc_cache);
+    p_srvc_cb->p_srvc_cache = NULL;
 
     while (num_attr > 0 && p_attr != NULL) {
         switch (p_attr->attr_type) {
         case BTA_GATTC_ATTR_TYPE_SRVC:
-            bta_gattc_add_srvc_to_cache(p_srvc_cb,
-                                        p_attr->s_handle,
-                                        p_attr->e_handle,
-                                        &p_attr->uuid,
-                                        p_attr->is_primary,
-                                        p_attr->id);
-            break;
+                bta_gattc_add_srvc_to_cache(p_srvc_cb,
+                                            p_attr->s_handle,
+                                            p_attr->e_handle,
+                                            &p_attr->uuid,
+                                            p_attr->is_primary);
+                break;
 
-        case BTA_GATTC_ATTR_TYPE_CHAR:
-        case BTA_GATTC_ATTR_TYPE_CHAR_DESCR:
-        case BTA_GATTC_ATTR_TYPE_INCL_SRVC:
-            bta_gattc_add_attr_to_cache(p_srvc_cb,
-                                        p_attr->s_handle,
-                                        &p_attr->uuid,
-                                        p_attr->prop,
-                                        p_attr->attr_type);
-            break;
+            case BTA_GATTC_ATTR_TYPE_CHAR:
+                //TODO(jpawlowski): store decl_handle properly.
+                bta_gattc_add_char_to_cache(p_srvc_cb,
+                                            p_attr->s_handle,
+                                            p_attr->s_handle,
+                                            &p_attr->uuid,
+                                            p_attr->prop);
+                break;
+
+            case BTA_GATTC_ATTR_TYPE_CHAR_DESCR:
+            case BTA_GATTC_ATTR_TYPE_INCL_SRVC:
+                bta_gattc_add_attr_to_cache(p_srvc_cb,
+                                            p_attr->s_handle,
+                                            &p_attr->uuid,
+                                            p_attr->prop,
+                                            p_attr->incl_srvc_handle,
+                                            p_attr->attr_type);
+                break;
         }
         p_attr ++;
         num_attr --;
@@ -1444,15 +1862,16 @@ void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr,
 **
 *******************************************************************************/
 void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR *p_attr, UINT8 type, UINT16 s_handle,
-                            UINT16 e_handle, UINT8 id, tBT_UUID uuid, UINT8 prop,
+                            UINT16 e_handle, tBT_UUID uuid, UINT8 prop, UINT16 incl_srvc_handle,
                             BOOLEAN is_primary)
 {
     p_attr->s_handle    = s_handle;
     p_attr->e_handle    = e_handle;
     p_attr->attr_type   = type;
     p_attr->is_primary  = is_primary;
-    p_attr->id          = id;
+    p_attr->id          = 0;
     p_attr->prop        = prop;
+    p_attr->incl_srvc_handle = incl_srvc_handle;
 
     memcpy(&p_attr->uuid, &uuid, sizeof(tBT_UUID));
 }
@@ -1465,60 +1884,221 @@ void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR *p_attr, UINT8 type, UINT16 s_han
 ** Returns          None.
 **
 *******************************************************************************/
-BOOLEAN bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id)
+void bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id)
 {
-    tBTA_GATTC_CACHE        *p_cur_srvc = p_srvc_cb->p_srvc_cache;
-    UINT8                   i = 0;
-    UINT16                  offset = 0;
-    tBTA_GATTC_NV_ATTR      nv_attr[BTA_GATTC_NV_LOAD_MAX];
-    tBTA_GATTC_CACHE_ATTR   *p_attr;
-    tBT_UUID                uuid;
-
-    while (p_cur_srvc && i < BTA_GATTC_NV_LOAD_MAX) {
-        if (offset ++ >= p_srvc_cb->attr_index) {
+    if (!p_srvc_cb->p_srvc_cache || list_is_empty(p_srvc_cb->p_srvc_cache))
+        return;
+
+    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));
+    if (!nv_attr) {
+        APPL_TRACE_WARNING("%s(), no resource.", __func__);
+        return;
+    }
+    for (list_node_t *sn = list_begin(p_srvc_cb->p_srvc_cache);
+         sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
+        tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn);
+
+        bta_gattc_fill_nv_attr(&nv_attr[i++],
+                                BTA_GATTC_ATTR_TYPE_SRVC,
+                               p_cur_srvc->s_handle,
+                               p_cur_srvc->e_handle,
+                               p_cur_srvc->uuid,
+                               0 /* properties */,
+                               0 /* incl_srvc_handle */,
+                               p_cur_srvc->is_primary);
+    }
+
+    for (list_node_t *sn = list_begin(p_srvc_cb->p_srvc_cache);
+         sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
+        tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn);
+
+        if (!p_cur_srvc->characteristics || list_is_empty(p_cur_srvc->characteristics))
+            continue;
+
+        for (list_node_t *cn = list_begin(p_cur_srvc->characteristics);
+             cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
+            tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
+
             bta_gattc_fill_nv_attr(&nv_attr[i++],
-                                   BTA_GATTC_ATTR_TYPE_SRVC,
-                                   p_cur_srvc->s_handle,
-                                   p_cur_srvc->e_handle,
-                                   p_cur_srvc->service_uuid.id.inst_id,
-                                   p_cur_srvc->service_uuid.id.uuid,
+                                   BTA_GATTC_ATTR_TYPE_CHAR,
+                                   p_char->handle,
                                    0,
-                                   p_cur_srvc->service_uuid.is_primary);
-        }
+                                   p_char->uuid,
+                                   p_char->properties,
+                                   0 /* incl_srvc_handle */,
+                                   FALSE);
 
-        p_attr = p_cur_srvc->p_attr;
+            if (!p_char->descriptors || list_is_empty(p_char->descriptors))
+                continue;
 
-        for (; p_attr && i < BTA_GATTC_NV_LOAD_MAX ; offset ++, p_attr = p_attr->p_next) {
-            if (offset >= p_srvc_cb->attr_index) {
-                if ((uuid.len = p_attr->uuid_len) == LEN_UUID_16) {
-                    uuid.uu.uuid16 = p_attr->p_uuid->uuid16;
-                } else {
-                    memcpy(uuid.uu.uuid128, p_attr->p_uuid->uuid128, LEN_UUID_128);
-                }
+            for (list_node_t *dn = list_begin(p_char->descriptors);
+                 dn != list_end(p_char->descriptors); dn = list_next(dn)) {
+                tBTA_GATTC_DESCRIPTOR *p_desc = list_node(dn);
 
                 bta_gattc_fill_nv_attr(&nv_attr[i++],
-                                       p_attr->attr_type,
-                                       p_attr->attr_handle,
+                                       BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
+                                       p_desc->handle,
                                        0,
-                                       p_attr->inst_id,
-                                       uuid,
-                                       p_attr->property,
+                                       p_desc->uuid,
+                                       0 /* properties */,
+                                       0 /* incl_srvc_handle */,
                                        FALSE);
             }
         }
-        p_cur_srvc = p_cur_srvc->p_next;
+
+        if (!p_cur_srvc->included_svc || list_is_empty(p_cur_srvc->included_svc))
+            continue;
+
+        for (list_node_t *an = list_begin(p_cur_srvc->included_svc);
+             an != list_end(p_cur_srvc->included_svc); an = list_next(an)) {
+            tBTA_GATTC_INCLUDED_SVC *p_isvc = list_node(an);
+
+            bta_gattc_fill_nv_attr(&nv_attr[i++],
+                                   BTA_GATTC_ATTR_TYPE_INCL_SRVC,
+                                   p_isvc->handle,
+                                   0,
+                                   p_isvc->uuid,
+                                   0 /* properties */,
+                                   p_isvc->included_service->s_handle,
+                                   FALSE);
+        }
+    }
+
+    bta_gattc_cache_write(p_srvc_cb->server_bda, db_size, nv_attr);
+    osi_free(nv_attr);
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_cache_load
+**
+** Description      Load GATT cache from storage for server.
+**
+** Parameter        p_clcb: pointer to server clcb, that will
+**                          be filled from storage
+** Returns          true on success, false otherwise
+**
+*******************************************************************************/
+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);
+
+    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));
+        return false;
     }
 
-    if (i > 0) {
-        bta_gattc_co_cache_save(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_SAVE_EVT, i,
-                                nv_attr, p_srvc_cb->attr_index, conn_id);
+    UINT16 cache_ver = 0;
+    tBTA_GATTC_NV_ATTR  *attr = NULL;
+    bool success = false;
 
-        p_srvc_cb->attr_index += i;
+    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;
+    }
 
-        return TRUE;
-    } else {
-        return FALSE;
+    if (cache_ver != GATT_CACHE_VERSION) {
+        APPL_TRACE_ERROR("%s: wrong GATT cache version: %s", __func__, fname);
+        goto done;
+    }
+
+    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;
+    }
+
+    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;
     }
+
+    bta_gattc_rebuild_cache(p_clcb->p_srcb, num_attr, attr);
+
+    success = true;
+
+done:
+    osi_free(attr);
+    fclose(fd);
+    return success;
+#endif
+    bool success = false;
+    return success;
+}
+
+/*******************************************************************************
+**
+** 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)
+{
+    char fname[255] = {0};
+    bta_gattc_generate_cache_file_name(fname, server_bda);
+    FILE *fd = fopen(fname, "wb");
+    if (!fd) {
+        APPL_TRACE_ERROR("%s: can't open GATT cache file for writing: %s", __func__, fname);
+        return;
+    }
+
+    UINT16 cache_ver = GATT_CACHE_VERSION;
+    if (fwrite(&cache_ver, sizeof(UINT16), 1, fd) != 1) {
+        APPL_TRACE_DEBUG("%s: can't write GATT cache version: %s", __func__, fname);
+        fclose(fd);
+        return;
+    }
+
+    if (fwrite(&num_attr, sizeof(UINT16), 1, fd) != 1) {
+        APPL_TRACE_DEBUG("%s: can't write GATT cache attribute count: %s", __func__, fname);
+        fclose(fd);
+        return;
+    }
+
+    if (fwrite(attr, sizeof(tBTA_GATTC_NV_ATTR), num_attr, fd) != num_attr) {
+        APPL_TRACE_DEBUG("%s: can't write GATT cache attributes: %s", __func__, fname);
+        fclose(fd);
+        return;
+    }
+
+    fclose(fd);
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_cache_reset
+**
+** Description      This callout function is executed by GATTC to reset cache in
+**                  application
+**
+** Parameter        server_bda: server bd address of this cache belongs to
+**
+** Returns          void.
+**
+*******************************************************************************/
+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);
+    //unlink(fname);
 }
-#endif /* GATTC_INCLUDED */
+#endif /* BTA_GATT_INCLUDED */
 
index 995d74cfd7c090286eac8bb896decbef6cbd3480..f7ae3101be5fcf2356c942b156e879046544e41a 100644 (file)
@@ -60,10 +60,6 @@ enum {
     BTA_GATTC_CONFIRM,
     BTA_GATTC_EXEC,
     BTA_GATTC_READ_MULTI,
-    BTA_GATTC_CI_OPEN,
-    BTA_GATTC_CI_LOAD,
-    BTA_GATTC_CI_SAVE,
-    BTA_GATTC_CACHE_OPEN,
     BTA_GATTC_IGNORE_OP_CMPL,
     BTA_GATTC_DISC_CLOSE,
     BTA_GATTC_RESTART_DISCOVER,
@@ -98,10 +94,6 @@ const tBTA_GATTC_ACTION bta_gattc_action[] = {
     bta_gattc_confirm,
     bta_gattc_execute,
     bta_gattc_read_multi,
-    bta_gattc_ci_open,
-    bta_gattc_ci_load,
-    bta_gattc_ci_save,
-    bta_gattc_cache_open,
     bta_gattc_ignore_op_cmpl,
     bta_gattc_disc_close,
     bta_gattc_restart_discover,
@@ -140,12 +132,6 @@ static const UINT8 bta_gattc_st_idle[][BTA_GATTC_NUM_COLS] = {
     /* BTA_GATTC_OP_CMPL_EVT            */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
     /* BTA_GATTC_INT_DISCONN_EVT       */    {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
 
-
-    /* ===> for cache loading, saving   */
-    /* BTA_GATTC_START_CACHE_EVT        */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
-    /* BTA_GATTC_CI_CACHE_OPEN_EVT      */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
-    /* BTA_GATTC_CI_CACHE_LOAD_EVT      */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
-    /* BTA_GATTC_CI_CACHE_SAVE_EVT      */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST}
 };
 
 /* state table for wait for open state */
@@ -174,11 +160,6 @@ static const UINT8 bta_gattc_st_w4_conn[][BTA_GATTC_NUM_COLS] = {
     /* BTA_GATTC_OP_CMPL_EVT            */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
     /* BTA_GATTC_INT_DISCONN_EVT      */     {BTA_GATTC_OPEN_FAIL,          BTA_GATTC_IDLE_ST},
 
-    /* ===> for cache loading, saving   */
-    /* BTA_GATTC_START_CACHE_EVT        */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
-    /* BTA_GATTC_CI_CACHE_OPEN_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
-    /* BTA_GATTC_CI_CACHE_LOAD_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
-    /* BTA_GATTC_CI_CACHE_SAVE_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST}
 };
 
 /* state table for open state */
@@ -208,11 +189,6 @@ static const UINT8 bta_gattc_st_connected[][BTA_GATTC_NUM_COLS] = {
 
     /* BTA_GATTC_INT_DISCONN_EVT        */   {BTA_GATTC_CLOSE,              BTA_GATTC_IDLE_ST},
 
-    /* ===> for cache loading, saving   */
-    /* BTA_GATTC_START_CACHE_EVT        */   {BTA_GATTC_CACHE_OPEN,         BTA_GATTC_DISCOVER_ST},
-    /* BTA_GATTC_CI_CACHE_OPEN_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_CONN_ST},
-    /* BTA_GATTC_CI_CACHE_LOAD_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_CONN_ST},
-    /* BTA_GATTC_CI_CACHE_SAVE_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_CONN_ST}
 };
 
 /* state table for discover state */
@@ -241,11 +217,6 @@ static const UINT8 bta_gattc_st_discover[][BTA_GATTC_NUM_COLS] = {
     /* BTA_GATTC_OP_CMPL_EVT            */   {BTA_GATTC_IGNORE_OP_CMPL,     BTA_GATTC_DISCOVER_ST},
     /* BTA_GATTC_INT_DISCONN_EVT        */   {BTA_GATTC_CLOSE,              BTA_GATTC_IDLE_ST},
 
-    /* ===> for cache loading, saving       */
-    /* BTA_GATTC_START_CACHE_EVT        */   {BTA_GATTC_IGNORE,             BTA_GATTC_DISCOVER_ST},
-    /* BTA_GATTC_CI_CACHE_OPEN_EVT      */   {BTA_GATTC_CI_OPEN,            BTA_GATTC_DISCOVER_ST},
-    /* BTA_GATTC_CI_CACHE_LOAD_EVT      */   {BTA_GATTC_CI_LOAD,            BTA_GATTC_DISCOVER_ST},
-    /* BTA_GATTC_CI_CACHE_SAVE_EVT      */   {BTA_GATTC_CI_SAVE,            BTA_GATTC_DISCOVER_ST}
 };
 
 /* type for state table */
@@ -477,14 +448,6 @@ static char *gattc_evt_code(tBTA_GATTC_INT_EVT evt_code)
         return "BTA_GATTC_OP_CMPL_EVT";
     case BTA_GATTC_INT_DISCONN_EVT:
         return "BTA_GATTC_INT_DISCONN_EVT";
-    case BTA_GATTC_START_CACHE_EVT:
-        return "BTA_GATTC_START_CACHE_EVT";
-    case BTA_GATTC_CI_CACHE_OPEN_EVT:
-        return "BTA_GATTC_CI_CACHE_OPEN_EVT";
-    case BTA_GATTC_CI_CACHE_LOAD_EVT:
-        return "BTA_GATTC_CI_CACHE_LOAD_EVT";
-    case BTA_GATTC_CI_CACHE_SAVE_EVT:
-        return "BTA_GATTC_CI_CACHE_SAVE_EVT";
     case BTA_GATTC_INT_START_IF_EVT:
         return "BTA_GATTC_INT_START_IF_EVT";
     case BTA_GATTC_API_REG_EVT:
index 30a0b395ae71b6f79af9478074c126153bfe41a8..dfa685f67dba4858538e967f93757ebe84dc738d 100644 (file)
@@ -74,10 +74,10 @@ void bta_gatt_convert_uuid16_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UINT16 uui
 ** Returns          TRUE if two uuid match; FALSE otherwise.
 **
 *******************************************************************************/
-BOOLEAN bta_gattc_uuid_compare (tBT_UUID *p_src, tBT_UUID *p_tar, BOOLEAN is_precise)
+BOOLEAN bta_gattc_uuid_compare (const tBT_UUID *p_src, const tBT_UUID *p_tar, BOOLEAN is_precise)
 {
     UINT8  su[LEN_UUID_128], tu[LEN_UUID_128];
-    UINT8  *ps, *pt;
+    const UINT8  *ps, *pt;
 
     /* any of the UUID is unspecified */
     if (p_src == 0 || p_tar == 0) {
@@ -296,10 +296,16 @@ void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb)
             p_srcb->connected = FALSE;
             p_srcb->state = BTA_GATTC_SERV_IDLE;
             p_srcb->mtu = 0;
-        }
-
-        utl_freebuf((void **)&p_clcb->p_q_cmd);
 
+            /* clean up cache */
+            if (p_srcb->p_srvc_cache) {
+                list_free(p_srcb->p_srvc_cache);
+                p_srcb->p_srvc_cache = NULL;
+            }
+        }
+        osi_free(p_clcb->p_q_cmd);
+        p_clcb->p_q_cmd = NULL;
+        //osi_free_and_reset((void **)&p_clcb->p_q_cmd);
         memset(p_clcb, 0, sizeof(tBTA_GATTC_CLCB));
     } else {
         APPL_TRACE_ERROR("bta_gattc_clcb_dealloc p_clcb=NULL");
@@ -396,25 +402,22 @@ tBTA_GATTC_SERV *bta_gattc_srcb_alloc(BD_ADDR bda)
     /* if not found, try to recycle one known device */
     if (!found && !p_recycle) {
         p_tcb = NULL;
-    } else if (!found && p_recycle) {
+       }
+    else if (!found && p_recycle) {
         p_tcb = p_recycle;
-    }
-
-    if (p_tcb != NULL) {
-        if (p_tcb->cache_buffer) {
-            while (!fixed_queue_is_empty(p_tcb->cache_buffer)) {
-                osi_free(fixed_queue_dequeue(p_tcb->cache_buffer));
-            }
-            fixed_queue_free(p_tcb->cache_buffer, NULL);
-        }
-
-        utl_freebuf((void **)&p_tcb->p_srvc_list);
+       }
+
+    if (p_tcb != NULL)
+    {
+        if (p_tcb->p_srvc_cache != NULL)
+            list_free(p_tcb->p_srvc_cache);
+        osi_free(p_tcb->p_srvc_list);
+        p_tcb->p_srvc_list = NULL;
+        //osi_free_and_reset((void **)&p_tcb->p_srvc_list);
         memset(p_tcb, 0 , sizeof(tBTA_GATTC_SERV));
 
         p_tcb->in_use = TRUE;
         bdcpy(p_tcb->server_bda, bda);
-
-        p_tcb->cache_buffer = fixed_queue_new(SIZE_MAX); //by Snake
     }
     return p_tcb;
 }
@@ -430,118 +433,15 @@ tBTA_GATTC_SERV *bta_gattc_srcb_alloc(BD_ADDR bda)
 BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
 {
 
-    if (p_clcb->p_q_cmd == NULL) {
+    if (p_clcb->p_q_cmd == NULL)
+    {
         p_clcb->p_q_cmd = p_data;
-    } else {
-        APPL_TRACE_ERROR("already has a pending command!!");
-        /* skip the callback now. ----- need to send callback ? */
-    }
-    return (p_clcb->p_q_cmd != NULL) ? TRUE : FALSE;
-
-}
-
-/*******************************************************************************
-**
-** Function         bta_gattc_pack_attr_uuid
-**
-** Description      pack UUID into a stream.
-**
-** Returns
-**
-*******************************************************************************/
-void bta_gattc_pack_attr_uuid(tBTA_GATTC_CACHE_ATTR   *p_attr, tBT_UUID *p_uuid)
-{
-    UINT8 *pp = (UINT8 *)p_attr->p_uuid;
-
-    memset(p_uuid, 0, sizeof(tBT_UUID));
-
-    p_uuid->len = p_attr->uuid_len;
-
-    if (p_attr->uuid_len == LEN_UUID_16) {
-        STREAM_TO_UINT16(p_uuid->uu.uuid16, pp);
-    } else {
-        memcpy(p_uuid->uu.uuid128, pp, LEN_UUID_128);
-    }
-
-    return;
-}
-/*******************************************************************************
-**
-** Function         bta_gattc_cpygattid
-**
-** Description      copy two tBTA_GATT_ID value
-**
-** Returns
-**
-*******************************************************************************/
-void bta_gattc_cpygattid(tBTA_GATT_ID *p_des, tBTA_GATT_ID *p_src)
-{
-    memset ((void *)p_des, 0, sizeof(tBTA_GATT_ID));
-
-    p_des->inst_id = p_src->inst_id;
-
-    p_des->uuid.len = p_src->uuid.len;
-
-    if (p_des->uuid.len == LEN_UUID_16) {
-        p_des->uuid.uu.uuid16 = p_src->uuid.uu.uuid16;
-    } else if (p_des->uuid.len == LEN_UUID_128) {
-        memcpy(p_des->uuid.uu.uuid128, p_src->uuid.uu.uuid128, LEN_UUID_128);
-    }
-}
-/*******************************************************************************
-**
-** Function         bta_gattc_gattid_compare
-**
-** Description      compare two tBTA_GATT_ID type of pointer
-**
-** Returns
-**
-*******************************************************************************/
-BOOLEAN bta_gattc_gattid_compare(tBTA_GATT_ID *p_src, tBTA_GATT_ID *p_tar)
-{
-    if (p_src->inst_id == p_tar->inst_id &&
-            bta_gattc_uuid_compare (&p_src->uuid, &p_tar->uuid, TRUE )) {
         return TRUE;
-    } else {
-        return FALSE;
     }
 
-}
-/*******************************************************************************
-**
-** Function         bta_gattc_srvcid_compare
-**
-** Description      compare two tBTA_GATT_SRVC_ID type of pointer
-**
-** Returns
-**
-*******************************************************************************/
-BOOLEAN bta_gattc_srvcid_compare(tBTA_GATT_SRVC_ID *p_src, tBTA_GATT_SRVC_ID *p_tar)
-{
-    if (p_src->is_primary == p_tar->is_primary &&
-            bta_gattc_gattid_compare (&p_src->id, &p_tar->id)) {
-        return TRUE;
-    } else {
-        return FALSE;
-    }
-}
-/*******************************************************************************
-**
-** Function         bta_gattc_charid_compare
-**
-** Description      compare two tBTA_GATTC_CHAR_ID type of pointer
-**
-** Returns
-**
-*******************************************************************************/
-BOOLEAN bta_gattc_charid_compare(tBTA_GATTC_CHAR_ID *p_src, tBTA_GATTC_CHAR_ID *p_tar)
-{
-    if (bta_gattc_gattid_compare (&p_src->char_id, &p_tar->char_id) &&
-            bta_gattc_srvcid_compare (&p_src->srvc_id, &p_tar->srvc_id)) {
-        return TRUE;
-    } else {
-        return FALSE;
-    }
+    APPL_TRACE_ERROR ("%s: already has a pending command!!", __func__);
+    /* skip the callback now. ----- need to send callback ? */
+    return FALSE;
 }
 
 /*******************************************************************************
@@ -558,10 +458,12 @@ BOOLEAN bta_gattc_check_notif_registry(tBTA_GATTC_RCB  *p_clreg, tBTA_GATTC_SERV
 {
     UINT8           i;
 
-    for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++) {
+    for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
+    {
         if (p_clreg->notif_reg[i].in_use &&
-                bdcmp(p_clreg->notif_reg[i].remote_bda, p_srcb->server_bda) == 0 &&
-                bta_gattc_charid_compare (&p_clreg->notif_reg[i].char_id, &p_notify->char_id)) {
+            bdcmp(p_clreg->notif_reg[i].remote_bda, p_srcb->server_bda) == 0 &&
+            p_clreg->notif_reg[i].handle == p_notify->handle)
+        {
             APPL_TRACE_DEBUG("Notification registered!");
             return TRUE;
         }
@@ -573,26 +475,36 @@ BOOLEAN bta_gattc_check_notif_registry(tBTA_GATTC_RCB  *p_clreg, tBTA_GATTC_SERV
 **
 ** Function         bta_gattc_clear_notif_registration
 **
-** Description      clear up the notification registration information by BD_ADDR.
+** Description      Clear up the notification registration information by BD_ADDR.
+**                  Where handle is between start_handle and end_handle, and
+**                  start_handle and end_handle are boundaries of service
+**                  containing characteristic.
 **
 ** Returns          None.
 **
 *******************************************************************************/
-void bta_gattc_clear_notif_registration(UINT16 conn_id)
+void bta_gattc_clear_notif_registration(tBTA_GATTC_SERV *p_srcb, UINT16 conn_id,
+                                        UINT16 start_handle, UINT16 end_handle)
 {
     BD_ADDR             remote_bda;
     tBTA_GATTC_IF       gatt_if;
     tBTA_GATTC_RCB      *p_clrcb ;
     UINT8       i;
     tGATT_TRANSPORT     transport;
+    UINT16              handle = 0;
 
     if (GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda, &transport)) {
         if ((p_clrcb = bta_gattc_cl_get_regcb(gatt_if)) != NULL) {
             for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++) {
                 if (p_clrcb->notif_reg[i].in_use &&
-                        !bdcmp(p_clrcb->notif_reg[i].remote_bda, remote_bda)) {
-                    memset(&p_clrcb->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
-                }
+                    !bdcmp(p_clrcb->notif_reg[i].remote_bda, remote_bda))
+
+                    /* It's enough to get service or characteristic handle, as
+                     * clear boundaries are always around service.
+                     */
+                    handle = p_clrcb->notif_reg[i].handle;
+                    if (handle >= start_handle && handle <= end_handle)
+                        memset(&p_clrcb->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
             }
         }
     } else {
@@ -601,50 +513,6 @@ void bta_gattc_clear_notif_registration(UINT16 conn_id)
     return;
 }
 
-/*******************************************************************************
-**
-** Function         bta_gattc_pack_cb_data
-**
-** Description      pack the data from read response into callback data structure.
-**
-** Returns
-**
-*******************************************************************************/
-tBTA_GATT_STATUS bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV *p_srcb,
-        tBT_UUID *p_descr_uuid,
-        tGATT_VALUE *p_attr,
-        tBTA_GATT_READ_VAL *p_value)
-{
-    UINT8                   i = 0, *pp = p_attr->value;
-    tBT_UUID                uuid = {LEN_UUID_16, {GATT_UUID_CHAR_AGG_FORMAT}};
-    UINT16                  handle;
-    tBTA_GATT_STATUS        status = BTA_GATT_OK;
-
-    /* GATT_UUID_CHAR_AGG_FORMAT */
-    if (bta_gattc_uuid_compare (&uuid, p_descr_uuid, TRUE)) {
-        while (p_attr->len >= 2 && i < BTA_GATTC_MULTI_MAX) {
-            STREAM_TO_UINT16(handle, pp);
-
-            if (bta_gattc_handle2id(p_srcb,
-                                    handle,
-                                    &p_value->aggre_value.pre_format[i].char_id.srvc_id,
-                                    &p_value->aggre_value.pre_format[i].char_id.char_id,
-                                    &p_value->aggre_value.pre_format[i].descr_id) == FALSE) {
-                status = BTA_GATT_INTERNAL_ERROR;
-                APPL_TRACE_ERROR("can not map to GATT ID. handle = 0x%04x", handle);
-                break;
-            }
-            i ++;
-            p_attr->len -= 2;
-        }
-        p_value->aggre_value.num_pres_fmt = i;
-    } else {
-        /* all others, take as raw format */
-        p_value->unformat.len = p_attr->len;
-        p_value->unformat.p_value = p_attr->value;
-    }
-    return status;
-}
 /*******************************************************************************
 **
 ** Function         bta_gattc_mark_bg_conn
@@ -982,4 +850,43 @@ tBTA_GATTC_CLCB *bta_gattc_find_int_disconn_clcb(tBTA_GATTC_DATA *p_msg)
     return p_clcb;
 }
 
+void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src)
+{
+    int i = 0;
+
+    if (p_src->len == LEN_UUID_16 || p_src->len == LEN_UUID_32)
+    {
+        for(i=0; i != 16; ++i)
+            p_dest->uu[i] = base_uuid[i];
+    }
+
+    switch (p_src->len)
+    {
+        case 0:
+            break;
+
+        case LEN_UUID_16:
+            p_dest->uu[12] = p_src->uu.uuid16 & 0xff;
+            p_dest->uu[13] = (p_src->uu.uuid16 >> 8) & 0xff;
+            break;
+
+        case LEN_UUID_32:
+            p_dest->uu[12] = p_src->uu.uuid16 & 0xff;
+            p_dest->uu[13] = (p_src->uu.uuid16 >> 8) & 0xff;
+            p_dest->uu[14] = (p_src->uu.uuid32 >> 16) & 0xff;
+            p_dest->uu[15] = (p_src->uu.uuid32 >> 24) & 0xff;
+            break;
+
+        case LEN_UUID_128:
+            for(i=0; i != 16; ++i)
+                p_dest->uu[i] = p_src->uu.uuid128[i];
+            break;
+
+        default:
+            LOG_ERROR("%s: Unknown UUID length %d!", __FUNCTION__, p_src->len);
+            break;
+    }
+}
+
+
 #endif /* BTA_GATT_INCLUDED */
index 4b4945aa5e0e382a2eabdaf7b7e207064fd3afc5..d81fa547e0a3b310bd0cb94d17d6862d53700bb1 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "bta_api.h"
 #include "gatt_api.h"
+#include "list.h"
 
 #ifndef     BTA_GATT_INCLUDED
 #warning BTA_GATT_INCLUDED not defined
 #define     BTA_GATT_DEBUG       FALSE
 #endif
 
+typedef enum {
+    BTGATT_DB_PRIMARY_SERVICE,
+    BTGATT_DB_SECONDARY_SERVICE,
+    BTGATT_DB_CHARACTERISTIC,
+    BTGATT_DB_DESCRIPTOR,
+    BTGATT_DB_INCLUDED_SERVICE,
+}bt_gatt_db_attribute_type_t;
+
+typedef enum {
+    GATT_OP_GET_SVC_BY_UUID,
+    GATT_OP_GET_ALL_CHAR,
+    GATT_OP_GET_ALL_DESCRI,
+    GATT_OP_GET_CHAR_BY_UUID,
+    GATT_OP_GET_DESCRI_BY_UUID,
+    GATT_OP_GET_DESCRI_BY_HANDLE,
+    GATT_OP_GET_INCLUDE_SVC,
+}bt_gatt_get_db_op_t;
+
+typedef struct {
+    bt_gatt_db_attribute_type_t type;
+    UINT16                      attribute_handle;
+    UINT16                      start_handle;
+    UINT16                      end_handle;
+    UINT16                      id;
+    UINT8                       properties;
+    bt_uuid_t                   uuid;
+}btgatt_db_element_t;
+
 /*****************************************************************************
 **  Constants and data types
 *****************************************************************************/
@@ -104,7 +133,7 @@ typedef struct {
 #define  BTA_GATT_APP_RSP                   GATT_APP_RSP                      /* 0xE1 */
 //Error caused by customer application or stack bug
 #define  BTA_GATT_UNKNOWN_ERROR             GATT_UNKNOWN_ERROR                /* 0XEF */
-
+                                             /* 0xE0 ~ 0xFC reserved for future use */
 #define  BTA_GATT_CCC_CFG_ERR               GATT_CCC_CFG_ERR     /* 0xFD Client Characteristic Configuration Descriptor Improperly Configured */
 #define  BTA_GATT_PRC_IN_PROGRESS           GATT_PRC_IN_PROGRESS /* 0xFE Procedure Already in progress */
 #define  BTA_GATT_OUT_OF_RANGE              GATT_OUT_OF_RANGE    /* 0xFFAttribute value out of range */
@@ -213,41 +242,13 @@ typedef struct {
     BOOLEAN             is_primary;
 } tBTA_GATT_SRVC_ID;
 
-typedef struct {
-    tBTA_GATT_SRVC_ID       srvc_id;
-    tBTA_GATT_ID            char_id;
-} tBTA_GATTC_CHAR_ID;
-
-typedef struct {
-    tBTA_GATTC_CHAR_ID      char_id;
-    tBTA_GATT_ID            descr_id;
-} tBTA_GATTC_CHAR_DESCR_ID;
-
-typedef struct {
-    tBTA_GATT_SRVC_ID       srvc_id;
-    tBTA_GATT_SRVC_ID       incl_svc_id;
-} tBTA_GATTC_INCL_SVC_ID;
-
-#define     BTA_GATT_TYPE_CHAR          0
-#define     BTA_GATT_TYPE_CHAR_DESCR    1
-typedef UINT8 tBTA_GATT_ID_TYPE;
-
-typedef struct {
-    tBTA_GATT_ID_TYPE               id_type;
-    union {
-        tBTA_GATTC_CHAR_ID         char_id;
-        tBTA_GATTC_CHAR_DESCR_ID   char_descr_id;
-
-    }                       id_value;
-} tBTA_GATTC_ATTR_ID;
 
 #define BTA_GATTC_MULTI_MAX    GATT_MAX_READ_MULTI_HANDLES
 
 typedef struct {
     UINT8                       num_attr;
-    tBTA_GATTC_ATTR_ID          id_list[BTA_GATTC_MULTI_MAX];
-
-} tBTA_GATTC_MULTI;
+    UINT16                      handles[BTA_GATTC_MULTI_MAX];
+}tBTA_GATTC_MULTI;
 
 /* relate to ESP_GATT_xxx in esp_gatt_def.h */
 #define BTA_GATT_AUTH_REQ_NONE           GATT_AUTH_REQ_NONE
@@ -275,44 +276,28 @@ typedef struct {
     UINT8       id;
     UINT8       prop;       /* used when attribute type is characteristic */
     BOOLEAN     is_primary; /* used when attribute type is service */
-} tBTA_GATTC_NV_ATTR;
+    UINT16      incl_srvc_handle; /* used when attribute type is included service */
+}tBTA_GATTC_NV_ATTR;
 
 /* callback data structure */
 typedef struct {
     tBTA_GATT_STATUS    status;
     tBTA_GATTC_IF       client_if;
-// btla-specific ++
     tBT_UUID            app_uuid;
-// btla-specific --
-} tBTA_GATTC_REG;
-
-typedef struct {
-    UINT8                       num_pres_fmt;   /* number of presentation format aggregated*/
-    tBTA_GATTC_CHAR_DESCR_ID    pre_format[BTA_GATTC_MULTI_MAX];
-} tBTA_GATT_CHAR_AGGRE_VALUE;
-
-typedef union {
-    tBTA_GATT_CHAR_AGGRE_VALUE      aggre_value;
-    tBTA_GATT_UNFMT                 unformat;
-
-} tBTA_GATT_READ_VAL;
+}tBTA_GATTC_REG;
 
 typedef struct {
     UINT16              conn_id;
     tBTA_GATT_STATUS    status;
-    tBTA_GATT_SRVC_ID   srvc_id;
-    tBTA_GATT_ID        char_id;
-    tBTA_GATT_ID        descr_type;
-    tBTA_GATT_READ_VAL  *p_value;
-} tBTA_GATTC_READ;
+    UINT16              handle;
+    tBTA_GATT_UNFMT  *p_value;
+}tBTA_GATTC_READ;
 
 typedef struct {
     UINT16              conn_id;
     tBTA_GATT_STATUS    status;
-    tBTA_GATT_SRVC_ID   srvc_id;
-    tBTA_GATT_ID        char_id;
-    tBTA_GATT_ID        descr_type;
-} tBTA_GATTC_WRITE;
+    UINT16              handle;
+}tBTA_GATTC_WRITE;
 
 typedef struct {
     UINT16              conn_id;
@@ -326,8 +311,10 @@ typedef struct {
 
 typedef struct {
     UINT16              conn_id;
-    tBTA_GATT_SRVC_ID   service_uuid;
-} tBTA_GATTC_SRVC_RES;
+    UINT16              start_handle;
+    UINT16              end_handle;
+    tBTA_GATT_ID        service_uuid;
+}tBTA_GATTC_SRVC_RES;
 
 typedef struct {
     UINT16              conn_id;
@@ -355,8 +342,7 @@ typedef struct {
 typedef struct {
     UINT16              conn_id;
     BD_ADDR             bda;
-    tBTA_GATTC_CHAR_ID  char_id;
-    tBTA_GATT_ID        descr_type;
+    UINT16              handle;
     UINT16              len;
     UINT8               value[BTA_GATT_MAX_ATTR_LEN];
     BOOLEAN             is_notify;
@@ -367,14 +353,12 @@ typedef struct {
     BOOLEAN congested; /* congestion indicator */
 } tBTA_GATTC_CONGEST;
 
-// btla-specific ++
 typedef struct {
     tBTA_GATT_STATUS        status;
     tBTA_GATTC_IF           client_if;
     UINT16                  conn_id;
     BD_ADDR                 remote_bda;
-} tBTA_GATTC_OPEN_CLOSE;
-// btla-specific --
+}tBTA_GATTC_OPEN_CLOSE;
 
 typedef struct {
     tBTA_GATTC_IF           client_if;
@@ -395,6 +379,8 @@ typedef struct {
     BD_ADDR             remote_bda;
 } tBTA_GATTC_DISCONNECT;
 
+
+
 typedef union {
     tBTA_GATT_STATUS        status;
 
@@ -541,33 +527,26 @@ typedef struct {
 typedef struct {
     tBTA_GATTS_IF       server_if;
     tBTA_GATT_STATUS    status;
-// btla-specific ++
     tBT_UUID            uuid;
-// btla-specific --
-} tBTA_GATTS_REG_OPER;
+}tBTA_GATTS_REG_OPER;
 
 
 typedef struct {
     tBTA_GATTS_IF       server_if;
     UINT16              service_id;
-// btla-specific ++
     UINT16              svc_instance;
     BOOLEAN             is_primary;
     tBTA_GATT_STATUS    status;
     tBT_UUID            uuid;
-// btla-specific --
-} tBTA_GATTS_CREATE;
+}tBTA_GATTS_CREATE;
 
 typedef struct {
     tBTA_GATTS_IF       server_if;
     UINT16              service_id;
     UINT16              attr_id;
     tBTA_GATT_STATUS    status;
-// btla-specific ++
     tBT_UUID            char_uuid;
-// btla-specific --
-} tBTA_GATTS_ADD_RESULT;
-
+}tBTA_GATTS_ADD_RESULT;
 typedef struct{
     tBTA_GATTS_IF       server_if;
     UINT16              service_id;
@@ -614,7 +593,6 @@ typedef struct {
     tBTA_GATT_STATUS    status;
     tBTA_GATTS_IF       server_if;
 } tBTA_GATTS_CANCEL_OPEN;
-
 /* GATTS callback data */
 typedef union {
     tBTA_GATTS_REG_OPER         reg_oper;
@@ -648,6 +626,41 @@ typedef void (tBTA_GATTS_ENB_CBACK)(tBTA_GATT_STATUS status);
 
 /* Server callback function */
 typedef void (tBTA_GATTS_CBACK)(tBTA_GATTS_EVT event,  tBTA_GATTS *p_data);
+typedef struct
+{
+    tBT_UUID                uuid;
+    BOOLEAN                 is_primary;
+    UINT16                  handle;
+    UINT16                  s_handle;
+    UINT16                  e_handle;
+    list_t                 *characteristics; /* list of tBTA_GATTC_CHARACTERISTIC */
+    list_t                 *included_svc; /* list of tBTA_GATTC_INCLUDED_SVC */
+} __attribute__((packed)) tBTA_GATTC_SERVICE;
+
+typedef struct
+{
+    tBT_UUID                uuid;
+    UINT16                  handle;
+    tBTA_GATT_CHAR_PROP     properties;
+    tBTA_GATTC_SERVICE     *service; /* owning service*/
+    list_t                 *descriptors; /* list of tBTA_GATTC_DESCRIPTOR */
+} __attribute__((packed)) tBTA_GATTC_CHARACTERISTIC;
+
+typedef struct
+{
+    tBT_UUID                    uuid;
+    UINT16                      handle;
+    tBTA_GATTC_CHARACTERISTIC  *characteristic; /* owning characteristic */
+} __attribute__((packed)) tBTA_GATTC_DESCRIPTOR;
+
+typedef struct
+{
+    tBT_UUID                uuid;
+    UINT16                  handle;
+    UINT16                  incl_srvc_s_handle;
+    tBTA_GATTC_SERVICE     *owning_service; /* owning service*/
+    tBTA_GATTC_SERVICE     *included_service;
+} __attribute__((packed)) tBTA_GATTC_INCLUDED_SVC;
 
 /*****************************************************************************
 **  External Function Declarations
@@ -770,175 +783,114 @@ extern void BTA_GATTC_ServiceSearchRequest(UINT16 conn_id, tBT_UUID *p_srvc_uuid
 
 /*******************************************************************************
 **
-** Function         BTA_GATTC_GetFirstChar
+** Function         BTA_GATTC_GetServices
 **
-** Description      This function is called to find the first charatceristic of the
-**                  service on the given server.
+** Description      This function is called to find the services on the given server.
 **
 ** Parameters       conn_id: connection ID which identify the server.
-**                  p_srvc_id: the service ID of which the characteristic is belonged to.
-**                  p_char_uuid_cond: Characteristic UUID, if NULL find the first available
-**                               characteristic.
-**                  p_char_result: output parameter which will store the GATT
-**                                  characteristic ID.
-**                  p_property: output parameter to carry the characteristic property.
 **
-** Returns          returns status.
+** Returns          returns list_t of tBTA_GATTC_SERVICE or NULL.
 **
 *******************************************************************************/
-extern tBTA_GATT_STATUS  BTA_GATTC_GetFirstChar (UINT16              conn_id,
-        tBTA_GATT_SRVC_ID   *p_srvc_id,
-        tBT_UUID            *p_char_uuid_cond,
-        tBTA_GATTC_CHAR_ID  *p_char_result,
-        tBTA_GATT_CHAR_PROP *p_property);
+extern const list_t* BTA_GATTC_GetServices(UINT16 conn_id);
 
 /*******************************************************************************
 **
-** Function         BTA_GATTC_GetNextChar
+** Function         BTA_GATTC_GetCharacteristic
 **
-** Description      This function is called to find the next charatceristic of the
-**                  service on the given server.
+** Description      This function is called to find the characteristic on the given server.
 **
 ** Parameters       conn_id: connection ID which identify the server.
-**                  p_start_char_id: start the characteristic search from the next record
-**                           after the one identified by char_id.
-**                  p_char_uuid_cond: Characteristic UUID, if NULL find the first available
-**                               characteristic.
-**                  p_char_result: output parameter which will store the GATT
-**                                  characteristic ID.
-**                  p_property: output parameter, characteristic property.
+**                  handle: characteristic handle
 **
-** Returns          returns status.
+** Returns          returns pointer to tBTA_GATTC_CHARACTERISTIC or NULL.
 **
 *******************************************************************************/
-extern tBTA_GATT_STATUS  BTA_GATTC_GetNextChar (UINT16 conn_id,
-        tBTA_GATTC_CHAR_ID  *p_start_char_id,
-        tBT_UUID            *p_char_uuid_cond,
-        tBTA_GATTC_CHAR_ID  *p_char_result,
-        tBTA_GATT_CHAR_PROP *p_property);
+extern const tBTA_GATTC_CHARACTERISTIC* BTA_GATTC_GetCharacteristic(UINT16 conn_id, UINT16 handle);
 
 /*******************************************************************************
 **
-** Function         BTA_GATTC_GetFirstCharDescr
+** Function         BTA_GATTC_GetDescriptor
 **
-** Description      This function is called to find the first charatceristic descriptor of the
-**                  charatceristic on the given server.
+** Description      This function is called to find the characteristic on the given server.
 **
 ** Parameters       conn_id: connection ID which identify the server.
-**                  p_char_id: the characteristic ID of which the descriptor is belonged to.
-**                  p_descr_uuid_cond: Characteristic Descr UUID, if NULL find the first available
-**                               characteristic.
-**                  p_descr_result: output parameter which will store the GATT
-**                                  characteristic descriptor ID.
+**                  handle: descriptor handle
 **
-** Returns          returns status.
+** Returns          returns pointer to tBTA_GATTC_DESCRIPTOR or NULL.
 **
 *******************************************************************************/
-extern tBTA_GATT_STATUS  BTA_GATTC_GetFirstCharDescr (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
-        tBT_UUID *p_descr_uuid_cond,
-        tBTA_GATTC_CHAR_DESCR_ID *p_descr_result);
+extern const tBTA_GATTC_DESCRIPTOR* BTA_GATTC_GetDescriptor(UINT16 conn_id, UINT16 handle);
 
-/*******************************************************************************
-**
-** Function         BTA_GATTC_GetNextCharDescr
-**
-** Description      This function is called to find the next charatceristic of the
-**                  service on the given server.
-**
-** Parameters       conn_id: connection ID which identify the server.
-**                  p_start_descr_id: start the characteristic search from the next record
-**                           after the one identified by p_start_descr_id.
-**                  p_descr_uuid_cond: Characteristic descriptor UUID, if NULL find
-**                               the first available characteristic descriptor.
-**                  p_descr_result: output parameter which will store the GATT
-**                                  characteristic descriptor ID.
-**
-** Returns          returns status.
-**
-*******************************************************************************/
-extern tBTA_GATT_STATUS  BTA_GATTC_GetNextCharDescr (UINT16 conn_id,
-        tBTA_GATTC_CHAR_DESCR_ID *p_start_descr_id,
-        tBT_UUID           *p_descr_uuid_cond,
-        tBTA_GATTC_CHAR_DESCR_ID *p_descr_result);
+extern void BTA_GATTC_GetServiceWithUUID(UINT16 conn_id, tBT_UUID *svc_uuid, 
+                                         btgatt_db_element_t **db, int *count);
 
+extern void BTA_GATTC_GetAllChar(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle,
+                                 btgatt_db_element_t **db, int *count);
 
-/*******************************************************************************
-**
-** Function         BTA_GATTC_GetFirstIncludedService
-**
-** Description      This function is called to find the first included service of the
-**                  service on the given server.
-**
-** Parameters       conn_id: connection ID which identify the server.
-**                  p_srvc_id: the service ID of which the included service is belonged to.
-**                  p_uuid_cond: include service UUID, if NULL find the first available
-**                               included service.
-**                  p_result: output parameter which will store the GATT ID
-**                              of the included service found.
-**
-** Returns          returns status.
-**
-*******************************************************************************/
-extern tBTA_GATT_STATUS  BTA_GATTC_GetFirstIncludedService(UINT16 conn_id,
-        tBTA_GATT_SRVC_ID    *p_srvc_id,
-        tBT_UUID               *p_uuid_cond,
-        tBTA_GATTC_INCL_SVC_ID *p_result);
+extern void BTA_GATTC_GetAllDescriptor(UINT16 conn_id, UINT16 char_handle,
+                                       btgatt_db_element_t **db, int *count);
+
+extern void BTA_GATTC_GetCharByUUID(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle, tBT_UUID char_uuid,
+                                    btgatt_db_element_t **db, int *count);
+
+extern void BTA_GATTC_GetDescrByUUID(UINT16 conn_id, uint16_t start_handle, uint16_t end_handle,
+                                     tBT_UUID char_uuid, tBT_UUID descr_uuid,
+                                     btgatt_db_element_t **db, int *count);
+
+extern void BTA_GATTC_GetDescrByCharHandle(UINT16 conn_id, UINT16 char_handle, tBT_UUID descr_uuid,
+                                           btgatt_db_element_t **db, int *count);
+
+extern void BTA_GATTC_GetIncludeService(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle,
+                                        tBT_UUID *incl_uuid, btgatt_db_element_t **db, int *count);
+
+extern void BTA_GATTC_GetDBSize(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle, int *count);
+
+extern void BTA_GATTC_GetDBSizeByType(UINT16 conn_id, bt_gatt_db_attribute_type_t type,
+                                      UINT16 start_handle, UINT16 end_handle, UINT16 char_handle, int *count);
 
 /*******************************************************************************
 **
-** Function         BTA_GATTC_GetNextIncludedService
+** Function         BTA_GATTC_GetGattDb
 **
-** Description      This function is called to find the next included service of the
-**                  service on the given server.
+** Description      This function is called to get gatt db.
 **
 ** Parameters       conn_id: connection ID which identify the server.
-**                  p_start_id: start the search from the next record
-**                                  after the one identified by p_start_id.
-**                  p_uuid_cond: Included service UUID, if NULL find the first available
-**                               included service.
-**                  p_result: output parameter which will store the GATT ID
-**                              of the included service found.
-**
-** Returns          returns status.
+**                  db: output parameter which will contain gatt db copy.
+**                      Caller is responsible for freeing it.
+**                  count: number of elements in db.
 **
 *******************************************************************************/
-extern tBTA_GATT_STATUS  BTA_GATTC_GetNextIncludedService(UINT16 conn_id,
-        tBTA_GATTC_INCL_SVC_ID *p_start_id,
-        tBT_UUID             *p_uuid_cond,
-        tBTA_GATTC_INCL_SVC_ID *p_result);
+extern void BTA_GATTC_GetGattDb(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle,
+                                btgatt_db_element_t **db, int *count);
 
 /*******************************************************************************
 **
 ** Function         BTA_GATTC_ReadCharacteristic
 **
-** Description      This function is called to read a service's characteristics of
-**                    the given characteritisc ID.
+** Description      This function is called to read a characteristics value
 **
-** Parameters       conn_id - connection ID.
-**                    p_char_id - characteritic ID to read.
+** Parameters       conn_id - connectino ID.
+**                  handle - characteritic handle to read.
 **
 ** Returns          None
 **
 *******************************************************************************/
-extern void BTA_GATTC_ReadCharacteristic (UINT16 conn_id,
-        tBTA_GATTC_CHAR_ID *p_char_id,
-        tBTA_GATT_AUTH_REQ auth_req);
+void BTA_GATTC_ReadCharacteristic(UINT16 conn_id, UINT16 handle, tBTA_GATT_AUTH_REQ auth_req);
 
 /*******************************************************************************
 **
 ** Function         BTA_GATTC_ReadCharDescr
 **
-** Description      This function is called to read a characteristics descriptor.
+** Description      This function is called to read a descriptor value.
 **
 ** Parameters       conn_id - connection ID.
-**                    p_char_descr_id - characteritic descriptor ID to read.
+**                  handle - descriptor handle to read.
 **
 ** Returns          None
 **
 *******************************************************************************/
-extern void BTA_GATTC_ReadCharDescr (UINT16 conn_id,
-                                     tBTA_GATTC_CHAR_DESCR_ID *p_char_descr_id,
-                                     tBTA_GATT_AUTH_REQ auth_req);
+void BTA_GATTC_ReadCharDescr (UINT16 conn_id, UINT16 handle, tBTA_GATT_AUTH_REQ auth_req);
 
 /*******************************************************************************
 **
@@ -947,40 +899,40 @@ extern void BTA_GATTC_ReadCharDescr (UINT16 conn_id,
 ** Description      This function is called to write characteristic value.
 **
 ** Parameters       conn_id - connection ID.
-**                    p_char_id - characteristic ID to write.
-**                    write_type - type of write.
+**                  handle - characteristic handle to write.
+**                  write_type - type of write.
 **                  len: length of the data to be written.
 **                  p_value - the value to be written.
 **
 ** Returns          None
 **
 *******************************************************************************/
-extern void BTA_GATTC_WriteCharValue (UINT16 conn_id,
-                                      tBTA_GATTC_CHAR_ID *p_char_id,
-                                      tBTA_GATTC_WRITE_TYPE  write_type,
-                                      UINT16 len,
-                                      UINT8 *p_value,
-                                      tBTA_GATT_AUTH_REQ auth_req);
+void BTA_GATTC_WriteCharValue ( UINT16 conn_id,
+                                UINT16 handle,
+                                tBTA_GATTC_WRITE_TYPE  write_type,
+                                UINT16 len,
+                                UINT8 *p_value,
+                                tBTA_GATT_AUTH_REQ auth_req);
 
 /*******************************************************************************
 **
 ** Function         BTA_GATTC_WriteCharDescr
 **
-** Description      This function is called to write characteristic descriptor value.
+** Description      This function is called to write descriptor value.
 **
 ** Parameters       conn_id - connection ID
-**                    p_char_descr_id - characteristic descriptor ID to write.
-**                    write_type - type of write.
+**                  handle - descriptor handle to write.
+**                  write_type - type of write.
 **                  p_value - the value to be written.
 **
 ** Returns          None
 **
 *******************************************************************************/
-extern void BTA_GATTC_WriteCharDescr (UINT16 conn_id,
-                                      tBTA_GATTC_CHAR_DESCR_ID *p_char_descr_id,
-                                      tBTA_GATTC_WRITE_TYPE  write_type,
-                                      tBTA_GATT_UNFMT   *p_data,
-                                      tBTA_GATT_AUTH_REQ auth_req);
+void BTA_GATTC_WriteCharDescr (UINT16 conn_id,
+                               UINT16 handle,
+                               tBTA_GATTC_WRITE_TYPE  write_type,
+                               tBTA_GATT_UNFMT      *p_data,
+                               tBTA_GATT_AUTH_REQ auth_req);
 
 /*******************************************************************************
 **
@@ -989,12 +941,12 @@ extern void BTA_GATTC_WriteCharDescr (UINT16 conn_id,
 ** Description      This function is called to send handle value confirmation.
 **
 ** Parameters       conn_id - connection ID.
-**                    p_char_id - characteristic ID to confrim.
+**                  handle - characteristic handle to confirm.
 **
 ** Returns          None
 **
 *******************************************************************************/
-extern void BTA_GATTC_SendIndConfirm (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id);
+extern void BTA_GATTC_SendIndConfirm (UINT16 conn_id, UINT16 handle);
 
 /*******************************************************************************
 **
@@ -1002,17 +954,16 @@ extern void BTA_GATTC_SendIndConfirm (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char
 **
 ** Description      This function is called to register for notification of a service.
 **
-** Parameters       client_if   - client interface.
-**                  remote_bda  - target GATT server.
-**                  p_char_id   - pointer to GATT characteristic ID.
+** Parameters       client_if - client interface.
+**                  remote_bda - target GATT server.
+**                  handle - GATT characteristic handle.
 **
 ** Returns          OK if registration succeed, otherwise failed.
 **
 *******************************************************************************/
 extern tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF      client_if,
-        BD_ADDR            remote_bda,
-        tBTA_GATTC_CHAR_ID *p_char_id);
-
+                                                            BD_ADDR            remote_bda,
+                                                            UINT16             handle);
 
 /*******************************************************************************
 **
@@ -1022,14 +973,14 @@ extern tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF      c
 **
 ** Parameters       client_if - client interface.
 **                  remote_bda - target GATT server.
-**                  p_char_id - pointer to a GATT characteristic ID.
+**                  handle - GATT characteristic handle.
 **
 ** Returns          OK if deregistration succeed, otherwise failed.
 **
 *******************************************************************************/
 extern tBTA_GATT_STATUS BTA_GATTC_DeregisterForNotifications (tBTA_GATTC_IF      client_if,
-        BD_ADDR            remote_bda,
-        tBTA_GATTC_CHAR_ID *p_char_id);
+                                                              BD_ADDR            remote_bda,
+                                                              UINT16             handle);
 
 /*******************************************************************************
 **
@@ -1038,16 +989,16 @@ extern tBTA_GATT_STATUS BTA_GATTC_DeregisterForNotifications (tBTA_GATTC_IF
 ** Description      This function is called to prepare write a characteristic value.
 **
 ** Parameters       conn_id - connection ID.
-**                  p_char_id - GATT characteritic ID of the service.
+**                  handle - GATT characteritic handle.
 **                  offset - offset of the write value.
-**                  len: length of the data to be written.
+**                  len - length of the data to be written.
 **                  p_value - the value to be written.
 **
 ** Returns          None
 **
 *******************************************************************************/
 extern void BTA_GATTC_PrepareWrite  (UINT16 conn_id,
-                                     tBTA_GATTC_CHAR_ID *p_char_id,
+                                     UINT16 handle,
                                      UINT16 offset,
                                      UINT16 len,
                                      UINT8 *p_value,
@@ -1069,7 +1020,7 @@ extern void BTA_GATTC_PrepareWrite  (UINT16 conn_id,
 **
 *******************************************************************************/
 extern void BTA_GATTC_PrepareWriteCharDescr  (UINT16 conn_id,
-                                              tBTA_GATTC_CHAR_DESCR_ID *p_char_descr_id,
+                                              UINT16 handle,
                                               UINT16 offset,
                                               tBTA_GATT_UNFMT   *p_data,
                                               tBTA_GATT_AUTH_REQ auth_req);
@@ -1360,9 +1311,9 @@ extern void BTA_GATTS_StopService(UINT16 service_id);
 **
 *******************************************************************************/
 extern void BTA_GATTS_HandleValueIndication (UINT16 conn_id, UINT16 attr_id,
-        UINT16 data_len,
-        UINT8 *p_data,
-        BOOLEAN need_confirm);
+                                             UINT16 data_len,
+                                             UINT8 *p_data,
+                                             BOOLEAN need_confirm);
 
 /*******************************************************************************
 **
index 6ea09ef8c1e5a8a4f8c06de0b278cfb62ef9c929..2515cb5225c7510843fdd22037d8f50f1ec0cfe5 100644 (file)
@@ -58,12 +58,6 @@ enum {
     BTA_GATTC_OP_CMPL_EVT,
     BTA_GATTC_INT_DISCONN_EVT,
 
-    /* for cache loading/saving */
-    BTA_GATTC_START_CACHE_EVT,
-    BTA_GATTC_CI_CACHE_OPEN_EVT,
-    BTA_GATTC_CI_CACHE_LOAD_EVT,
-    BTA_GATTC_CI_CACHE_SAVE_EVT,
-
     BTA_GATTC_INT_START_IF_EVT,
     BTA_GATTC_API_REG_EVT,
     BTA_GATTC_API_DEREG_EVT,
@@ -74,6 +68,8 @@ enum {
 };
 typedef UINT16 tBTA_GATTC_INT_EVT;
 
+#define BTA_GATTC_SERVICE_CHANGED_LEN    4
+
 /* max client application GATTC can support */
 #ifndef     BTA_GATTC_CL_MAX
 #define     BTA_GATTC_CL_MAX    3 // 32
@@ -95,7 +91,7 @@ typedef UINT16 tBTA_GATTC_INT_EVT;
 #endif
 
 #define BTA_GATTC_WRITE_PREPARE          GATT_WRITE_PREPARE
-
+#define BTA_GATTC_INVALID_HANDLE         0
 
 /* internal strucutre for GATTC register API  */
 typedef struct {
@@ -125,17 +121,15 @@ typedef tBTA_GATTC_API_OPEN tBTA_GATTC_API_CANCEL_OPEN;
 typedef struct {
     BT_HDR                  hdr;
     tBTA_GATT_AUTH_REQ      auth_req;
-    tBTA_GATT_SRVC_ID       srvc_id;
-    tBTA_GATT_ID            char_id;
-    tBTA_GATT_ID            *p_descr_type;
+    UINT16                  handle;
+    tBTA_GATTC_EVT          cmpl_evt;
 } tBTA_GATTC_API_READ;
 
 typedef struct {
     BT_HDR                  hdr;
     tBTA_GATT_AUTH_REQ      auth_req;
-    tBTA_GATT_SRVC_ID       srvc_id;
-    tBTA_GATT_ID            char_id;
-    tBTA_GATT_ID            *p_descr_type;
+    UINT16                  handle;
+    tBTA_GATTC_EVT          cmpl_evt;
     tBTA_GATTC_WRITE_TYPE   write_type;
     UINT16                  offset;
     UINT16                  len;
@@ -149,8 +143,7 @@ typedef struct {
 
 typedef struct {
     BT_HDR                  hdr;
-    tBTA_GATT_SRVC_ID       srvc_id;
-    tBTA_GATT_ID            char_id;
+    UINT16                  handle;
 } tBTA_GATTC_API_CONFIRM;
 
 typedef tGATT_CL_COMPLETE tBTA_GATTC_CMPL;
@@ -171,8 +164,8 @@ typedef struct {
     BT_HDR                  hdr;
     tBTA_GATT_AUTH_REQ      auth_req;
     UINT8                   num_attr;
-    tBTA_GATTC_ATTR_ID      *p_id_list;
-} tBTA_GATTC_API_READ_MULTI;
+    UINT16                  handles[GATT_MAX_READ_MULTI_HANDLES];
+}tBTA_GATTC_API_READ_MULTI;
 
 typedef struct {
     BT_HDR                  hdr;
@@ -215,9 +208,6 @@ typedef union {
     tBTA_GATTC_API_READ_MULTI   api_read_multi;
     tBTA_GATTC_API_CFG_MTU      api_mtu;
     tBTA_GATTC_OP_CMPL          op_cmpl;
-    tBTA_GATTC_CI_EVT           ci_open;
-    tBTA_GATTC_CI_EVT           ci_save;
-    tBTA_GATTC_CI_LOAD          ci_load;
     tBTA_GATTC_INT_CONN         int_conn;
     tBTA_GATTC_ENC_CMPL         enc_cmpl;
 
@@ -230,43 +220,13 @@ typedef union {
 
 
 /* GATT server cache on the client */
-typedef union {
-    UINT8               uuid128[LEN_UUID_128];
-    UINT16              uuid16;
-} tBTA_GATTC_UUID;
-
-typedef struct gattc_attr_cache {
-    tBTA_GATTC_UUID         *p_uuid;
-    struct                  gattc_attr_cache *p_next;
-    UINT16                  uuid_len;
-    UINT16                  attr_handle;
-    UINT8                   inst_id;
-    tBTA_GATT_CHAR_PROP     property; /* if characteristic, it is char property;
-                                         if included service, flag primary,
-                                         if descriptor, not used */
-    tBTA_GATTC_ATTR_TYPE    attr_type;
-// btla-specific ++
-} __attribute__((packed)) tBTA_GATTC_CACHE_ATTR;
-// btla-specific --
-
-typedef struct gattc_svc_cache {
-    tBTA_GATT_SRVC_ID       service_uuid;
-    tBTA_GATTC_CACHE_ATTR   *p_attr;
-    tBTA_GATTC_CACHE_ATTR   *p_last_attr;
-    UINT16                  s_handle;
-    UINT16                  e_handle;
-    struct                  gattc_svc_cache *p_next;
-    tBTA_GATTC_CACHE_ATTR   *p_cur_char;
-// btla-specific ++
-} __attribute__((packed)) tBTA_GATTC_CACHE;
-// btla-specific --
-
 typedef struct {
     tBT_UUID            uuid;
     UINT16              s_handle;
     UINT16              e_handle;
+    // this field is set only for characteristic
+    UINT16              char_decl_handle;
     BOOLEAN             is_primary;
-    UINT8               srvc_inst_id;
     tBTA_GATT_CHAR_PROP property;
 } tBTA_GATTC_ATTR_REC;
 
@@ -299,11 +259,7 @@ typedef struct {
 
     UINT8               state;
 
-    tBTA_GATTC_CACHE    *p_srvc_cache;
-    tBTA_GATTC_CACHE    *p_cur_srvc;
-    fixed_queue_t       *cache_buffer;   /* buffer queue used for storing the cache data */
-    UINT8               *p_free;        /* starting point to next available byte */
-    UINT16              free_byte;      /* number of available bytes in server cache buffer */
+    list_t              *p_srvc_cache;  /* list of tBTA_GATTC_SERVICE */
     UINT8               update_count;   /* indication received */
     UINT8               num_clcb;       /* number of associated CLCB */
 
@@ -314,7 +270,7 @@ typedef struct {
     UINT8               next_avail_idx;
     UINT8               total_srvc;
     UINT8               total_char;
-
+    UINT16              total_attr;
     UINT8               srvc_hdl_chg;   /* service handle change indication pending */
     UINT16              attr_index;     /* cahce NV saving/loading attribute index */
 
@@ -328,8 +284,8 @@ typedef struct {
 typedef struct {
     BOOLEAN             in_use;
     BD_ADDR             remote_bda;
-    tBTA_GATTC_CHAR_ID  char_id;
-} tBTA_GATTC_NOTIF_REG;
+    UINT16              handle;
+}tBTA_GATTC_NOTIF_REG;
 
 typedef struct {
     tBTA_GATTC_CBACK        *p_cback;
@@ -403,11 +359,7 @@ typedef struct {
 
     tBTA_GATTC_CLCB     clcb[BTA_GATTC_CLCB_MAX];
     tBTA_GATTC_SERV     known_server[BTA_GATTC_KNOWN_SR_MAX];
-#if (SDP_INCLUDED == TRUE)
-    tSDP_DISCOVERY_DB   *p_sdp_db;
-#endif  ///SDP_INCLUDED == TRUE
-    UINT16              sdp_conn_id;
-} tBTA_GATTC_CB;
+}tBTA_GATTC_CB;
 
 typedef enum {
     SERVICE_CHANGE_CCC_WRITTEN_SUCCESS = 0,
@@ -474,10 +426,7 @@ extern void bta_gattc_confirm(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
 extern void bta_gattc_execute(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
 extern void bta_gattc_read_multi(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
 extern void bta_gattc_ci_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
-extern void bta_gattc_ci_load(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
 extern void bta_gattc_ci_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
-extern void bta_gattc_ci_save(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
-extern void bta_gattc_cache_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
 extern void bta_gattc_ignore_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
 extern void bta_gattc_restart_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_msg);
 extern void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *p_clreg);
@@ -509,20 +458,13 @@ extern tBTA_GATTC_CLCB *bta_gattc_find_int_disconn_clcb(tBTA_GATTC_DATA *p_msg);
 
 extern BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
 
-extern UINT16 bta_gattc_id2handle(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_SRVC_ID *p_service_id, tBTA_GATT_ID *p_char_id, tBTA_GATT_ID *p_descr_uuid);
-extern BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SRVC_ID *service_id, tBTA_GATT_ID *char_id, tBTA_GATT_ID *p_type);
-extern BOOLEAN bta_gattc_uuid_compare (tBT_UUID *p_src, tBT_UUID *p_tar, BOOLEAN is_precise);
-extern void bta_gattc_pack_attr_uuid(tBTA_GATTC_CACHE_ATTR   *p_attr, tBT_UUID *p_uuid);
+extern BOOLEAN bta_gattc_uuid_compare (const tBT_UUID *p_src, const tBT_UUID *p_tar, BOOLEAN is_precise);
 extern BOOLEAN bta_gattc_check_notif_registry(tBTA_GATTC_RCB  *p_clreg, tBTA_GATTC_SERV *p_srcb, tBTA_GATTC_NOTIFY  *p_notify);
-extern tBTA_GATT_STATUS bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV *p_srcb, tBT_UUID *p_descr_uuid, tGATT_VALUE *p_attr, tBTA_GATT_READ_VAL *p_value);
 extern BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR_PTR remote_bda, BOOLEAN add, BOOLEAN is_listen);
 extern BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR remote_bda, UINT8 role);
 extern UINT8 bta_gattc_num_reg_app(void);
-extern void bta_gattc_clear_notif_registration(UINT16 conn_id);
-extern tBTA_GATTC_SERV *bta_gattc_find_srvr_cache(BD_ADDR bda);
-extern BOOLEAN bta_gattc_charid_compare(tBTA_GATTC_CHAR_ID *p_src, tBTA_GATTC_CHAR_ID *p_tar);
-extern BOOLEAN bta_gattc_srvcid_compare(tBTA_GATT_SRVC_ID *p_src, tBTA_GATT_SRVC_ID *p_tar);
-extern void bta_gattc_cpygattid(tBTA_GATT_ID *p_des, tBTA_GATT_ID *p_src);
+extern void bta_gattc_clear_notif_registration(tBTA_GATTC_SERV *p_srcb, UINT16 conn_id, UINT16 start_handle, UINT16 end_handle);
+extern tBTA_GATTC_SERV * bta_gattc_find_srvr_cache(BD_ADDR bda);
 
 /* discovery functions */
 extern void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data);
@@ -530,17 +472,41 @@ extern void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type
 extern tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type);
 extern tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type);
 extern void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid);
-extern tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id, UINT8 query_type, tBTA_GATT_SRVC_ID *p_srvc_id,
-        tBTA_GATT_ID *p_start_rec, tBT_UUID *p_uuid_cond,
-        tBTA_GATT_ID *p_output, void *p_param);
-extern tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb);
-extern void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srcv, UINT16 num_attr, tBTA_GATTC_NV_ATTR *p_attr, UINT16 attr_index);
-extern BOOLEAN bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id);
+extern const list_t* bta_gattc_get_services(UINT16 conn_id);
+extern const tBTA_GATTC_SERVICE* bta_gattc_get_service_for_handle(UINT16 conn_id, UINT16 handle);
+tBTA_GATTC_CHARACTERISTIC*  bta_gattc_get_characteristic_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle);
+extern tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic(UINT16 conn_id, UINT16 handle);
+extern tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor(UINT16 conn_id, UINT16 handle);
+extern void bta_gattc_get_db_size_handle(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle, int *count);
+extern void bta_gattc_get_db_size_with_type_handle(UINT16 conn_id, bt_gatt_db_attribute_type_t type,
+                                                   UINT16 start_handle, UINT16 end_handle, UINT16 char_handle, int *count);
+extern void bta_gattc_get_service_with_uuid(UINT16 conn_id, tBT_UUID *svc_uuid,
+                                            btgatt_db_element_t **svc_db,
+                                            int *count);
+
+extern void bta_gattc_get_db_with_opration(UINT16 conn_id,
+                                                      bt_gatt_get_db_op_t op,
+                                                      UINT16 char_handle,
+                                                      tBT_UUID *incl_uuid,
+                                                      tBT_UUID *char_uuid,
+                                                      tBT_UUID *descr_uuid,
+                                                      UINT16 start_handle, UINT16 end_handle,
+                                                      btgatt_db_element_t **char_db,
+                                                      int *count);
+
+extern void bta_gattc_get_gatt_db(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle, btgatt_db_element_t **db, int *count);
 
+extern tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb);
+extern void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srcv, UINT16 num_attr, tBTA_GATTC_NV_ATTR *attr);
+extern void bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id);
+extern void bta_gattc_reset_discover_st(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_STATUS status);
 
 extern tBTA_GATTC_CONN *bta_gattc_conn_alloc(BD_ADDR remote_bda);
 extern tBTA_GATTC_CONN *bta_gattc_conn_find(BD_ADDR remote_bda);
 extern tBTA_GATTC_CONN *bta_gattc_conn_find_alloc(BD_ADDR remote_bda);
 extern BOOLEAN bta_gattc_conn_dealloc(BD_ADDR remote_bda);
 
+extern bool bta_gattc_cache_load(tBTA_GATTC_CLCB *p_clcb);
+extern void bta_gattc_cache_reset(BD_ADDR server_bda);
+
 #endif /* BTA_GATTC_INT_H */
index ca2a847d0a84875d814b742cca27f28fa226c13a..14cdb57217386af41fa0a0370c7ccf137781ec4f 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "blufi_int.h"
 
-#include "esp_wifi.h"
+//#include "esp_wifi.h"
 
 #if (GATTS_INCLUDED == TRUE)
 extern tBLUFI_ENV blufi_env;
index e326eff9afce3bb435a692799f0efc254c947eff..8cb0080ee1b49502b1614745319ba6af6cf69691 100644 (file)
@@ -174,42 +174,28 @@ uint16_t get_uuid16(tBT_UUID *p_uuid)
         return (UINT16) p_uuid->uu.uuid32;
     }
 }
+
 uint16_t set_read_value(uint8_t *gattc_if, esp_ble_gattc_cb_param_t *p_dest, tBTA_GATTC_READ *p_src)
 {
-    uint16_t descr_type = 0;
     uint16_t len = 0;
 
     p_dest->read.status = p_src->status;
     p_dest->read.conn_id = BTC_GATT_GET_CONN_ID(p_src->conn_id);
     *gattc_if = BTC_GATT_GET_GATT_IF(p_src->conn_id);
-    bta_to_btc_srvc_id(&p_dest->read.srvc_id, &p_src->srvc_id);
-    bta_to_btc_gatt_id(&p_dest->read.char_id, &p_src->char_id);
-    bta_to_btc_gatt_id(&p_dest->read.descr_id, &p_src->descr_type);
-
-    descr_type = get_uuid16(&p_src->descr_type.uuid);
-
-    switch (descr_type) {
-    case GATT_UUID_CHAR_AGG_FORMAT:
-        /* not supported */
-        p_dest->read.value_type = GATTC_READ_VALUE_TYPE_AGG_FORMAT;
-        p_dest->read.value_len = 0;
-        break;
-
-    default:
-        if (( p_src->status == BTA_GATT_OK ) && (p_src->p_value != NULL)) {
-            LOG_INFO("%s unformat.len = %d ", __FUNCTION__, p_src->p_value->unformat.len);
-            p_dest->read.value_len = p_src->p_value->unformat.len;
-            if ( p_src->p_value->unformat.len > 0  && p_src->p_value->unformat.p_value != NULL ) {
-                p_dest->read.value = p_src->p_value->unformat.p_value;
-            }
-            len += p_src->p_value->unformat.len;
-        } else {
-            p_dest->read.value_len = 0;
+    p_dest->read.status = p_src->status;
+    p_dest->read.handle = p_src->handle;
+
+    if (( p_src->status == BTA_GATT_OK ) && (p_src->p_value != NULL))
+    {
+        LOG_DEBUG("%s len = %d ", __func__, p_src->p_value->len);
+        p_dest->read.value_len = p_src->p_value->len;
+        if ( p_src->p_value->len > 0  && p_src->p_value->p_value != NULL ) {
+            p_dest->read.value = p_src->p_value->p_value;
         }
-
-        p_dest->read.value_type = GATTC_READ_VALUE_TYPE_VALUE;
-        break;
+        len += p_src->p_value->len;
+    } else {
+        p_dest->read.value_len = 0;
     }
 
     return len;
-}
+}
\ No newline at end of file
index 67098e8bf6cc00bf0f5d71fb6e254a32e6a06873..37f17fcca2f1350b4993c38f0472874504e78b44 100644 (file)
@@ -116,7 +116,6 @@ void btc_gattc_arg_deep_free(btc_msg_t *msg)
 
 }
 
-// TODO: to be finished, used in deep-copying data from lower layer
 static void btc_gattc_copy_req_data(btc_msg_t *msg, void *p_dest, void *p_src)
 {
     tBTA_GATTC *p_dest_data = (tBTA_GATTC *) p_dest;
@@ -128,14 +127,39 @@ static void btc_gattc_copy_req_data(btc_msg_t *msg, void *p_dest, void *p_src)
 
     // Allocate buffer for request data if necessary
     switch (msg->act) {
-    default:
-        break;
+        case BTA_GATTC_READ_DESCR_EVT:
+        case BTA_GATTC_READ_CHAR_EVT: {
+            if (p_src_data->read.p_value && p_src_data->read.p_value->p_value) {
+                p_dest_data->read.p_value = (tBTA_GATT_UNFMT  *)osi_malloc(sizeof(tBTA_GATT_UNFMT) + p_src_data->read.p_value->len);
+                p_dest_data->read.p_value->p_value = (uint8_t *)(p_dest_data->read.p_value + 1);
+                if (p_dest_data->read.p_value && p_dest_data->read.p_value->p_value) {
+                    p_dest_data->read.p_value->len = p_src_data->read.p_value->len;
+                    memcpy(p_dest_data->read.p_value->p_value, p_src_data->read.p_value->p_value, p_src_data->read.p_value->len);
+                } else {
+                    LOG_ERROR("%s %d no mem\n", __func__, msg->act);
+                }
+            }
+            break;
+        } 
+        default:
+            break;
     }
 }
 
-// TODO: to be finished, used to free deep-copied data allocated using btc_gattc_copy_req_data()
 static void btc_gattc_free_req_data(btc_msg_t *msg)
 {
+    tBTA_GATTC *arg = (tBTA_GATTC *)(msg->arg);
+    switch (msg->act) {
+        case BTA_GATTC_READ_DESCR_EVT:
+        case BTA_GATTC_READ_CHAR_EVT: {
+            if (arg->read.p_value) {
+                osi_free(arg->read.p_value);
+            }
+            break;
+        }
+        default:
+            break;
+    }
     return;
 }
 
@@ -184,6 +208,74 @@ static void btc_gattc_cfg_mtu(btc_ble_gattc_args_t *arg)
     BTA_GATTC_ConfigureMTU (arg->cfg_mtu.conn_id);
 }
 
+static esp_gatt_status_t btc_gattc_check_valid_param(int num, uint16_t offset)
+{
+    if (num == 0) {
+        return ESP_GATT_NOT_FOUND;
+    } else if (offset >= num) {
+        return ESP_GATT_INVALID_OFFSET;
+    }
+
+    return ESP_GATT_OK;
+}
+
+static void btc_gattc_fill_gatt_db_conversion(uint16_t count, uint16_t num, esp_gatt_db_attr_type_t type,
+                                                                  uint16_t offset, void *result, btgatt_db_element_t *db)
+{
+    tBT_UUID bta_uuid = {0};
+    uint16_t db_size = (count + offset > num) ? (num - offset) : count;
+    switch(type) {
+        case ESP_GATT_DB_PRIMARY_SERVICE:
+        case ESP_GATT_DB_SECONDARY_SERVICE: {
+            esp_gattc_service_elem_t *svc_result = (esp_gattc_service_elem_t *)result;
+            for (int i = 0; i < db_size; i++) {
+                svc_result->is_primary = (db[offset + i].type == BTGATT_DB_PRIMARY_SERVICE) ? true : false;
+                svc_result->start_handle = db[offset + i].start_handle;
+                svc_result->end_handle = db[offset + i].end_handle;
+                btc128_to_bta_uuid(&bta_uuid, db[offset + i].uuid.uu);
+                bta_to_btc_uuid(&svc_result->uuid, &bta_uuid);
+                svc_result++;
+            }
+            break;
+        }
+        case ESP_GATT_DB_CHARACTERISTIC: {
+            esp_gattc_char_elem_t *char_result = (esp_gattc_char_elem_t *)result;
+            for (int i = 0; i < db_size; i++) {
+                char_result->char_handle = db[offset + i].attribute_handle;
+                char_result->properties = db[offset + i].properties;
+                btc128_to_bta_uuid(&bta_uuid, db[offset + i].uuid.uu);
+                bta_to_btc_uuid(&char_result->uuid, &bta_uuid);
+                char_result++;
+            }
+            break;
+        }
+        case ESP_GATT_DB_DESCRIPTOR: {
+            esp_gattc_descr_elem_t *descr_result = (esp_gattc_descr_elem_t *)result;
+            for (int i = 0; i < (num - offset); i++) {
+                descr_result->handle = db[offset + i].attribute_handle;
+                btc128_to_bta_uuid(&bta_uuid, db[offset + i].uuid.uu);
+                bta_to_btc_uuid(&descr_result->uuid, &bta_uuid);
+                descr_result++;
+            }
+            break;
+        }
+        case ESP_GATT_DB_INCLUDED_SERVICE: {
+            esp_gattc_incl_svc_elem_t *incl_result = (esp_gattc_incl_svc_elem_t *)result;
+            for (int i = 0; i < db_size; i++) {
+                incl_result->handle = db[offset + i].attribute_handle;
+                incl_result->incl_srvc_s_handle = db[offset + i].start_handle;
+                btc128_to_bta_uuid(&bta_uuid, db[offset + i].uuid.uu);
+                bta_to_btc_uuid(&incl_result->uuid, &bta_uuid);
+                incl_result++;
+            }
+            break;
+        }
+        default:
+            LOG_WARN("%s(), Not support type(%d)", __func__, type);
+            break;
+    }
+}
+
 static void btc_gattc_search_service(btc_ble_gattc_args_t *arg)
 {
     tBT_UUID srvc_uuid;
@@ -196,198 +288,305 @@ static void btc_gattc_search_service(btc_ble_gattc_args_t *arg)
     }
 }
 
-static void btc_gattc_get_first_char(btc_ble_gattc_args_t *arg)
+esp_gatt_status_t btc_ble_gattc_get_service(uint16_t conn_id, esp_bt_uuid_t *svc_uuid, 
+                                                           esp_gattc_service_elem_t *result,
+                                                           uint16_t *count, uint16_t offset)
 {
-    esp_gatt_id_t char_id;
-    tBTA_GATT_STATUS status;
-    tBTA_GATTC_CHAR_ID out_char_id;
-    tBTA_GATT_CHAR_PROP out_char_prop;
-    tBTA_GATT_SRVC_ID srvc_id;
-    esp_ble_gattc_cb_param_t param;
-    esp_gatt_if_t gattc_if;
-
-    btc_to_bta_srvc_id(&srvc_id, &arg->get_first_char.service_id);
-    status = BTA_GATTC_GetFirstChar(arg->get_first_char.conn_id, &srvc_id, NULL,
-                                    &out_char_id, &out_char_prop);
-    if (status == 0) {
-        bta_to_btc_gatt_id(&char_id, &out_char_id.char_id);
+    esp_gatt_status_t status;
+    btgatt_db_element_t *db = NULL;
+    int svc_num = 0;
+    tBT_UUID *bta_uuid = NULL;
+    if (svc_uuid) {
+        bta_uuid = osi_malloc(sizeof(tBT_UUID));
+        btc_to_bta_uuid(bta_uuid, svc_uuid);
+    }
+    
+    BTA_GATTC_GetServiceWithUUID(conn_id, bta_uuid, &db, &svc_num);
+
+    if ((status = btc_gattc_check_valid_param(svc_num, offset)) != ESP_GATT_OK) {
+        if (db) {
+            osi_free(db);
+        }
+        if (bta_uuid) {
+            osi_free(bta_uuid);
+        }
+        return status; 
+    } else {
+        btc_gattc_fill_gatt_db_conversion(*count, (uint16_t)svc_num, ESP_GATT_DB_PRIMARY_SERVICE, offset, (void *)result, db);
     }
 
-    gattc_if = BTC_GATT_GET_GATT_IF(arg->get_first_char.conn_id);
-    memset(&param, 0, sizeof(esp_ble_gattc_cb_param_t));
-    param.get_char.conn_id = BTC_GATT_GET_CONN_ID(arg->get_first_char.conn_id);
-    param.get_char.status = status;
-    memcpy(&param.get_char.srvc_id, &arg->get_first_char.service_id, sizeof(esp_gatt_srvc_id_t));
-    memcpy(&param.get_char.char_id, &char_id, sizeof(esp_gatt_id_t));
-    param.get_char.char_prop = out_char_prop;
-    btc_gattc_cb_to_app(ESP_GATTC_GET_CHAR_EVT, gattc_if, &param);
+    *count = svc_num;
+    //don't forget to free the db buffer after used.
+    if (db) {
+        osi_free(db);
+    }
+    if (bta_uuid) {
+        osi_free(bta_uuid);
+    }
+    return ESP_GATT_OK;
 }
 
-static void btc_gattc_get_next_char(btc_ble_gattc_args_t *arg)
+esp_gatt_status_t btc_ble_gattc_get_all_char(uint16_t conn_id,
+                                             uint16_t start_handle,
+                                             uint16_t end_handle,
+                                             esp_gattc_char_elem_t *result,
+                                             uint16_t *count, uint16_t offset)
 {
-    esp_gatt_id_t char_id;
-    tBTA_GATT_STATUS status;
-    tBTA_GATTC_CHAR_ID in_char_id;
-    tBTA_GATTC_CHAR_ID out_char_id;
-    tBTA_GATT_CHAR_PROP out_char_prop;
-    esp_ble_gattc_cb_param_t param;
-    esp_gatt_if_t gattc_if;
-
-    btc_to_bta_srvc_id(&in_char_id.srvc_id, &arg->get_next_char.service_id);
-    btc_to_bta_gatt_id(&in_char_id.char_id, &arg->get_next_char.char_id);
-
-    status = BTA_GATTC_GetNextChar(arg->get_next_char.conn_id, &in_char_id, NULL,
-                                   &out_char_id, &out_char_prop);
-
-    if (status == 0) {
-        bta_to_btc_gatt_id(&char_id, &out_char_id.char_id);
+    esp_gatt_status_t status;
+    btgatt_db_element_t *db = NULL;
+    int char_num = 0;
+    BTA_GATTC_GetAllChar(conn_id, start_handle, end_handle, &db, &char_num);
+
+    if ((status = btc_gattc_check_valid_param(char_num, offset)) != ESP_GATT_OK) {
+        if (db) {
+            osi_free(db);
+        }
+        return status;
+    } else {
+        btc_gattc_fill_gatt_db_conversion(*count, (uint16_t)char_num, ESP_GATT_DB_CHARACTERISTIC, offset, (void *)result, db);
     }
 
-    gattc_if = BTC_GATT_GET_GATT_IF(arg->get_next_char.conn_id);
-    memset(&param, 0, sizeof(esp_ble_gattc_cb_param_t));
-    param.get_char.conn_id = BTC_GATT_GET_CONN_ID(arg->get_next_char.conn_id);
-    param.get_char.status = status;
-    memcpy(&param.get_char.srvc_id, &arg->get_next_char.service_id, sizeof(esp_gatt_srvc_id_t));
-    memcpy(&param.get_char.char_id, &char_id, sizeof(esp_gatt_id_t));
-    param.get_char.char_prop = out_char_prop;
-    btc_gattc_cb_to_app(ESP_GATTC_GET_CHAR_EVT, gattc_if, &param);
+    *count = char_num;
+    //don't forget to free the db buffer after used.
+    if (db) {
+        osi_free(db);
+    }
+    return ESP_GATT_OK;
 }
 
-static void btc_gattc_get_first_descr(btc_ble_gattc_args_t *arg)
+esp_gatt_status_t btc_ble_gattc_get_all_descr(uint16_t conn_id,
+                                              uint16_t char_handle,
+                                              esp_gattc_descr_elem_t *result,
+                                              uint16_t *count, uint16_t offset)
 {
-    esp_gatt_id_t descr_id;
-    tBTA_GATT_STATUS status;
-    tBTA_GATTC_CHAR_ID in_char_id;
-    tBTA_GATTC_CHAR_DESCR_ID out_char_descr_id;
-    esp_ble_gattc_cb_param_t param;
-    esp_gatt_if_t gattc_if;
-
-    btc_to_bta_srvc_id(&in_char_id.srvc_id, &arg->get_first_descr.service_id);
-    btc_to_bta_gatt_id(&in_char_id.char_id, &arg->get_first_descr.char_id);
-
-    status = BTA_GATTC_GetFirstCharDescr(arg->get_first_descr.conn_id, &in_char_id, NULL,
-                                         &out_char_descr_id);
-
-    if (status == 0) {
-        bta_to_btc_gatt_id(&descr_id, &out_char_descr_id.descr_id);
+    esp_gatt_status_t status;
+    btgatt_db_element_t *db = NULL;
+    int descr_num = 0;
+    BTA_GATTC_GetAllDescriptor(conn_id, char_handle, &db, &descr_num);
+
+    if ((status = btc_gattc_check_valid_param(descr_num, offset)) != ESP_GATT_OK) {
+        if (db) {
+            osi_free(db);
+        }
+        return status; 
+    } else {
+        btc_gattc_fill_gatt_db_conversion(*count, (uint16_t)descr_num, ESP_GATT_DB_DESCRIPTOR, offset, (void *)result, db);
     }
 
-    gattc_if = BTC_GATT_GET_GATT_IF(arg->get_first_descr.conn_id);
-    memset(&param, 0, sizeof(esp_ble_gattc_cb_param_t));
-    param.get_descr.conn_id = BTC_GATT_GET_CONN_ID(arg->get_first_descr.conn_id);
-    param.get_descr.status = status;
-    memcpy(&param.get_descr.srvc_id, &arg->get_first_descr.service_id, sizeof(esp_gatt_srvc_id_t));
-    memcpy(&param.get_descr.char_id, &arg->get_first_descr.char_id, sizeof(esp_gatt_id_t));
-    memcpy(&param.get_descr.descr_id, &descr_id, sizeof(esp_gatt_id_t));
-    btc_gattc_cb_to_app(ESP_GATTC_GET_DESCR_EVT, gattc_if, &param);
+    *count = descr_num;
+    //don't forget to free the db buffer after used.
+    if (db) {
+        osi_free(db);
+    }
+    return ESP_GATT_OK;
 }
 
-static void btc_gattc_get_next_descr(btc_ble_gattc_args_t *arg)
+esp_gatt_status_t btc_ble_gattc_get_char_by_uuid(uint16_t conn_id,
+                                                 uint16_t start_handle,
+                                                 uint16_t end_handle,
+                                                 esp_bt_uuid_t char_uuid,
+                                                 esp_gattc_char_elem_t *result, 
+                                                 uint16_t *count)
 {
-    esp_gatt_id_t descr_id;
-    tBTA_GATT_STATUS status;
-    tBTA_GATTC_CHAR_DESCR_ID in_char_descr_id;
-    tBTA_GATTC_CHAR_DESCR_ID out_char_descr_id;
-    esp_ble_gattc_cb_param_t param;
-    esp_gatt_if_t gattc_if;
-
-    btc_to_bta_srvc_id(&in_char_descr_id.char_id.srvc_id, &arg->get_next_descr.service_id);
-    btc_to_bta_gatt_id(&in_char_descr_id.char_id.char_id, &arg->get_next_descr.char_id);
-    btc_to_bta_gatt_id(&in_char_descr_id.descr_id, &arg->get_next_descr.descr_id);
+    esp_gatt_status_t status;
+    btgatt_db_element_t *db = NULL;
+    int char_num = 0;
+    tBT_UUID bta_uuid = {0};
+    btc_to_bta_uuid(&bta_uuid, &char_uuid);
+    BTA_GATTC_GetCharByUUID(conn_id, start_handle, end_handle, bta_uuid, &db, &char_num);
+
+    if ((status = btc_gattc_check_valid_param(char_num, 0)) != ESP_GATT_OK) {
+        if (db) {
+            osi_free(db);
+        }
+        return status;
+    } else {
+        btc_gattc_fill_gatt_db_conversion(*count, (uint16_t)char_num, ESP_GATT_DB_CHARACTERISTIC, 0, (void *)result, db);
+    }
 
-    status = BTA_GATTC_GetNextCharDescr(arg->get_next_descr.conn_id, &in_char_descr_id
-                                        , NULL, &out_char_descr_id);
-    if (status == 0) {
-        bta_to_btc_gatt_id(&descr_id, &out_char_descr_id.descr_id);
+    *count = char_num;
+    //don't forget to free the db buffer after used.
+    if (db) {
+        osi_free(db);
     }
+    return ESP_GATT_OK;
+}
 
-    gattc_if = BTC_GATT_GET_GATT_IF(arg->get_next_descr.conn_id);
-    memset(&param, 0, sizeof(esp_ble_gattc_cb_param_t));
-    param.get_descr.conn_id = BTC_GATT_GET_CONN_ID(arg->get_next_descr.conn_id);
-    param.get_descr.status = status;
-    memcpy(&param.get_descr.srvc_id, &arg->get_next_descr.service_id, sizeof(esp_gatt_srvc_id_t));
-    memcpy(&param.get_descr.char_id, &arg->get_next_descr.char_id, sizeof(esp_gatt_id_t));
-    memcpy(&param.get_descr.descr_id, &descr_id, sizeof(esp_gatt_id_t));
-    btc_gattc_cb_to_app(ESP_GATTC_GET_DESCR_EVT, gattc_if, &param);
+esp_gatt_status_t btc_ble_gattc_get_descr_by_uuid(uint16_t conn_id,
+                                                  uint16_t start_handle,
+                                                  uint16_t end_handle,
+                                                  esp_bt_uuid_t char_uuid,
+                                                  esp_bt_uuid_t descr_uuid,
+                                                  esp_gattc_descr_elem_t *result, 
+                                                  uint16_t *count)
+{
+    esp_gatt_status_t status;
+    btgatt_db_element_t *db = NULL;
+    int descr_num = 0;
+    tBT_UUID bta_char_uuid = {0};
+    tBT_UUID bta_descr_uuid = {0};
+    btc_to_bta_uuid(&bta_char_uuid, &char_uuid);
+    btc_to_bta_uuid(&bta_descr_uuid, &descr_uuid);
+    
+    BTA_GATTC_GetDescrByUUID(conn_id, start_handle, end_handle, 
+                             bta_char_uuid, bta_descr_uuid, &db, &descr_num);
+
+    if ((status = btc_gattc_check_valid_param(descr_num, 0)) != ESP_GATT_OK) {
+        if (db) {
+            osi_free(db);
+        }
+        return status;
+    } else {
+        btc_gattc_fill_gatt_db_conversion(*count, (uint16_t)descr_num, ESP_GATT_DB_DESCRIPTOR, 0, (void *)result, db);
+    }
+    
+    *count = descr_num;
+    //don't forget to free the db buffer after used.
+    if (db) {
+        osi_free(db);
+    }
+    return ESP_GATT_OK;
 }
 
-static void btc_gattc_get_first_incl_service(btc_ble_gattc_args_t *arg)
+esp_gatt_status_t btc_ble_gattc_get_descr_by_char_handle(uint16_t conn_id,
+                                                         uint16_t char_handle,
+                                                         esp_bt_uuid_t descr_uuid,
+                                                         esp_gattc_descr_elem_t *result,
+                                                         uint16_t *count)
 {
-    esp_gatt_srvc_id_t incl_srvc_id;
-    tBTA_GATT_STATUS status;
-    tBTA_GATT_SRVC_ID srvc_id;
-    tBTA_GATTC_INCL_SVC_ID out_incl_svc_id;
-    esp_ble_gattc_cb_param_t param;
-    esp_gatt_if_t gattc_if;
+    esp_gatt_status_t status;
+    btgatt_db_element_t *db = NULL;
+    int descr_num = 0;
+    tBT_UUID bta_descr_uuid = {0};
+    btc_to_bta_uuid(&bta_descr_uuid, &descr_uuid);
+    
+    BTA_GATTC_GetDescrByCharHandle(conn_id, char_handle, bta_descr_uuid, &db, &descr_num);
+
+    if ((status = btc_gattc_check_valid_param(descr_num, 0)) != ESP_GATT_OK) {
+        if (db) {
+            osi_free(db);
+        }
+        return status;
+    } else {
+        btc_gattc_fill_gatt_db_conversion(*count, (uint16_t)descr_num, ESP_GATT_DB_DESCRIPTOR, 0, (void *)result, db);
+    }
 
-    btc_to_bta_srvc_id(&srvc_id, &arg->get_first_incl_srvc.service_id);
+    *count = descr_num;
+    //don't forget to free the db buffer after used.
+    if (db) {
+        osi_free(db);
+    }
+    return ESP_GATT_OK;
+    
+}
 
-    status = BTA_GATTC_GetFirstIncludedService(arg->get_first_incl_srvc.conn_id, &srvc_id,
-             NULL, &out_incl_svc_id);
+esp_gatt_status_t btc_ble_gattc_get_include_service(uint16_t conn_id,
+                                                    uint16_t start_handle,
+                                                    uint16_t end_handle,
+                                                    esp_bt_uuid_t *incl_uuid,
+                                                    esp_gattc_incl_svc_elem_t *result,
+                                                    uint16_t *count)
+{
+    esp_gatt_status_t status;
+    btgatt_db_element_t *db = NULL;
+    int incl_num = 0;
+    tBT_UUID bta_uuid = {0};
+
+    if (incl_uuid != NULL) {
+        btc_to_bta_uuid(&bta_uuid, incl_uuid);
+        BTA_GATTC_GetIncludeService(conn_id, start_handle, end_handle, &bta_uuid, &db, &incl_num);
+    } else {
+        BTA_GATTC_GetIncludeService(conn_id, start_handle, end_handle, NULL, &db, &incl_num);
+    }
 
-    bta_to_btc_srvc_id(&incl_srvc_id, &out_incl_svc_id.incl_svc_id);
+    if ((status = btc_gattc_check_valid_param(incl_num, 0)) != ESP_GATT_OK) {
+        if (db) {
+            osi_free(db);
+        }
+        return status;
+    }else {
+        btc_gattc_fill_gatt_db_conversion(*count, (uint16_t)incl_num, ESP_GATT_DB_INCLUDED_SERVICE, 0, (void *)result, db);
+    }
 
-    gattc_if = BTC_GATT_GET_GATT_IF(arg->get_first_incl_srvc.conn_id);
-    memset(&param, 0, sizeof(esp_ble_gattc_cb_param_t));
-    param.get_incl_srvc.conn_id = BTC_GATT_GET_CONN_ID(arg->get_first_incl_srvc.conn_id);
-    param.get_incl_srvc.status = status;
-    memcpy(&param.get_incl_srvc.srvc_id, &arg->get_first_incl_srvc.service_id, sizeof(esp_gatt_srvc_id_t));
-    memcpy(&param.get_incl_srvc.incl_srvc_id, &incl_srvc_id, sizeof(esp_gatt_srvc_id_t));
-    btc_gattc_cb_to_app(ESP_GATTC_GET_INCL_SRVC_EVT, gattc_if, &param);
+    *count = incl_num;
+    //don't forget to free the db buffer after used.
+    if (db) {
+        osi_free(db);
+    }
+    return ESP_GATT_OK;
 }
 
-static void btc_gattc_get_next_incl_service(btc_ble_gattc_args_t *arg)
+esp_gatt_status_t btc_ble_gattc_get_attr_count(uint16_t conn_id,
+                                               esp_gatt_db_attr_type_t type,
+                                               uint16_t start_handle,
+                                               uint16_t end_handle,
+                                               uint16_t char_handle,
+                                               uint16_t *count)
 {
-    esp_gatt_srvc_id_t incl_srvc_id;
-    tBTA_GATT_STATUS status;
-    tBTA_GATTC_INCL_SVC_ID in_incl_svc_id;
-    tBTA_GATTC_INCL_SVC_ID out_incl_svc_id;
-    esp_ble_gattc_cb_param_t param;
-    esp_gatt_if_t gattc_if;
-
-    btc_to_bta_srvc_id(&in_incl_svc_id.srvc_id, &arg->get_next_incl_srvc.service_id);
-    btc_to_bta_srvc_id(&in_incl_svc_id.incl_svc_id, &arg->get_next_incl_srvc.start_service_id);
+    if (type == ESP_GATT_DB_ALL) {
+        BTA_GATTC_GetDBSize(conn_id, start_handle, end_handle, (int *)count);
+    } else {
+        BTA_GATTC_GetDBSizeByType(conn_id, type, start_handle, end_handle, char_handle, (int *)count);
+    }
 
-    status = BTA_GATTC_GetNextIncludedService(arg->get_next_incl_srvc.conn_id, &in_incl_svc_id,
-             NULL, &out_incl_svc_id);
+    return ESP_GATT_OK;
+}
 
-    bta_to_btc_srvc_id(&incl_srvc_id, &out_incl_svc_id.incl_svc_id);
+esp_gatt_status_t btc_ble_gattc_get_db(uint16_t conn_id, uint16_t start_handle, uint16_t end_handle,
+                                       esp_gattc_db_elem_t *db, uint16_t *count)
+{
+    btgatt_db_element_t *get_db = NULL;
+    int num = 0;
+    tBT_UUID bta_uuid;
+    uint16_t db_size = 0;
+    BTA_GATTC_GetGattDb(conn_id, start_handle, end_handle, &get_db, &num);
+
+    if (num == 0) {
+        if (get_db) {
+            osi_free(get_db);
+        }
+        return ESP_GATT_NOT_FOUND;
+    }
 
-    gattc_if = BTC_GATT_GET_GATT_IF(arg->get_next_incl_srvc.conn_id);
-    memset(&param, 0, sizeof(esp_ble_gattc_cb_param_t));
-    param.get_incl_srvc.conn_id = BTC_GATT_GET_CONN_ID(arg->get_next_incl_srvc.conn_id);
-    param.get_incl_srvc.status = status;
-    memcpy(&param.get_incl_srvc.srvc_id, &arg->get_next_incl_srvc.service_id, sizeof(esp_gatt_srvc_id_t));
-    memcpy(&param.get_incl_srvc.incl_srvc_id, &incl_srvc_id, sizeof(esp_gatt_srvc_id_t));
-    btc_gattc_cb_to_app(ESP_GATTC_GET_INCL_SRVC_EVT, gattc_if, &param);
+    db_size = (*count > num) ? num : (*count);
+    for (int i = 0; i < db_size; i++) {
+        db[i].type = get_db[i].type;
+        db[i].attribute_handle = get_db[i].id;
+        db[i].start_handle = get_db[i].start_handle;
+        db[i].end_handle = get_db[i].end_handle;
+        btc128_to_bta_uuid(&bta_uuid, get_db[i].uuid.uu);
+        bta_to_btc_uuid(&db[i].uuid, &bta_uuid);
+    }
+    *count = num;
+    //don't forget to free the db buffer after used.
+    if (get_db) {
+        osi_free(get_db);
+    }
+    return ESP_GATT_OK;
 }
 
 static void btc_gattc_read_char(btc_ble_gattc_args_t *arg)
 {
-    tBTA_GATTC_CHAR_ID in_char_id;
-    btc_to_bta_srvc_id(&in_char_id.srvc_id, &arg->read_char.service_id);
-    btc_to_bta_gatt_id(&in_char_id.char_id, &arg->read_char.char_id);
-    BTA_GATTC_ReadCharacteristic(arg->read_char.conn_id, &in_char_id, arg->read_char.auth_req);
+    BTA_GATTC_ReadCharacteristic(arg->read_char.conn_id, arg->read_char.handle, arg->read_char.auth_req);
 }
 
-static void btc_gattc_read_char_descr(btc_ble_gattc_args_t *arg)
+static void btc_gattc_read_multiple_char(btc_ble_gattc_args_t *arg)
 {
-    tBTA_GATTC_CHAR_DESCR_ID in_char_descr_id;
-    btc_to_bta_srvc_id(&in_char_descr_id.char_id.srvc_id, &arg->read_descr.service_id);
-    btc_to_bta_gatt_id(&in_char_descr_id.char_id.char_id, &arg->read_descr.char_id);
-    btc_to_bta_gatt_id(&in_char_descr_id.descr_id, &arg->read_descr.descr_id);
+    tBTA_GATTC_MULTI bta_multi;
+    bta_multi.num_attr = arg->read_multiple.num_attr;
+    memcpy(bta_multi.handles, arg->read_multiple.handles, BTA_GATTC_MULTI_MAX);
+    BTA_GATTC_ReadMultiple(arg->read_multiple.conn_id, &bta_multi, arg->read_multiple.auth_req);
+}
 
-    BTA_GATTC_ReadCharDescr(arg->read_descr.conn_id, &in_char_descr_id, arg->read_descr.auth_req);
+static void btc_gattc_read_char_descr(btc_ble_gattc_args_t *arg)
+{
+    BTA_GATTC_ReadCharDescr(arg->read_descr.conn_id, arg->read_descr.handle, arg->read_descr.auth_req);
 }
 
 static void btc_gattc_write_char(btc_ble_gattc_args_t *arg)
 {
-    tBTA_GATTC_CHAR_ID in_char_id;
-
-    btc_to_bta_srvc_id(&in_char_id.srvc_id, &arg->write_char.service_id);
-    btc_to_bta_gatt_id(&in_char_id.char_id, &arg->write_char.char_id);
-
-    BTA_GATTC_WriteCharValue(arg->write_char.conn_id, &in_char_id,
+    BTA_GATTC_WriteCharValue(arg->write_char.conn_id, 
+                             arg->write_char.handle,
                              arg->write_char.write_type,
                              arg->write_char.value_len,
                              arg->write_char.value,
@@ -396,28 +595,21 @@ static void btc_gattc_write_char(btc_ble_gattc_args_t *arg)
 
 static void btc_gattc_write_char_descr(btc_ble_gattc_args_t *arg)
 {
-    tBTA_GATTC_CHAR_DESCR_ID in_char_descr_id;
     tBTA_GATT_UNFMT descr_val;
-    btc_to_bta_srvc_id(&in_char_descr_id.char_id.srvc_id, &arg->write_descr.service_id);
-    btc_to_bta_gatt_id(&in_char_descr_id.char_id.char_id, &arg->write_descr.char_id);
-    btc_to_bta_gatt_id(&in_char_descr_id.descr_id, &arg->write_descr.descr_id);
 
     descr_val.len = arg->write_descr.value_len;
     descr_val.p_value = arg->write_descr.value;
 
-    BTA_GATTC_WriteCharDescr(arg->write_descr.conn_id, &in_char_descr_id,
+    BTA_GATTC_WriteCharDescr(arg->write_descr.conn_id, 
+                             arg->write_descr.handle,
                              arg->write_descr.write_type, &descr_val,
                              arg->write_descr.auth_req);
 }
 
 static void btc_gattc_prepare_write(btc_ble_gattc_args_t *arg)
 {
-    tBTA_GATTC_CHAR_ID in_char_id;
-    btc_to_bta_srvc_id(&in_char_id.srvc_id, &arg->prep_write.service_id);
-    btc_to_bta_gatt_id(&in_char_id.char_id, &arg->prep_write.char_id);
-
     BTA_GATTC_PrepareWrite(arg->prep_write.conn_id,
-                           &in_char_id,
+                           arg->prep_write.handle,
                            arg->prep_write.offset,
                            arg->prep_write.value_len,
                            arg->prep_write.value,
@@ -425,16 +617,12 @@ static void btc_gattc_prepare_write(btc_ble_gattc_args_t *arg)
 }
 static void btc_gattc_prepare_write_char_descr(btc_ble_gattc_args_t *arg)
 {
-    tBTA_GATTC_CHAR_DESCR_ID in_char_descr_id;
     tBTA_GATT_UNFMT descr_val;
-    btc_to_bta_srvc_id(&in_char_descr_id.char_id.srvc_id, &arg->prep_write_descr.service_id);
-    btc_to_bta_gatt_id(&in_char_descr_id.char_id.char_id, &arg->prep_write_descr.char_id);
-    btc_to_bta_gatt_id(&in_char_descr_id.descr_id, &arg->prep_write_descr.descr_id);
 
     descr_val.len = arg->prep_write_descr.value_len;
     descr_val.p_value = arg->prep_write_descr.value;
     BTA_GATTC_PrepareWriteCharDescr(arg->prep_write_descr.conn_id,
-                                    &in_char_descr_id,
+                                    arg->prep_write_descr.handle,
                                     arg->prep_write_descr.offset,
                                     &descr_val,
                                     arg->prep_write_descr.auth_req);
@@ -448,40 +636,30 @@ static void btc_gattc_execute_wrtie(btc_ble_gattc_args_t *arg)
 static void btc_gattc_reg_for_notify(btc_ble_gattc_args_t *arg)
 {
     tBTA_GATT_STATUS status;
-    tBTA_GATTC_CHAR_ID in_char_id;
     esp_ble_gattc_cb_param_t param;
 
-    btc_to_bta_srvc_id(&in_char_id.srvc_id, &arg->reg_for_notify.service_id);
-    btc_to_bta_gatt_id(&in_char_id.char_id, &arg->reg_for_notify.char_id);
-
     status = BTA_GATTC_RegisterForNotifications(arg->reg_for_notify.gattc_if,
              arg->reg_for_notify.remote_bda,
-             &in_char_id);
+             arg->reg_for_notify.handle);
 
     memset(&param, 0, sizeof(esp_ble_gattc_cb_param_t));
     param.reg_for_notify.status = status;
-    memcpy(&param.reg_for_notify.srvc_id, &arg->reg_for_notify.service_id, sizeof(esp_gatt_srvc_id_t));
-    memcpy(&param.reg_for_notify.char_id, &arg->reg_for_notify.char_id, sizeof(esp_gatt_id_t));
+    param.reg_for_notify.handle = arg->reg_for_notify.handle;
     btc_gattc_cb_to_app(ESP_GATTC_REG_FOR_NOTIFY_EVT, arg->reg_for_notify.gattc_if, &param);
 }
 
 static void btc_gattc_unreg_for_notify(btc_ble_gattc_args_t *arg)
 {
     tBTA_GATT_STATUS status;
-    tBTA_GATTC_CHAR_ID in_char_id;
     esp_ble_gattc_cb_param_t param;
 
-    btc_to_bta_srvc_id(&in_char_id.srvc_id, &arg->unreg_for_notify.service_id);
-    btc_to_bta_gatt_id(&in_char_id.char_id, &arg->unreg_for_notify.char_id);
-
     status = BTA_GATTC_DeregisterForNotifications(arg->unreg_for_notify.gattc_if,
              arg->unreg_for_notify.remote_bda,
-             &in_char_id);
+             arg->unreg_for_notify.handle);
 
     memset(&param, 0, sizeof(esp_ble_gattc_cb_param_t));
     param.unreg_for_notify.status = status;
-    memcpy(&param.unreg_for_notify.srvc_id, &arg->unreg_for_notify.service_id, sizeof(esp_gatt_srvc_id_t));
-    memcpy(&param.unreg_for_notify.char_id, &arg->unreg_for_notify.char_id, sizeof(esp_gatt_id_t));
+    param.unreg_for_notify.handle = arg->unreg_for_notify.handle;
     btc_gattc_cb_to_app(ESP_GATTC_UNREG_FOR_NOTIFY_EVT, arg->unreg_for_notify.gattc_if, &param);
 }
 
@@ -490,6 +668,7 @@ void btc_gattc_call_handler(btc_msg_t *msg)
     btc_ble_gattc_args_t *arg = (btc_ble_gattc_args_t *)(msg->arg);
     switch (msg->act) {
     case BTC_GATTC_ACT_APP_REGISTER:
+        LOG_ERROR("%s()", __func__);
         btc_gattc_app_register(arg);
         break;
     case BTC_GATTC_ACT_APP_UNREGISTER:
@@ -507,27 +686,12 @@ void btc_gattc_call_handler(btc_msg_t *msg)
     case BTC_GATTC_ACT_SEARCH_SERVICE:
         btc_gattc_search_service(arg);
         break;
-    case BTC_GATTC_ACT_GET_FIRST_CHAR:
-        btc_gattc_get_first_char(arg);
-        break;
-    case BTC_GATTC_ACT_GET_NEXT_CHAR:
-        btc_gattc_get_next_char(arg);
-        break;
-    case BTC_GATTC_ACT_GET_FIRST_DESCR:
-        btc_gattc_get_first_descr(arg);
-        break;
-    case BTC_GATTC_ACT_GET_NEXT_DESCR:
-        btc_gattc_get_next_descr(arg);
-        break;
-    case BTC_GATTC_ACT_GET_FIRST_INCL_SERVICE:
-        btc_gattc_get_first_incl_service(arg);
-        break;
-    case BTC_GATTC_ACT_GET_NEXT_INCL_SERVICE:
-        btc_gattc_get_next_incl_service(arg);
-        break;
     case BTC_GATTC_ACT_READ_CHAR:
         btc_gattc_read_char(arg);
         break;
+    case BTC_GATTC_ACT_READ_MULTIPLE_CHAR:
+        btc_gattc_read_multiple_char(arg);
+        break;
     case BTC_GATTC_ACT_READ_CHAR_DESCR:
         btc_gattc_read_char_descr(arg);
         break;
@@ -566,8 +730,8 @@ void btc_gattc_call_handler(btc_msg_t *msg)
 void btc_gattc_cb_handler(btc_msg_t *msg)
 {
     tBTA_GATTC *arg = (tBTA_GATTC *)(msg->arg);
-    esp_gatt_if_t gattc_if;
-    esp_ble_gattc_cb_param_t param;
+    esp_gatt_if_t gattc_if = 0;
+    esp_ble_gattc_cb_param_t param = {0};
 
     memset(&param, 0, sizeof(esp_ble_gattc_cb_param_t));
 
@@ -602,8 +766,7 @@ void btc_gattc_cb_handler(btc_msg_t *msg)
         gattc_if = BTC_GATT_GET_GATT_IF(write->conn_id);
         param.write.conn_id = BTC_GATT_GET_CONN_ID(write->conn_id);
         param.write.status = write->status;
-        bta_to_btc_srvc_id(&param.write.srvc_id, &write->srvc_id);
-        bta_to_btc_gatt_id(&param.write.char_id, &write->char_id);
+        param.write.handle = write->handle;
         btc_gattc_cb_to_app(ret_evt, gattc_if, &param);
         break;
     }
@@ -632,7 +795,9 @@ void btc_gattc_cb_handler(btc_msg_t *msg)
 
         gattc_if = BTC_GATT_GET_GATT_IF(srvc_res->conn_id);
         param.search_res.conn_id = BTC_GATT_GET_CONN_ID(srvc_res->conn_id);
-        bta_to_btc_srvc_id(&param.search_res.srvc_id, &srvc_res->service_uuid);
+        param.search_res.start_handle = srvc_res->start_handle;
+        param.search_res.end_handle = srvc_res->end_handle;
+        bta_to_btc_gatt_id(&param.search_res.srvc_id, &srvc_res->service_uuid);
         btc_gattc_cb_to_app(ESP_GATTC_SEARCH_RES_EVT, gattc_if, &param);
         break;
     }
@@ -647,9 +812,7 @@ void btc_gattc_cb_handler(btc_msg_t *msg)
         gattc_if = BTC_GATT_GET_GATT_IF(write->conn_id);
         param.write.conn_id = BTC_GATT_GET_CONN_ID(write->conn_id);
         param.write.status = write->status;
-        bta_to_btc_srvc_id(&param.write.srvc_id, &write->srvc_id);
-        bta_to_btc_gatt_id(&param.write.char_id, &write->char_id);
-        bta_to_btc_gatt_id(&param.write.descr_id, &write->descr_type);
+        param.write.handle = write->handle;
         btc_gattc_cb_to_app(ESP_GATTC_WRITE_DESCR_EVT, gattc_if, &param);
         break;
     }
@@ -659,16 +822,14 @@ void btc_gattc_cb_handler(btc_msg_t *msg)
         gattc_if = BTC_GATT_GET_GATT_IF(notify->conn_id);
         param.notify.conn_id = BTC_GATT_GET_CONN_ID(notify->conn_id);
         memcpy(param.notify.remote_bda, notify->bda, sizeof(esp_bd_addr_t));
-        bta_to_btc_srvc_id(&param.notify.srvc_id, &notify->char_id.srvc_id);
-        bta_to_btc_gatt_id(&param.notify.char_id, &notify->char_id.char_id);
-        bta_to_btc_gatt_id(&param.notify.descr_id, &notify->descr_type);
+        param.notify.handle = notify->handle;
         param.notify.is_notify = (notify->is_notify == TRUE) ? true : false;
         param.notify.value_len = (notify->len > ESP_GATT_MAX_ATTR_LEN) ? \
                                  ESP_GATT_MAX_ATTR_LEN : notify->len;
         param.notify.value = notify->value;
 
         if (notify->is_notify == FALSE) {
-            BTA_GATTC_SendIndConfirm(notify->conn_id, &notify->char_id);
+            BTA_GATTC_SendIndConfirm(notify->conn_id, notify->handle);
         }
 
         btc_gattc_cb_to_app(ESP_GATTC_NOTIFY_EVT, gattc_if, &param);
@@ -750,7 +911,7 @@ void btc_gattc_cb_handler(btc_msg_t *msg)
         break;
     }
     default:
-        LOG_ERROR("%s: Unhandled event (%d)!", __FUNCTION__, msg->act);
+        LOG_DEBUG("%s: Unhandled event (%d)!", __FUNCTION__, msg->act);
         break;
     }
 
index d1e0e9680d7aecb9732f87c2554eda599ce9f777..5087e5d2333d10cf7d14d43bafc6eeb1d43152a6 100644 (file)
@@ -27,13 +27,8 @@ typedef enum {
     BTC_GATTC_ACT_CLOSE,
     BTC_GATTC_ACT_CFG_MTU,
     BTC_GATTC_ACT_SEARCH_SERVICE,
-    BTC_GATTC_ACT_GET_FIRST_CHAR,
-    BTC_GATTC_ACT_GET_NEXT_CHAR,
-    BTC_GATTC_ACT_GET_FIRST_DESCR,
-    BTC_GATTC_ACT_GET_NEXT_DESCR,
-    BTC_GATTC_ACT_GET_FIRST_INCL_SERVICE,
-    BTC_GATTC_ACT_GET_NEXT_INCL_SERVICE,
     BTC_GATTC_ACT_READ_CHAR,
+    BTC_GATTC_ACT_READ_MULTIPLE_CHAR,
     BTC_GATTC_ACT_READ_CHAR_DESCR,
     BTC_GATTC_ACT_WRITE_CHAR,
     BTC_GATTC_ACT_WRITE_CHAR_DESCR,
@@ -75,82 +70,67 @@ typedef union {
         bool filter_uuid_enable;
         esp_bt_uuid_t filter_uuid;
     } search_srvc;
-    //BTC_GATTC_ACT_GET_FIRST_CHAR,
-    struct get_first_char_arg {
+    //BTC_GATTC_ACT_GET_CHAR,
+    struct get_char_arg {
         uint16_t conn_id;
-        esp_gatt_srvc_id_t service_id;
-    } get_first_char;
-    //BTC_GATTC_ACT_GET_NEXT_CHAR,
-    struct get_next_char_arg {
+        uint16_t handle;
+    } get_char;
+    //BTC_GATTC_ACT_GET_DESCR,
+    struct get_descr_arg {
         uint16_t conn_id;
-        esp_gatt_srvc_id_t service_id;
-        esp_gatt_id_t char_id;
-    } get_next_char;
-    //BTC_GATTC_ACT_GET_FIRST_DESCR,
-    struct get_first_descr_arg {
-        uint16_t conn_id;
-        esp_gatt_srvc_id_t service_id;
-        esp_gatt_id_t char_id;
-    } get_first_descr;
-    //BTC_GATTC_ACT_GET_NEXT_DESCR,
-    struct get_next_descr_arg {
-        uint16_t conn_id;
-        esp_gatt_srvc_id_t service_id;
-        esp_gatt_id_t char_id;
-        esp_gatt_id_t descr_id;
-    } get_next_descr;
+        uint16_t handle;
+    } get_descr;
     //BTC_GATTC_ACT_GET_FIRST_INCL_SERVICE,
     struct get_first_incl_srvc_arg {
         uint16_t conn_id;
-        esp_gatt_srvc_id_t service_id;
+        uint16_t handle;
     } get_first_incl_srvc;
     //BTC_GATTC_ACT_GET_NEXT_INCL_SERVICE,
     struct get_next_incl_srvc_arg {
         uint16_t conn_id;
-        esp_gatt_srvc_id_t service_id;
-        esp_gatt_srvc_id_t start_service_id;
+        uint16_t handle;
     } get_next_incl_srvc;
     //BTC_GATTC_ACT_READ_CHAR,
     struct read_char_arg {
         uint16_t conn_id;
-        esp_gatt_srvc_id_t service_id;
-        esp_gatt_id_t char_id;
+        uint16_t handle;
         esp_gatt_auth_req_t auth_req;
     } read_char;
+    //BTC_GATTC_ACT_READ_MULTIPLE_CHAR
+    struct read_multiple_arg {
+        uint16_t conn_id;
+        uint8_t  num_attr;
+        uint16_t handles[ESP_GATT_MAX_READ_MULTI_HANDLES];
+        esp_gatt_auth_req_t auth_req;
+    } read_multiple;
     //BTC_GATTC_ACT_READ_CHAR_DESCR,
     struct read_descr_arg {
         uint16_t conn_id;
-        esp_gatt_srvc_id_t service_id;
-        esp_gatt_id_t char_id;
-        esp_gatt_id_t descr_id;
+        uint16_t handle;
         esp_gatt_auth_req_t auth_req;
     } read_descr;
     //BTC_GATTC_ACT_WRITE_CHAR,
     struct write_char_arg {
         uint16_t conn_id;
         uint16_t value_len;
-        esp_gatt_srvc_id_t service_id;
-        esp_gatt_id_t char_id;
+        uint16_t handle;
         uint8_t *value;
-               esp_gatt_write_type_t write_type;
+        esp_gatt_write_type_t write_type;
         esp_gatt_auth_req_t auth_req;
     } write_char;
     //BTC_GATTC_ACT_WRITE_CHAR_DESCR,
     struct write_descr_arg {
         uint16_t conn_id;
         uint16_t value_len;
-        esp_gatt_srvc_id_t service_id;
-        esp_gatt_id_t char_id;
-        esp_gatt_id_t descr_id;
+        uint16_t handle;
         uint8_t *value;
-               esp_gatt_write_type_t write_type;
+        esp_gatt_write_type_t write_type;
         esp_gatt_auth_req_t auth_req;
     } write_descr;
     //BTC_GATTC_ACT_PREPARE_WRITE,
     struct prep_write_arg {
         uint16_t conn_id;
-        esp_gatt_srvc_id_t service_id;
-        esp_gatt_id_t char_id;
+        uint16_t handle;
         uint16_t offset;
         uint16_t value_len;
         uint8_t *value;
@@ -159,9 +139,7 @@ typedef union {
     //BTC_GATTC_ACT_PREPARE_WRITE_CHAR_DESCR,
     struct prep_write_descr_arg {
         uint16_t conn_id;
-        esp_gatt_srvc_id_t service_id;
-        esp_gatt_id_t char_id;
-        esp_gatt_id_t descr_id;
+        uint16_t handle;
         uint16_t offset;
         uint16_t value_len;
         uint8_t *value;
@@ -176,15 +154,13 @@ typedef union {
     struct reg_for_notify_arg {
         esp_gatt_if_t gattc_if;
         esp_bd_addr_t remote_bda;
-        esp_gatt_srvc_id_t service_id;
-        esp_gatt_id_t char_id;
+        uint16_t handle;
     } reg_for_notify;
     //BTC_GATTC_ACT_UNREG_FOR_NOTIFY
     struct unreg_for_notify_arg {
         esp_gatt_if_t gattc_if;
         esp_bd_addr_t remote_bda;
-        esp_gatt_srvc_id_t service_id;
-        esp_gatt_id_t char_id;
+        uint16_t handle;
     } unreg_for_notify;
     //BTC_GATTC_ACT_CACHE_REFRESH,
     struct cache_refresh_arg {
@@ -195,5 +171,56 @@ typedef union {
 void btc_gattc_call_handler(btc_msg_t *msg);
 void btc_gattc_cb_handler(btc_msg_t *msg);
 void btc_gattc_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src);
+esp_gatt_status_t btc_ble_gattc_get_service(uint16_t conn_id, esp_bt_uuid_t *svc_uuid, 
+                                            esp_gattc_service_elem_t *result,
+                                            uint16_t *count, uint16_t offset);
+esp_gatt_status_t btc_ble_gattc_get_all_char(uint16_t conn_id,
+                                             uint16_t start_handle,
+                                             uint16_t end_handle,
+                                             esp_gattc_char_elem_t *result,
+                                             uint16_t *count, uint16_t offset);
+esp_gatt_status_t btc_ble_gattc_get_all_descr(uint16_t conn_id,
+                                              uint16_t char_handle,
+                                              esp_gattc_descr_elem_t *result,
+                                              uint16_t *count, uint16_t offset);
+esp_gatt_status_t btc_ble_gattc_get_char_by_uuid(uint16_t conn_id,
+                                                 uint16_t start_handle,
+                                                 uint16_t end_handle,
+                                                 esp_bt_uuid_t char_uuid,
+                                                 esp_gattc_char_elem_t *result,
+                                                 uint16_t *count);
+esp_gatt_status_t btc_ble_gattc_get_descr_by_uuid(uint16_t conn_id,
+                                                  uint16_t start_handle,
+                                                  uint16_t end_handle,
+                                                  esp_bt_uuid_t char_uuid,
+                                                  esp_bt_uuid_t descr_uuid,
+                                                  esp_gattc_descr_elem_t *result,
+                                                  uint16_t *count);
+
+esp_gatt_status_t btc_ble_gattc_get_descr_by_char_handle(uint16_t conn_id,
+                                                         uint16_t char_handle,
+                                                         esp_bt_uuid_t descr_uuid,
+                                                         esp_gattc_descr_elem_t *result,
+                                                         uint16_t *count);
+
+esp_gatt_status_t btc_ble_gattc_get_include_service(uint16_t conn_id,
+                                                    uint16_t start_handle,
+                                                    uint16_t end_handle,
+                                                    esp_bt_uuid_t *incl_uuid,
+                                                    esp_gattc_incl_svc_elem_t *result,
+                                                    uint16_t *count);
+
+esp_gatt_status_t btc_ble_gattc_get_attr_count(uint16_t conn_id,
+                                               esp_gatt_db_attr_type_t type,
+                                               uint16_t start_handle,
+                                               uint16_t end_handle,
+                                               uint16_t char_handle,
+                                               uint16_t *count);
+
+esp_gatt_status_t btc_ble_gattc_get_db(uint16_t conn_id, uint16_t start_handle, uint16_t end_handle, 
+                                       esp_gattc_db_elem_t *db, uint16_t *count);
+
+
+
 
 #endif /* __BTC_GATTC_H__ */
index 0266a212d5ad85aa4bb9e0eed06d79f25e2ca5c3..3439a31d14468f7b3b75e2e674e2803f809968b8 100644 (file)
@@ -2216,10 +2216,10 @@ void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason, tBT_TRANSPORT transport)
         gatt_free_pending_ind(p_tcb);
         gatt_free_pending_enc_queue(p_tcb);
         gatt_free_pending_prepare_write_queue(p_tcb);
-#if (GATTS_INCLUDED == TRUE)
+#if (GATTS_INCLUDED)
         fixed_queue_free(p_tcb->sr_cmd.multi_rsp_q, osi_free_func);
         p_tcb->sr_cmd.multi_rsp_q = NULL;
-#endif  ///GATTS_INCLUDED == TRUE
+#endif /* #if (GATTS_INCLUDED) */
         for (i = 0; i < GATT_MAX_APPS; i ++) {
             p_reg = &gatt_cb.cl_rcb[i];
             if (p_reg->in_use && p_reg->app_cb.p_conn_cb) {
index 76b809ede6832827ea87f21ef6b26389ae5b3826..24fe67ac04736e54558e88c45c5cb91ec915975b 100644 (file)
 #define GATTC_TAG "GATTC_DEMO"
 #define REMOTE_SERVICE_UUID        0x00FF
 #define REMOTE_NOTIFY_CHAR_UUID    0xFF01
+#define PROFILE_NUM      1
+#define PROFILE_A_APP_ID 0
+#define INVALID_HANDLE   0
+
+static const char remote_device_name[] = "ESP_GATTS_DEMO";
+static bool connect    = false;
+static bool get_server = false;
+static esp_gattc_char_elem_t *char_elem_result   = NULL;
+static esp_gattc_descr_elem_t *descr_elem_result = NULL;
 
-///Declare static functions
+/* eclare static functions */
 static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
 static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
 static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
 
 
-static esp_gatt_srvc_id_t gatt_server_demo_service_id = {
-    .id = {
-        .uuid = {
-            .len = ESP_UUID_LEN_16,
-            .uuid = {.uuid16 = REMOTE_SERVICE_UUID,},
-        },
-        .inst_id = 0,
-    },
-    .is_primary = true,
-};
-
 static esp_bt_uuid_t remote_filter_service_uuid = {
     .len = ESP_UUID_LEN_16,
     .uuid = {.uuid16 = REMOTE_SERVICE_UUID,},
 };
 
-static esp_gatt_id_t notify_descr_id = {
-    .uuid = {
-        .len = ESP_UUID_LEN_16,
-        .uuid = {.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG,},
-    },
-    .inst_id = 0,
+static esp_bt_uuid_t remote_filter_char_uuid = {
+    .len = ESP_UUID_LEN_16,
+    .uuid = {.uuid16 = REMOTE_NOTIFY_CHAR_UUID,},
 };
 
-
-static bool connect    = false;
-static bool get_server = false;
-static const char remote_device_name[] = "ESP_GATTS_DEMO";
+static esp_bt_uuid_t notify_descr_uuid = {
+    .len = ESP_UUID_LEN_16,
+    .uuid = {.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG,},
+};
 
 static esp_ble_scan_params_t ble_scan_params = {
     .scan_type              = BLE_SCAN_TYPE_ACTIVE,
@@ -85,15 +80,14 @@ static esp_ble_scan_params_t ble_scan_params = {
     .scan_window            = 0x30
 };
 
-
-#define PROFILE_NUM 1
-#define PROFILE_A_APP_ID 0
-
 struct gattc_profile_inst {
     esp_gattc_cb_t gattc_cb;
     uint16_t gattc_if;
     uint16_t app_id;
     uint16_t conn_id;
+    uint16_t service_start_handle;
+    uint16_t service_end_handle;
+    uint16_t char_handle;
     esp_bd_addr_t remote_bda;
 };
 
@@ -107,7 +101,6 @@ static struct gattc_profile_inst gl_profile_tab[PROFILE_NUM] = {
 
 static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
 {
-    uint16_t conn_id = 0;
     esp_ble_gattc_cb_param_t *p_data = (esp_ble_gattc_cb_param_t *)param;
 
     switch (event) {
@@ -120,13 +113,12 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
         break;
     case ESP_GATTC_CONNECT_EVT:{
         //p_data->connect.status always be ESP_GATT_OK
-        ESP_LOGI(GATTC_TAG, "ESP_GATTC_CONNECT_EVT conn_id %d, if %d, status %d", conn_id, gattc_if, p_data->connect.status);
-        conn_id = p_data->connect.conn_id;
+        ESP_LOGI(GATTC_TAG, "ESP_GATTC_CONNECT_EVT conn_id %d, if %d, status %d", p_data->connect.conn_id, gattc_if, p_data->connect.status);
         gl_profile_tab[PROFILE_A_APP_ID].conn_id = p_data->connect.conn_id;
         memcpy(gl_profile_tab[PROFILE_A_APP_ID].remote_bda, p_data->connect.remote_bda, sizeof(esp_bd_addr_t));
         ESP_LOGI(GATTC_TAG, "REMOTE BDA:");
         esp_log_buffer_hex(GATTC_TAG, gl_profile_tab[PROFILE_A_APP_ID].remote_bda, sizeof(esp_bd_addr_t));
-        esp_err_t mtu_ret = esp_ble_gattc_send_mtu_req (gattc_if, conn_id);
+        esp_err_t mtu_ret = esp_ble_gattc_send_mtu_req (gattc_if, p_data->connect.conn_id);
         if (mtu_ret){
             ESP_LOGE(GATTC_TAG, "config MTU error, error code = %x", mtu_ret);
         }
@@ -147,10 +139,13 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
         esp_ble_gattc_search_service(gattc_if, param->cfg_mtu.conn_id, &remote_filter_service_uuid);
         break;
     case ESP_GATTC_SEARCH_RES_EVT: {
-        esp_gatt_srvc_id_t *srvc_id = &p_data->search_res.srvc_id;
-        conn_id = p_data->search_res.conn_id;
+        ESP_LOGI(GATTC_TAG, "ESP_GATTC_SEARCH_RES_EVT");
+        esp_gatt_srvc_id_t *srvc_id =(esp_gatt_srvc_id_t *)&p_data->search_res.srvc_id;
         if (srvc_id->id.uuid.len == ESP_UUID_LEN_16 && srvc_id->id.uuid.uuid.uuid16 == REMOTE_SERVICE_UUID) {
+            ESP_LOGI(GATTC_TAG, "service found");
             get_server = true;
+            gl_profile_tab[PROFILE_A_APP_ID].service_start_handle = p_data->search_res.start_handle;
+            gl_profile_tab[PROFILE_A_APP_ID].service_end_handle = p_data->search_res.end_handle;
             ESP_LOGI(GATTC_TAG, "UUID16: %x", srvc_id->id.uuid.uuid.uuid16);
         }
         break;
@@ -160,56 +155,110 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
             ESP_LOGE(GATTC_TAG, "search service failed, error status = %x", p_data->search_cmpl.status);
             break;
         }
-        conn_id = p_data->search_cmpl.conn_id;
+        ESP_LOGI(GATTC_TAG, "ESP_GATTC_SEARCH_CMPL_EVT");
         if (get_server){
-            esp_ble_gattc_get_characteristic(gattc_if, conn_id, &gatt_server_demo_service_id, NULL);
-        }
-        break;
-    case ESP_GATTC_GET_CHAR_EVT:
-        if (p_data->get_char.status != ESP_GATT_OK) {
-            ESP_LOGE(GATTC_TAG, "get char failed, error status = %x", p_data->get_char.status);
-            break;
-        }
-        ESP_LOGI(GATTC_TAG, "get char success");
-        ESP_LOGI(GATTC_TAG, "GET CHAR: srvc_id = %04x, char_id = %04x", p_data->get_char.srvc_id.id.uuid.uuid.uuid16, p_data->get_char.char_id.uuid.uuid.uuid16);
+            uint16_t count = 0;
+            esp_gatt_status_t status = esp_ble_gattc_get_attr_count( gattc_if,
+                                                                     p_data->search_cmpl.conn_id,
+                                                                     ESP_GATT_DB_CHARACTERISTIC,
+                                                                     gl_profile_tab[PROFILE_A_APP_ID].service_start_handle,
+                                                                     gl_profile_tab[PROFILE_A_APP_ID].service_end_handle,
+                                                                     INVALID_HANDLE,
+                                                                     &count);
+            if (status != ESP_GATT_OK){
+                ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_attr_count error");
+            }
 
-        if (p_data->get_char.char_id.uuid.uuid.uuid16 == REMOTE_NOTIFY_CHAR_UUID) {
-            esp_ble_gattc_register_for_notify(gattc_if, gl_profile_tab[PROFILE_A_APP_ID].remote_bda, &gatt_server_demo_service_id, &p_data->get_char.char_id);
-        }
+            if (count > 0){
+                char_elem_result = (esp_gattc_char_elem_t *)malloc(sizeof(char_elem_result) * count);
+                if (!char_elem_result){
+                    ESP_LOGE(GATTC_TAG, "gattc no mem");
+                }else{
+                    status = esp_ble_gattc_get_char_by_uuid( gattc_if,
+                                                             p_data->search_cmpl.conn_id,
+                                                             gl_profile_tab[PROFILE_A_APP_ID].service_start_handle,
+                                                             gl_profile_tab[PROFILE_A_APP_ID].service_end_handle,
+                                                             remote_filter_char_uuid,
+                                                             char_elem_result,
+                                                             &count);
+                    if (status != ESP_GATT_OK){
+                        ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_char_by_uuid error");
+                    }
 
-        esp_ble_gattc_get_characteristic(gattc_if, conn_id, &gatt_server_demo_service_id, &p_data->get_char.char_id);
-        break;
+                    /*  Every service have only one char in our 'ESP_GATTS_DEMO' demo, so we used first 'char_elem_result' */
+                    if (count > 0 && (char_elem_result[0].properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY)){
+                        gl_profile_tab[PROFILE_A_APP_ID].char_handle = char_elem_result[0].char_handle;
+                        esp_ble_gattc_register_for_notify (gattc_if, gl_profile_tab[PROFILE_A_APP_ID].remote_bda, char_elem_result[0].char_handle);
+                    }
+                }
+                /* free char_elem_result */
+                free(char_elem_result);
+            }else{
+                ESP_LOGE(GATTC_TAG, "no char found");
+            }
+        }
+         break;
     case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
+        ESP_LOGI(GATTC_TAG, "ESP_GATTC_REG_FOR_NOTIFY_EVT");
         if (p_data->reg_for_notify.status != ESP_GATT_OK){
             ESP_LOGE(GATTC_TAG, "REG FOR NOTIFY failed: error status = %d", p_data->reg_for_notify.status);
-            break;
-        }
+        }else{
+            uint16_t count = 0;
+            uint16_t notify_en = 1;
+            esp_gatt_status_t ret_status = esp_ble_gattc_get_attr_count( gattc_if,
+                                                                         gl_profile_tab[PROFILE_A_APP_ID].conn_id,
+                                                                         ESP_GATT_DB_DESCRIPTOR,
+                                                                         gl_profile_tab[PROFILE_A_APP_ID].service_start_handle,
+                                                                         gl_profile_tab[PROFILE_A_APP_ID].service_end_handle,
+                                                                         gl_profile_tab[PROFILE_A_APP_ID].char_handle,
+                                                                         &count);
+            if (ret_status != ESP_GATT_OK){
+                ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_attr_count error");
+            }
+            if (count > 0){
+                descr_elem_result = malloc(sizeof(descr_elem_result) * count);
+                if (!descr_elem_result){
+                    ESP_LOGE(GATTC_TAG, "malloc error, gattc no mem");
+                }else{
+                    ret_status = esp_ble_gattc_get_descr_by_char_handle( gattc_if,
+                                                                         gl_profile_tab[PROFILE_A_APP_ID].conn_id,
+                                                                         p_data->reg_for_notify.handle,
+                                                                         notify_descr_uuid,
+                                                                         descr_elem_result,
+                                                                         &count);
+                    if (ret_status != ESP_GATT_OK){
+                        ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_descr_by_char_handle error");
+                    }
 
-        ESP_LOGI(GATTC_TAG, "REG FOR_NOTIFY: srvc_id = %04x, char_id = %04x", p_data->reg_for_notify.srvc_id.id.uuid.uuid.uuid16, p_data->reg_for_notify.char_id.uuid.uuid.uuid16);
-        uint16_t notify_en = 1;
-        esp_ble_gattc_write_char_descr( gattc_if,
-                                        conn_id,
-                                        &gatt_server_demo_service_id,
-                                        &p_data->reg_for_notify.char_id,
-                                        &notify_descr_id,
-                                        sizeof(notify_en),
-                                        (uint8_t *)&notify_en,
-                                        ESP_GATT_WRITE_TYPE_RSP,
-                                        ESP_GATT_AUTH_REQ_NONE);
+                    /* Erery char have only one descriptor in our 'ESP_GATTS_DEMO' demo, so we used first 'descr_elem_result' */
+                    if (count > 0 && descr_elem_result[0].uuid.len == ESP_UUID_LEN_16 && descr_elem_result[0].uuid.uuid.uuid16 == ESP_GATT_UUID_CHAR_CLIENT_CONFIG){
+                        ret_status = esp_ble_gattc_write_char_descr( gattc_if,
+                                                                     gl_profile_tab[PROFILE_A_APP_ID].conn_id,
+                                                                     descr_elem_result[0].handle,
+                                                                     sizeof(notify_en),
+                                                                     (uint8_t *)&notify_en,
+                                                                     ESP_GATT_WRITE_TYPE_RSP,
+                                                                     ESP_GATT_AUTH_REQ_NONE);
+                    }
+
+                    if (ret_status != ESP_GATT_OK){
+                        ESP_LOGE(GATTC_TAG, "esp_ble_gattc_write_char_descr error");
+                    }
+
+                    /* free descr_elem_result */
+                    free(descr_elem_result);
+                }
+            }
+            else{
+                ESP_LOGE(GATTC_TAG, "decsr not found");
+            }
+
+        }
         break;
     }
     case ESP_GATTC_NOTIFY_EVT:
-        ESP_LOGI(GATTC_TAG, "ESP_GATTC_NOTIFY_EVT, Receive notify value:");
+        ESP_LOGI(GATTC_TAG, "ESP_GATTC_NOTIFY_EVT, receive notify value:");
         esp_log_buffer_hex(GATTC_TAG, p_data->notify.value, p_data->notify.value_len);
-        //write  back
-        esp_ble_gattc_write_char(gattc_if,
-                                gl_profile_tab[PROFILE_A_APP_ID].conn_id,
-                                &gatt_server_demo_service_id,
-                                &p_data->notify.char_id,
-                                p_data->notify.value_len,
-                                p_data->notify.value,
-                                ESP_GATT_WRITE_TYPE_RSP,
-                                ESP_GATT_AUTH_REQ_NONE);
         break;
     case ESP_GATTC_WRITE_DESCR_EVT:
         if (p_data->write.status != ESP_GATT_OK){
@@ -217,6 +266,18 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
             break;
         }
         ESP_LOGI(GATTC_TAG, "write descr success ");
+        uint8_t write_char_data[35];
+        for (int i = 0; i < sizeof(write_char_data); ++i)
+        {
+            write_char_data[i] = i % 256;
+        }
+        esp_ble_gattc_write_char( gattc_if,
+                                  gl_profile_tab[PROFILE_A_APP_ID].conn_id,
+                                  gl_profile_tab[PROFILE_A_APP_ID].char_handle,
+                                  sizeof(write_char_data),
+                                  write_char_data,
+                                  ESP_GATT_WRITE_TYPE_RSP,
+                                  ESP_GATT_AUTH_REQ_NONE);
         break;
     case ESP_GATTC_SRVC_CHG_EVT: {
         esp_bd_addr_t bda;
@@ -324,8 +385,6 @@ static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *par
 
 static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
 {
-    ESP_LOGI(GATTC_TAG, "EVT %d, gattc if %d", event, gattc_if);
-
     /* If event is register event, store the gattc_if for each profile */
     if (event == ESP_GATTC_REG_EVT) {
         if (param->reg.status == ESP_GATT_OK) {
index 2964602c962d3ae67a2c77ee14b24448d3beb004..cf9ec505a163a6719b08728be78d7592f98f46e5 100644 (file)
 #define REMOTE_SERVICE_UUID   0x1809
 #define REMOTE_NOTIFY_UUID    0x2A37
 
+static esp_gattc_char_elem_t *char_elem_result   = NULL;
+static esp_gattc_descr_elem_t *descr_elem_result = NULL;
+
 ///Declare static functions
 static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
 static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
 static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
 
 
-
-static esp_gatt_srvc_id_t heart_rate_service_id = {
-    .id = {
-        .uuid = {
-            .len = ESP_UUID_LEN_16,
-            .uuid = {.uuid16 = REMOTE_SERVICE_UUID,},
-        },
-        .inst_id = 0,
-    },
-    .is_primary = true,
-};
-
 static esp_bt_uuid_t remote_filter_service_uuid = {
     .len = ESP_UUID_LEN_16,
     .uuid = {.uuid16 = REMOTE_SERVICE_UUID,},
 };
 
-static esp_gatt_id_t remote_notify_descr_id = {
-    .uuid = {
-        .len = ESP_UUID_LEN_16,
-        .uuid = {.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG,},
-    },
-    .inst_id = 0,
-};
-
-
 static bool connect = false;
 static bool get_service = false;
 static const char remote_device_name[] = "ESP_BLE_SECURITY";
@@ -88,12 +70,16 @@ static esp_ble_scan_params_t ble_scan_params = {
 
 #define PROFILE_NUM 1
 #define PROFILE_A_APP_ID 0
+#define INVALID_HANDLE   0
 
 struct gattc_profile_inst {
     esp_gattc_cb_t gattc_cb;
     uint16_t gattc_if;
     uint16_t app_id;
     uint16_t conn_id;
+    uint16_t service_start_handle;
+    uint16_t service_end_handle;
+    uint16_t notify_char_handle;
     esp_bd_addr_t remote_bda;
 };
 
@@ -146,7 +132,6 @@ static char *esp_key_type_to_str(esp_ble_key_type_t key_type)
 
 static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
 {
-    uint16_t conn_id = 0;
     esp_ble_gattc_cb_param_t *p_data = (esp_ble_gattc_cb_param_t *)param;
 
     switch (event) {
@@ -160,12 +145,11 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
             break;
         }
         ESP_LOGI(GATTC_TAG, "open success");
-        conn_id = p_data->open.conn_id;
         gl_profile_tab[PROFILE_A_APP_ID].conn_id = p_data->open.conn_id;
         memcpy(gl_profile_tab[PROFILE_A_APP_ID].remote_bda, p_data->open.remote_bda, sizeof(esp_bd_addr_t));
         ESP_LOGI(GATTC_TAG, "REMOTE BDA:");
         esp_log_buffer_hex(GATTC_TAG, gl_profile_tab[PROFILE_A_APP_ID].remote_bda, sizeof(esp_bd_addr_t));
-        esp_err_t mtu_ret = esp_ble_gattc_send_mtu_req (gattc_if, conn_id);
+        esp_err_t mtu_ret = esp_ble_gattc_send_mtu_req (gattc_if, p_data->open.conn_id);
         if (mtu_ret){
             ESP_LOGE(GATTC_TAG, "config MTU error, error code = %x", mtu_ret);
         }
@@ -178,12 +162,13 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
         esp_ble_gattc_search_service(gattc_if, param->cfg_mtu.conn_id, &remote_filter_service_uuid);
         break;
     case ESP_GATTC_SEARCH_RES_EVT: {
-        esp_gatt_srvc_id_t *srvc_id = &p_data->search_res.srvc_id;
-        conn_id = p_data->search_res.conn_id;
-        ESP_LOGI(GATTC_TAG, "SEARCH RES: conn_id = %x", conn_id);
+        esp_gatt_srvc_id_t *srvc_id =(esp_gatt_srvc_id_t *)&p_data->search_res.srvc_id;
+        ESP_LOGI(GATTC_TAG, "SEARCH RES: conn_id = %x", p_data->search_res.conn_id);
         if (srvc_id->id.uuid.len == ESP_UUID_LEN_16 && srvc_id->id.uuid.uuid.uuid16 == REMOTE_SERVICE_UUID) {
             ESP_LOGI(GATTC_TAG, "UUID16: %x", srvc_id->id.uuid.uuid.uuid16);
             get_service = true;
+            gl_profile_tab[PROFILE_A_APP_ID].service_start_handle = p_data->search_res.start_handle;
+            gl_profile_tab[PROFILE_A_APP_ID].service_end_handle = p_data->search_res.end_handle;
         }
         break;
     }
@@ -192,26 +177,53 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
             ESP_LOGE(GATTC_TAG, "search service failed, error status = %x", p_data->search_cmpl.status);
             break;
         }
-        conn_id = p_data->search_cmpl.conn_id;
         if (get_service){
-            esp_ble_gattc_get_characteristic(gattc_if, conn_id, &heart_rate_service_id, NULL);
-        }
-
-        break;
-    case ESP_GATTC_GET_CHAR_EVT:
-        if (p_data->get_char.status != ESP_GATT_OK) {
-            ESP_LOGE(GATTC_TAG, "get char failed, error status = %x", p_data->get_char.status);
-            break;
-        }
-        ESP_LOGI(GATTC_TAG, "GET CHAR: conn_id = %x, status %d", p_data->get_char.conn_id, p_data->get_char.status);
-        ESP_LOGI(GATTC_TAG, "GET CHAR: srvc_id = %04x, char_id = %04x", p_data->get_char.srvc_id.id.uuid.uuid.uuid16, p_data->get_char.char_id.uuid.uuid.uuid16);
-
-        if (p_data->get_char.char_id.uuid.uuid.uuid16 == REMOTE_NOTIFY_UUID) {
-            ESP_LOGI(GATTC_TAG, "register notify");
-            esp_ble_gattc_register_for_notify(gattc_if, gl_profile_tab[PROFILE_A_APP_ID].remote_bda, &heart_rate_service_id, &p_data->get_char.char_id);
+            uint16_t count  = 0;
+            uint16_t offset = 0;
+            esp_gatt_status_t ret_status = esp_ble_gattc_get_attr_count(gattc_if,
+                                                                        gl_profile_tab[PROFILE_A_APP_ID].conn_id,
+                                                                        ESP_GATT_DB_CHARACTERISTIC,
+                                                                        gl_profile_tab[PROFILE_A_APP_ID].service_start_handle,
+                                                                        gl_profile_tab[PROFILE_A_APP_ID].service_end_handle,
+                                                                        INVALID_HANDLE,
+                                                                        &count);
+            if (ret_status != ESP_GATT_OK){
+                ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_attr_count error, %d", __LINE__);
+            }
+            if (count > 0){
+                char_elem_result = (esp_gattc_char_elem_t *)malloc(sizeof(char_elem_result) * count);
+                if (!char_elem_result){
+                    ESP_LOGE(GATTC_TAG, "gattc no mem");
+                }else{
+                    ret_status = esp_ble_gattc_get_all_char(gattc_if,
+                                                            gl_profile_tab[PROFILE_A_APP_ID].conn_id,
+                                                            gl_profile_tab[PROFILE_A_APP_ID].service_start_handle,
+                                                            gl_profile_tab[PROFILE_A_APP_ID].service_end_handle,
+                                                            char_elem_result,
+                                                            &count,
+                                                            offset);
+                    if (ret_status != ESP_GATT_OK){
+                        ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_all_char error, %d", __LINE__);
+                    }
+                    if (count > 0){
+
+                        for (int i = 0; i < count; ++i)
+                        {
+                            if (char_elem_result[i].uuid.len == ESP_UUID_LEN_16 && char_elem_result[i].uuid.uuid.uuid16 == REMOTE_NOTIFY_UUID && (char_elem_result[i].properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY))
+                            {
+                                gl_profile_tab[PROFILE_A_APP_ID].notify_char_handle = char_elem_result[i].char_handle;
+                                esp_ble_gattc_register_for_notify (gattc_if,
+                                                                   gl_profile_tab[PROFILE_A_APP_ID].remote_bda,
+                                                                   char_elem_result[i].char_handle);
+                                break;
+                            }
+                        }
+                    }
+                }
+                free(char_elem_result);
+            }
         }
 
-        esp_ble_gattc_get_characteristic(gattc_if, conn_id, &heart_rate_service_id, &p_data->get_char.char_id);
         break;
     case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
         if (p_data->reg_for_notify.status != ESP_GATT_OK){
@@ -219,31 +231,58 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
             break;
         }
 
-        ESP_LOGI(GATTC_TAG, "REG FOR_NOTIFY: srvc_id = %04x, char_id = %04x", p_data->reg_for_notify.srvc_id.id.uuid.uuid.uuid16, p_data->reg_for_notify.char_id.uuid.uuid.uuid16);
-        uint16_t notify_en = 1;
-        esp_ble_gattc_write_char_descr( gattc_if,
-                                        conn_id,
-                                        &heart_rate_service_id,
-                                        &p_data->reg_for_notify.char_id,
-                                        &remote_notify_descr_id,
-                                        sizeof(notify_en),
-                                        (uint8_t *)&notify_en,
-                                        ESP_GATT_WRITE_TYPE_RSP,
-                                        ESP_GATT_AUTH_REQ_NONE);
+            uint16_t count = 0;
+            uint16_t offset = 0;
+            uint16_t notify_en = 1;
+            esp_gatt_status_t ret_status = esp_ble_gattc_get_attr_count(gattc_if,
+                                                                        gl_profile_tab[PROFILE_A_APP_ID].conn_id,
+                                                                        ESP_GATT_DB_DESCRIPTOR,
+                                                                        gl_profile_tab[PROFILE_A_APP_ID].service_start_handle,
+                                                                        gl_profile_tab[PROFILE_A_APP_ID].service_end_handle,
+                                                                        p_data->reg_for_notify.handle,
+                                                                        &count);
+            if (ret_status != ESP_GATT_OK){
+                ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_attr_count error, %d", __LINE__);
+            }
+            if (count > 0){
+                descr_elem_result = malloc(sizeof(descr_elem_result) * count);
+                if (!descr_elem_result){
+                    ESP_LOGE(GATTC_TAG, "malloc error, gattc no mem");
+                }else{
+                    ret_status = esp_ble_gattc_get_all_descr(gattc_if,
+                                                             gl_profile_tab[PROFILE_A_APP_ID].conn_id,
+                                                             p_data->reg_for_notify.handle,
+                                                             descr_elem_result,
+                                                             &count,
+                                                             offset);
+                if (ret_status != ESP_GATT_OK){
+                    ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_all_descr error, %d", __LINE__);
+                }
+
+                    for (int i = 0; i < count; ++i)
+                    {
+                        if (descr_elem_result[i].uuid.len == ESP_UUID_LEN_16 && descr_elem_result[i].uuid.uuid.uuid16 == ESP_GATT_UUID_CHAR_CLIENT_CONFIG)
+                        {
+                            esp_ble_gattc_write_char_descr (gattc_if,
+                                                            gl_profile_tab[PROFILE_A_APP_ID].conn_id,
+                                                            descr_elem_result[i].handle,
+                                                            sizeof(notify_en),
+                                                            (uint8_t *)&notify_en,
+                                                            ESP_GATT_WRITE_TYPE_RSP,
+                                                            ESP_GATT_AUTH_REQ_NONE);
+
+                            break;
+                        }
+                    }
+                }
+                free(descr_elem_result);
+            }
+
         break;
     }
     case ESP_GATTC_NOTIFY_EVT:
         ESP_LOGI(GATTC_TAG, "ESP_GATTC_NOTIFY_EVT, receive notify value:");
         esp_log_buffer_hex(GATTC_TAG, p_data->notify.value, p_data->notify.value_len);
-        //write  back
-        esp_ble_gattc_write_char(gattc_if,
-                                gl_profile_tab[PROFILE_A_APP_ID].conn_id,
-                                &heart_rate_service_id,
-                                &p_data->notify.char_id,
-                                p_data->notify.value_len,
-                                p_data->notify.value,
-                                ESP_GATT_WRITE_TYPE_RSP,
-                                ESP_GATT_AUTH_REQ_NONE);
         break;
     case ESP_GATTC_WRITE_DESCR_EVT:
         if (p_data->write.status != ESP_GATT_OK){
index 2bee5d759a8da7462babfc6f8803e2c3c5579d23..0722476dbac99cddca9baa5f612be212d5c5720a 100644 (file)
@@ -339,6 +339,8 @@ static void gatts_profile_event_handler(esp_gatts_cb_event_t event,
         case ESP_GATTS_READ_EVT:
             break;
         case ESP_GATTS_WRITE_EVT: 
+            ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_WRITE_EVT, write value:");
+            esp_log_buffer_hex(GATTS_TABLE_TAG, param->write.value, param->write.len);
             break;
         case ESP_GATTS_EXEC_WRITE_EVT:
             break;
@@ -356,12 +358,12 @@ static void gatts_profile_event_handler(esp_gatts_cb_event_t event,
             break;
         case ESP_GATTS_CONNECT_EVT:
             ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_CONNECT_EVT");
-            //start security connect with peer device when receive the connect event sent by the master.
+            /* start security connect with peer device when receive the connect event sent by the master */
             esp_ble_set_encryption(param->connect.remote_bda, ESP_BLE_SEC_ENCRYPT_MITM);
             break;
         case ESP_GATTS_DISCONNECT_EVT:
             ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_DISCONNECT_EVT");
-            ///start advertising again when missing the connect.
+            /* start advertising again when missing the connect */
             esp_ble_gap_start_advertising(&heart_rate_adv_params);
             break;
         case ESP_GATTS_OPEN_EVT:
index adeb070f544cc8fa07a068346ab72d424c4365ca..61c29edc0e564577e4e4aaeb8238504b52b7e35f 100644 (file)
 #define REMOTE_SERVICE_UUID        0x00FF
 #define REMOTE_NOTIFY_CHAR_UUID    0xFF01
 
-///Declare static functions
+/* register three profiles, each profile corresponds to one connection,
+   which makes it easy to handle each connection event */
+#define PROFILE_NUM 3
+#define PROFILE_A_APP_ID 0
+#define PROFILE_B_APP_ID 1
+#define PROFILE_C_APP_ID 2
+#define INVALID_HANDLE   0
+
+/* Declare static functions */
 static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
 static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
 static void gattc_profile_a_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
 static void gattc_profile_b_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
 static void gattc_profile_c_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
 
-static esp_gatt_srvc_id_t remote_service_id = {
-    .id = {
-        .uuid = {
-            .len = ESP_UUID_LEN_16,
-            .uuid = {.uuid16 = REMOTE_SERVICE_UUID,},
-        },
-        .inst_id = 0,
-    },
-    .is_primary = true,
-};
-
 static esp_bt_uuid_t remote_filter_service_uuid = {
     .len = ESP_UUID_LEN_16,
     .uuid = {.uuid16 = REMOTE_SERVICE_UUID,},
 };
 
-static esp_gatt_id_t notify_descr_id = {
-    .uuid = {
-        .len = ESP_UUID_LEN_16,
-        .uuid = {.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG,},
-    },
-    .inst_id = 0,
+static esp_bt_uuid_t remote_filter_char_uuid = {
+    .len = ESP_UUID_LEN_16,
+    .uuid = {.uuid16 = REMOTE_NOTIFY_CHAR_UUID,},
+};
+
+static esp_bt_uuid_t notify_descr_uuid = {
+    .len = ESP_UUID_LEN_16,
+    .uuid = {.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG,},
 };
 
 static bool conn_device_a   = false;
@@ -87,6 +86,13 @@ static bool get_service_c   = false;
 static bool Isconnecting    = false;
 static bool stop_scan_done  = false;
 
+static esp_gattc_char_elem_t  *char_elem_result_a   = NULL;
+static esp_gattc_descr_elem_t *descr_elem_result_a  = NULL;
+static esp_gattc_char_elem_t  *char_elem_result_b   = NULL;
+static esp_gattc_descr_elem_t *descr_elem_result_b  = NULL;
+static esp_gattc_char_elem_t  *char_elem_result_c   = NULL;
+static esp_gattc_descr_elem_t *descr_elem_result_c  = NULL;
+
 static const char remote_device_name[3][20] = {"ESP_GATTS_DEMO_a", "ESP_GATTS_DEMO_b", "ESP_GATTS_DEMO_c"};
 
 static esp_ble_scan_params_t ble_scan_params = {
@@ -97,19 +103,14 @@ static esp_ble_scan_params_t ble_scan_params = {
     .scan_window            = 0x30
 };
 
-//register three profiles, each profile corresponds to one connection,
-//which makes it easy to handle each connection event
-#define PROFILE_NUM 3
-#define PROFILE_A_APP_ID 0
-#define PROFILE_B_APP_ID 1
-#define PROFILE_C_APP_ID 2
-
-
 struct gattc_profile_inst {
     esp_gattc_cb_t gattc_cb;
     uint16_t gattc_if;
     uint16_t app_id;
     uint16_t conn_id;
+    uint16_t service_start_handle;
+    uint16_t service_end_handle;
+    uint16_t char_handle;
     esp_bd_addr_t remote_bda;
 };
 
@@ -159,7 +160,7 @@ static void gattc_profile_a_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
             //open failed, ignore the first device, connect the second device
             ESP_LOGE(GATTC_TAG, "connect device failed, status %d", p_data->open.status);
             conn_device_a = false;
-            start_scan();
+            //start_scan();
             break;
         }
         memcpy(gl_profile_tab[PROFILE_A_APP_ID].remote_bda, p_data->open.remote_bda, 6);
@@ -180,11 +181,13 @@ static void gattc_profile_a_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
         esp_ble_gattc_search_service(gattc_if, param->cfg_mtu.conn_id, &remote_filter_service_uuid);
         break;
     case ESP_GATTC_SEARCH_RES_EVT: {
-        esp_gatt_srvc_id_t *srvc_id = &p_data->search_res.srvc_id;
+        esp_gatt_srvc_id_t *srvc_id = (esp_gatt_srvc_id_t *)&p_data->search_res.srvc_id;
         ESP_LOGI(GATTC_TAG, "SEARCH RES: conn_id = %x", p_data->search_res.conn_id);
         if (srvc_id->id.uuid.len == ESP_UUID_LEN_16 && srvc_id->id.uuid.uuid.uuid16 == REMOTE_SERVICE_UUID) {
             ESP_LOGI(GATTC_TAG, "UUID16: %x", srvc_id->id.uuid.uuid.uuid16);
             get_service_a = true;
+            gl_profile_tab[PROFILE_A_APP_ID].service_start_handle = p_data->search_res.start_handle;
+            gl_profile_tab[PROFILE_A_APP_ID].service_end_handle = p_data->search_res.end_handle;
         }
         break;
     }
@@ -194,57 +197,105 @@ static void gattc_profile_a_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
             break;
         }
         if (get_service_a){
-            esp_ble_gattc_get_characteristic(gattc_if, p_data->search_cmpl.conn_id, &remote_service_id, NULL);
-        }
-        break;
-    case ESP_GATTC_GET_CHAR_EVT:
-        if (p_data->get_char.status != ESP_GATT_OK) {
-            break;
-        }
-        ESP_LOGI(GATTC_TAG, "GET CHAR: conn_id = %x, status %d", p_data->get_char.conn_id, p_data->get_char.status);
-        ESP_LOGI(GATTC_TAG, "GET CHAR: srvc_id = %04x, char_id = %04x", p_data->get_char.srvc_id.id.uuid.uuid.uuid16, p_data->get_char.char_id.uuid.uuid.uuid16);
+            uint16_t count = 0;
+            esp_gatt_status_t status = esp_ble_gattc_get_attr_count( gattc_if,
+                                                                     p_data->search_cmpl.conn_id,
+                                                                     ESP_GATT_DB_CHARACTERISTIC,
+                                                                     gl_profile_tab[PROFILE_A_APP_ID].service_start_handle,
+                                                                     gl_profile_tab[PROFILE_A_APP_ID].service_end_handle,
+                                                                     INVALID_HANDLE,
+                                                                     &count);
+            if (status != ESP_GATT_OK){
+                ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_attr_count error");
+            }
+            if (count > 0) {
+                char_elem_result_a = (esp_gattc_char_elem_t *)malloc(sizeof(char_elem_result_a) * count);
+                if (!char_elem_result_a){
+                    ESP_LOGE(GATTC_TAG, "gattc no mem");
+                }else {
+                    status = esp_ble_gattc_get_char_by_uuid( gattc_if,
+                                                             p_data->search_cmpl.conn_id,
+                                                             gl_profile_tab[PROFILE_A_APP_ID].service_start_handle,
+                                                             gl_profile_tab[PROFILE_A_APP_ID].service_end_handle,
+                                                             remote_filter_char_uuid,
+                                                             char_elem_result_a,
+                                                             &count);
+                    if (status != ESP_GATT_OK){
+                        ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_char_by_uuid error");
+                    }
 
-        if (p_data->get_char.char_id.uuid.uuid.uuid16 == REMOTE_NOTIFY_CHAR_UUID) {
-            ESP_LOGI(GATTC_TAG, "register notify");
-            esp_ble_gattc_register_for_notify(gattc_if, gl_profile_tab[PROFILE_A_APP_ID].remote_bda, &remote_service_id, &p_data->get_char.char_id);
+                    /*  Every service have only one char in our 'ESP_GATTS_DEMO' demo, so we used first 'char_elem_result' */
+                    if (count > 0 && (char_elem_result_a[0].properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY)){
+                        gl_profile_tab[PROFILE_A_APP_ID].char_handle = char_elem_result_a[0].char_handle;
+                        esp_ble_gattc_register_for_notify (gattc_if, gl_profile_tab[PROFILE_A_APP_ID].remote_bda, char_elem_result_a[0].char_handle);
+                    }
+                }
+                /* free char_elem_result */
+                free(char_elem_result_a);
+            }else {
+                ESP_LOGE(GATTC_TAG, "no char found");
+            }
         }
-
-        esp_ble_gattc_get_characteristic(gattc_if, p_data->get_char.conn_id, &remote_service_id, &p_data->get_char.char_id);
         break;
     case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
         if (p_data->reg_for_notify.status != ESP_GATT_OK){
             ESP_LOGE(GATTC_TAG, "reg notify failed, error status =%x", p_data->reg_for_notify.status);
             break;
         }
+        uint16_t count = 0;
         uint16_t notify_en = 1;
-        ESP_LOGI(GATTC_TAG, "REG FOR NOTIFY: status %d, srvc_id = %04x, char_id = %04x",
-                p_data->reg_for_notify.status,
-                p_data->reg_for_notify.srvc_id.id.uuid.uuid.uuid16,
-                p_data->reg_for_notify.char_id.uuid.uuid.uuid16);
-
-        esp_ble_gattc_write_char_descr(gattc_if,
-                                       gl_profile_tab[PROFILE_A_APP_ID].conn_id,
-                                       &remote_service_id,
-                                       &p_data->reg_for_notify.char_id,
-                                       &notify_descr_id,
-                                       sizeof(notify_en),
-                                       (uint8_t *)&notify_en,
-                                       ESP_GATT_WRITE_TYPE_RSP,
-                                       ESP_GATT_AUTH_REQ_NONE);
+        esp_gatt_status_t ret_status = esp_ble_gattc_get_attr_count( gattc_if,
+                                                                     gl_profile_tab[PROFILE_A_APP_ID].conn_id,
+                                                                     ESP_GATT_DB_DESCRIPTOR,
+                                                                     gl_profile_tab[PROFILE_A_APP_ID].service_start_handle,
+                                                                     gl_profile_tab[PROFILE_A_APP_ID].service_end_handle,
+                                                                     gl_profile_tab[PROFILE_A_APP_ID].char_handle,
+                                                                     &count);
+        if (ret_status != ESP_GATT_OK){
+            ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_attr_count error");
+        }
+        if (count > 0){
+            descr_elem_result_a = malloc(sizeof(descr_elem_result_a) * count);
+            if (!descr_elem_result_a){
+                ESP_LOGE(GATTC_TAG, "malloc error, gattc no mem");
+            }else{
+                ret_status = esp_ble_gattc_get_descr_by_char_handle( gattc_if,
+                                                                     gl_profile_tab[PROFILE_A_APP_ID].conn_id,
+                                                                     p_data->reg_for_notify.handle,
+                                                                     notify_descr_uuid,
+                                                                     descr_elem_result_a,
+                                                                     &count);
+                if (ret_status != ESP_GATT_OK){
+                    ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_descr_by_char_handle error");
+                }
+
+                /* Erery char have only one descriptor in our 'ESP_GATTS_DEMO' demo, so we used first 'descr_elem_result' */
+                if (count > 0 && descr_elem_result_a[0].uuid.len == ESP_UUID_LEN_16 && descr_elem_result_a[0].uuid.uuid.uuid16 == ESP_GATT_UUID_CHAR_CLIENT_CONFIG){
+                    ret_status = esp_ble_gattc_write_char_descr( gattc_if,
+                                                                 gl_profile_tab[PROFILE_A_APP_ID].conn_id,
+                                                                 descr_elem_result_a[0].handle,
+                                                                 sizeof(notify_en),
+                                                                 (uint8_t *)&notify_en,
+                                                                 ESP_GATT_WRITE_TYPE_RSP,
+                                                                 ESP_GATT_AUTH_REQ_NONE);
+                }
+
+                if (ret_status != ESP_GATT_OK){
+                    ESP_LOGE(GATTC_TAG, "esp_ble_gattc_write_char_descr error");
+                }
+
+                /* free descr_elem_result */
+                free(descr_elem_result_a);
+            }
+        }
+        else{
+            ESP_LOGE(GATTC_TAG, "decsr not found");
+        }
         break;
     }
     case ESP_GATTC_NOTIFY_EVT:
         ESP_LOGI(GATTC_TAG, "ESP_GATTC_NOTIFY_EVT, Receive notify value:");
         esp_log_buffer_hex(GATTC_TAG, p_data->notify.value, p_data->notify.value_len);
-        //write  back
-        esp_ble_gattc_write_char(gattc_if,
-                                gl_profile_tab[PROFILE_A_APP_ID].conn_id,
-                                &remote_service_id,
-                                &p_data->notify.char_id,
-                                p_data->notify.value_len,
-                                p_data->notify.value,
-                                ESP_GATT_WRITE_TYPE_RSP,
-                                ESP_GATT_AUTH_REQ_NONE);
         break;
     case ESP_GATTC_WRITE_DESCR_EVT:
         if (p_data->write.status != ESP_GATT_OK){
@@ -252,6 +303,18 @@ static void gattc_profile_a_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
             break;
         }
         ESP_LOGI(GATTC_TAG, "write descr success");
+        uint8_t write_char_data[35];
+        for (int i = 0; i < sizeof(write_char_data); ++i)
+        {
+            write_char_data[i] = i % 256;
+        }
+        esp_ble_gattc_write_char( gattc_if,
+                                  gl_profile_tab[PROFILE_A_APP_ID].conn_id,
+                                  gl_profile_tab[PROFILE_A_APP_ID].char_handle,
+                                  sizeof(write_char_data),
+                                  write_char_data,
+                                  ESP_GATT_WRITE_TYPE_RSP,
+                                  ESP_GATT_AUTH_REQ_NONE);
         break;
     case ESP_GATTC_WRITE_CHAR_EVT:
         if (p_data->write.status != ESP_GATT_OK){
@@ -269,8 +332,6 @@ static void gattc_profile_a_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
         break;
     }
     case ESP_GATTC_DISCONNECT_EVT:
-        ESP_LOGI(GATTC_TAG,"ESP_GATTC_DISCONNECT_EVT");
-        ESP_LOGI(GATTC_TAG, "conn_id %d, if %d", p_data->disconnect.conn_id, gattc_if);
         //Start scanning again
         start_scan();
         if (memcmp(p_data->disconnect.remote_bda, gl_profile_tab[PROFILE_A_APP_ID].remote_bda, 6) == 0){
@@ -299,7 +360,7 @@ static void gattc_profile_b_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
             //open failed, ignore the second device, connect the third device
             ESP_LOGE(GATTC_TAG, "connect device failed, status %d", p_data->open.status);
             conn_device_b = false;
-            start_scan();
+            //start_scan();
             break;
         }
         memcpy(gl_profile_tab[PROFILE_B_APP_ID].remote_bda, p_data->open.remote_bda, 6);
@@ -320,11 +381,13 @@ static void gattc_profile_b_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
         esp_ble_gattc_search_service(gattc_if, param->cfg_mtu.conn_id, &remote_filter_service_uuid);
         break;
     case ESP_GATTC_SEARCH_RES_EVT: {
-        esp_gatt_srvc_id_t *srvc_id = &p_data->search_res.srvc_id;
+        esp_gatt_srvc_id_t *srvc_id = (esp_gatt_srvc_id_t *)&p_data->search_res.srvc_id;
         ESP_LOGI(GATTC_TAG, "SEARCH RES: conn_id = %x", p_data->search_res.conn_id);
         if (srvc_id->id.uuid.len == ESP_UUID_LEN_16 && srvc_id->id.uuid.uuid.uuid16 == REMOTE_SERVICE_UUID) {
             ESP_LOGI(GATTC_TAG, "UUID16: %x", srvc_id->id.uuid.uuid.uuid16);
             get_service_b = true;
+            gl_profile_tab[PROFILE_B_APP_ID].service_start_handle = p_data->search_res.start_handle;
+            gl_profile_tab[PROFILE_B_APP_ID].service_end_handle = p_data->search_res.end_handle;
         }
         break;
     }
@@ -334,53 +397,107 @@ static void gattc_profile_b_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
             break;
         }
         if (get_service_b){
-            esp_ble_gattc_get_characteristic(gattc_if, p_data->search_cmpl.conn_id, &remote_service_id, NULL);
+            uint16_t count = 0;
+            esp_gatt_status_t status = esp_ble_gattc_get_attr_count( gattc_if,
+                                                                     p_data->search_cmpl.conn_id,
+                                                                     ESP_GATT_DB_CHARACTERISTIC,
+                                                                     gl_profile_tab[PROFILE_B_APP_ID].service_start_handle,
+                                                                     gl_profile_tab[PROFILE_B_APP_ID].service_end_handle,
+                                                                     INVALID_HANDLE,
+                                                                     &count);
+            if (status != ESP_GATT_OK){
+                ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_attr_count error");
+            }
+
+            if (count > 0){
+                char_elem_result_b = (esp_gattc_char_elem_t *)malloc(sizeof(char_elem_result_b) * count);
+                if (!char_elem_result_b){
+                    ESP_LOGE(GATTC_TAG, "gattc no mem");
+                }else{
+                    status = esp_ble_gattc_get_char_by_uuid( gattc_if,
+                                                             p_data->search_cmpl.conn_id,
+                                                             gl_profile_tab[PROFILE_B_APP_ID].service_start_handle,
+                                                             gl_profile_tab[PROFILE_B_APP_ID].service_end_handle,
+                                                             remote_filter_char_uuid,
+                                                             char_elem_result_b,
+                                                             &count);
+                    if (status != ESP_GATT_OK){
+                        ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_char_by_uuid error");
+                    }
+
+                    /*  Every service have only one char in our 'ESP_GATTS_DEMO' demo, so we used first 'char_elem_result' */
+                    if (count > 0 && (char_elem_result_b[0].properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY)){
+                        gl_profile_tab[PROFILE_B_APP_ID].char_handle = char_elem_result_b[0].char_handle;
+                        esp_ble_gattc_register_for_notify (gattc_if, gl_profile_tab[PROFILE_B_APP_ID].remote_bda, char_elem_result_b[0].char_handle);
+                    }
+                }
+                /* free char_elem_result */
+                free(char_elem_result_b);
+            }else{
+                ESP_LOGE(GATTC_TAG, "no char found");
+            }
         }
         break;
-    case ESP_GATTC_GET_CHAR_EVT:
-        if (p_data->get_char.status != ESP_GATT_OK) {
+    case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
+
+        if (p_data->reg_for_notify.status != ESP_GATT_OK){
+            ESP_LOGE(GATTC_TAG, "reg notify failed, error status =%x", p_data->reg_for_notify.status);
             break;
         }
-        ESP_LOGI(GATTC_TAG, "GET CHAR: conn_id = %x, status %d", p_data->get_char.conn_id, p_data->get_char.status);
-        ESP_LOGI(GATTC_TAG, "GET CHAR: srvc_id = %04x, char_id = %04x", p_data->get_char.srvc_id.id.uuid.uuid.uuid16, p_data->get_char.char_id.uuid.uuid.uuid16);
+        uint16_t count = 0;
+        uint16_t notify_en = 1;
+        esp_gatt_status_t ret_status = esp_ble_gattc_get_attr_count( gattc_if,
+                                                                     gl_profile_tab[PROFILE_B_APP_ID].conn_id,
+                                                                     ESP_GATT_DB_DESCRIPTOR,
+                                                                     gl_profile_tab[PROFILE_B_APP_ID].service_start_handle,
+                                                                     gl_profile_tab[PROFILE_B_APP_ID].service_end_handle,
+                                                                     gl_profile_tab[PROFILE_B_APP_ID].char_handle,
+                                                                     &count);
+        if (ret_status != ESP_GATT_OK){
+            ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_attr_count error");
+        }
+        if (count > 0){
+            descr_elem_result_b = malloc(sizeof(descr_elem_result_b) * count);
+            if (!descr_elem_result_b){
+                ESP_LOGE(GATTC_TAG, "malloc error, gattc no mem");
+            }else{
+                ret_status = esp_ble_gattc_get_descr_by_char_handle( gattc_if,
+                                                                     gl_profile_tab[PROFILE_B_APP_ID].conn_id,
+                                                                     p_data->reg_for_notify.handle,
+                                                                     notify_descr_uuid,
+                                                                     descr_elem_result_b,
+                                                                     &count);
+                if (ret_status != ESP_GATT_OK){
+                    ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_descr_by_char_handle error");
+                }
 
-        if (p_data->get_char.char_id.uuid.uuid.uuid16 == REMOTE_NOTIFY_CHAR_UUID) {
-            ESP_LOGI(GATTC_TAG, "register notify");
-            esp_ble_gattc_register_for_notify(gattc_if, gl_profile_tab[PROFILE_B_APP_ID].remote_bda, &remote_service_id, &p_data->get_char.char_id);
-        }
+                /* Erery char have only one descriptor in our 'ESP_GATTS_DEMO' demo, so we used first 'descr_elem_result' */
+                if (count > 0 && descr_elem_result_b[0].uuid.len == ESP_UUID_LEN_16 && descr_elem_result_b[0].uuid.uuid.uuid16 == ESP_GATT_UUID_CHAR_CLIENT_CONFIG){
+                    ret_status = esp_ble_gattc_write_char_descr( gattc_if,
+                                                                 gl_profile_tab[PROFILE_B_APP_ID].conn_id,
+                                                                 descr_elem_result_b[0].handle,
+                                                                 sizeof(notify_en),
+                                                                 (uint8_t *)&notify_en,
+                                                                 ESP_GATT_WRITE_TYPE_RSP,
+                                                                 ESP_GATT_AUTH_REQ_NONE);
+                }
 
-        esp_ble_gattc_get_characteristic(gattc_if, p_data->get_char.conn_id, &remote_service_id, &p_data->get_char.char_id);
-        break;
-    case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
+                if (ret_status != ESP_GATT_OK){
+                    ESP_LOGE(GATTC_TAG, "esp_ble_gattc_write_char_descr error");
+                }
 
-        ESP_LOGI(GATTC_TAG, "REG FOR NOTIFY: status %d, srvc_id = %04x, char_id = %04x",
-                p_data->reg_for_notify.status,
-                p_data->reg_for_notify.srvc_id.id.uuid.uuid.uuid16,
-                p_data->reg_for_notify.char_id.uuid.uuid.uuid16);
-        uint16_t notify_en = 1;
-        esp_ble_gattc_write_char_descr(gattc_if,
-                                       gl_profile_tab[PROFILE_B_APP_ID].conn_id,
-                                       &remote_service_id,
-                                       &p_data->reg_for_notify.char_id,
-                                       &notify_descr_id,
-                                       sizeof(notify_en),
-                                       (uint8_t *)&notify_en,
-                                       ESP_GATT_WRITE_TYPE_RSP,
-                                       ESP_GATT_AUTH_REQ_NONE);
+                /* free descr_elem_result */
+                free(descr_elem_result_b);
+            }
+        }
+        else{
+            ESP_LOGE(GATTC_TAG, "decsr not found");
+        }
         break;
     }
     case ESP_GATTC_NOTIFY_EVT:
         ESP_LOGI(GATTC_TAG, "ESP_GATTC_NOTIFY_EVT, Receive notify value:");
         esp_log_buffer_hex(GATTC_TAG, p_data->notify.value, p_data->notify.value_len);
-        //write  back
-        esp_ble_gattc_write_char(gattc_if,
-                                gl_profile_tab[PROFILE_B_APP_ID].conn_id,
-                                &remote_service_id,
-                                &p_data->notify.char_id,
-                                p_data->notify.value_len,
-                                p_data->notify.value,
-                                ESP_GATT_WRITE_TYPE_RSP,
-                                ESP_GATT_AUTH_REQ_NONE);
         break;
     case ESP_GATTC_WRITE_DESCR_EVT:
         if (p_data->write.status != ESP_GATT_OK){
@@ -388,6 +505,18 @@ static void gattc_profile_b_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
             break;
         }
         ESP_LOGI(GATTC_TAG, "write descr success");
+        uint8_t write_char_data[35];
+        for (int i = 0; i < sizeof(write_char_data); ++i)
+        {
+            write_char_data[i] = i % 256;
+        }
+        esp_ble_gattc_write_char( gattc_if,
+                                  gl_profile_tab[PROFILE_B_APP_ID].conn_id,
+                                  gl_profile_tab[PROFILE_B_APP_ID].char_handle,
+                                  sizeof(write_char_data),
+                                  write_char_data,
+                                  ESP_GATT_WRITE_TYPE_RSP,
+                                  ESP_GATT_AUTH_REQ_NONE);
         break;
     case ESP_GATTC_WRITE_CHAR_EVT:
         if (p_data->write.status != ESP_GATT_OK){
@@ -405,8 +534,6 @@ static void gattc_profile_b_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
         break;
     }
     case ESP_GATTC_DISCONNECT_EVT:
-        ESP_LOGI(GATTC_TAG,"ESP_GATTC_DISCONNECT_EVT");
-        ESP_LOGI(GATTC_TAG, "conn_id %d, if %d", p_data->disconnect.conn_id, gattc_if);
         if (memcmp(p_data->disconnect.remote_bda, gl_profile_tab[PROFILE_B_APP_ID].remote_bda, 6) == 0){
             ESP_LOGI(GATTC_TAG, "device b disconnect");
             conn_device_b = false;
@@ -432,7 +559,7 @@ static void gattc_profile_c_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
         if (p_data->open.status != ESP_GATT_OK){
             ESP_LOGE(GATTC_TAG, "connect device failed, status %d", p_data->open.status);
             conn_device_c = false;
-            start_scan();
+            //start_scan();
             break;
         }
         memcpy(gl_profile_tab[PROFILE_C_APP_ID].remote_bda, p_data->open.remote_bda, 6);
@@ -453,11 +580,13 @@ static void gattc_profile_c_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
         esp_ble_gattc_search_service(gattc_if, param->cfg_mtu.conn_id, &remote_filter_service_uuid);
         break;
     case ESP_GATTC_SEARCH_RES_EVT: {
-        esp_gatt_srvc_id_t *srvc_id = &p_data->search_res.srvc_id;
+        esp_gatt_srvc_id_t *srvc_id = (esp_gatt_srvc_id_t *)&p_data->search_res.srvc_id;
         ESP_LOGI(GATTC_TAG, "SEARCH RES: conn_id = %x", p_data->search_res.conn_id);
         if (srvc_id->id.uuid.len == ESP_UUID_LEN_16 && srvc_id->id.uuid.uuid.uuid16 == REMOTE_SERVICE_UUID) {
             ESP_LOGI(GATTC_TAG, "UUID16: %x", srvc_id->id.uuid.uuid.uuid16);
             get_service_c = true;
+            gl_profile_tab[PROFILE_C_APP_ID].service_start_handle = p_data->search_res.start_handle;
+            gl_profile_tab[PROFILE_C_APP_ID].service_end_handle = p_data->search_res.end_handle;
         }
         break;
     }
@@ -467,51 +596,106 @@ static void gattc_profile_c_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
             break;
         }
         if (get_service_c){
-            esp_ble_gattc_get_characteristic(gattc_if, p_data->search_cmpl.conn_id, &remote_service_id, NULL);
+            uint16_t count = 0;
+            esp_gatt_status_t status = esp_ble_gattc_get_attr_count( gattc_if,
+                                                                     p_data->search_cmpl.conn_id,
+                                                                     ESP_GATT_DB_CHARACTERISTIC,
+                                                                     gl_profile_tab[PROFILE_C_APP_ID].service_start_handle,
+                                                                     gl_profile_tab[PROFILE_C_APP_ID].service_end_handle,
+                                                                     INVALID_HANDLE,
+                                                                     &count);
+            if (status != ESP_GATT_OK){
+                ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_attr_count error");
+            }
+
+            if (count > 0){
+                char_elem_result_c = (esp_gattc_char_elem_t *)malloc(sizeof(char_elem_result_c) * count);
+                if (!char_elem_result_c){
+                    ESP_LOGE(GATTC_TAG, "gattc no mem");
+                }else{
+                    status = esp_ble_gattc_get_char_by_uuid( gattc_if,
+                                                             p_data->search_cmpl.conn_id,
+                                                             gl_profile_tab[PROFILE_C_APP_ID].service_start_handle,
+                                                             gl_profile_tab[PROFILE_C_APP_ID].service_end_handle,
+                                                             remote_filter_char_uuid,
+                                                             char_elem_result_c,
+                                                             &count);
+                    if (status != ESP_GATT_OK){
+                        ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_char_by_uuid error");
+                    }
+
+                    /*  Every service have only one char in our 'ESP_GATTS_DEMO' demo, so we used first 'char_elem_result' */
+                    if (count > 0 && (char_elem_result_c[0].properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY)){
+                        gl_profile_tab[PROFILE_C_APP_ID].char_handle = char_elem_result_c[0].char_handle;
+                        esp_ble_gattc_register_for_notify (gattc_if, gl_profile_tab[PROFILE_C_APP_ID].remote_bda, char_elem_result_c[0].char_handle);
+                    }
+                }
+                /* free char_elem_result */
+                free(char_elem_result_c);
+            }else{
+                ESP_LOGE(GATTC_TAG, "no char found");
+            }
         }
         break;
-    case ESP_GATTC_GET_CHAR_EVT:
-        if (p_data->get_char.status != ESP_GATT_OK) {
-            ESP_LOGE(GATTC_TAG, "GET CHAR failed, error status = %x", p_data->get_char.status);
+    case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
+        if (p_data->reg_for_notify.status != ESP_GATT_OK){
+            ESP_LOGE(GATTC_TAG, "reg notify failed, error status =%x", p_data->reg_for_notify.status);
             break;
         }
-        ESP_LOGI(GATTC_TAG, "GET CHAR: srvc_id = %04x, char_id = %04x", p_data->get_char.srvc_id.id.uuid.uuid.uuid16, p_data->get_char.char_id.uuid.uuid.uuid16);
-        if (p_data->get_char.char_id.uuid.uuid.uuid16 == REMOTE_NOTIFY_CHAR_UUID) {
-            ESP_LOGI(GATTC_TAG, "register notify");
-            esp_ble_gattc_register_for_notify(gattc_if, gl_profile_tab[PROFILE_C_APP_ID].remote_bda, &remote_service_id, &p_data->get_char.char_id);
-        }
-        esp_ble_gattc_get_characteristic(gattc_if, p_data->get_char.conn_id, &remote_service_id, &p_data->get_char.char_id);
-        break;
-    case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
+        uint16_t count = 0;
         uint16_t notify_en = 1;
-        ESP_LOGI(GATTC_TAG, "REG FOR NOTIFY: status %d, srvc_id = %04x, char_id = %04x",
-                p_data->reg_for_notify.status,
-                p_data->reg_for_notify.srvc_id.id.uuid.uuid.uuid16,
-                p_data->reg_for_notify.char_id.uuid.uuid.uuid16);
-
-        esp_ble_gattc_write_char_descr(gattc_if,
-                                       gl_profile_tab[PROFILE_C_APP_ID].conn_id,
-                                       &remote_service_id,
-                                       &p_data->reg_for_notify.char_id,
-                                       &notify_descr_id,
-                                       sizeof(notify_en),
-                                       (uint8_t *)&notify_en,
-                                       ESP_GATT_WRITE_TYPE_RSP,
-                                       ESP_GATT_AUTH_REQ_NONE);
+        esp_gatt_status_t ret_status = esp_ble_gattc_get_attr_count( gattc_if,
+                                                                     gl_profile_tab[PROFILE_C_APP_ID].conn_id,
+                                                                     ESP_GATT_DB_DESCRIPTOR,
+                                                                     gl_profile_tab[PROFILE_C_APP_ID].service_start_handle,
+                                                                     gl_profile_tab[PROFILE_C_APP_ID].service_end_handle,
+                                                                     gl_profile_tab[PROFILE_C_APP_ID].char_handle,
+                                                                     &count);
+        if (ret_status != ESP_GATT_OK){
+            ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_attr_count error");
+        }
+        if (count > 0){
+            descr_elem_result_c = malloc(sizeof(descr_elem_result_c) * count);
+            if (!descr_elem_result_c){
+                ESP_LOGE(GATTC_TAG, "malloc error, gattc no mem");
+            }else{
+                ret_status = esp_ble_gattc_get_descr_by_char_handle( gattc_if,
+                                                                     gl_profile_tab[PROFILE_C_APP_ID].conn_id,
+                                                                     p_data->reg_for_notify.handle,
+                                                                     notify_descr_uuid,
+                                                                     descr_elem_result_c,
+                                                                     &count);
+                if (ret_status != ESP_GATT_OK){
+                    ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_descr_by_char_handle error");
+                }
+
+                /* Erery char have only one descriptor in our 'ESP_GATTS_DEMO' demo, so we used first 'descr_elem_result' */
+                if (count > 0 && descr_elem_result_c[0].uuid.len == ESP_UUID_LEN_16 && descr_elem_result_c[0].uuid.uuid.uuid16 == ESP_GATT_UUID_CHAR_CLIENT_CONFIG){
+                    ret_status = esp_ble_gattc_write_char_descr( gattc_if,
+                                                                 gl_profile_tab[PROFILE_C_APP_ID].conn_id,
+                                                                 descr_elem_result_c[0].handle,
+                                                                 sizeof(notify_en),
+                                                                 (uint8_t *)&notify_en,
+                                                                 ESP_GATT_WRITE_TYPE_RSP,
+                                                                 ESP_GATT_AUTH_REQ_NONE);
+                }
+
+                if (ret_status != ESP_GATT_OK){
+                    ESP_LOGE(GATTC_TAG, "esp_ble_gattc_write_char_descr error");
+                }
+
+                /* free descr_elem_result */
+                free(descr_elem_result_c);
+            }
+        }
+        else{
+            ESP_LOGE(GATTC_TAG, "decsr not found");
+        }
         break;
     }
     case ESP_GATTC_NOTIFY_EVT:
         ESP_LOGI(GATTC_TAG, "ESP_GATTC_NOTIFY_EVT, Receive notify value:");
         esp_log_buffer_hex(GATTC_TAG, p_data->notify.value, p_data->notify.value_len);
-        //write  back
-        esp_ble_gattc_write_char(gattc_if,
-                                gl_profile_tab[PROFILE_C_APP_ID].conn_id,
-                                &remote_service_id,
-                                &p_data->notify.char_id,
-                                p_data->notify.value_len,
-                                p_data->notify.value,
-                                ESP_GATT_WRITE_TYPE_RSP,
-                                ESP_GATT_AUTH_REQ_NONE);
         break;
     case ESP_GATTC_WRITE_DESCR_EVT:
         if (p_data->write.status != ESP_GATT_OK){
@@ -519,6 +703,18 @@ static void gattc_profile_c_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
             break;
         }
         ESP_LOGI(GATTC_TAG, "write descr success");
+        uint8_t write_char_data[35];
+        for (int i = 0; i < sizeof(write_char_data); ++i)
+        {
+            write_char_data[i] = i % 256;
+        }
+        esp_ble_gattc_write_char( gattc_if,
+                                  gl_profile_tab[PROFILE_C_APP_ID].conn_id,
+                                  gl_profile_tab[PROFILE_C_APP_ID].char_handle,
+                                  sizeof(write_char_data),
+                                  write_char_data,
+                                  ESP_GATT_WRITE_TYPE_RSP,
+                                  ESP_GATT_AUTH_REQ_NONE);
         break;
     case ESP_GATTC_WRITE_CHAR_EVT:
         if (p_data->write.status != ESP_GATT_OK){
@@ -536,8 +732,6 @@ static void gattc_profile_c_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
         break;
     }
     case ESP_GATTC_DISCONNECT_EVT:
-        ESP_LOGI(GATTC_TAG,"ESP_GATTC_DISCONNECT_EVT");
-        ESP_LOGI(GATTC_TAG, "conn_id %d, if %d", p_data->disconnect.conn_id, gattc_if);
         if (memcmp(p_data->disconnect.remote_bda, gl_profile_tab[PROFILE_C_APP_ID].remote_bda, 6) == 0){
             ESP_LOGI(GATTC_TAG, "device c disconnect");
             conn_device_c = false;
@@ -554,6 +748,15 @@ static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *par
     uint8_t *adv_name = NULL;
     uint8_t adv_name_len = 0;
     switch (event) {
+    case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
+         ESP_LOGI(GATTC_TAG, "update connetion params status = %d, min_int = %d, max_int = %d,conn_int = %d,latency = %d, timeout = %d",
+                  param->update_conn_params.status,
+                  param->update_conn_params.min_int,
+                  param->update_conn_params.max_int,
+                  param->update_conn_params.conn_int,
+                  param->update_conn_params.latency,
+                  param->update_conn_params.timeout);
+        break;
     case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: {
         //the unit of the duration is second
         uint32_t duration = 30;
@@ -593,7 +796,7 @@ static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *par
                 if (strlen(remote_device_name[0]) == adv_name_len && strncmp((char *)adv_name, remote_device_name[0], adv_name_len) == 0) {
                     if (conn_device_a == false) {
                         conn_device_a = true;
-                        ESP_LOGI(GATTC_TAG, "Searched device %s\n", remote_device_name[0]);
+                        ESP_LOGI(GATTC_TAG, "Searched device %s", remote_device_name[0]);
                         esp_ble_gap_stop_scanning();
                         esp_ble_gattc_open(gl_profile_tab[PROFILE_A_APP_ID].gattc_if, scan_result->scan_rst.bda, true);
                         Isconnecting = true;
@@ -603,7 +806,7 @@ static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *par
                 else if (strlen(remote_device_name[1]) == adv_name_len && strncmp((char *)adv_name, remote_device_name[1], adv_name_len) == 0) {
                     if (conn_device_b == false) {
                         conn_device_b = true;
-                        ESP_LOGI(GATTC_TAG, "Searched device %s\n", remote_device_name[1]);
+                        ESP_LOGI(GATTC_TAG, "Searched device %s", remote_device_name[1]);
                         esp_ble_gap_stop_scanning();
                         esp_ble_gattc_open(gl_profile_tab[PROFILE_B_APP_ID].gattc_if, scan_result->scan_rst.bda, true);
                         Isconnecting = true;
@@ -613,7 +816,7 @@ static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *par
                 else if (strlen(remote_device_name[2]) == adv_name_len && strncmp((char *)adv_name, remote_device_name[2], adv_name_len) == 0) {
                     if (conn_device_c == false) {
                         conn_device_c = true;
-                        ESP_LOGI(GATTC_TAG, "Searched device %s\n", remote_device_name[2]);
+                        ESP_LOGI(GATTC_TAG, "Searched device %s", remote_device_name[2]);
                         esp_ble_gap_stop_scanning();
                         esp_ble_gattc_open(gl_profile_tab[PROFILE_C_APP_ID].gattc_if, scan_result->scan_rst.bda, true);
                         Isconnecting = true;