GATT-Clinet: Fix the Write and read dbus reply parameter mismatch.
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-gatt-client.c
old mode 100755 (executable)
new mode 100644 (file)
index 2707994..872b21f
 #include <stdint.h>
 
 #include "bt-common.h"
+#include "bt-event-handler.h"
+#include "bt-gatt-client.h"
 #include "bt-internal-types.h"
 #include "bt-request-sender.h"
 
-#define GATT_SERV_INTERFACE            "org.bluez.GattService1"
-#define GATT_CHAR_INTERFACE            "org.bluez.GattCharacteristic1"
-#define GATT_DESC_INTERFACE            "org.bluez.GattDescriptor1"
-
-#define GATT_USER_DESC_UUID             "00002901-0000-1000-8000-00805f9b34fb"
-#define GATT_CHAR_CLIENT_CONF          "00002902-0000-1000-8000-00805f9b34fb"
-#define GATT_CHAR_SERVER_CONF           "00002903-0000-1000-8000-00805f9b34fb"
-#define GATT_CHAR_FORMAT               "00002904-0000-1000-8000-00805f9b34fb"
+#define GATT_DEFAULT_TIMEOUT  (6 * 1000) // Dependent on supervision timeout 6 sec
 
 typedef enum {
        TYPE_NONE,
@@ -41,12 +36,12 @@ typedef enum {
        CLIENT_CONF,
        SERVER_CONF,
        CHAR_FORMAT
-}char_descriptor_type_t;
+} char_descriptor_type_t;
+
+static GSList *service_monitor_list = NULL;
 
 BT_EXPORT_API int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty)
 {
-       BT_DBG("+");
-
        BT_CHECK_PARAMETER(svc_pty, return);
 
        g_free(svc_pty->uuid);
@@ -56,14 +51,11 @@ BT_EXPORT_API int bluetooth_gatt_free_service_property(bt_gatt_service_property_
 
        memset(svc_pty, 0, sizeof(bt_gatt_service_property_t));
 
-       BT_DBG("-");
        return BLUETOOTH_ERROR_NONE;
 }
 
 BT_EXPORT_API int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty)
 {
-       BT_DBG("+");
-
        BT_CHECK_PARAMETER(char_pty, return);
 
        g_free(char_pty->uuid);
@@ -75,14 +67,11 @@ BT_EXPORT_API int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *cha
 
        memset(char_pty, 0, sizeof(bt_gatt_char_property_t));
 
-       BT_DBG("-");
        return BLUETOOTH_ERROR_NONE;
 }
 
 BT_EXPORT_API int bluetooth_gatt_free_desc_property(bt_gatt_char_descriptor_property_t *desc_pty)
 {
-       BT_DBG("+");
-
        BT_CHECK_PARAMETER(desc_pty, return);
 
        g_free(desc_pty->uuid);
@@ -91,7 +80,6 @@ BT_EXPORT_API int bluetooth_gatt_free_desc_property(bt_gatt_char_descriptor_prop
 
        memset(desc_pty, 0, sizeof(bt_gatt_char_descriptor_property_t));
 
-       BT_DBG("-");
        return BLUETOOTH_ERROR_NONE;
 }
 
@@ -106,19 +94,95 @@ static char **__get_string_array_from_gptr_array(GPtrArray *gp)
 
        path = g_malloc0((gp->len + 1) * sizeof(char *));
 
-       /* Fix : NULL_RETURNS */
-       if (path == NULL)
-               return NULL;
-
        for (i = 0; i < gp->len; i++) {
                gp_path = g_ptr_array_index(gp, i);
                path[i] = g_strdup(gp_path);
-               BT_DBG("path[%d] : [%s]", i, path[i]);
+       //      BT_DBG("path[%d] : [%s]", i, path[i]);
        }
 
        return path;
 }
 
