Apply Tizen3.0 Gatt client product patch 87/142987/1 accepted/tizen/unified/20170809.135136 accepted/tizen/unified/20170811.021135 submit/tizen/20170808.231821 submit/tizen/20170809.230017
authorh.sandeep <h.sandeep@samsung.com>
Tue, 8 Aug 2017 06:31:06 +0000 (12:01 +0530)
committerh.sandeep <h.sandeep@samsung.com>
Tue, 8 Aug 2017 06:33:20 +0000 (12:03 +0530)
===============================================
 commit 4a721c92d78ddb62650f596a4af26637db60a36e
 Author: Seungyoun Ju <sy39.ju@samsung.com>
 Date:   Wed Apr 26 18:03:40 2017 +0900
     Fix : Simultaneous GATT client requests are failed
===============================================

Change-Id: Ifc3012d97c68c8bdcc14a7b1a1ab1cb4441253b6
Signed-off-by: h.sandeep <h.sandeep@samsung.com>
include/bluetooth_private.h
src/bluetooth-common.c
src/bluetooth-gatt.c

index 923fff2..bba2f2f 100644 (file)
@@ -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
index 4742fa3..f3a06a2 100644 (file)
@@ -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;
index 6d73ad3..289fc5e 100644 (file)
@@ -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;