From: Yulong Date: Thu, 24 Aug 2017 06:24:04 +0000 (-0400) Subject: This is a combination of 4 commits. X-Git-Tag: v3.1-dev~258^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1759a47060e4708e264e11b395a0fbaeeca7863a;p=esp-idf This is a combination of 4 commits. 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. --- diff --git a/components/bt/bluedroid/api/esp_gattc_api.c b/components/bt/bluedroid/api/esp_gattc_api.c index 75970ad3f1..d486c14c6a 100644 --- a/components/bt/bluedroid/api/esp_gattc_api.c +++ b/components/bt/bluedroid/api/esp_gattc_api.c @@ -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); } diff --git a/components/bt/bluedroid/api/include/esp_gatt_defs.h b/components/bt/bluedroid/api/include/esp_gatt_defs.h index d0f73dd32c..a98069eadb 100644 --- a/components/bt/bluedroid/api/include/esp_gatt_defs.h +++ b/components/bt/bluedroid/api/include/esp_gatt_defs.h @@ -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 diff --git a/components/bt/bluedroid/api/include/esp_gattc_api.h b/components/bt/bluedroid/api/include/esp_gattc_api.h index b950d438f0..ba5cfffac0 100644 --- a/components/bt/bluedroid/api/include/esp_gattc_api.h +++ b/components/bt/bluedroid/api/include/esp_gattc_api.h @@ -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); /** diff --git a/components/bt/bluedroid/bta/dm/bta_dm_act.c b/components/bt/bluedroid/bta/dm/bta_dm_act.c index 12ceef36cc..eed5241a5a 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_act.c @@ -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: diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c index 2738b52ad0..159baa0632 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c @@ -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, - ¬ify.char_id.srvc_id, - ¬ify.char_id.char_id, - ¬ify.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, ¬ify, handle)) { - /* if app registered for the notification */ - if (bta_gattc_check_notif_registry(p_clrcb, p_srcb, ¬ify)) { - /* 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, ¬ify, &p_data->att_value)) { + /* if app registered for the notification */ + if (bta_gattc_check_notif_registry(p_clrcb, p_srcb, ¬ify)) { + /* 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, ¬ify); - } + 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, ¬ify); } - } - } 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; } diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_api.c b/components/bt/bluedroid/bta/gatt/bta_gattc_api.c index eaaf77cccf..802310b901 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_api.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_api.c @@ -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) */ diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c b/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c index 506fd9e140..5e0943a9bb 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c @@ -37,19 +37,53 @@ #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 */ diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_main.c b/components/bt/bluedroid/bta/gatt/bta_gattc_main.c index 995d74cfd7..f7ae3101be 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_main.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_main.c @@ -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: diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c index 30a0b395ae..dfa685f67d 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c @@ -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 */ diff --git a/components/bt/bluedroid/bta/include/bta_gatt_api.h b/components/bt/bluedroid/bta/include/bta_gatt_api.h index 4b4945aa5e..d81fa547e0 100644 --- a/components/bt/bluedroid/bta/include/bta_gatt_api.h +++ b/components/bt/bluedroid/bta/include/bta_gatt_api.h @@ -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 @@ -43,6 +44,34 @@ #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); /******************************************************************************* ** diff --git a/components/bt/bluedroid/bta/include/bta_gattc_int.h b/components/bt/bluedroid/bta/include/bta_gattc_int.h index 6ea09ef8c1..2515cb5225 100644 --- a/components/bt/bluedroid/bta/include/bta_gattc_int.h +++ b/components/bt/bluedroid/bta/include/bta_gattc_int.h @@ -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 */ diff --git a/components/bt/bluedroid/btc/profile/esp/blufi/blufi_protocol.c b/components/bt/bluedroid/btc/profile/esp/blufi/blufi_protocol.c index ca2a847d0a..14cdb57217 100644 --- a/components/bt/bluedroid/btc/profile/esp/blufi/blufi_protocol.c +++ b/components/bt/bluedroid/btc/profile/esp/blufi/blufi_protocol.c @@ -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; diff --git a/components/bt/bluedroid/btc/profile/std/gatt/btc_gatt_util.c b/components/bt/bluedroid/btc/profile/std/gatt/btc_gatt_util.c index e326eff9af..8cb0080ee1 100644 --- a/components/bt/bluedroid/btc/profile/std/gatt/btc_gatt_util.c +++ b/components/bt/bluedroid/btc/profile/std/gatt/btc_gatt_util.c @@ -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 diff --git a/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c b/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c index 67098e8bf6..37f17fcca2 100644 --- a/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c +++ b/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c @@ -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(¶m, 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(¶m.get_char.srvc_id, &arg->get_first_char.service_id, sizeof(esp_gatt_srvc_id_t)); - memcpy(¶m.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, ¶m); + *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(¶m, 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(¶m.get_char.srvc_id, &arg->get_next_char.service_id, sizeof(esp_gatt_srvc_id_t)); - memcpy(¶m.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, ¶m); + *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(¶m, 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(¶m.get_descr.srvc_id, &arg->get_first_descr.service_id, sizeof(esp_gatt_srvc_id_t)); - memcpy(¶m.get_descr.char_id, &arg->get_first_descr.char_id, sizeof(esp_gatt_id_t)); - memcpy(¶m.get_descr.descr_id, &descr_id, sizeof(esp_gatt_id_t)); - btc_gattc_cb_to_app(ESP_GATTC_GET_DESCR_EVT, gattc_if, ¶m); + *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(¶m, 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(¶m.get_descr.srvc_id, &arg->get_next_descr.service_id, sizeof(esp_gatt_srvc_id_t)); - memcpy(¶m.get_descr.char_id, &arg->get_next_descr.char_id, sizeof(esp_gatt_id_t)); - memcpy(¶m.get_descr.descr_id, &descr_id, sizeof(esp_gatt_id_t)); - btc_gattc_cb_to_app(ESP_GATTC_GET_DESCR_EVT, gattc_if, ¶m); +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(¶m, 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(¶m.get_incl_srvc.srvc_id, &arg->get_first_incl_srvc.service_id, sizeof(esp_gatt_srvc_id_t)); - memcpy(¶m.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, ¶m); + *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(¶m, 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(¶m.get_incl_srvc.srvc_id, &arg->get_next_incl_srvc.service_id, sizeof(esp_gatt_srvc_id_t)); - memcpy(¶m.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, ¶m); + 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(¶m, 0, sizeof(esp_ble_gattc_cb_param_t)); param.reg_for_notify.status = status; - memcpy(¶m.reg_for_notify.srvc_id, &arg->reg_for_notify.service_id, sizeof(esp_gatt_srvc_id_t)); - memcpy(¶m.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, ¶m); } 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(¶m, 0, sizeof(esp_ble_gattc_cb_param_t)); param.unreg_for_notify.status = status; - memcpy(¶m.unreg_for_notify.srvc_id, &arg->unreg_for_notify.service_id, sizeof(esp_gatt_srvc_id_t)); - memcpy(¶m.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, ¶m); } @@ -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(¶m, 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(¶m.write.srvc_id, &write->srvc_id); - bta_to_btc_gatt_id(¶m.write.char_id, &write->char_id); + param.write.handle = write->handle; btc_gattc_cb_to_app(ret_evt, gattc_if, ¶m); 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(¶m.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(¶m.search_res.srvc_id, &srvc_res->service_uuid); btc_gattc_cb_to_app(ESP_GATTC_SEARCH_RES_EVT, gattc_if, ¶m); 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(¶m.write.srvc_id, &write->srvc_id); - bta_to_btc_gatt_id(¶m.write.char_id, &write->char_id); - bta_to_btc_gatt_id(¶m.write.descr_id, &write->descr_type); + param.write.handle = write->handle; btc_gattc_cb_to_app(ESP_GATTC_WRITE_DESCR_EVT, gattc_if, ¶m); 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(¶m.notify.srvc_id, ¬ify->char_id.srvc_id); - bta_to_btc_gatt_id(¶m.notify.char_id, ¬ify->char_id.char_id); - bta_to_btc_gatt_id(¶m.notify.descr_id, ¬ify->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, ¬ify->char_id); + BTA_GATTC_SendIndConfirm(notify->conn_id, notify->handle); } btc_gattc_cb_to_app(ESP_GATTC_NOTIFY_EVT, gattc_if, ¶m); @@ -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; } diff --git a/components/bt/bluedroid/btc/profile/std/include/btc_gattc.h b/components/bt/bluedroid/btc/profile/std/include/btc_gattc.h index d1e0e9680d..5087e5d233 100644 --- a/components/bt/bluedroid/btc/profile/std/include/btc_gattc.h +++ b/components/bt/bluedroid/btc/profile/std/include/btc_gattc.h @@ -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__ */ diff --git a/components/bt/bluedroid/stack/gatt/gatt_utils.c b/components/bt/bluedroid/stack/gatt/gatt_utils.c index 0266a212d5..3439a31d14 100644 --- a/components/bt/bluedroid/stack/gatt/gatt_utils.c +++ b/components/bt/bluedroid/stack/gatt/gatt_utils.c @@ -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) { diff --git a/examples/bluetooth/gatt_client/main/gattc_demo.c b/examples/bluetooth/gatt_client/main/gattc_demo.c index 76b809ede6..24fe67ac04 100644 --- a/examples/bluetooth/gatt_client/main/gattc_demo.c +++ b/examples/bluetooth/gatt_client/main/gattc_demo.c @@ -41,41 +41,36 @@ #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, - ¬ify_descr_id, - sizeof(notify_en), - (uint8_t *)¬ify_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 *)¬ify_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) { diff --git a/examples/bluetooth/gatt_security_client/main/example_ble_sec_gattc_demo.c b/examples/bluetooth/gatt_security_client/main/example_ble_sec_gattc_demo.c index 2964602c96..cf9ec505a1 100644 --- a/examples/bluetooth/gatt_security_client/main/example_ble_sec_gattc_demo.c +++ b/examples/bluetooth/gatt_security_client/main/example_ble_sec_gattc_demo.c @@ -41,38 +41,20 @@ #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 *)¬ify_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 *)¬ify_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){ diff --git a/examples/bluetooth/gatt_security_server/main/example_ble_sec_gatts_demo.c b/examples/bluetooth/gatt_security_server/main/example_ble_sec_gatts_demo.c index 2bee5d759a..0722476dba 100644 --- a/examples/bluetooth/gatt_security_server/main/example_ble_sec_gatts_demo.c +++ b/examples/bluetooth/gatt_security_server/main/example_ble_sec_gatts_demo.c @@ -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: diff --git a/examples/bluetooth/gattc_multi_connect/main/gattc_multi_connect.c b/examples/bluetooth/gattc_multi_connect/main/gattc_multi_connect.c index adeb070f54..61c29edc0e 100644 --- a/examples/bluetooth/gattc_multi_connect/main/gattc_multi_connect.c +++ b/examples/bluetooth/gattc_multi_connect/main/gattc_multi_connect.c @@ -45,35 +45,34 @@ #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, - ¬ify_descr_id, - sizeof(notify_en), - (uint8_t *)¬ify_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 *)¬ify_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 *)¬ify_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, - ¬ify_descr_id, - sizeof(notify_en), - (uint8_t *)¬ify_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, - ¬ify_descr_id, - sizeof(notify_en), - (uint8_t *)¬ify_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 *)¬ify_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;