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.
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;
}
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;
}
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;
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;
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;
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;
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;
}
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;
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;
}
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,
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;
}
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,
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;
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;
}
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);
}
#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 */
/**@{
*/
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;
/**
* @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;
*/
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;
*/
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;
*/
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 {
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
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 */
*/
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
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 */
* @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
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
*/
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
* - 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);
/**
*
* @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
*
*/
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);
/**
*
* @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.
*/
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);
*
* @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.
*/
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,
*
* @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.
* - 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,
*
* @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.
*/
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,
*
* @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
*
*/
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);
/**
*
* @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
*
*/
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);
/**
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:
** Action Functions
*****************************************************************************/
+
+void bta_gattc_reset_discover_st(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_STATUS status);
+
/*******************************************************************************
**
** Function bta_gattc_enable
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;
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) {
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;
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
* 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);
}
}
/*******************************************************************************
*******************************************************************************/
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) {
bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_READ, status, NULL);
}
- }
}
/*******************************************************************************
**
*********************************************************************************/
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);
}
*******************************************************************************/
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);
}
}
/*******************************************************************************
*******************************************************************************/
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);
}
}
}
{
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);
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);
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 */
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) {
{
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
}
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);
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;
}
/* 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);
}
/*******************************************************************************
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;
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 */
}
}
/* 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) {
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;
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);
}
}
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;
** 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;
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;
}
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 {
}
/* 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
}
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;
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;
}
/*******************************************************************************
**
-** 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;
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);
}
**
** 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));
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);
}
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);
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;
** 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.
**
**
*******************************************************************************/
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,
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;
**
** 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.
**
**
*******************************************************************************/
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;
}
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);
** 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)
{
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;
** 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;
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);
}
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;
** 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);
}
**
** 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;
}
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;
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;
}
** 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;
}
/*******************************************************************************
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;
return;
}
-#endif /* BTA_GATT_INCLUDED */
+#endif /* defined(GATTC_INCLUDED) && (GATTC_INCLUDED == TRUE) */
#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[] = {
};
/* 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
** 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(" ");
}
#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
*******************************************************************************/
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);
}
/*******************************************************************************
**
*******************************************************************************/
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;
}
/*******************************************************************************
**
**
*******************************************************************************/
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;
}
/*******************************************************************************
**
*******************************************************************************/
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;
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;
#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);
}
/*******************************************************************************
**
/* 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 ++;
{
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);
**
*******************************************************************************/
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;
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 ++;
**
*******************************************************************************/
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;
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));
**
*******************************************************************************/
#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)) {
}
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
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
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 */
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;
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;
}
}
}
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;
}
}
/*******************************************************************************
**
-** 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);
}
/*******************************************************************************
**
*******************************************************************************/
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 --;
**
*******************************************************************************/
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));
}
** 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 */
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,
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,
/* 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 */
/* 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 */
/* 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 */
/* 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 */
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:
** 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) {
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");
/* 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;
}
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;
}
/*******************************************************************************
{
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;
}
**
** 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 {
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
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 */
#include "bta_api.h"
#include "gatt_api.h"
+#include "list.h"
#ifndef BTA_GATT_INCLUDED
#warning BTA_GATT_INCLUDED not defined
#define BTA_GATT_DEBUG FALSE
#endif
+typedef enum {
+ BTGATT_DB_PRIMARY_SERVICE,
+ BTGATT_DB_SECONDARY_SERVICE,
+ BTGATT_DB_CHARACTERISTIC,
+ BTGATT_DB_DESCRIPTOR,
+ BTGATT_DB_INCLUDED_SERVICE,
+}bt_gatt_db_attribute_type_t;
+
+typedef enum {
+ GATT_OP_GET_SVC_BY_UUID,
+ GATT_OP_GET_ALL_CHAR,
+ GATT_OP_GET_ALL_DESCRI,
+ GATT_OP_GET_CHAR_BY_UUID,
+ GATT_OP_GET_DESCRI_BY_UUID,
+ GATT_OP_GET_DESCRI_BY_HANDLE,
+ GATT_OP_GET_INCLUDE_SVC,
+}bt_gatt_get_db_op_t;
+
+typedef struct {
+ bt_gatt_db_attribute_type_t type;
+ UINT16 attribute_handle;
+ UINT16 start_handle;
+ UINT16 end_handle;
+ UINT16 id;
+ UINT8 properties;
+ bt_uuid_t uuid;
+}btgatt_db_element_t;
+
/*****************************************************************************
** Constants and data types
*****************************************************************************/
#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 */
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
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;
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;
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;
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;
BD_ADDR remote_bda;
} tBTA_GATTC_DISCONNECT;
+
+
typedef union {
tBTA_GATT_STATUS status;
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;
tBTA_GATT_STATUS status;
tBTA_GATTS_IF server_if;
} tBTA_GATTS_CANCEL_OPEN;
-
/* GATTS callback data */
typedef union {
tBTA_GATTS_REG_OPER reg_oper;
/* 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
/*******************************************************************************
**
-** 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);
/*******************************************************************************
**
** 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);
/*******************************************************************************
**
** 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);
/*******************************************************************************
**
**
** 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);
/*******************************************************************************
**
**
** 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);
/*******************************************************************************
**
** 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,
**
*******************************************************************************/
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);
**
*******************************************************************************/
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);
/*******************************************************************************
**
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,
};
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
#endif
#define BTA_GATTC_WRITE_PREPARE GATT_WRITE_PREPARE
-
+#define BTA_GATTC_INVALID_HANDLE 0
/* internal strucutre for GATTC register API */
typedef struct {
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;
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;
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;
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;
/* 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;
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 */
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 */
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;
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,
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);
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);
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 */
#include "blufi_int.h"
-#include "esp_wifi.h"
+//#include "esp_wifi.h"
#if (GATTS_INCLUDED == TRUE)
extern tBLUFI_ENV blufi_env;
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
}
-// 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;
// 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;
}
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;
}
}
-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,
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,
}
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);
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);
}
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:
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;
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));
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;
}
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;
}
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;
}
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);
break;
}
default:
- LOG_ERROR("%s: Unhandled event (%d)!", __FUNCTION__, msg->act);
+ LOG_DEBUG("%s: Unhandled event (%d)!", __FUNCTION__, msg->act);
break;
}
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,
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;
//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;
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 {
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__ */
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) {
#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,
.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;
};
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) {
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);
}
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;
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){
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;
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) {
#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";
#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;
};
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) {
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);
}
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;
}
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){
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){
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;
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:
#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;
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 = {
.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;
};
//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);
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;
}
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){
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){
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){
//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);
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;
}
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){
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){
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;
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);
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;
}
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){
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){
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;
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;
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;
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;
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;