Apply Tizen3.0 Gatt client product patch
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-gatt-client.c
index aa0c4c4..9819f1e 100644 (file)
@@ -42,8 +42,6 @@ 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);
@@ -53,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);
@@ -72,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);
@@ -88,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;
 }
 
@@ -103,14 +94,10 @@ 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;
@@ -174,18 +161,9 @@ BT_EXPORT_API int bluetooth_gatt_set_service_change_watcher(
                addr = g_malloc0(sizeof(bluetooth_device_address_t));
                memcpy(addr, address, sizeof(bluetooth_device_address_t));
 
-               if (service_monitor_list == NULL) {
-                       BT_ERR("There is NO watcher");
-                       return BLUETOOTH_ERROR_NONE;
-               }
-
                service_monitor_list =
                        g_slist_append(service_monitor_list, addr);
        } else {
-               if (service_monitor_list == NULL) {
-                       BT_ERR("There is NO watcher");
-                       return BLUETOOTH_ERROR_NONE;
-               }
 
                for (l = service_monitor_list; l != NULL; l = l->next) {
                        addr = l->data;
@@ -489,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) {
@@ -611,7 +589,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);
 
@@ -678,11 +655,10 @@ BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
                } 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);
@@ -704,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;
 }
 
@@ -824,7 +799,6 @@ 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);
 
@@ -895,48 +869,95 @@ 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;
 }
 
+static int __bluetooth_get_att_error_code(GError *error)
+{
+       int att_ecode = 0;
+       int len;
+       char *str = NULL;
+
+       BT_ERR("Error : %s", error->message);
+       str = g_strrstr(error->message, "ATT error: 0x");
+       if (str) {
+               len = strlen(str);
+               att_ecode =  g_ascii_xdigit_value(str[len-2]) << 4;
+               att_ecode += g_ascii_xdigit_value(str[len-1]);
+       } else
+               return BLUETOOTH_ATT_ERROR_INTERNAL;
+
+       switch (att_ecode) {
+       case BLUETOOTH_ATT_ERROR_READ_NOT_PERMITTED:
+               BT_ERR("Read not permitted");
+               break;
+       case BLUETOOTH_ATT_ERROR_WRITE_NOT_PERMITTED:
+               BT_ERR("Write not permitted");
+               break;
+       case BLUETOOTH_ATT_ERROR_AUTHENTICATION:
+               break;
+       case BLUETOOTH_ATT_ERROR_INSUFFICIENT_ENCRYPTION:
+       case BLUETOOTH_ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE:
+               BT_ERR("Not paired");
+               break;
+       case BLUETOOTH_ATT_ERROR_INVALID_OFFSET:
+               BT_ERR("Invalid offset");
+               break;
+       case BLUETOOTH_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN:
+               BT_ERR("Invalid Length");
+               break;
+       case BLUETOOTH_ATT_ERROR_AUTHORIZATION:
+               BT_ERR("Operation not Authorized");
+               break;
+       }
+
+       if (att_ecode >= 0x80 && att_ecode <= 0x9F)
+               BT_ERR("Application error");
+
+       return att_ecode;
+}
+
 static void __bluetooth_internal_read_cb(GObject *source_object,
-                       GAsyncResult *res,
-                       gpointer user_data)
+                                        GAsyncResult *res, gpointer user_data)
 {
        GError *error = NULL;
-       bt_user_info_t *user_info;
-       bt_gatt_char_value_t char_value =  { 0, };
        GDBusConnection *system_gconn = NULL;
        GVariant *value;
-       GByteArray *gp_byte_array = NULL;
+       bt_user_info_t *user_info;
        GVariantIter *iter;
+       GByteArray *gp_byte_array = NULL;
        guint8 g_byte;
-       int ret = BLUETOOTH_ERROR_NONE;
+       int att_ecode = 0;
+       bt_gatt_resp_data_t *resp_data = user_data;
 
        BT_DBG("+");
-       user_info = _bt_get_user_data(BT_COMMON);
 
        system_gconn = _bt_gdbus_get_system_gconn();
        value = g_dbus_connection_call_finish(system_gconn, res, &error);
 
-       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;
+       user_info = _bt_get_user_data(BT_COMMON);
+       if (!user_info) {
+               g_free(resp_data);
+               if (error) {
+                       BT_ERR("Error : %s", error->message);
+                       g_clear_error(&error);
+                       return;
+               }
+               g_variant_unref(value);
+               return;
+       }
 
+       if (error) {
+               att_ecode = __bluetooth_get_att_error_code(error);
                g_clear_error(&error);
-               if (user_info) {
-                       _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
-                               ret, NULL,
-                               user_info->cb, user_info->user_data);
-               }
-               g_free(user_data);
+
+               _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
+                                   att_ecode, resp_data,
+                                   user_info->cb, user_info->user_data);
+               g_free(resp_data);
                return;
        }
 