+gboolean _bluetooth_gatt_check_service_change_watcher_address(
+               const bluetooth_device_address_t *device_addr)
+{
+       GSList *l;
+       char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
+       char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
+
+       _bt_convert_addr_type_to_string(device_address,
+                       (unsigned char *)device_addr->addr);
+
+       for (l = service_monitor_list; l != NULL; l = l->next) {
+               char device_address2[BT_ADDRESS_STRING_SIZE] = { 0 };
+               char secure_address2[BT_ADDRESS_STRING_SIZE] = { 0 };
+               bluetooth_device_address_t *addr = l->data;
+
+               _bt_convert_addr_type_to_string(device_address2,
+                               (unsigned char *)addr->addr);
+               _bt_convert_addr_string_to_secure_string(secure_address,
+                               device_address);
+               _bt_convert_addr_string_to_secure_string(secure_address2,
+                               device_address2);
+               BT_INFO("service_monitor_list [%s] - Input [%s]",
+                               secure_address2, secure_address);
+
+               if (!memcmp(device_addr, addr,
+                               sizeof(bluetooth_device_address_t)))
+                       return TRUE;
+       }
+
+       return FALSE;
+}
+
+BT_EXPORT_API int bluetooth_gatt_set_service_change_watcher(
+               const bluetooth_device_address_t *address, gboolean enable)
+{
+       GSList *l;
+       bluetooth_device_address_t *addr = NULL;
+       char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
+       char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
+
+       _bt_convert_addr_type_to_string(device_address,
+                       (unsigned char *)address->addr);
+       _bt_convert_addr_string_to_secure_string(secure_address,
+                       device_address);
+       BT_INFO("Set watcher for %s with %d", secure_address, enable);
+
+       if (enable == TRUE) {
+               if (service_monitor_list == NULL)
+                       _bt_register_manager_subscribe_signal(TRUE);
+
+               if (_bluetooth_gatt_check_service_change_watcher_address(address)
+                               == TRUE) {
+                       BT_INFO("The watcher is already set");
+                       return BLUETOOTH_ERROR_NONE;
+               }
+               addr = g_malloc0(sizeof(bluetooth_device_address_t));
+               memcpy(addr, address, sizeof(bluetooth_device_address_t));
+
+               service_monitor_list =
+                       g_slist_append(service_monitor_list, addr);
+       } else {
+
+               for (l = service_monitor_list; l != NULL; l = l->next) {
+                       addr = l->data;
+                       if (!memcmp(address, addr,
+                                       sizeof(bluetooth_device_address_t))) {
+                               service_monitor_list =
+                                       g_slist_remove(service_monitor_list, addr);
+                               g_free(addr);
+                               break;
+                       }
+               }
+
+               if (service_monitor_list == NULL)
+                       _bt_register_manager_subscribe_signal(FALSE);
+       }
+
+       return BLUETOOTH_ERROR_NONE;
+}
+
 BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle,
                                                bt_gatt_service_property_t *service)
 {
@@ -129,13 +193,13 @@ BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle
        gsize len;
        char *char_handle = NULL;
        GPtrArray *gp_array  = NULL ;
-       GVariantIter *property_iter, *char_iter;
+       GVariantIter *property_iter, *char_iter = NULL;
        const gchar *key;
        GVariant *value;
 
        BT_CHECK_PARAMETER(service_handle, return);
        BT_CHECK_PARAMETER(service, return);
-       BT_CHECK_ENABLED_ANY(return);
+       BT_CHECK_ENABLED(return);
 
        g_conn = _bt_gdbus_get_system_gconn();
        retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
@@ -172,36 +236,42 @@ BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle
        memset(service, 0, sizeof(bt_gatt_service_property_t));
 
        while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
-               if (!g_strcmp0(key,"UUID")) {
-                       service->uuid = g_variant_dup_string(value,&len);
-
-               } else if(!g_strcmp0(key, "Primary")) {
+               if (!g_strcmp0(key, "UUID")) {
+                       char *name = NULL;
+                       service->uuid = g_variant_dup_string(value, &len);
+                       _bt_get_uuid_specification_name(service->uuid, &name);
+                       BT_INFO("======> Service : %s [%s]", service->uuid, name);
+                       g_free(name);
+               } else if (!g_strcmp0(key, "Primary")) {
                        service->primary = g_variant_get_boolean(value);
 
                } else if (!g_strcmp0(key, "Includes")) {
                        g_variant_get(value, "ao", &char_iter);
                        gp_array = g_ptr_array_new();
-                       while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
+                       while (g_variant_iter_loop(char_iter, "&o", &char_handle))
                                g_ptr_array_add(gp_array, (gpointer)char_handle);
-                       }
+
                        if (gp_array->len != 0) {
                                service->include_handles.count = gp_array->len;
                                service->include_handles.handle =
                                                __get_string_array_from_gptr_array(gp_array);
                        }
                        g_ptr_array_free(gp_array, TRUE);
+                       g_variant_iter_free(char_iter);
                } else if (!g_strcmp0(key, "Characteristics")) {
                        g_variant_get(value, "ao", &char_iter);
                        gp_array = g_ptr_array_new();
-                       while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
+                       while (g_variant_iter_loop(char_iter, "&o", &char_handle))
                                g_ptr_array_add(gp_array, (gpointer)char_handle);
-                       }
+
                        if (gp_array->len != 0) {
                                service->char_handle.count = gp_array->len;
                                service->char_handle.handle =
                                                __get_string_array_from_gptr_array(gp_array);
                        }
+                       BT_DBG("Characteristics count : %d", service->char_handle.count);
                        g_ptr_array_free(gp_array, TRUE);
+                       g_variant_iter_free(char_iter);
                }
        }
 
