Fixing BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED for notify
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-gatt-client.c
index 9214c7f..a3258ee 100755 (executable)
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdint.h>
+#include <gio/gunixfdlist.h>
 
 #include "bt-common.h"
 #include "bt-event-handler.h"
@@ -31,6 +32,8 @@
 #ifdef TIZEN_GATT_CLIENT
 #include "bluetooth-gatt-client-api.h"
 #include <arpa/inet.h>
+static GSList *gatt_characteristic_notify_list;
+static GSList *gatt_characteristic_write_list = NULL;;
 #endif
 
 #define GATT_DEFAULT_TIMEOUT  (6 * 1000) // Dependent on supervision timeout 6 sec
@@ -325,7 +328,7 @@ BT_EXPORT_API int bluetooth_gatt_get_primary_services(
        int ret = BLUETOOTH_ERROR_INTERNAL;
        int idx = 0;
 
-       BT_INFO("+");
+       BT_DBG("+");
        BT_CHECK_PARAMETER(address, return);
        BT_CHECK_PARAMETER(prim_svc, return);
        BT_CHECK_ENABLED(return);
@@ -561,8 +564,6 @@ static int __get_permission_flag(char *permission)
 
        retv_if(permission == NULL, ret);
 
-       BT_INFO("permission = %s", permission);
-
        if (!g_strcmp0(permission, "broadcast"))
                ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
        else if (!g_strcmp0(permission, "read"))
@@ -648,7 +649,6 @@ BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
        GVariantIter *char_perm_iter;
        GVariantIter *char_desc_iter;
 
-       BT_DBG("+");
        BT_CHECK_PARAMETER(char_handle, return);
        BT_CHECK_PARAMETER(characteristic, return);
 
@@ -741,7 +741,6 @@ BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
        g_variant_unref(result);
        g_object_unref(properties_proxy);
 
-       BT_DBG("-");
        return BLUETOOTH_ERROR_NONE;
 }
 
@@ -861,7 +860,6 @@ BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
        GByteArray *gb_array = NULL;
        GVariantIter *desc_value_iter;
 
-       BT_INFO("+");
        BT_CHECK_PARAMETER(descriptor_handle, return);
        BT_CHECK_PARAMETER(descriptor, return);
 
@@ -932,17 +930,16 @@ BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
        g_variant_unref(result);
        g_object_unref(properties_proxy);
 
-       BT_INFO("-");
        return BLUETOOTH_ERROR_NONE;
 }
 