-       char_value.char_handle = user_data;
        gp_byte_array = g_byte_array_new();
        g_variant_get(value, "(ay)", &iter);
 
@@ -944,61 +965,114 @@ static void __bluetooth_internal_read_cb(GObject *source_object,
                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;
+               resp_data->len = gp_byte_array->len;
+               resp_data->value = gp_byte_array->data;
        }
 
-       if (user_info) {
-               _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
-                               BLUETOOTH_ERROR_NONE, &char_value,
-                               user_info->cb, user_info->user_data);
-       }
+       _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
+                           BLUETOOTH_ATT_ERROR_NONE, resp_data,
+                           user_info->cb, user_info->user_data);
+       g_free(resp_data);
 
-       g_free(char_value.char_handle);
        g_byte_array_free(gp_byte_array, TRUE);
-       g_variant_unref(value);
        g_variant_iter_free(iter);
+       g_variant_unref(value);
 
        BT_DBG("-");
 }
 
-BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *characteristic)
+BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *chr,
+                                                          gpointer user_data)
 {
        GDBusConnection *conn;
-       char *handle;
+       bt_gatt_resp_data_t *resp_data;
+       GVariantBuilder *builder = NULL;
+       guint16 offset = 0;
 
-       BT_CHECK_PARAMETER(characteristic, return);
+       BT_CHECK_PARAMETER(chr, return);
        BT_CHECK_ENABLED(return);
 
        conn = _bt_gdbus_get_system_gconn();
        retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
 
-       handle = g_strdup(characteristic);
+       resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
+       resp_data->user_data = user_data;
 
-       g_dbus_connection_call(conn,
-                       BT_BLUEZ_NAME,
-                       characteristic,
-                       GATT_CHAR_INTERFACE,
-                       "ReadValue",
-                       NULL,
-                       G_VARIANT_TYPE("(ay)"),
-                       G_DBUS_CALL_FLAGS_NONE,
-                       -1,
-                       NULL,
+       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, chr, GATT_CHAR_INTERFACE,
+                       "ReadValue", g_variant_new("(a{sv})", builder),
+                       G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
                        (GAsyncReadyCallback)__bluetooth_internal_read_cb,
-                       (gpointer)handle);
+                       (gpointer)resp_data);
+       g_variant_builder_unref(builder);
 
        return BLUETOOTH_ERROR_NONE;
 }
 