@@ -234,7 +304,7 @@ BT_EXPORT_API int bluetooth_gatt_get_primary_services(
        BT_INFO("+");
        BT_CHECK_PARAMETER(address, return);
        BT_CHECK_PARAMETER(prim_svc, return);
-       BT_CHECK_ENABLED_ANY(return);
+       BT_CHECK_ENABLED(return);
 
        result = _bt_get_managed_objects();
        if (result == NULL)
@@ -304,7 +374,7 @@ BT_EXPORT_API int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_
        BT_CHECK_PARAMETER(address, return);
        BT_CHECK_PARAMETER(service_uuid, return);
        BT_CHECK_PARAMETER(service, return);
-       BT_CHECK_ENABLED_ANY(return);
+       BT_CHECK_ENABLED(return);
 
        result = _bt_get_managed_objects();
        if (result == NULL)
@@ -397,7 +467,7 @@ static void __bluetooth_internal_get_char_cb(GDBusProxy *proxy,
        g_variant_get(char_value, "ao", &char_iter);
 
        gp_array = g_ptr_array_new();
-       while(g_variant_iter_loop(char_iter, "&o",  &char_handle));
+       while (g_variant_iter_loop(char_iter, "&o",  &char_handle))
                g_ptr_array_add(gp_array, (gpointer)char_handle);
 
        if (gp_array->len != 0) {
@@ -416,6 +486,7 @@ static void __bluetooth_internal_get_char_cb(GDBusProxy *proxy,
        g_strfreev(svc_char.handle_info.handle);
        g_free(svc_char.service_handle);
        g_variant_iter_free(char_iter);
+       g_variant_unref(value);
        g_object_unref(proxy);
 }
 
@@ -430,7 +501,7 @@ BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(
        BT_DBG("+");
 
        BT_CHECK_PARAMETER(service_handle, return);
-       BT_CHECK_ENABLED_ANY(return);
+       BT_CHECK_ENABLED(return);
 
        g_conn = _bt_gdbus_get_system_gconn();
        retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
@@ -466,27 +537,34 @@ static int __get_permission_flag(char *permission)
 
        retv_if(permission == NULL, ret);
 
-       BT_DBG("permission = %s",permission);
+       BT_INFO("permission = %s", permission);
 
-       if (!g_strcmp0(permission,"broadcast")) {
+       if (!g_strcmp0(permission, "broadcast"))
                ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
-       } else if (!g_strcmp0(permission,"read")) {
+       else if (!g_strcmp0(permission, "read"))
                ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
-       } else if (!g_strcmp0(permission,"write-without-response")) {
+       else if (!g_strcmp0(permission, "write-without-response"))
                ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
-       } else if (!g_strcmp0(permission,"write")) {
+       else if (!g_strcmp0(permission, "write"))
                ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
-       } else if (!g_strcmp0(permission,"notify")) {
+       else if (!g_strcmp0(permission, "notify"))
                ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
-       } else if (!g_strcmp0(permission,"indicate")) {
+       else if (!g_strcmp0(permission, "indicate"))
                ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
-       } else if (!g_strcmp0(permission,"authenticated-signed-writes")) {
+       else if (!g_strcmp0(permission, "authenticated-signed-writes"))
                ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
-       } else if (!g_strcmp0(permission,"reliable-write")) {
-               ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS;
-       } else if (!g_strcmp0(permission,"writable-auxiliaries")) {
-               ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS;
-       }
+       else if (!g_strcmp0(permission, "reliable-write"))
+               ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
+       else if (!g_strcmp0(permission, "writable-auxiliaries"))
+               ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
+       else if (!g_strcmp0(permission, "encrypt-read"))
+               ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
+       else if (!g_strcmp0(permission, "encrypt-write"))
+               ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
+       else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
+               ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
+       else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
+               ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
 
        return ret;
 }
@@ -511,11 +589,10 @@ 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);
 
-       BT_CHECK_ENABLED_ANY(return);
+       BT_CHECK_ENABLED(return);
 
        g_conn = _bt_gdbus_get_system_gconn();
        retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
@@ -553,15 +630,17 @@ BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
        characteristic->handle = g_strdup(char_handle);
 
        while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
-               BT_DBG("property");
-               if (!g_strcmp0(key,"UUID")) {
-                       characteristic->uuid = g_variant_dup_string(value,&len);
-                       BT_DBG("UUID of the char = %s",characteristic->uuid);
-               } else if(!g_strcmp0(key, "Value")) {
+               if (!g_strcmp0(key, "UUID")) {
+                       char *name = NULL;
+                       characteristic->uuid = g_variant_dup_string(value, &len);
+                       _bt_get_uuid_specification_name(characteristic->uuid, &name);
+                       BT_INFO("Characteristic : %s [%s]", characteristic->uuid, name);
+                       g_free(name);
+               } else if (!g_strcmp0(key, "Value")) {
                        gb_array = g_byte_array_new();
                        g_variant_get(value, "ay", &char_value_iter);
-                       while(g_variant_iter_loop(char_value_iter, "y",  &char_value)) {
-                               BT_DBG("value of char = %d",char_value);
+                       while (g_variant_iter_loop(char_value_iter, "y",  &char_value)) {
+                       //      BT_DBG("value of char = %d",char_value);
                                g_byte_array_append(gb_array, &char_value, 1);
                        }
                        g_variant_iter_free(char_value_iter);
@@ -573,21 +652,20 @@ BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
                        }
                        characteristic->val_len = gb_array->len;
                        g_byte_array_free(gb_array, TRUE);
-               } else if(!g_strcmp0(key, "Flags")) {
+               } else if (!g_strcmp0(key, "Flags")) {
                        g_variant_get(value, "as", &char_perm_iter);
                        characteristic->permission = 0x00;
-                       while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
-                               BT_DBG("permission = %s",permission);
+
+                       while (g_variant_iter_loop(char_perm_iter, "s", &permission))
                                characteristic->permission |= __get_permission_flag(permission);
-                               BT_DBG("permission check = %d",characteristic->permission);
-                       }
+
                        g_variant_iter_free(char_perm_iter);
                } else if (!g_strcmp0(key, "Descriptors")) {
                        g_variant_get(value, "ao", &char_desc_iter);
                        gp_array = g_ptr_array_new();
-                       while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
+                       while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle))
                                g_ptr_array_add(gp_array, (gpointer)char_desc_handle);
-                       }
+
                        g_variant_iter_free(char_desc_iter);
                        if (gp_array->len != 0) {
                                characteristic->char_desc_handle.count = gp_array->len;
@@ -602,7 +680,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;
 }
 
