From 988d621f1cfb674698c3b3d54ff6e18bb8650e7c Mon Sep 17 00:00:00 2001 From: "h.sandeep" Date: Tue, 8 Aug 2017 12:01:06 +0530 Subject: [PATCH] Apply Tizen3.0 Gatt client product patch =============================================== commit 4a721c92d78ddb62650f596a4af26637db60a36e Author: Seungyoun Ju Date: Wed Apr 26 18:03:40 2017 +0900 Fix : Simultaneous GATT client requests are failed =============================================== Change-Id: Ifc3012d97c68c8bdcc14a7b1a1ab1cb4441253b6 Signed-off-by: h.sandeep --- include/bluetooth_private.h | 16 +++ src/bluetooth-common.c | 79 +++--------- src/bluetooth-gatt.c | 305 ++++++++++++++++++++++++++++---------------- 3 files changed, 226 insertions(+), 174 deletions(-) diff --git a/include/bluetooth_private.h b/include/bluetooth_private.h index 923fff2..bba2f2f 100644 --- a/include/bluetooth_private.h +++ b/include/bluetooth_private.h @@ -376,6 +376,12 @@ typedef struct { int value_length; char *value; + + bt_gatt_client_request_completed_cb read_cb; + void *read_user_data; + + bt_gatt_client_request_completed_cb write_cb; + void *write_user_data; } bt_gatt_characteristic_s; typedef struct { @@ -395,6 +401,12 @@ typedef struct { int value_length; char *value; + + bt_gatt_client_request_completed_cb read_cb; + void *read_user_data; + + bt_gatt_client_request_completed_cb write_cb; + void *write_user_data; } bt_gatt_descriptor_s; typedef struct { @@ -636,6 +648,10 @@ int _bt_convert_address_to_string(char **addr_str, bluetooth_device_address_t *a */ void _bt_convert_address_to_hex(bluetooth_device_address_t *addr_hex, const char *addr_str); +void _handle_gatt_client_read_completed_event(int result, bt_gatt_resp_data_t *resp); + +void _handle_gatt_client_write_completed_event(int result, bt_gatt_resp_data_t *resp); + /** * @internal diff --git a/src/bluetooth-common.c b/src/bluetooth-common.c index 4742fa3..f3a06a2 100644 --- a/src/bluetooth-common.c +++ b/src/bluetooth-common.c @@ -1127,6 +1127,10 @@ static bool __bt_need_to_handle(int event) case BLUETOOTH_EVENT_OTP_WRITE_CHAR_VAL: case BLUETOOTH_EVENT_OTP_INDICATION: case BLUETOOTH_EVENT_OTC_STATE_CHANGED: + case BLUETOOTH_EVENT_GATT_READ_CHAR: + case BLUETOOTH_EVENT_GATT_WRITE_CHAR: + case BLUETOOTH_EVENT_GATT_READ_DESC: + case BLUETOOTH_EVENT_GATT_WRITE_DESC: return true; default: break; @@ -2146,11 +2150,7 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us bt_event_slot_container[event_index].user_data); break; - case BLUETOOTH_EVENT_GATT_READ_CHAR: { - int ret; - bt_gatt_client_request_completed_cb cb = bt_event_slot_container[event_index].callback; - bt_gatt_client_cb_data_s *cb_data = bt_event_slot_container[event_index].user_data; - + case BLUETOOTH_EVENT_GATT_READ_CHAR: BT_INFO("BLUETOOTH_EVENT_GATT_READ_CHAR"); if (TIZEN_FEATURE_ENABLE_LEGACY_GATT_CLIENT && _bt_gatt_is_legacy_client_mode()) { @@ -2164,25 +2164,10 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us break; } } - _bt_unset_cb(BT_EVENT_GATT_CLIENT_READ_CHARACTERISTIC); - ret = param->result; - if (ret == BT_ATT_ERROR_NONE) { - char_val = (bt_gatt_char_value_t *)(param->param_data); - bt_gatt_set_value(cb_data->gatt_handle, - (char *)char_val->char_value, (int)char_val->val_len); - } - cb(ret, cb_data->gatt_handle, cb_data->user_data); - g_free(cb_data); - + _handle_gatt_client_read_completed_event(param->result, + param->param_data); break; - } - case BLUETOOTH_EVENT_GATT_WRITE_CHAR: { - int ret; - bt_gatt_client_request_completed_cb cb = bt_event_slot_container[event_index].callback; - bt_gatt_client_cb_data_s *cb_data = bt_event_slot_container[event_index].user_data; - - BT_INFO("BLUETOOTH_EVENT_GATT_WRITE_CHAR"); - + case BLUETOOTH_EVENT_GATT_WRITE_CHAR: if (TIZEN_FEATURE_ENABLE_LEGACY_GATT_CLIENT && _bt_gatt_is_legacy_client_mode()) { if (_bt_gatt_is_legacy_client_mode()) { ((bt_gatt_characteristic_write_cb)bt_event_slot_container[event_index].callback) @@ -2192,52 +2177,20 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us break; } } - _bt_unset_cb(BT_EVENT_GATT_CLIENT_WRITE_CHARACTERISTIC); - - ret = param->result; - - if (ret != BT_ATT_ERROR_NONE) - BT_ERR("BLUETOOTH_EVENT_GATT_WRITE_CHAR - ret [%d]", ret); - - cb(ret, cb_data->gatt_handle, cb_data->user_data); - g_free(cb_data); + _handle_gatt_client_write_completed_event(param->result, + param->param_data); break; - } - case BLUETOOTH_EVENT_GATT_READ_DESC: { - int ret; - bt_gatt_client_request_completed_cb cb = bt_event_slot_container[event_index].callback; - bt_gatt_client_cb_data_s *cb_data = bt_event_slot_container[event_index].user_data; - bt_gatt_char_property_t *desc_val = NULL; - + case BLUETOOTH_EVENT_GATT_READ_DESC: BT_INFO("BLUETOOTH_EVENT_GATT_READ_DESC"); - - _bt_unset_cb(BT_EVENT_GATT_CLIENT_READ_DESCRIPTOR); - ret = param->result; - if (ret == BT_ATT_ERROR_NONE) { - desc_val = (bt_gatt_char_property_t *)(param->param_data); - bt_gatt_set_value(cb_data->gatt_handle, - desc_val->description, (int)desc_val->val_len); - } - cb(ret, cb_data->gatt_handle, cb_data->user_data); - g_free(cb_data); - + _handle_gatt_client_read_completed_event(param->result, + param->param_data); break; - } - case BLUETOOTH_EVENT_GATT_WRITE_DESC: { - int ret; - bt_gatt_client_request_completed_cb cb = bt_event_slot_container[event_index].callback; - bt_gatt_client_cb_data_s *cb_data = bt_event_slot_container[event_index].user_data; - + case BLUETOOTH_EVENT_GATT_WRITE_DESC: BT_INFO("BLUETOOTH_EVENT_GATT_WRITE_DESC"); - - _bt_unset_cb(BT_EVENT_GATT_CLIENT_WRITE_DESCRIPTOR); - ret = param->result; - cb(ret, cb_data->gatt_handle, cb_data->user_data); - g_free(cb_data); - + _handle_gatt_client_write_completed_event(param->result, + param->param_data); break; - } case BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED: { bt_gatt_read_req_t *read_req = param->param_data; bt_gatt_server_read_value_requested_cb cb; diff --git a/src/bluetooth-gatt.c b/src/bluetooth-gatt.c index 6d73ad3..289fc5e 100644 --- a/src/bluetooth-gatt.c +++ b/src/bluetooth-gatt.c @@ -763,7 +763,7 @@ int bt_gatt_read_characteristic_value(bt_gatt_attribute_h characteristic, BT_CHECK_INPUT_PARAMETER(characteristic); BT_CHECK_INPUT_PARAMETER(callback); /* LCOV_EXCL_START */ - ret = _bt_get_error_code(bluetooth_gatt_read_characteristic_value((const char *)characteristic)); + ret = _bt_get_error_code(bluetooth_gatt_read_characteristic_value((const char *)characteristic, NULL)); if (ret != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); @@ -863,7 +863,11 @@ static void __bt_gatt_free_descriptor(bt_gatt_h gatt_handle) g_free(desc->path); g_free(desc->uuid); g_free(desc->value); - g_free(desc); + + if (!desc->read_cb && !desc->write_cb) + g_free(desc); + else + desc->parent = NULL; } static void __bt_gatt_free_characteristic(bt_gatt_h gatt_handle) @@ -888,7 +892,11 @@ static void __bt_gatt_free_characteristic(bt_gatt_h gatt_handle) g_free(chr->path); g_free(chr->uuid); g_free(chr->value); - g_free(chr); + + if (!chr->read_cb && !chr->write_cb) + g_free(chr); + else + chr->parent = NULL; } static void __bt_gatt_free_service(bt_gatt_h gatt_handle) @@ -1090,6 +1098,32 @@ int bt_gatt_destroy(bt_gatt_h gatt_handle) return BT_ERROR_NONE; } +static int __get_write_prop(bt_gatt_write_type_e type, bt_gatt_property_e *prop) +{ + if (!prop) + return BT_ERROR_INVALID_PARAMETER; + + switch (type) { + case BT_GATT_WRITE_TYPE_WRITE: + *prop = BT_GATT_PROPERTY_WRITE; + break; + case BT_GATT_WRITE_TYPE_WRITE_NO_RESPONSE: + *prop = BT_GATT_PROPERTY_WRITE_WITHOUT_RESPONSE; + break; +/* After ACR for BT_GATT_WRITE_TYPE_SIGNED_WRITE, will enable this code */ +#if 0 + case BT_GATT_WRITE_TYPE_SIGNED_WRITE: + *prop = BT_GATT_PROPERTY_AUTHENTICATED_SIGNED_WRITES; + break; +#endif + default: + BT_ERR("Unknow write type : %d", type); + return BT_ERROR_INVALID_PARAMETER; + } + + return BT_ERROR_NONE; +} + int bt_gatt_service_destroy(bt_gatt_h gatt_handle) { bt_gatt_common_s *handle = (bt_gatt_common_s *)gatt_handle; @@ -2082,7 +2116,8 @@ int bt_gatt_characteristic_set_write_type(bt_gatt_h characteristic, bt_gatt_write_type_e write_type) { bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s *)characteristic; - int property; + bt_gatt_property_e property = BT_GATT_PROPERTY_WRITE; + int ret; BT_CHECK_GATT_SUPPORT(); BT_CHECK_INIT_STATUS(); @@ -2094,22 +2129,9 @@ int bt_gatt_characteristic_set_write_type(bt_gatt_h characteristic, return BT_ERROR_INVALID_PARAMETER; /* LCOV_EXCL_LINE */ } - switch (write_type) { - case BT_GATT_WRITE_TYPE_WRITE: - property = BT_GATT_PROPERTY_WRITE; - break; - case BT_GATT_WRITE_TYPE_WRITE_NO_RESPONSE: - property = BT_GATT_PROPERTY_WRITE_WITHOUT_RESPONSE; - break; -/* After ACR for BT_GATT_WRITE_TYPE_SIGNED_WRITE, will enable this code */ -#if 0 - case BT_GATT_WRITE_TYPE_SIGNED_WRITE: - property = BT_GATT_PROPERTY_AUTHENTICATED_SIGNED_WRITES; - break; -#endif - default: + ret = __get_write_prop(write_type, &property); + if (ret != BT_ERROR_NONE) return BT_ERROR_NOT_SUPPORTED; - } if (!(chr->properties & property)) return BT_ERROR_NOT_SUPPORTED; @@ -2818,17 +2840,109 @@ int bt_gatt_client_get_remote_address(bt_gatt_client_h client, return BT_ERROR_NONE; } -static bool __bt_gatt_client_is_in_progress(void) +void _handle_gatt_client_read_completed_event(int result, bt_gatt_resp_data_t *resp) { - if (_bt_check_cb(BT_EVENT_GATT_CLIENT_WRITE_CHARACTERISTIC) || - _bt_check_cb(BT_EVENT_GATT_CLIENT_WRITE_DESCRIPTOR) || - _bt_check_cb(BT_EVENT_GATT_CLIENT_READ_CHARACTERISTIC) || - _bt_check_cb(BT_EVENT_GATT_CLIENT_READ_DESCRIPTOR)) { - BT_ERR("Operation is in progress"); - return true; + bt_gatt_common_s *handle; + bt_gatt_client_request_completed_cb cb = NULL; + void *user_data = NULL; + + if (resp == NULL) { + BT_ERR("GATT Client response data is NULL"); + return; + } + + handle = resp->user_data; + if (handle->type == BT_GATT_TYPE_CHARACTERISTIC) { + bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s *)handle; + + cb = chr->read_cb; + user_data = chr->read_user_data; + + chr->read_cb = NULL; + chr->read_user_data = NULL; + + if (!chr->parent) { + BT_INFO("Already destroyed handle : %p", chr); + if (!chr->write_cb) + g_free(chr); + return; + } + } else if (handle->type == BT_GATT_TYPE_DESCRIPTOR) { + bt_gatt_descriptor_s *desc = (bt_gatt_descriptor_s *)handle; + + cb = desc->read_cb; + user_data = desc->read_user_data; + + desc->read_cb = NULL; + desc->read_user_data = NULL; + + if (!desc->parent) { + BT_INFO("Already destroyed handle : %p", desc); + if (!desc->write_cb) + g_free(desc); + return; + } + } + + if (result == BLUETOOTH_ATT_ERROR_NONE) { + bt_gatt_set_value(handle, + (char *)resp->value, (int)resp->len); + } + + if (cb) + cb(result, handle, user_data); + + return; +} + +void _handle_gatt_client_write_completed_event(int result, bt_gatt_resp_data_t *resp) +{ + bt_gatt_common_s *handle; + bt_gatt_client_request_completed_cb cb = NULL; + void *user_data = NULL; + + if (resp == NULL) { + BT_ERR("GATT Client response data is NULL"); + return; + } + + handle = resp->user_data; + if (handle->type == BT_GATT_TYPE_CHARACTERISTIC) { + bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s *)handle; + + cb = chr->write_cb; + user_data = chr->write_user_data; + + chr->write_cb = NULL; + chr->write_user_data = NULL; + + if (!chr->parent) { + BT_INFO("Already destroyed handle : %p", chr); + if (!chr->read_cb) + g_free(chr); + return; + } + } else if (handle->type == BT_GATT_TYPE_DESCRIPTOR) { + bt_gatt_descriptor_s *desc = (bt_gatt_descriptor_s *)handle; + + cb = desc->write_cb; + user_data = desc->write_user_data; + + desc->write_cb = NULL; + desc->write_user_data = NULL; + + if (!desc->parent) { + BT_INFO("Already destroyed handle : %p", desc); + if (!desc->read_cb) + g_free(desc); + return; + } } - return false; /* LCOV_EXCL_STOP */ + if (cb) + cb(result, handle, user_data); + + return; /* LCOV_EXCL_STOP */ } int bt_gatt_client_read_value(bt_gatt_h gatt_handle, @@ -2836,56 +2950,47 @@ int bt_gatt_client_read_value(bt_gatt_h gatt_handle, { int ret = BT_ERROR_NONE; bt_gatt_common_s *c = (bt_gatt_common_s *)gatt_handle; - bt_gatt_client_cb_data_s *cb_data; BT_CHECK_GATT_SUPPORT(); BT_CHECK_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(gatt_handle); BT_CHECK_INPUT_PARAMETER(callback); /* LCOV_EXCL_START */ - if (__bt_gatt_client_is_in_progress()) { - BT_ERR("Operation is in progress"); - return BT_ERROR_NOW_IN_PROGRESS; - } - - cb_data = malloc(sizeof(bt_gatt_client_cb_data_s)); - if (cb_data == NULL) { - BT_ERR("Cannot alloc cb_data"); - return BT_ERROR_OPERATION_FAILED; - } - - cb_data->gatt_handle = gatt_handle; - cb_data->user_data = user_data; - if (c->type == BT_GATT_TYPE_CHARACTERISTIC) { bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s *)gatt_handle; + if (chr->read_cb) { + BT_ERR("read request is now in progress"); + return BT_ERROR_NOW_IN_PROGRESS; + } + ret = _bt_get_error_code( - bluetooth_gatt_read_characteristic_value(chr->path)); - if (ret != BT_ERROR_NONE) { - g_free(cb_data); - BT_ERR("%s(0x%08x)", - _bt_convert_error_to_string(ret), ret); + bluetooth_gatt_read_characteristic_value(chr->path, gatt_handle)); + if (ret == BT_ERROR_NONE) { + chr->read_cb = callback; + chr->read_user_data = user_data; } else { - _bt_set_cb(BT_EVENT_GATT_CLIENT_READ_CHARACTERISTIC, - callback, cb_data); + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); } } else if (c->type == BT_GATT_TYPE_DESCRIPTOR) { bt_gatt_descriptor_s *desc = (bt_gatt_descriptor_s *)gatt_handle; + if (desc->read_cb) { + BT_ERR("read request is now in progress"); + return BT_ERROR_NOW_IN_PROGRESS; + } + ret = _bt_get_error_code( - bluetooth_gatt_read_descriptor_value(desc->path)); - if (ret != BT_ERROR_NONE) { - g_free(cb_data); - BT_ERR("%s(0x%08x)", - _bt_convert_error_to_string(ret), ret); + bluetooth_gatt_read_descriptor_value(desc->path, gatt_handle)); + if (ret == BT_ERROR_NONE) { + desc->read_cb = callback; + desc->read_user_data = user_data; } else { - _bt_set_cb(BT_EVENT_GATT_CLIENT_READ_DESCRIPTOR, - callback, cb_data); + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); } } else { + ret = BT_ERROR_INVALID_PARAMETER; BT_ERR("Invalid handle type for read "); - g_free(cb_data); } return ret; /* LCOV_EXCL_STOP */ @@ -2894,78 +2999,56 @@ int bt_gatt_client_read_value(bt_gatt_h gatt_handle, int bt_gatt_client_write_value(bt_gatt_h gatt_handle, bt_gatt_client_request_completed_cb callback, void *user_data) { - int ret = BT_ERROR_NONE; bt_gatt_common_s *c = (bt_gatt_common_s *)gatt_handle; - bt_gatt_client_cb_data_s *cb_data; + bt_gatt_property_e write_prop = BT_GATT_PROPERTY_WRITE; + int ret = BT_ERROR_NONE; BT_CHECK_GATT_SUPPORT(); BT_CHECK_INIT_STATUS(); - BT_CHECK_INPUT_PARAMETER(gatt_handle); - BT_CHECK_INPUT_PARAMETER(callback); /* LCOV_EXCL_START */ - - if (__bt_gatt_client_is_in_progress()) { - BT_ERR("Operation is in progress"); - return BT_ERROR_NOW_IN_PROGRESS; - } - - cb_data = malloc(sizeof(bt_gatt_client_cb_data_s)); - if (cb_data == NULL) { - BT_ERR("Cannot alloc cb_data"); - return BT_ERROR_OPERATION_FAILED; - } - - cb_data->gatt_handle = gatt_handle; - cb_data->user_data = user_data; + BT_CHECK_INPUT_PARAMETER(gatt_handle); /* LCOV_EXCL_START */ if (c->type == BT_GATT_TYPE_CHARACTERISTIC) { bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s *)gatt_handle; - BT_DBG("path : %s", chr->path); - if (chr->write_type == BT_GATT_WRITE_TYPE_WRITE) - ret = _bt_get_error_code(bluetooth_gatt_set_characteristics_value_by_type( - chr->path, (guint8 *)chr->value, - chr->value_length, - BT_GATT_PROPERTY_WRITE)); - else if (chr->write_type == BT_GATT_WRITE_TYPE_WRITE_NO_RESPONSE) - ret = _bt_get_error_code(bluetooth_gatt_set_characteristics_value_by_type( - chr->path, (guint8 *)chr->value, - chr->value_length, - BT_GATT_PROPERTY_WRITE_WITHOUT_RESPONSE)); -/* After ACR for BT_GATT_WRITE_TYPE_SIGNED_WRITE, will enable this code */ -#if 0 - - else if (chr->write_type == BT_GATT_WRITE_TYPE_SIGNED_WRITE) - ret = _bt_get_error_code(bluetooth_gatt_set_characteristics_value_by_type( - chr->path, (guint8 *)chr->value, chr->value_length, - BT_GATT_PROPERTY_AUTHENTICATED_SIGNED_WRITES)); -#endif - else { - BT_ERR("Unknow write type : %d", chr->write_type); - BT_ERR("path : %s", chr->path); - ret = BT_ERROR_OPERATION_FAILED; + if (chr->write_cb) { + BT_ERR("write request is now in progress"); + return BT_ERROR_NOW_IN_PROGRESS; } - if (ret != BT_ERROR_NONE) { - g_free(cb_data); - BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + + ret = __get_write_prop(chr->write_type, &write_prop); + if (ret != BT_ERROR_NONE) + return BT_ERROR_OPERATION_FAILED; + + ret = _bt_get_error_code(bluetooth_gatt_set_characteristics_value_by_type( + chr->path, (guint8 *)chr->value, + chr->value_length, write_prop, + gatt_handle)); + if (ret == BT_ERROR_NONE) { + chr->write_cb = callback; + chr->write_user_data = user_data; } else { - _bt_set_cb(BT_EVENT_GATT_CLIENT_WRITE_CHARACTERISTIC, callback, cb_data); + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); } } else if (c->type == BT_GATT_TYPE_DESCRIPTOR) { bt_gatt_descriptor_s *desc = (bt_gatt_descriptor_s *)gatt_handle; + if (desc->write_cb) { + BT_ERR("write request is now in progress"); + return BT_ERROR_NOW_IN_PROGRESS; + } + ret = _bt_get_error_code(bluetooth_gatt_write_descriptor_value( - desc->path, - (guint8 *)desc->value, - desc->value_length)); - if (ret != BT_ERROR_NONE) { - g_free(cb_data); - BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + desc->path, (guint8 *)desc->value, + desc->value_length, gatt_handle)); + if (ret == BT_ERROR_NONE) { + desc->write_cb = callback; + desc->write_user_data = user_data; } else { - _bt_set_cb(BT_EVENT_GATT_CLIENT_WRITE_DESCRIPTOR, callback, cb_data); + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); } } else { - BT_ERR("Invalid handle type for write "); - g_free(cb_data); + BT_ERR("Invalid handle type for write"); + ret = BT_ERROR_INVALID_PARAMETER; } return ret; -- 2.7.4