+static void __bluetooth_internal_write_cb(GObject *source_object,
+                                         GAsyncResult *res, gpointer user_data)
+{
+       GError *error = NULL;
+       GDBusConnection *system_gconn = NULL;
+       bt_user_info_t *user_info;
+       GVariant *value;
+       int att_ecode = 0;
+       bt_gatt_resp_data_t *resp_data = user_data;
+
+       system_gconn = _bt_gdbus_get_system_gconn();
+       value = g_dbus_connection_call_finish(system_gconn, res, &error);
+
+       user_info = _bt_get_user_data(BT_COMMON);
+       if (!user_info) {
+               g_free(resp_data);
+               if (error) {
+                       BT_ERR("Error : %s", error->message);
+                       g_clear_error(&error);
+                       return;
+               }
+               g_variant_unref(value);
+               return;
+       }
+
+       if (error) {
+               att_ecode = __bluetooth_get_att_error_code(error);
+               g_clear_error(&error);
+
+               _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
+                               att_ecode, resp_data,
+                               user_info->cb, user_info->user_data);
+               g_free(resp_data);
+               return;
+       }
+
+       _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
+                       BLUETOOTH_ATT_ERROR_NONE, resp_data,
+                       user_info->cb, user_info->user_data);
+       g_free(resp_data);
+
+       g_variant_unref(value);
+       return;
+}
+
 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
                const char *char_handle, const guint8 *value, int length)
 {
-       GVariant *val;
-       GVariantBuilder *builder;
+       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);
@@ -1009,89 +1083,64 @@ BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
        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]);
 
-       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;
-       }
+       val = g_variant_new("ay", builder1);
 
-       g_variant_builder_unref(builder);
+       builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       /*offset*/
+       g_variant_builder_add(builder2, "{sv}", "offset",
+                               g_variant_new_uint16(offset));
 
-       BT_DBG("-");
-       return BLUETOOTH_ERROR_NONE;
-}
+       /* Device Object path*/
+//     g_variant_builder_add(builder2, "{sv}", "device",
+//     g_variant_new_object("o", NULL));
 
-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;
+       options = g_variant_new("a{sv}", builder2);
 
-       user_info = _bt_get_user_data(BT_COMMON);
+       g_dbus_connection_call(conn,
+                               BT_BLUEZ_NAME,
+                               char_handle,
+                               GATT_CHAR_INTERFACE,
+                               "WriteValue",
+                               g_variant_new("(@ay@a{sv})",
+                               val, options),
+                               NULL,
+                               G_DBUS_CALL_FLAGS_NONE,
+                               -1, NULL,
+                               (GAsyncReadyCallback)__bluetooth_internal_write_cb,
+                               NULL);
 
-       system_gconn = _bt_gdbus_get_system_gconn();
-       value = g_dbus_connection_call_finish(system_gconn, res, &error);
 
        if (error) {
-               BT_ERR("Error : %s \n", error->message);
+               BT_ERR("Set value Failed: %s", 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_CHAR,
-                               result, NULL,
-                               user_info->cb, user_info->user_data);
-       } else {
-               BT_ERR("user info is null");
+               g_variant_builder_unref(builder1);
+               return BLUETOOTH_ERROR_INTERNAL;
        }
+       g_variant_builder_unref(builder1);
+       g_variant_builder_unref(builder2);
 
-       if (value)
-               g_variant_unref(value);
        BT_DBG("-");
-       return;
+       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)
+                       const char *chr, const guint8 *value, int length,
+                       guint8 write_type, gpointer user_data)
 {
-       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_gatt_resp_data_t *resp_data;
 
-       BT_CHECK_PARAMETER(char_handle, return);
+       BT_CHECK_PARAMETER(chr, return);
        BT_CHECK_PARAMETER(value, return);
        retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
        BT_CHECK_ENABLED_INTERNAL(return);
@@ -1099,34 +1148,49 @@ BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
        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]);
 
-       val = g_variant_new("ay", builder);
-       g_dbus_connection_call(conn,
-                       BT_BLUEZ_NAME,
-                       char_handle,
-                       GATT_CHAR_INTERFACE,
+       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);
+
+       resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
+       resp_data->user_data = user_data;
+
+       g_dbus_connection_call(conn, BT_BLUEZ_NAME, chr, GATT_CHAR_INTERFACE,
                        "WriteValuebyType",
-                       g_variant_new("(y@ay)", write_type, val),
-                       G_VARIANT_TYPE("(y)"),
-                       G_DBUS_CALL_FLAGS_NONE,
-                       -1, NULL,
+                       g_variant_new("(y@ay@a{sv})", write_type, val, options),
+                       NULL,
+                       G_DBUS_CALL_FLAGS_NONE, -1, NULL,
                        (GAsyncReadyCallback)__bluetooth_internal_write_cb,
-                       NULL);
+                       (gpointer)resp_data);
+
+       g_variant_builder_unref(builder1);
+       g_variant_builder_unref(builder2);
 