@@ -611,7 +688,6 @@ void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
 {
        GVariant *value;
        GVariantIter *char_iter;
-       int i, len;
        char *char_handle;
        GError *error = NULL;
        bt_user_info_t *user_info;
@@ -642,10 +718,7 @@ void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
 
        g_variant_get(value, "(ao)", &char_iter);
 
-       len = g_variant_get_size((GVariant *)char_iter);
-
-       for (i = 0; i < len; i++) {
-               g_variant_iter_loop(char_iter, "o",  &char_handle);
+       while (g_variant_iter_loop(char_iter, "&o",  &char_handle)) {
                if (!char_handle)
                        continue;
                ret = bluetooth_gatt_get_characteristics_property(char_handle,
@@ -669,6 +742,7 @@ void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
 
        bluetooth_gatt_free_char_property(&characteristic);
        g_variant_iter_free(char_iter);
+       g_variant_unref(value);
        g_free(user_data);
 }
 
@@ -682,7 +756,7 @@ BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
 
        BT_CHECK_PARAMETER(service_handle, return);
        BT_CHECK_PARAMETER(char_uuid, return);
-       BT_CHECK_ENABLED_ANY(return);
+       BT_CHECK_ENABLED(return);
 
        g_conn = _bt_gdbus_get_system_gconn();
        retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
@@ -725,11 +799,10 @@ BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
        GByteArray *gb_array = NULL;
        GVariantIter *desc_value_iter;
 
-       BT_DBG("+");
        BT_CHECK_PARAMETER(descriptor_handle, return);
        BT_CHECK_PARAMETER(descriptor, return);
 
-       BT_CHECK_ENABLED_ANY(return);
+       BT_CHECK_ENABLED(return);
 
        g_conn = _bt_gdbus_get_system_gconn();
        retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
@@ -767,18 +840,21 @@ BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
        descriptor->handle = g_strdup(descriptor_handle);
 
        while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
-               BT_DBG("property");
-               if (!g_strcmp0(key,"UUID")) {
-                       descriptor->uuid = g_variant_dup_string(value,&len);
-                       BT_DBG("UUID of the char_desc = %s",descriptor->uuid);
-               } else if(!g_strcmp0(key, "Value")) {
+               if (!g_strcmp0(key, "UUID")) {
+                       char *name = NULL;
+                       descriptor->uuid = g_variant_dup_string(value, &len);
+                       _bt_get_uuid_specification_name(descriptor->uuid, &name);
+                       BT_INFO("Descriptor : %s [%s]", descriptor->uuid, name);
+                       g_free(name);
+               } else if (!g_strcmp0(key, "Value")) {
                        gb_array = g_byte_array_new();
                        g_variant_get(value, "ay", &desc_value_iter);
-                       while(g_variant_iter_loop(desc_value_iter, "y",  &char_value)) {
-                               BT_DBG("value of descriptor = %d",char_value);
+                       while (g_variant_iter_loop(desc_value_iter, "y",  &char_value)) {
+                               BT_DBG("value of descriptor = %d", char_value);
                                g_byte_array_append(gb_array, &char_value, 1);
                        }
                        g_variant_iter_free(desc_value_iter);
+
                        if (gb_array->len != 0) {
                                descriptor->val = g_malloc0(gb_array->len *
                                                                sizeof(unsigned char));
@@ -793,7 +869,6 @@ BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
        g_variant_unref(result);
        g_object_unref(properties_proxy);
 
-       BT_DBG("-");
        return BLUETOOTH_ERROR_NONE;
 }
 
@@ -809,6 +884,8 @@ static void __bluetooth_internal_read_cb(GObject *source_object,
        GByteArray *gp_byte_array = NULL;
        GVariantIter *iter;
        guint8 g_byte;
+       gint att_error_code;
+       int ret = BLUETOOTH_ERROR_NONE;
 
        BT_DBG("+");
        user_info = _bt_get_user_data(BT_COMMON);
@@ -818,10 +895,15 @@ static void __bluetooth_internal_read_cb(GObject *source_object,
 
        if (error) {
                BT_ERR("Error : %s \n", error->message);
+               if (g_strrstr(error->message, "Not paired"))
+                       ret = BLUETOOTH_ERROR_NOT_PAIRED;
+               else
+                       ret = BLUETOOTH_ERROR_INTERNAL;
+
                g_clear_error(&error);
                if (user_info) {
                        _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
-                               BLUETOOTH_ERROR_INTERNAL, NULL,
+                               ret, NULL,
                                user_info->cb, user_info->user_data);
                }
                g_free(user_data);
@@ -829,13 +911,25 @@ static void __bluetooth_internal_read_cb(GObject *source_object,
        }
 
        char_value.char_handle = user_data;
-       gp_byte_array = g_byte_array_new();
-       g_variant_get(value, "(ay)", &iter);
 
-       while (g_variant_iter_loop(iter, "y", &g_byte)) {
-               g_byte_array_append(gp_byte_array, &g_byte, 1);
+       g_variant_get(value, "(yay)", &att_error_code, &iter);
+
+       if (att_error_code != 0) {
+               if (user_info) {
+                       _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
+                               att_error_code, NULL,
+                               user_info->cb, user_info->user_data);
+               }
+               g_free(char_value.char_handle);
+               g_variant_unref(value);
+               g_variant_iter_free(iter);
+               return;
        }
 
+       gp_byte_array = g_byte_array_new();
+       while (g_variant_iter_loop(iter, "y", &g_byte))
+               g_byte_array_append(gp_byte_array, &g_byte, 1);
+
        if (gp_byte_array->len != 0) {
                char_value.val_len = gp_byte_array->len;
                char_value.char_value = gp_byte_array->data;
@@ -859,77 +953,41 @@ BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *character
 {
        GDBusConnection *conn;
        char *handle;
+       GVariantBuilder *builder = NULL;
+       guint16 offset = 0;
 
        BT_CHECK_PARAMETER(characteristic, return);
-       BT_CHECK_ENABLED_ANY(return);
+       BT_CHECK_ENABLED(return);
 
        conn = _bt_gdbus_get_system_gconn();
        retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
 
        handle = g_strdup(characteristic);
 
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+
+       /*offset*/
+       g_variant_builder_add(builder, "{sv}", "offset",
+               g_variant_new("q", offset));
+
+       /* Device Object path*/
+//     g_variant_builder_add(builder, "{sv}", "device",
+//     g_variant_new_object("o", NULL));
+
        g_dbus_connection_call(conn,
                        BT_BLUEZ_NAME,
                        characteristic,
                        GATT_CHAR_INTERFACE,
                        "ReadValue",
-                       NULL,
-                       G_VARIANT_TYPE("(ay)"),
+                       g_variant_new("(a{sv})", builder),
+                       G_VARIANT_TYPE("(yay)"),
                        G_DBUS_CALL_FLAGS_NONE,
                        -1,
                        NULL,
                        (GAsyncReadyCallback)__bluetooth_internal_read_cb,
                        (gpointer)handle);
-
-       return BLUETOOTH_ERROR_NONE;
-}
-
-BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
-               const char *char_handle, const guint8 *value, int length)
-{
-       GVariant *val;
-       GVariantBuilder *builder;
-       GError *error = NULL;
-       GDBusConnection *conn;
-       int i = 0;
-
-       BT_DBG("+");
-       BT_CHECK_PARAMETER(char_handle, return);
-       BT_CHECK_PARAMETER(value, return);
-       retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
-       BT_CHECK_ENABLED_ANY(return);
-
-       conn = _bt_gdbus_get_system_gconn();
-       retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
-
-       builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
-
-       for (i = 0; i < length; i++) {
-               g_variant_builder_add(builder, "y", value[i]);
-       }
-
-       val = g_variant_new("(ay)", builder);
-
-       g_dbus_connection_call_sync(conn,
-                       BT_BLUEZ_NAME,
-                       char_handle,
-                       GATT_CHAR_INTERFACE,
-                       "WriteValue",
-                       val,
-                       NULL,
-                       G_DBUS_CALL_FLAGS_NONE,
-                       -1, NULL, &error);
-
-       if (error) {
-               BT_ERR("Set value Failed: %s", error->message);
-               g_clear_error(&error);
-               g_variant_builder_unref(builder);
-               return BLUETOOTH_ERROR_INTERNAL;
-       }
-
        g_variant_builder_unref(builder);
 
-       BT_DBG("-");
        return BLUETOOTH_ERROR_NONE;
 }
 
@@ -937,12 +995,12 @@ static void __bluetooth_internal_write_cb(GObject *source_object,
                        GAsyncResult *res,
                        gpointer user_data)
 {
-       BT_DBG("+");
        GError *error = NULL;
        bt_user_info_t *user_info;
        GDBusConnection *system_gconn = NULL;
        GVariant *value;
        int result = BLUETOOTH_ERROR_NONE;
+       guint8 att_ecode = 0;
 
        user_info = _bt_get_user_data(BT_COMMON);
 
@@ -953,99 +1011,201 @@ static void __bluetooth_internal_write_cb(GObject *source_object,
                BT_ERR("Error : %s \n", error->message);
                g_clear_error(&error);
                result = BLUETOOTH_ERROR_INTERNAL;
+       } else {
+               g_variant_get(value, "(y)", &att_ecode);
+               if (att_ecode) {
+                       result =  att_ecode;
+                       BT_ERR("ATT Error code: %d \n", att_ecode);
+               }
        }
+
        if (user_info) {
-               BT_DBG("result = %d", result);
                _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
                                result, NULL,
                                user_info->cb, user_info->user_data);
+       } else {
+               BT_ERR("user info is null");
        }
 
        if (value)
                g_variant_unref(value);
-       BT_DBG("-");
+
        return;
 }
 
+BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
+               const char *char_handle, const guint8 *value, int length)
+{
+       GVariant *val, *options;
+       GVariantBuilder *builder1;
+       GVariantBuilder *builder2;
+       GError *error = NULL;
+       GDBusConnection *conn;
+       int i = 0;
+       guint16 offset = 0;
+
+       BT_DBG("+");
+       BT_CHECK_PARAMETER(char_handle, return);
+       BT_CHECK_PARAMETER(value, return);
+       retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
+       BT_CHECK_ENABLED(return);
+
+       conn = _bt_gdbus_get_system_gconn();
+       retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+       builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
+       for (i = 0; i < length; i++)
+               g_variant_builder_add(builder1, "y", value[i]);
+
+       val = g_variant_new("ay", builder1);
+
+       builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       /*offset*/
+       g_variant_builder_add(builder2, "{sv}", "offset",
+                               g_variant_new_uint16(offset));
+
+       /* Device Object path*/
+//     g_variant_builder_add(builder2, "{sv}", "device",
+//     g_variant_new_object("o", NULL));
+
+       options = g_variant_new("a{sv}", builder2);
+
+       g_dbus_connection_call(conn,
+                               BT_BLUEZ_NAME,
+                               char_handle,
+                               GATT_CHAR_INTERFACE,
+                               "WriteValue",
+                               g_variant_new("(@ay@a{sv})",
+                               val, options),
+                               G_VARIANT_TYPE("(y)"),
+                               G_DBUS_CALL_FLAGS_NONE,
+                               -1, NULL,
+                               (GAsyncReadyCallback)__bluetooth_internal_write_cb,
+                               NULL);
+
+
+       if (error) {
+               BT_ERR("Set value Failed: %s", error->message);
+               g_clear_error(&error);
+               g_variant_builder_unref(builder1);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+       g_variant_builder_unref(builder1);
+       g_variant_builder_unref(builder2);
+
+       BT_DBG("-");
+       return BLUETOOTH_ERROR_NONE;
+}
+
 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
                const char *char_handle, const guint8 *value, int length, guint8 write_type)
 {
-       GVariant *val;
-       GVariantBuilder *builder;
+       GVariant *val, *options;
+       GVariantBuilder *builder1;
+       GVariantBuilder *builder2;
        GDBusConnection *conn;
+       guint16 offset = 0;
        int i = 0;
        int ret = BLUETOOTH_ERROR_NONE;
 
        BT_CHECK_PARAMETER(char_handle, return);
        BT_CHECK_PARAMETER(value, return);
        retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
-       BT_CHECK_ENABLED_ANY(return);
+       BT_CHECK_ENABLED_INTERNAL(return);
 
        conn = _bt_gdbus_get_system_gconn();
        retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
 
-       builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
+       builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
 
-       for (i = 0; i < length; i++) {
-               g_variant_builder_add(builder, "y", value[i]);
-       }
+       for (i = 0; i < length; i++)
+               g_variant_builder_add(builder1, "y", value[i]);
+
+       val = g_variant_new("ay", builder1);
+
+       builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       /*offset*/
+       g_variant_builder_add(builder2, "{sv}", "offset",
+                       g_variant_new_uint16(offset));
+
+       /* Device Object path*/
+//     g_variant_builder_add(builder2, "{sv}", "device",
+//     g_variant_new_object("o", NULL));
+
+       options = g_variant_new("a{sv}", builder2);
 
-       val = g_variant_new("ay", builder);
        g_dbus_connection_call(conn,
                        BT_BLUEZ_NAME,
                        char_handle,
                        GATT_CHAR_INTERFACE,
                        "WriteValuebyType",
-                       g_variant_new("(y@ay)", write_type, val),
-                       NULL,
+                       g_variant_new("(y@ay@a{sv})",
+                       write_type, val, options),
+                       G_VARIANT_TYPE("(y)"),
                        G_DBUS_CALL_FLAGS_NONE,
                        -1, NULL,
                        (GAsyncReadyCallback)__bluetooth_internal_write_cb,
                        NULL);
 
-       g_variant_builder_unref(builder);
+       g_variant_builder_unref(builder1);
+       g_variant_builder_unref(builder2);
        return ret;
 }
 
 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
                        const char *char_handle, const guint8 *value, int length)
 {
-       GVariant *val;
+       GVariant *val, *options;
        GDBusConnection *conn;
-       GVariantBuilder *builder;
+       GVariantBuilder *builder1;
+       GVariantBuilder *builder2;
+       guint offset = 0;
        int i;
 
        BT_DBG("+");
        BT_CHECK_PARAMETER(char_handle, return);
        BT_CHECK_PARAMETER(value, return);
        retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
-       BT_CHECK_ENABLED_ANY(return);
+       BT_CHECK_ENABLED(return);
 
        conn = _bt_gdbus_get_system_gconn();
        retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
 
-       builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
+       builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
 
        for (i = 0; i < length; i++) {
-               g_variant_builder_add(builder, "y", value[i]);
+               g_variant_builder_add(builder1, "y", value[i]);
                BT_DBG("value [] = %d", value[i]);
        }
 
-       val = g_variant_new("(ay)", builder);
+       val = g_variant_new("ay", builder1);
+
+       builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       /*offset*/
+       g_variant_builder_add(builder2, "{sv}", "offset",
+                               g_variant_new_uint16(offset));
+
+       /* Device Object path*/
+//     g_variant_builder_add(builder2, "{sv}", "device",
+//     g_variant_new_object("o", NULL));
+
+       options = g_variant_new("a{sv}", builder2);
 
        g_dbus_connection_call(conn,
                                BT_BLUEZ_NAME,
                                char_handle,
                                GATT_CHAR_INTERFACE,
                                "WriteValue",
-                               val,
-                               NULL,
+                               g_variant_new("(@ay@a{sv})",
+                               val, options),
+                               G_VARIANT_TYPE("(y)"),
                                G_DBUS_CALL_FLAGS_NONE,
                                -1, NULL,
                                (GAsyncReadyCallback)__bluetooth_internal_write_cb,
                                NULL);
 
-       g_variant_builder_unref(builder);
+       g_variant_builder_unref(builder1);
+       g_variant_builder_unref(builder2);
 
        BT_DBG("-");
        return BLUETOOTH_ERROR_NONE;
@@ -1098,7 +1258,7 @@ static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
        }
        g_variant_get(result, "(a{sv})", &property_iter);
        while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
-               if (!g_strcmp0(key,"UUID")) {
+               if (!g_strcmp0(key, "UUID")) {
                        uuid = g_variant_get_string(value, &len);
                        if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
                                BT_DBG("GATT_USER_DESC_UUID");
@@ -1116,47 +1276,43 @@ static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
                                BT_DBG("descriptor uuid = %s", uuid);
                        }
                } else if (!g_strcmp0(key, "Value")) {
-                       switch(desc_type) {
-                               case CHAR_FORMAT :
-                                       BT_DBG("Format descriptor");
-                                       g_variant_get(value, "(yyqyq)",
-                                                       &(characteristic->format.format),
-                                                       &(characteristic->format.exponent),
-                                                       &(characteristic->format.unit),
-                                                       &(characteristic->format.name_space),
-                                                       &(characteristic->format.description));
-                                       break;
-                               case USER_DESC:
-                                       BT_DBG("User descriptor");
-                                       g_variant_get(value, "ay", &desc_value_iter);
-                                       len = g_variant_get_size((GVariant *)desc_value_iter);
-
-                                       if (len > 0) {
-                                               characteristic->description = (char *)g_malloc0(len + 1);
-                                               if (!characteristic->description) {
-                                                       ret = BLUETOOTH_ERROR_OUT_OF_MEMORY;
-                                                       goto done;
-                                               }
-                                       }
-                                       for (i = 0; i < len; i++) {
-                                               g_variant_iter_loop(desc_value_iter, "y",
-                                                       &characteristic->description[i]);
-                                               BT_DBG("description = %s", characteristic->description);
-                                       }
-                                       g_variant_iter_free(desc_value_iter);
-                                       break;
-                               case CLIENT_CONF :
-                                       BT_DBG(" CLIENT_CONF");
-                                       break;
-                               case SERVER_CONF :
-                                       BT_DBG(" SERVER_CONF");
-                                       break;
-                               default:break;
+                       switch (desc_type) {
+                       case CHAR_FORMAT:
+                               BT_DBG("Format descriptor");
+                               g_variant_get(value, "(yyqyq)",
+                                               &(characteristic->format.format),
+                                               &(characteristic->format.exponent),
+                                               &(characteristic->format.unit),
+                                               &(characteristic->format.name_space),
+                                               &(characteristic->format.description));
+                               break;
+                       case USER_DESC:
+                               BT_DBG("User descriptor");
+                               g_variant_get(value, "ay", &desc_value_iter);
+                               len = g_variant_get_size((GVariant *)desc_value_iter);
+
+                               if (len > 0)
+                                       characteristic->description = (char *)g_malloc0(len + 1);
+
+                               for (i = 0; i < len; i++) {
+                                       g_variant_iter_loop(desc_value_iter, "y",
+                                               &characteristic->description[i]);
+                                       BT_DBG("description = %s", characteristic->description);
+                               }
+                               g_variant_iter_free(desc_value_iter);
+                               break;
+                       case CLIENT_CONF:
+                               BT_DBG(" CLIENT_CONF");
+                               break;
+                       case SERVER_CONF:
+                               BT_DBG(" SERVER_CONF");
+                               break;
+                       default:
+                               break;
                        }
                }
        }
 
-done:
        g_variant_iter_free(property_iter);
        g_variant_unref(result);
        g_object_unref(properties_proxy);
@@ -1204,12 +1360,12 @@ static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
        g_variant_get(value, "(v)", &char_value);
        g_variant_get(char_value, "ao", &char_iter);
 
-       while(g_variant_iter_loop(char_iter, "&o",  &char_handle)) {
-               BT_DBG("object path of descriptor = %s",char_handle);
-               if(char_handle) {
-                               ret = __bluetooth_gatt_descriptor_iter(char_handle,
-                                                       &characteristic);
-                               BT_DBG("Descriptor read status [%d]",ret);
+       while (g_variant_iter_loop(char_iter, "&o",  &char_handle)) {
+               BT_DBG("object path of descriptor = %s", char_handle);
+               if (char_handle) {
+                       ret = __bluetooth_gatt_descriptor_iter(char_handle,
+                                               &characteristic);
+                       BT_DBG("Descriptor read status [%d]", ret);
                }
        }
 
@@ -1221,6 +1377,7 @@ static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
        bluetooth_gatt_free_char_property(&characteristic);
 
        g_variant_iter_free(char_iter);
+       g_variant_unref(value);
        BT_DBG("-");
 }
 
@@ -1233,7 +1390,7 @@ BT_EXPORT_API int bluetooth_gatt_discover_characteristic_descriptor(
        GError *error = NULL;
 
        BT_CHECK_PARAMETER(characteristic_handle, return);
-       BT_CHECK_ENABLED_ANY(return);
+       BT_CHECK_ENABLED(return);
 
        g_conn = _bt_gdbus_get_system_gconn();
        retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
@@ -1272,6 +1429,7 @@ static void __bluetooth_internal_read_desc_cb(GObject *source_object,
        GByteArray *gp_byte_array = NULL;
        GVariantIter *iter;
        guint8 g_byte;
+       gint att_error_code;
 
        BT_DBG("+");
        user_info = _bt_get_user_data(BT_COMMON);
@@ -1292,16 +1450,27 @@ static void __bluetooth_internal_read_desc_cb(GObject *source_object,
                return;
        }
 
-       gp_byte_array = g_byte_array_new();
-       g_variant_get(value, "(ay)", &iter);
+       g_variant_get(value, "(yay)", &att_error_code, &iter);
 
-       while(g_variant_iter_loop(iter, "y",  &g_byte)) {
-               g_byte_array_append(gp_byte_array, &g_byte, 1);
+       if (att_error_code != 0) {
+               if (user_info) {
+                       _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
+                               att_error_code, NULL,
+                               user_info->cb, user_info->user_data);
+               }
+               g_free(char_value.handle);
+               g_variant_unref(value);
+               g_variant_iter_free(iter);
+               return;
        }
 
+       gp_byte_array = g_byte_array_new();
+       while (g_variant_iter_loop(iter, "y",  &g_byte))
+               g_byte_array_append(gp_byte_array, &g_byte, 1);
+
        if (gp_byte_array->len != 0) {
-               char_value.val_len = (unsigned int )gp_byte_array->len;
-               char_value.description= (char *)gp_byte_array->data;
+               char_value.val_len = (unsigned int)gp_byte_array->len;
+               char_value.description = (char *)gp_byte_array->data;
        }
 
        if (user_info) {
@@ -1321,29 +1490,41 @@ static void __bluetooth_internal_read_desc_cb(GObject *source_object,
 BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *char_descriptor)
 {
        GDBusConnection *conn;
+       GVariantBuilder *builder;
+       guint offset = 0;
        char *handle;
 
        BT_DBG("+");
        BT_CHECK_PARAMETER(char_descriptor, return);
-       BT_CHECK_ENABLED_ANY(return);
+       BT_CHECK_ENABLED(return);
 
        conn = _bt_gdbus_get_system_gconn();
        retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
 
        handle = g_strdup(char_descriptor);
 
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+
+       /*offset*/
+       g_variant_builder_add(builder, "{sv}", "offset",
+                               g_variant_new("q", offset));
+       /* Device Object path*/
+//  g_variant_builder_add(builder, "{sv}", "device",
+//  g_variant_new("o", serv_info->serv_path));
+
        g_dbus_connection_call(conn,
                        BT_BLUEZ_NAME,
                        char_descriptor,
                        GATT_DESC_INTERFACE,
                        "ReadValue",
-                       NULL,
-                       G_VARIANT_TYPE("(ay)"),
+                       g_variant_new("(a{sv})", builder),
+                       G_VARIANT_TYPE("(yay)"),
                        G_DBUS_CALL_FLAGS_NONE,
                        -1,
                        NULL,
                        (GAsyncReadyCallback)__bluetooth_internal_read_desc_cb,
                        (gpointer)handle);
+       g_variant_builder_unref(builder);
 
        BT_DBG("-");
        return BLUETOOTH_ERROR_NONE;
@@ -1358,6 +1539,7 @@ static void __bluetooth_internal_write_desc_cb(GObject *source_object,
        GDBusConnection *system_gconn = NULL;
        GVariant *value;
        int result = BLUETOOTH_ERROR_NONE;
+       guint8 att_ecode = 0;
 
        BT_DBG("+");
        user_info = _bt_get_user_data(BT_COMMON);
@@ -1369,14 +1551,21 @@ static void __bluetooth_internal_write_desc_cb(GObject *source_object,
                BT_ERR("Error : %s \n", error->message);
                g_clear_error(&error);
                result = BLUETOOTH_ERROR_INTERNAL;
+       } else {
+               g_variant_get(value, "(y)", &att_ecode);
+               if (att_ecode) {
+                       result =  att_ecode;
+                       BT_ERR("ATT Error code: %d \n", att_ecode);
+               }
        }
+
        if (user_info) {
                _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
                                result, NULL,
                                user_info->cb, user_info->user_data);
        }
 
-       if(value)
+       if (value)
                g_variant_unref(value);
 
        BT_DBG("-");
@@ -1385,78 +1574,70 @@ static void __bluetooth_internal_write_desc_cb(GObject *source_object,
 BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(
                        const char *desc_handle, const guint8 *value, int length)
 {
-       GVariant *val;
+       GVariant *val, *options;
        GDBusConnection *conn;
-       GVariantBuilder *builder;
+       GVariantBuilder *builder1;
+       GVariantBuilder *builder2;
+       guint offset = 0;
        int i;
 
        BT_DBG("+");
        BT_CHECK_PARAMETER(desc_handle, return);
        BT_CHECK_PARAMETER(value, return);
        retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
-       BT_CHECK_ENABLED_ANY(return);
+       BT_CHECK_ENABLED(return);
 
        conn = _bt_gdbus_get_system_gconn();
        retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
 
-       builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
+       builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
 
-       for (i = 0; i < length; i++) {
-               g_variant_builder_add(builder, "y", value[i]);
-       }
+       for (i = 0; i < length; i++)
+               g_variant_builder_add(builder1, "y", value[i]);
+
+       val = g_variant_new("ay", builder1);
 
-       val = g_variant_new("(ay)", builder);
+       builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       /*offset*/
+       g_variant_builder_add(builder2, "{sv}", "offset",
+                               g_variant_new_uint16(offset));
+
+       /* Device Object path*/
+//     g_variant_builder_add(builder2, "{sv}", "device",
+//     g_variant_new_object("o", NULL));
+
+       options = g_variant_new("a{sv}", builder2);
 
        g_dbus_connection_call(conn,
                                BT_BLUEZ_NAME,
                                desc_handle,
                                GATT_DESC_INTERFACE,
                                "WriteValue",
-                               val,
-                               NULL,
+                               g_variant_new("(@ay@a{sv})",
+                               val, options),
+                               G_VARIANT_TYPE("(y)"),
                                G_DBUS_CALL_FLAGS_NONE,
                                -1, NULL,
                                (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
                                NULL);
 
-       g_variant_builder_unref(builder);
+       g_variant_builder_unref(builder1);
+       g_variant_builder_unref(builder2);
 
        BT_DBG("-");
        return BLUETOOTH_ERROR_NONE;
 }
 
-#ifndef GATT_NO_RELAY
-static int __bluetooth_gatt_watch_characteristics(void)
-{
-       int result = BLUETOOTH_ERROR_NONE;
-
-       BT_INIT_PARAMS();
-       BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
-
-       result = _bt_send_request(BT_BLUEZ_SERVICE,
-                       BT_GATT_WATCH_CHARACTERISTIC,
-                       in_param1, in_param2, in_param3, in_param4, &out_param);
-
-       if (result != BLUETOOTH_ERROR_NONE)
-                       BT_ERR("Watch Characteristic request failed !");
-
-       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
-       return result;
-}
-#endif
-
 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle)
 {
-
        GDBusConnection *conn;
        GError *error = NULL;
        int ret = BLUETOOTH_ERROR_NONE;
-       BT_DBG("+");
-       BT_CHECK_PARAMETER(char_handle, return);
 
-       BT_CHECK_ENABLED_ANY(return);
+       BT_CHECK_PARAMETER(char_handle, return);
+       BT_CHECK_ENABLED(return);
 
-       BT_DBG("Entered characteristic handle:%s \n ", char_handle);
+       BT_INFO_C("### Enable CCCD : %s", char_handle);
 
        conn = _bt_gdbus_get_system_gconn();
        retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
@@ -1469,10 +1650,11 @@ BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle)
                        NULL,
                        NULL,
                        G_DBUS_CALL_FLAGS_NONE,
-                       -1, NULL, &error);
+                       GATT_DEFAULT_TIMEOUT, NULL, &error);
 
        if (error) {
-               BT_ERR("Watch Failed: %s", error->message);
+               g_dbus_error_strip_remote_error(error);
+               BT_ERR_C("### Watch Failed: %s", error->message);
                if (g_strrstr(error->message, "Already notifying"))
                        ret = BLUETOOTH_ERROR_NONE;
                else if (g_strrstr(error->message, "In Progress"))
@@ -1492,47 +1674,21 @@ BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle)
 
                g_clear_error(&error);
        }
-#ifndef GATT_NO_RELAY
-       else {
-               /* Register the client sender to bt-service */
-               ret = __bluetooth_gatt_watch_characteristics();
-       }
-#endif
 
        return ret;
 }
 
-#ifndef GATT_NO_RELAY
-static void __bluetooth_gatt_unwatch_characteristics(void)
-{
-       int result = BLUETOOTH_ERROR_NONE;
-
-       BT_INIT_PARAMS();
-       BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
-
-       result = _bt_send_request(BT_BLUEZ_SERVICE,
-                       BT_GATT_UNWATCH_CHARACTERISTIC,
-                       in_param1, in_param2, in_param3, in_param4, &out_param);
-
-       if (result != BLUETOOTH_ERROR_NONE)
-                       BT_ERR("Unwatch Characteristic request failed !");
-
-       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
-}
-#endif
-
 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle)
 {
 
        GDBusConnection *conn;
        GError *error = NULL;
        int ret = BLUETOOTH_ERROR_NONE;
-       BT_DBG("+");
        BT_CHECK_PARAMETER(char_handle, return);
 
-       BT_CHECK_ENABLED_ANY(return);
+       BT_CHECK_ENABLED(return);
 
-       BT_DBG("Entered characteristic handle:%s \n ", char_handle);
+       BT_INFO("Disable CCCD : %s", char_handle);
 
        conn = _bt_gdbus_get_system_gconn();
        retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
@@ -1545,19 +1701,13 @@ BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle
                        NULL,
                        NULL,
                        G_DBUS_CALL_FLAGS_NONE,
-                       -1, NULL, &error);
+                       GATT_DEFAULT_TIMEOUT, NULL, &error);
 
        if (error) {
                BT_ERR("Watch Failed: %s", error->message);
                g_clear_error(&error);
                ret =  BLUETOOTH_ERROR_INTERNAL;
        }
-#ifndef GATT_NO_RELAY
-       else {
-               /* Unregister the client sender to bt-service */
-               __bluetooth_gatt_unwatch_characteristics();
-       }
-#endif
-       BT_DBG("-");
+
        return ret;
 }