-static int __bluetooth_get_att_error_code(GError *error)
+static int __bluetooth_get_att_error_code(GError *error, char *handle)
 {
        int att_ecode = 0;
        int len;
        char *str = NULL;
 
-       BT_ERR("Error : %s", error->message);
+       BT_ERR("Error : %s [%s]", error->message, handle + 15);
        str = g_strrstr(error->message, "ATT error: 0x");
        if (str) {
                len = strlen(str);
@@ -1003,18 +1000,19 @@ static void __bluetooth_internal_read_cb(GObject *source_object,
 
        user_info = _bt_get_user_data(BT_COMMON);
        if (!user_info) {
-               g_free(resp_data);
                if (error) {
-                       BT_ERR("Error : %s", error->message);
+                       BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
                        g_clear_error(&error);
+                       g_free(resp_data);
                        return;
                }
+               g_free(resp_data);
                g_variant_unref(value);
                return;
        }
 
        if (error) {
-               att_ecode = __bluetooth_get_att_error_code(error);
+               att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
                g_clear_error(&error);
 
                _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
@@ -1063,6 +1061,7 @@ BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *chr,
 
        resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
        resp_data->user_data = user_data;
+       resp_data->handle = (char *)chr;
 
        builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
 
@@ -1099,18 +1098,19 @@ static void __bluetooth_internal_write_cb(GObject *source_object,
 
        user_info = _bt_get_user_data(BT_COMMON);
        if (!user_info) {
-               g_free(resp_data);
                if (error) {
-                       BT_ERR("Error : %s", error->message);
+                       BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
                        g_clear_error(&error);
+                       g_free(resp_data);
                        return;
                }
+               g_free(resp_data);
                g_variant_unref(value);
                return;
        }
 
        if (error) {
-               att_ecode = __bluetooth_get_att_error_code(error);
+               att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
                g_clear_error(&error);
 
                _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
@@ -1234,6 +1234,7 @@ BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
 
        resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
        resp_data->user_data = user_data;
+       resp_data->handle = (char *)chr;
 
        g_dbus_connection_call(conn, BT_BLUEZ_NAME, chr, GATT_CHAR_INTERFACE,
                        "WriteValuebyType",
@@ -1535,18 +1536,19 @@ static void __bluetooth_internal_read_desc_cb(GObject *source_object,
 
        user_info = _bt_get_user_data(BT_COMMON);
        if (!user_info) {
-               g_free(resp_data);
                if (error) {
-                       BT_ERR("Error : %s", error->message);
+                       BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
                        g_clear_error(&error);
+                       g_free(resp_data);
                        return;
                }
+               g_free(resp_data);
                g_variant_unref(value);
                return;
        }
 
        if (error) {
-               att_ecode = __bluetooth_get_att_error_code(error);
+               att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
                g_clear_error(&error);
 
                _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
@@ -1598,6 +1600,7 @@ BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *desc,
 
        resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
        resp_data->user_data = user_data;
+       resp_data->handle = (char *)desc;
 
        builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
 
@@ -1637,18 +1640,19 @@ static void __bluetooth_internal_write_desc_cb(GObject *source_object,
 
        user_info = _bt_get_user_data(BT_COMMON);
        if (!user_info) {
-               g_free(resp_data);
                if (error) {
-                       BT_ERR("Error : %s", error->message);
+                       BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
                        g_clear_error(&error);
+                       g_free(resp_data);
                        return;
                }
+               g_free(resp_data);
                g_variant_unref(value);
                return;
        }
 
        if (error) {
-               att_ecode = __bluetooth_get_att_error_code(error);
+               att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
                g_clear_error(&error);
 
                _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
@@ -1708,6 +1712,7 @@ BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(const char *desc,
 
        resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
        resp_data->user_data = user_data;
+       resp_data->handle = (char *)desc;
 
        g_dbus_connection_call(conn, BT_BLUEZ_NAME, desc, GATT_DESC_INTERFACE,
                        "WriteValue", g_variant_new("(@ay@a{sv})",
@@ -1775,7 +1780,6 @@ BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle,
 
 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle)
 {
-
        GDBusConnection *conn;
        GError *error = NULL;
        int ret = BLUETOOTH_ERROR_NONE;
@@ -1848,8 +1852,7 @@ static void __bt_fill_service_handle_informations(bt_services_browse_info_t *pro
        }
 }
 
-static void __bt_fill_char_handle_informations(bt_char_browse_info_t *props,
-               bt_gatt_service_property_t *service)
+static void __bt_fill_char_handle_informations(bt_char_browse_info_t *props, bt_gatt_service_property_t *service)
 {
        int count;
        char uuid_string[BLUETOOTH_UUID_STRING_MAX];
@@ -2146,21 +2149,154 @@ BT_EXPORT_API int bluetooth_gatt_client_get_char_descriptor_property(
                as an asyn function and leave every thing else in the callback */
 }
 
+
+static gboolean  bluetooth_gatt_client_notify_channel_watch_cb(GIOChannel *gio,
+                                       GIOCondition cond, gpointer data)
+{
+       bt_gatt_characteristic_notify_info_t *chr_info = (bt_gatt_characteristic_notify_info_t *)data;
+
+       BT_INFO(" FD io NOTIFICATION recived\n");
+
+       if (!chr_info) {
+               BT_ERR("char INFO nort recieved");
+               return FALSE;
+       }
+       if (cond & G_IO_IN) {
+               GIOStatus status = G_IO_STATUS_NORMAL;
+               GError *err = NULL;
+               char *buffer = NULL;
+               gsize len = 0;
+               bt_event_info_t *event_info;
+
+               buffer = g_malloc0(chr_info->mtu + 1);
+               memset(buffer, 0, chr_info->mtu + 1);
+
+               status = g_io_channel_read_chars(gio, buffer,
+                               chr_info->mtu, &len, &err);
+               if (status != G_IO_STATUS_NORMAL) {
+                       BT_ERR("IO Channel read is failed with %d", status);
+                       g_free(buffer);
+                       if (err) {
+                               BT_ERR("IO Channel read error [%s]", err->message);
+                               if (status == G_IO_STATUS_ERROR) {
+                                       BT_ERR("cond : %d", cond);
+                                       g_error_free(err);
+                                       g_io_channel_shutdown(gio, TRUE, NULL);
+                                       g_io_channel_unref(gio);
+
+                                       gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
+                                       g_free(chr_info);
+                                       return FALSE;
+                               }
+                               g_error_free(err);
+                       }
+                       return FALSE;
+               }
+
+               if (len > 0 && len < chr_info->mtu) {
+
+                       bt_gatt_char_property_t char_val;
+                       BT_INFO("FD io sending  value changed  %x %x %x %x %x %x %x %d \n", buffer[0], buffer[1], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], len);
+
+
+                       memcpy(char_val.prop.uuid, chr_info->UUID, 16);
+                       memcpy(char_val.value, buffer, len);
+                       char_val.val_len = len;
+                       memcpy(char_val.address, chr_info->adress, 18);
+
+                       event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
+
+                       if (event_info) {
+
+                               _bt_common_event_cb(BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED,
+                                                       BLUETOOTH_ERROR_NONE, &char_val,
+                                               event_info->cb, event_info->user_data);
+                       } else {
+                               BT_ERR("eventinfo failed");
+                       }
+
+               } else
+                       BT_ERR("Packet corrupted");
+               g_free(buffer);
+
+               return TRUE;
+       }
+       if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
+               BT_ERR("Error : GIOCondition %d, [%s]", cond, chr_info->UUID);
+               g_io_channel_shutdown(gio, TRUE, NULL);
+               g_io_channel_unref(gio);
+
+               gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
+               g_free(chr_info);
+
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static bt_gatt_characteristic_notify_info_t * bluetooth_gatt_client_get_characteristic_notify_info(unsigned  char *handle , int id)
+{
+       GSList *l;
+
+       for (l = gatt_characteristic_notify_list; l != NULL; l = l->next) {
+               bt_gatt_characteristic_notify_info_t *info = l->data;
+               if (memcmp(info->UUID, handle, 16) == 0 && info->id == id)
+                       return info;
+       }
+       return NULL;
+}
+
+static bt_gatt_characteristic_notify_info_t *  bluetooth_gatt_client_create_watch_io(int fd, int id, int mtu, char * address, unsigned char *uuid)
+{
+       GIOChannel *channel;
+       bt_gatt_characteristic_notify_info_t *chr_info;
+
+       chr_info = g_malloc0(sizeof(bt_gatt_characteristic_notify_info_t));
+       chr_info->notify_fd = fd;
+       chr_info->id = id;
+       chr_info->mtu = mtu;
+       g_strlcpy(chr_info->adress, address, 18);
+       memcpy(chr_info->UUID, uuid, 16);
+
+       channel = g_io_channel_unix_new(fd);
+       g_io_channel_set_encoding(channel, NULL, NULL);
+       g_io_channel_set_buffered(channel, FALSE);
+       g_io_channel_set_close_on_unref(channel, FALSE);
+       g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
+       g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP),
+                        bluetooth_gatt_client_notify_channel_watch_cb, chr_info);
+
+       return chr_info;
+
+}
+
 BT_EXPORT_API int bluetooth_gatt_client_watch_characteristics(
                        const char *address,
                        bt_gatt_handle_property_t *service_handle,
                        bt_gatt_handle_property_t *char_handle,
                        int client_id,
-                       gboolean is_notify)
+                       gboolean is_notify,
+                       gboolean is_indicate)
 {
        int result = BLUETOOTH_ERROR_NONE;
        bluetooth_gatt_client_char_prop_info_t param;
+       bt_gatt_characteristic_notify_info_t *chr_info;
+
        BT_DBG("+");
 
        BT_CHECK_PARAMETER(address, return);
        BT_CHECK_PARAMETER(service_handle, return);
        BT_CHECK_PARAMETER(char_handle, return);
 
+       chr_info = bluetooth_gatt_client_get_characteristic_notify_info(char_handle->uuid , char_handle->instance_id);
+       if (chr_info && !is_notify) {
+               BT_INFO("Already CCCD enabled. fd %d", chr_info->notify_fd);
+
+               close(chr_info->notify_fd);
+               return result;
+       }
+
        /* ASync Function, result expected in callback from bt-service */
 
        BT_INIT_PARAMS();
@@ -2180,10 +2316,48 @@ BT_EXPORT_API int bluetooth_gatt_client_watch_characteristics(
        g_array_append_vals(in_param1, &param, sizeof(bluetooth_gatt_client_char_prop_info_t));
        g_array_append_vals(in_param2, &client_id, sizeof(int));
        g_array_append_vals(in_param3, &is_notify, sizeof(gboolean));
+       g_array_append_vals(in_param4, &is_indicate, sizeof(gboolean));
 
-       result = _bt_send_request(BT_BLUEZ_SERVICE,
+
+       GUnixFDList *out_fd_list = NULL;
+
+       result  = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_WATCH_CHARACTERISTIC,
+                                                       in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
+       BT_DBG("result: %x", result);
+
+       if (result != BLUETOOTH_ERROR_NONE) {
+               BT_ERR("Fail to send request");
+               return result;
+       } else if (NULL == out_fd_list) {
+               BT_ERR("out_fd_list is NULL");
+
+       } else {
+
+               int *fd_list_array;
+               int len = 0;
+               int mtu;
+               int fd = -1;;
+
+               if (!out_fd_list)
+                       return BLUETOOTH_ERROR_INTERNAL;
+
+               fd_list_array = g_unix_fd_list_steal_fds(out_fd_list, &len);
+               BT_INFO("Num fds in fd_list is : %d, fd_list[0]: %d", len, fd_list_array[0]);
+               fd = fd_list_array[0];
+               mtu =  g_array_index(out_param, int, 0);
+
+               chr_info = bluetooth_gatt_client_create_watch_io(fd, char_handle->instance_id, mtu, (char *)address, char_handle->uuid);
+
+               gatt_characteristic_notify_list = g_slist_append(gatt_characteristic_notify_list, chr_info);
+
+               g_free(fd_list_array);
+               g_object_unref(out_fd_list);
+
+       }
+
+       /*result = _bt_send_request(BT_BLUEZ_SERVICE,
                        BT_GATT_WATCH_CHARACTERISTIC,
-                       in_param1, in_param2, in_param3, in_param4, &out_param);
+                       in_param1, in_param2, in_param3, in_param4, &out_param);*/
 
        BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
 
@@ -2286,6 +2460,85 @@ BT_EXPORT_API int bluetooth_gatt_client_read_descriptor_value(
        return result;
 }
 
+
+static bt_gatt_characteristic_write_info_t *  bluetooth_gatt_client_get_characteristic_fd(unsigned  char *handle, int id)
+{
+       GSList *l;
+       char  str[37];
+       _bt_convert_uuid_type_to_string(str, handle);
+       BT_INFO("request found UUID [%s], sid [ %d]", str, id);
+       for (l = gatt_characteristic_write_list; l != NULL; l = l->next) {
+               bt_gatt_characteristic_write_info_t *info = l->data;
+               _bt_convert_uuid_type_to_string(str, info->UUID);
+               BT_INFO("UUID [%s], sid [ %d]" , str, info->id);
+               if (memcmp(info->UUID, handle, 16) ==  0 &&  info->id == id)
+                       return info;
+       }
+       return NULL;
+}
+
+static gboolean  bluetooth_gatt_client_write_channel_watch_cb(GIOChannel *gio,
+                                       GIOCondition cond, gpointer data)
+{
+       bt_gatt_characteristic_write_info_t *chr_info = (bt_gatt_characteristic_write_info_t *)data;
+
+       if (!chr_info)
+               return FALSE;
+
+       if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
+               BT_ERR("Error : GIOCondition %d, [%s]", cond, chr_info->UUID);
+               g_io_channel_shutdown(gio, TRUE, NULL);
+               g_io_channel_unref(gio);
+
+               gatt_characteristic_write_list = g_slist_remove(gatt_characteristic_write_list, chr_info);
+               g_free(chr_info);
+
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static int  bluetooth_gatt_client_write_characteristics_value_to_fd(
+                        int fd, const guint8 *value, int length, int mtu,
+                       gpointer user_data)
+{
+               int written;
+               int att_result = BLUETOOTH_ERROR_NONE;
+               BT_CHECK_PARAMETER(value, return);
+               written = write(fd, value, length);
+               if (written != length) {
+                       att_result = BLUETOOTH_ERROR_INTERNAL;
+                       BT_INFO("write data failed  %d is ", written);
+               } else
+                       BT_INFO("write data %s is sucess ", value);
+
+               return att_result;
+}
+
+static void  bluetooth_gatt_client_create_write_io_channel(int fd, unsigned char * uuid, int id, int mtu)
+{
+       bt_gatt_characteristic_write_info_t *chr_info;
+       GIOChannel *channel;
+
+       chr_info = g_malloc0(sizeof(bt_gatt_characteristic_write_info_t));
+       chr_info->write_fd = fd;
+       chr_info->id = id;
+       chr_info->mtu = mtu;
+
+       memcpy(chr_info->UUID, uuid, 16);
+       channel = g_io_channel_unix_new(fd);
+       g_io_channel_set_encoding(channel, NULL, NULL);
+       g_io_channel_set_buffered(channel, FALSE);
+       g_io_channel_set_close_on_unref(channel, TRUE);
+       g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
+       g_io_add_watch(channel, (G_IO_ERR | G_IO_HUP | G_IO_NVAL),
+                        bluetooth_gatt_client_write_channel_watch_cb, chr_info);
+
+       gatt_characteristic_write_list = g_slist_append(gatt_characteristic_write_list, chr_info);
+
+}
+
 BT_EXPORT_API int bluetooth_gatt_client_write_characteristic_value_by_type(
                const char *address,
                bt_gatt_handle_property_t *service_handle,
@@ -2324,10 +2577,75 @@ BT_EXPORT_API int bluetooth_gatt_client_write_characteristic_value_by_type(
        g_array_append_vals(in_param2, data, sizeof(bluetooth_gatt_att_data_t));
        g_array_append_vals(in_param3, &write_type, sizeof(bluetooth_gatt_write_type_e));
 
-       result = _bt_send_request_async(BT_BLUEZ_SERVICE,
+       if (write_type == BLUETOOTH_GATT_TYPE_WRITE_NO_RESPONSE) {
+               int fd = -1;
+               int mtu = 0;
+               bt_gatt_characteristic_write_info_t *info;
+               info =  bluetooth_gatt_client_get_characteristic_fd(char_handle->uuid, service_handle->instance_id);
+
+               if (info) {
+                       fd = info->write_fd;
+                       mtu = info->mtu;
+               }
+
+               if (fd < 0) {
+
+                       GUnixFDList *out_fd_list = NULL;
+
+                       result  = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_ACQUIRE_WRITE,
+                                       in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
+                       BT_DBG("result: %x", result);
+
+                       mtu =  g_array_index(out_param, int, 0);
+
+                       if (result != BLUETOOTH_ERROR_NONE) {
+                                       BT_ERR("Fail to send request");
+                                       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+                                       return result;
+                       } else if (NULL == out_fd_list) {
+                               BT_ERR("out_fd_list is NULL");
+                               return BLUETOOTH_ERROR_INTERNAL;
+                       } else {
+                               int *fd_list_array;
+                               int len = 0;
+
+                               if (!out_fd_list) {
+                                       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+                                       return BLUETOOTH_ERROR_INTERNAL;
+                               }
+
+                               fd_list_array = g_unix_fd_list_steal_fds(out_fd_list, &len);
+                               BT_INFO("Num fds in fd_list is : %d, fd_list[0]: %d", len, fd_list_array[0]);
+                               fd = fd_list_array[0];
+
+                               g_free(fd_list_array);
+                               g_object_unref(out_fd_list);
+                       }
+                       BT_INFO("Acquired characteristic fd %d --------------- mtu %d,    ", fd, mtu);
+
+                       if (fd > -1) {
+
+                               bluetooth_gatt_client_create_write_io_channel(fd, char_handle->uuid, service_handle->instance_id, mtu);
+
+                               result =  bluetooth_gatt_client_write_characteristics_value_to_fd(fd, data->data, data->length, mtu, NULL);
+
+                       } else {
+                               BT_INFO(" characteristic info  FD is invalid\n");
+                               goto done;
+                       }
+
+               } else {
+                       BT_INFO("Acquired characteristic fd %d --------------- mtu %d,    ", fd, mtu);
+                       result =  bluetooth_gatt_client_write_characteristics_value_to_fd(fd, data->data, data->length, mtu, NULL);
+               }
+
+       } else {
+done:
+               result = _bt_send_request_async(BT_BLUEZ_SERVICE,
                        BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE,
                        in_param1, in_param2, in_param3, in_param4,
                        user_info->cb, user_info->user_data);
+       }
 
        BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
 
@@ -2411,7 +2729,7 @@ BT_EXPORT_API int bluetooth_gatt_client_set_service_change_watcher(
                if (_bluetooth_gatt_check_service_change_watcher_address(address)
                                == TRUE) {
                        BT_INFO("The watcher is already set");
-                       return BLUETOOTH_ERROR_NONE;
+                       goto done;
                }
 
                if (service_monitor_list == NULL) {
@@ -2451,6 +2769,7 @@ BT_EXPORT_API int bluetooth_gatt_client_set_service_change_watcher(
                }
        }
 
+done:
        BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
        return result;
 }