-       g_variant_builder_unref(builder);
        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("+");
@@ -1138,28 +1202,41 @@ BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
        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,
+                               g_variant_new("(@ay@a{sv})",
+                               val, options),
                                NULL,
                                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;
@@ -1245,13 +1322,9 @@ static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
                                g_variant_get(value, "ay", &desc_value_iter);
                                len = g_variant_get_size((GVariant *)desc_value_iter);
 
-                               if (len > 0) {
+                               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]);
@@ -1271,7 +1344,6 @@ static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
                }
        }
 
-done:
        g_variant_iter_free(property_iter);
        g_variant_unref(result);
        g_object_unref(properties_proxy);
@@ -1297,6 +1369,7 @@ static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
        user_info = _bt_get_user_data(BT_COMMON);
 
        value = g_dbus_proxy_call_finish(proxy, res, &error);
+       characteristic.handle = user_data;
 
        if (value == NULL) {
                if (error != NULL) {
@@ -1311,7 +1384,7 @@ static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
                                BLUETOOTH_ERROR_INTERNAL, NULL,
                                user_info->cb, user_info->user_data);
                }
-               g_free(user_data);
+               g_free(characteristic.handle);
                g_object_unref(proxy);
                return;
        }
@@ -1328,13 +1401,13 @@ static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
                }
        }
 
-       characteristic.handle = user_data;
        if (user_info) {
                _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
                                ret, &characteristic, user_info->cb, user_info->user_data);
        }
        bluetooth_gatt_free_char_property(&characteristic);
 
+       g_free(characteristic.handle);
        g_variant_iter_free(char_iter);
        g_variant_unref(value);
        BT_DBG("-");
@@ -1381,140 +1454,168 @@ static void __bluetooth_internal_read_desc_cb(GObject *source_object,
                        gpointer user_data)
 {
        GError *error = NULL;
-       bt_user_info_t *user_info;
-       bt_gatt_char_property_t char_value =  { 0, };
        GDBusConnection *system_gconn = NULL;
        GVariant *value;
+       bt_user_info_t *user_info;
        GByteArray *gp_byte_array = NULL;
        GVariantIter *iter;
        guint8 g_byte;
+       int att_ecode = 0;
+       bt_gatt_resp_data_t *resp_data = user_data;
 
        BT_DBG("+");
-       user_info = _bt_get_user_data(BT_COMMON);
-       system_gconn = _bt_gdbus_get_system_gconn();
 
-       char_value.handle = user_data;
+       system_gconn = _bt_gdbus_get_system_gconn();
        value = g_dbus_connection_call_finish(system_gconn, res, &error);
 
+       user_info = _bt_get_user_data(BT_COMMON);
+       if (!user_info) {
+               g_free(resp_data);
+               if (error) {
+                       BT_ERR("Error : %s", error->message);
+                       g_clear_error(&error);
+                       return;
+               }
+               g_variant_unref(value);
+               return;
+       }
+
        if (error) {
-               BT_ERR("Error : %s \n", error->message);
+               att_ecode = __bluetooth_get_att_error_code(error);
                g_clear_error(&error);
-               if (user_info) {
-                       _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
-                                       BLUETOOTH_ERROR_INTERNAL, NULL,
-                                       user_info->cb, user_info->user_data);
-               }
-               g_free(char_value.handle);
+
+               _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
+                               att_ecode, resp_data,
+                               user_info->cb, user_info->user_data);
+               g_free(resp_data);
                return;
        }
 
        gp_byte_array = g_byte_array_new();
        g_variant_get(value, "(ay)", &iter);
 
-       while (g_variant_iter_loop(iter, "y",  &g_byte))
+       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;
+               resp_data->len = gp_byte_array->len;
+               resp_data->value = gp_byte_array->data;
        }
 
-       if (user_info) {
-               _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
-                               BLUETOOTH_ERROR_NONE, &char_value,
-                               user_info->cb, user_info->user_data);
-       }
+       _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
+                       BLUETOOTH_ATT_ERROR_NONE, resp_data,
+                       user_info->cb, user_info->user_data);
+       g_free(resp_data);
+
 
        g_byte_array_free(gp_byte_array, TRUE);
-       g_free(char_value.handle);
-       g_variant_unref(value);
        g_variant_iter_free(iter);
+       g_variant_unref(value);
 
        BT_DBG("-");
 }
 
-BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *char_descriptor)
+BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *desc,
+                                                      gpointer user_data)
 {
        GDBusConnection *conn;
-       char *handle;
+       GVariantBuilder *builder;
+       guint offset = 0;
+       bt_gatt_resp_data_t *resp_data;
 
        BT_DBG("+");
-       BT_CHECK_PARAMETER(char_descriptor, return);
+
+       BT_CHECK_PARAMETER(desc, return);
        BT_CHECK_ENABLED(return);
 
        conn = _bt_gdbus_get_system_gconn();
        retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
 
-       handle = g_strdup(char_descriptor);
+       resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
+       resp_data->user_data = user_data;
 
-       g_dbus_connection_call(conn,
-                       BT_BLUEZ_NAME,
-                       char_descriptor,
-                       GATT_DESC_INTERFACE,
-                       "ReadValue",
-                       NULL,
+       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, desc, GATT_DESC_INTERFACE,
+                       "ReadValue", g_variant_new("(a{sv})", builder),
                        G_VARIANT_TYPE("(ay)"),
-                       G_DBUS_CALL_FLAGS_NONE,
-                       -1,
-                       NULL,
+                       G_DBUS_CALL_FLAGS_NONE, -1, NULL,
                        (GAsyncReadyCallback)__bluetooth_internal_read_desc_cb,
-                       (gpointer)handle);
+                       (gpointer)resp_data);
+       g_variant_builder_unref(builder);
 
        BT_DBG("-");
        return BLUETOOTH_ERROR_NONE;
 }
 
 static void __bluetooth_internal_write_desc_cb(GObject *source_object,
-                       GAsyncResult *res,
-                       gpointer user_data)
+                                       GAsyncResult *res, gpointer user_data)
 {
        GError *error = NULL;
        bt_user_info_t *user_info;
        GDBusConnection *system_gconn = NULL;
        GVariant *value;
-       int result = BLUETOOTH_ERROR_NONE;
-       guint8 att_ecode = 0;
+       int att_ecode = BLUETOOTH_ATT_ERROR_NONE;
+       bt_gatt_resp_data_t *resp_data = user_data;
 
        BT_DBG("+");
-       user_info = _bt_get_user_data(BT_COMMON);
 
        system_gconn = _bt_gdbus_get_system_gconn();
        value = g_dbus_connection_call_finish(system_gconn, res, &error);
 
-       if (error) {
-               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);
+       user_info = _bt_get_user_data(BT_COMMON);
+       if (!user_info) {
+               g_free(resp_data);
+               if (error) {
+                       BT_ERR("Error : %s", error->message);
+                       g_clear_error(&error);
+                       return;
                }
+               g_variant_unref(value);
+               return;
        }
 
-       if (user_info) {
+       if (error) {
+               att_ecode = __bluetooth_get_att_error_code(error);
+               g_clear_error(&error);
+
                _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
-                               result, NULL,
+                               att_ecode, resp_data,
                                user_info->cb, user_info->user_data);
+               g_free(resp_data);
+               return;
        }
 
-       if (value)
-               g_variant_unref(value);
+       _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
+                               BLUETOOTH_ATT_ERROR_NONE, resp_data,
+                       user_info->cb, user_info->user_data);
+       g_free(resp_data);
 
+       g_variant_unref(value);
        BT_DBG("-");
 }
 
-BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(
-                       const char *desc_handle, const guint8 *value, int length)
+BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(const char *desc,
+                       const guint8 *value, int length, gpointer user_data)
 {
-       GVariant *val;
+       GVariant *val, *options;
        GDBusConnection *conn;
-       GVariantBuilder *builder;
+       GVariantBuilder *builder1;
+       GVariantBuilder *builder2;
+       guint offset = 0;
        int i;
+       bt_gatt_resp_data_t *resp_data;
 
        BT_DBG("+");
-       BT_CHECK_PARAMETER(desc_handle, return);
+
+       BT_CHECK_PARAMETER(desc, return);
        BT_CHECK_PARAMETER(value, return);
        retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
        BT_CHECK_ENABLED(return);
@@ -1522,51 +1623,40 @@ BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(
        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]);
 
-       val = g_variant_new("(ay)", builder);
+       val = g_variant_new("ay", builder1);
 
-       g_dbus_connection_call(conn,
-                               BT_BLUEZ_NAME,
-                               desc_handle,
-                               GATT_DESC_INTERFACE,
-                               "WriteValue",
-                               val,
-                               G_VARIANT_TYPE("(y)"),
-                               G_DBUS_CALL_FLAGS_NONE,
-                               -1, NULL,
-                               (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
-                               NULL);
-
-       g_variant_builder_unref(builder);
-
-       BT_DBG("-");
-       return BLUETOOTH_ERROR_NONE;
-}
+       builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       /*offset*/
+       g_variant_builder_add(builder2, "{sv}", "offset",
+                               g_variant_new_uint16(offset));
 
-#ifndef GATT_NO_RELAY
-static int __bluetooth_gatt_watch_characteristics(void)
-{
-       int result = BLUETOOTH_ERROR_NONE;
+       /* Device Object path*/
+//     g_variant_builder_add(builder2, "{sv}", "device",
+//     g_variant_new_object("o", NULL));
 
-       BT_INIT_PARAMS();
-       BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+       options = g_variant_new("a{sv}", builder2);
 
-       result = _bt_send_request(BT_BLUEZ_SERVICE,
-                       BT_GATT_WATCH_CHARACTERISTIC,
-                       in_param1, in_param2, in_param3, in_param4, &out_param);
+       resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
+       resp_data->user_data = user_data;
 
-       if (result != BLUETOOTH_ERROR_NONE)
-                       BT_ERR("Watch Characteristic request failed !");
+       g_dbus_connection_call(conn, BT_BLUEZ_NAME, desc, GATT_DESC_INTERFACE,
+                       "WriteValue", g_variant_new("(@ay@a{sv})",
+                       val, options), NULL,
+                       G_DBUS_CALL_FLAGS_NONE, -1, NULL,
+                       (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
+                       (gpointer)resp_data);
 
-       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+       g_variant_builder_unref(builder1);
+       g_variant_builder_unref(builder2);
 
-       return result;
+       BT_DBG("-");
+       return BLUETOOTH_ERROR_NONE;
 }
-#endif
 
 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle)
 {
@@ -1614,44 +1704,16 @@ 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 int __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);
-
-       return result;
-}
-#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(return);
@@ -1676,12 +1738,6 @@ BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle
                g_clear_error(&error);
                ret =  BLUETOOTH_ERROR_INTERNAL;
        }
-#ifndef GATT_NO_RELAY
-       else {
-               /* Unregister the client sender to bt-service */
-               ret = __bluetooth_gatt_unwatch_characteristics();
-       }
-#endif
-       BT_DBG("-");
+
        return ret;
 }