Fix the warning errors
[platform/core/connectivity/bluetooth-frwk.git] / bt-oal / bluez_hal / src / bt-hal-gatt-client.c
index ec6f955..6895eb0 100644 (file)
@@ -28,6 +28,7 @@
 #include <dlog.h>
 #include <gio/gio.h>
 #include <glib.h>
+#include <gio/gunixfdlist.h>
 
 
 #include "bt-hal-log.h"
@@ -116,6 +117,7 @@ typedef struct {
 typedef struct {
        gchar *svc_path;
        bt_uuid_t svc_uuid;
+       int is_primary;
        GSList *gatt_list_chars;
 } hal_gattc_service_t;
 
@@ -138,7 +140,6 @@ typedef struct {
 /* Linked list of connected GATT client connection */
 static GSList * hal_gattc_client_info_list = NULL;
 
-
 static bt_pending_le_conn_info_s *pending_le_conn_info = NULL;
 static guint pending_le_conn_timer_id = 0;
 static int bt_conn_id = 0;
@@ -148,12 +149,12 @@ static int bt_inst_id = 0;
 
 typedef struct {
        int conn_id;
+       int result;
        btgatt_srvc_id_t srvc_id;
        btgatt_gatt_id_t char_id;
        btgatt_gatt_id_t desc_id;
 } hal_gatt_resp_data_t;
 
-
 typedef struct {
        int client_if;
        bt_uuid_t app_uuid;
@@ -175,6 +176,8 @@ static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int  conn_
 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
                                                const char* uuid_str, int inst_id);
 static void _bt_hal_send_search_service_complete_event(int conn_id, int status);
+static hal_gattc_server_info_t *__bt_find_gatt_conn_info(bt_bdaddr_t *serv_addr);
+static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
 
 
 /* To send stack event to hal-av handler */
@@ -245,11 +248,6 @@ static hal_gatt_client_app *__hal_gattc_add_client_app(bt_uuid_t *app_uuid)
 
        //add client app
        gattc_app = g_malloc0(sizeof(hal_gatt_client_app));
-       if (gattc_app == NULL) {
-               DBG("Failed to allocate memory");
-               return NULL;
-       }
-
        gattc_app->client_if = __hal_generate_client_id();
        memcpy(&gattc_app->app_uuid, app_uuid, sizeof(bt_uuid_t));
 
@@ -273,11 +271,6 @@ static bt_status_t __hal_gattc_register_client_app(bt_uuid_t *app_uuid)
 
        /*send event */
        client_app_info = g_malloc0(sizeof(hal_gatt_client_app));
-       if (NULL == client_app_info) {
-               ERR("Failed to allocate memory");
-               return BT_STATUS_FAIL;
-       }
-
        client_app_info->client_if = gattc_app->client_if;
        memcpy(&client_app_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
        g_idle_add(__bt_hal_register_client_cb, (gpointer)client_app_info);
@@ -473,12 +466,6 @@ bt_status_t _hal_gattc_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
        }
 
        gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
-       if (NULL == gattc_data) {
-               ERR("Unable to allocate memory");
-               ret = BT_STATUS_FAIL;
-               goto fail;
-       }
-
        memcpy(gattc_data->bd_addr.address, bd_addr->address,
                        BT_HAL_ADDRESS_LENGTH_MAX);
        gattc_data->client_if = client_if;
@@ -493,13 +480,6 @@ bt_status_t _hal_gattc_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
                        NULL,
                        (GAsyncReadyCallback)__le_disconnection_req_cb, gattc_data);
        return ret;
-fail:
-       if (device_proxy)
-               g_object_unref(device_proxy);
-
-       g_free(gattc_data);
-
-       return ret;
 }
 
 /** Disconnect a remote device or cancel a pending connection */
@@ -541,7 +521,8 @@ static hal_gattc_service_t* _gattc_find_service_from_uuid(hal_gattc_server_info_
 }
 
 
-static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid)
+static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid,
+                               bt_gatt_characteristic_property_t prop)
 {
        DBG("+");
 
@@ -553,7 +534,30 @@ static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_s
                if (info == NULL)
                        continue;
 
-               if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t))) {
+               if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
+                       (info->permission & prop)) {
+                       INFO("Found GATT char uuid");
+                       return info;
+               }
+       }
+       return NULL;
+}
+
+static hal_gattc_char_t* _gattc_find_char_from_uuid_for_notify(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid)
+{
+       DBG("+");
+
+       GSList *l;
+       hal_gattc_char_t *info = NULL;
+
+       for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
+               info = (hal_gattc_char_t*)l->data;
+               if (info == NULL)
+                       continue;
+
+               if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
+                       ((info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) ||
+                               (info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE))) {
                        INFO("Found GATT char uuid");
                        return info;
                }
@@ -583,7 +587,7 @@ static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char
 
 
 static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
-               const char *uuid_str, char *object_path)
+               const char *uuid_str, char *object_path, int is_primary)
 {
        DBG("+");
        hal_gattc_service_t *gattc_service = NULL;
@@ -591,6 +595,7 @@ static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t
        gattc_service = g_malloc0(sizeof(hal_gattc_service_t));
        gattc_service->svc_path = g_strdup(object_path);
        _bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str);
+       gattc_service->is_primary = is_primary;
 
        DBG("service count[%d]", g_slist_length(conn_info->gatt_list_services));
 
@@ -625,7 +630,7 @@ static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboole
        DBG("+");
 
        /* add the service */
-       gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path);
+       gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary);
        if (gatt_svc == NULL) {
                ERR("Failed to add service");
                return;
@@ -968,7 +973,7 @@ static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_ch
        GVariantIter *property_iter;
        GVariantIter *char_desc_iter;
        char* char_handle = NULL;
-       const gchar *char_uuid_str = NULL;
+       gchar *char_uuid_str = NULL;
        GPtrArray *gp_desc_array  = NULL;
        GVariantIter *char_perm_iter;
        gchar* permission;
@@ -1047,6 +1052,7 @@ static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_ch
 
        _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
 
+       g_free(char_uuid_str);
        g_variant_iter_free(property_iter);
        g_variant_unref(result);
        g_object_unref(properties_proxy);
@@ -1192,13 +1198,13 @@ static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
 
        while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
                if (!g_strcmp0(key, "UUID")) {
-                       desc_uuid_str = g_variant_dup_string(value, &len);
+                       desc_uuid_str = g_variant_get_string(value, &len);
                        DBG("desc UUID [%s]", desc_uuid_str);
+                       _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
+                       break;
                }
        }
 
-       _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
-
        g_variant_iter_free(property_iter);
        g_variant_unref(result);
        g_object_unref(properties_proxy);
@@ -1243,6 +1249,7 @@ static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
        hal_gattc_server_info_t * conn_info = NULL;
        hal_gattc_service_t *gattc_service = NULL;
        GSList *l;
+       GSList *m;
        hal_gattc_char_t *gattc_char = NULL;
        hal_gattc_desc_t *gattc_desc = NULL;
        char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
@@ -1269,26 +1276,33 @@ static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
        DBG("service uuid [%s]", svc_uuid_str);
 
        /* find characteristics */
-       gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid);
-       if (NULL == gattc_char) {
-               DBG("Failed to get the gatt char");
-               return BT_STATUS_FAIL;
-       }
+       /* a service can have two char with same uuid */
+       for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
+               gattc_char = (hal_gattc_char_t*)l->data;
+               if (gattc_char == NULL)
+                       continue;
 
-       DBG("char path [%s]", gattc_char->chr_path);
-       _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
-       DBG("char uuid [%s]", char_uuid_str);
+               if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
+                       INFO("Found GATT char uuid");
+                       DBG("char path [%s]", gattc_char->chr_path);
+                       _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
+                       DBG("char uuid [%s]", char_uuid_str);
+
+                       /* get descriptor uuid */
+                       for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
+                               gattc_desc = (hal_gattc_desc_t *)m->data;
+                               if (gattc_desc == NULL)
+                                       continue;
 
-       /* get descriptor uuid */
-       for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
-               gattc_desc = (hal_gattc_desc_t *)l->data;
-               status = _hal_gattc_get_descriptor_info(gattc_desc);
+                               status = _hal_gattc_get_descriptor_info(gattc_desc);
 
-               /* send event */
-               if (BT_STATUS_SUCCESS == status) {
-                       DBG("Sending the success descriptor event");
-                       _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
-                                       char_id, &gattc_desc->desc_uuid);
+                               /* send event */
+                               if (BT_STATUS_SUCCESS == status) {
+                                       DBG("Sending the success descriptor event");
+                                       _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
+                                                       char_id, &gattc_desc->desc_uuid);
+                               }
+                       }
                }
        }
 
@@ -1373,7 +1387,7 @@ static void __hal_internal_read_char_cb(GObject *source_object,
        value = g_dbus_connection_call_finish(system_gconn, res, &error);
 
        if (error) {
-               ERR("Read Characteristic dbus failed Error:", error->message);
+               ERR("Read Characteristic dbus failed Error:[%s]", error->message);
 
                //send failed event
                result  = BT_STATUS_FAIL;
@@ -1443,7 +1457,8 @@ static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t
 
 
        /* find characteristic */
-       gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid);
+       gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
+                       HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
        if (NULL == gattc_char) {
                DBG("Failed to get the gatt char");
                return BT_STATUS_FAIL;
@@ -1460,11 +1475,6 @@ static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t
        }
 
        resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
-       if (NULL == resp_data) {
-               ERR("failed to get the memory");
-               return BT_STATUS_FAIL;
-       }
-
        resp_data->conn_id = conn_id;
        memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
        memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
@@ -1540,7 +1550,7 @@ static void __hal_bluetooth_internal_write_cb(GObject *source_object,
        value = g_dbus_connection_call_finish(system_gconn, res, &error);
 
        if (error) {
-               ERR("write Characteristic dbus failed Error:", error->message);
+               ERR("write Characteristic dbus failed Error:[%s]", error->message);
 
                result  = BT_STATUS_FAIL;
                //send failed event
@@ -1559,14 +1569,14 @@ static void __hal_bluetooth_internal_write_cb(GObject *source_object,
        DBG("-");
 }
 
-static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, hal_gatt_property_e *prop)
+static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
 {
        switch (type) {
        case HAL_GATT_WRITE_TYPE_WRITE:
-               *prop = HAL_GATT_PROPERTY_WRITE;
+               *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
                break;
        case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
-               *prop = HAL_GATT_PROPERTY_WRITE_WITHOUT_RESPONSE;
+               *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
                break;
        default:
                ERR("Unknow write type : %d", type);
@@ -1576,6 +1586,108 @@ static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, hal_gatt_pro
        return BT_STATUS_SUCCESS;
 }
 
+
+static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
+{
+       GDBusConnection *conn;
+       GVariantBuilder *builder = NULL;
+       guint16 offset = 0;
+       GError *err = NULL;
+       GVariant *value;
+       gint32 idx;
+       guint16 att_mtu;
+       GUnixFDList *fd_list = NULL;
+
+       conn = _bt_hal_get_system_gconn();
+       if (NULL == conn) {
+               ERR("_bt_gdbus_get_system_gconn returned NULL");
+               return BT_STATUS_FAIL;
+       }
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       //val = g_variant_new("ay", builder1);
+
+       g_variant_builder_add(builder, "{sv}", "offset",
+       g_variant_new("q", offset));
+
+       value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
+                       "AcquireWrite", g_variant_new("(a{sv})", builder),
+                       G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
+                       NULL, &fd_list, NULL, &err);
+       if (err != NULL) {
+               g_dbus_error_strip_remote_error(err);
+               ERR("Error: %s", err->message);
+               g_error_free(err);
+               g_variant_builder_unref(builder);
+               return BT_STATUS_FAIL;
+       }
+
+       g_variant_get(value, "(hq)", &idx, &att_mtu);
+       *fd = g_unix_fd_list_get(fd_list, idx, NULL);
+
+       INFO("FD is %d index is %d mtu is %d", *fd, idx, att_mtu);
+       *mtu = att_mtu;
+
+       g_object_unref(fd_list);
+       g_variant_unref(value);
+       g_variant_builder_unref(builder);
+
+       return BT_STATUS_SUCCESS;
+}
+
+static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
+{
+       GDBusConnection *conn;
+       GVariantBuilder *builder = NULL;
+       guint16 offset = 0;
+       GError *err = NULL;
+       GVariant *value;
+       gint32 idx, notify_fd;
+       guint16 att_mtu;
+       GUnixFDList *fd_list = NULL;
+
+       conn = _bt_hal_get_system_gconn();
+
+       if (NULL == conn) {
+               ERR("_bt_gdbus_get_system_gconn returned NULL");
+               return BT_STATUS_FAIL;
+       }
+
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+
+
+       g_variant_builder_add(builder, "{sv}", "offset",
+               g_variant_new("q", offset));
+
+       value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
+               "AcquireNotify", g_variant_new("(a{sv})", builder),
+               G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
+               NULL, &fd_list, NULL, &err);
+       if (err != NULL) {
+               g_dbus_error_strip_remote_error(err);
+               ERR("Error: %s", err->message);
+               g_error_free(err);
+               g_variant_builder_unref(builder);
+               return BT_STATUS_FAIL;
+       }
+
+       g_variant_get(value, "(hq)", &idx, &att_mtu);
+       notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
+       *mtu = att_mtu;
+
+       INFO("Acquired characteristic Notify fd %d, mtu %d", notify_fd, *mtu);
+
+       *fd = notify_fd;
+
+       g_object_unref(fd_list);
+       g_variant_unref(value);
+       g_variant_builder_unref(builder);
+
+       return BT_STATUS_SUCCESS;
+}
+
+
 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
                btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
 {
@@ -1592,7 +1704,7 @@ static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t
        char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
        char char_uuid_str[BT_HAL_UUID_STRING_LEN];
        char* char_handle = NULL;
-       hal_gatt_property_e write_prop = HAL_GATT_PROPERTY_WRITE;
+       bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
        int ret = BT_STATUS_SUCCESS;
 
        DBG("+");
@@ -1622,7 +1734,7 @@ static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t
        DBG("service uuid [%s]", svc_uuid_str);
 
        /* find characteristic */
-       gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid);
+       gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
        if (NULL == gattc_char) {
                DBG("Failed to get the gatt char");
                return BT_STATUS_FAIL;
@@ -1639,11 +1751,6 @@ static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t
        }
 
        resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
-       if (NULL == resp_data) {
-               ERR("failed to get the memory");
-               return BT_STATUS_FAIL;
-       }
-
        resp_data->conn_id = conn_id;
        memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
        memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
@@ -1678,6 +1785,119 @@ static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t
        return BT_STATUS_SUCCESS;
 }
 
+bt_status_t btif_get_acquire_write_fd(int conn_id,
+               btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
+               int auth_req, int *fd, int*mtu)
+{
+       CHECK_BTGATT_INIT();
+
+       DBG("+");
+
+       DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
+
+
+       hal_gattc_service_t *gattc_service = NULL;
+       hal_gattc_server_info_t * conn_info = NULL;
+       hal_gattc_char_t *gattc_char = NULL;
+       char char_uuid_str[BT_HAL_UUID_STRING_LEN];
+
+       bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
+       int ret = BT_STATUS_SUCCESS;
+
+       DBG("+");
+
+               /* get the connection info */
+       conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
+       if (NULL == conn_info) {
+               DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
+               return BT_STATUS_FAIL;
+       }
+
+       /* find service */
+       gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
+       if (NULL == gattc_service) {
+               DBG("Failed to get the gatt service");
+               return BT_STATUS_FAIL;
+       }
+
+       gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
+               if (NULL == gattc_char) {
+                       DBG("Failed to get the gatt char");
+                       return BT_STATUS_FAIL;
+               }
+
+       DBG("char path [%s]", gattc_char->chr_path);
+       _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
+       DBG("char uuid [%s]", char_uuid_str);
+
+
+       ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
+       if (ret != BT_STATUS_SUCCESS)
+               return ret;
+
+
+               ERR("Characterstics FD erite  characterstics fd is %d", *fd);
+
+               return ret;
+}
+
+bt_status_t btif_get_acquire_notify_fd(int conn_id,
+               btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
+{
+       CHECK_BTGATT_INIT();
+
+       DBG("+");
+
+       DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
+
+
+       hal_gattc_service_t *gattc_service = NULL;
+       hal_gattc_server_info_t * conn_info = NULL;
+       hal_gattc_char_t *gattc_char = NULL;
+       char char_uuid_str[BT_HAL_UUID_STRING_LEN];
+
+       bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
+       int ret = BT_STATUS_SUCCESS;
+
+       DBG("+");
+
+               /* get the connection info */
+               conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
+               if (NULL == conn_info) {
+                       DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
+                       return BT_STATUS_FAIL;
+               }
+
+       /* find service */
+       gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
+       if (NULL == gattc_service) {
+               DBG("Failed to get the gatt service");
+               return BT_STATUS_FAIL;
+       }
+
+       gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
+               if (NULL == gattc_char) {
+                       DBG("Failed to get the gatt char");
+                       return BT_STATUS_FAIL;
+               }
+
+       DBG("char path [%s]", gattc_char->chr_path);
+       _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
+       DBG("char uuid [%s]", char_uuid_str);
+
+
+       ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
+       if (ret != BT_STATUS_SUCCESS)
+               return ret;
+
+
+       ERR("Characterstics FD write characterstics fd is %d", *fd);
+
+               return ret;
+
+}
+
+
 /** Write a remote characteristic */
 bt_status_t btif_write_characteristic(int conn_id,
                btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
@@ -1744,7 +1964,7 @@ static void __hal_internal_read_desc_cb(GObject *source_object,
        value = g_dbus_connection_call_finish(system_gconn, res, &error);
 
        if (error) {
-               ERR("Read descriptor dbus failed Error:", error->message);
+               ERR("Read descriptor dbus failed Error:[%s]", error->message);
 
                //send failed event
                result  = BT_STATUS_FAIL;
@@ -1791,6 +2011,7 @@ static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srv
        char char_uuid_str[BT_HAL_UUID_STRING_LEN];
        char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
        char* desc_handle = NULL;
+       GSList *l;
 
        hal_gattc_desc_t *gattc_desc = NULL;
 
@@ -1815,27 +2036,34 @@ static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srv
        DBG("service uuid [%s]", svc_uuid_str);
 
        /* find characteristic */
-       gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid);
-       if (NULL == gattc_char) {
-               DBG("Failed to get the gatt char");
-               return BT_STATUS_FAIL;
-       }
+       /* service can have two char with same uuid */
+       for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
+               gattc_char = (hal_gattc_char_t*)l->data;
+               if (gattc_char == NULL)
+                       continue;
 
-       DBG("char path [%s]", gattc_char->chr_path);
-       _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
-       DBG("char uuid [%s]", char_uuid_str);
+               if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
+                       INFO("Found GATT char uuid");
+                       DBG("char path [%s]", gattc_char->chr_path);
+                       _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
+                       DBG("char uuid [%s]", char_uuid_str);
+
+                       /* find descriptor */
+                       gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
+                       if (gattc_desc) {
+                               DBG("desc path [%s]", gattc_desc->desc_path);
+                               _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
+                               DBG("desc uuid [%s]", desc_uuid_str);
+                               break;
+                       }
+               }
+       }
 
-       /* find descriptor */
-       gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
        if (NULL == gattc_desc) {
                DBG("Failed to get the gatt desc");
                return BT_STATUS_FAIL;
        }
 
-       DBG("desc path [%s]", gattc_desc->desc_path);
-       _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
-       DBG("desc uuid [%s]", desc_uuid_str);
-
        g_conn = _bt_hal_get_system_gconn();
        if (NULL == g_conn) {
                 ERR("_bt_gdbus_get_system_gconn returned NULL");
@@ -1843,11 +2071,6 @@ static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srv
        }
 
        resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
-       if (NULL == resp_data) {
-               ERR("failed to get the memory");
-               return BT_STATUS_FAIL;
-       }
-
        resp_data->conn_id = conn_id;
        memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
        memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
@@ -1924,7 +2147,7 @@ static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
        value = g_dbus_connection_call_finish(system_gconn, res, &error);
 
        if (error) {
-               ERR("write descriptor dbus failed Error:", error->message);
+               ERR("write descriptor dbus failed Error: [%s]", error->message);
 
                //send failed event
                result  = BT_STATUS_FAIL;
@@ -1962,8 +2185,9 @@ static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *sr
        char char_uuid_str[BT_HAL_UUID_STRING_LEN];
        char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
        char* desc_handle = NULL;
-       hal_gatt_property_e write_prop = HAL_GATT_PROPERTY_WRITE;
+       bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
        int ret = BT_STATUS_SUCCESS;
+       GSList *l;
 
        DBG("+");
 
@@ -1992,27 +2216,34 @@ static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *sr
        DBG("service uuid [%s]", svc_uuid_str);
 
        /* find characteristic */
-       gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid);
-       if (NULL == gattc_char) {
-               DBG("Failed to get the gatt char");
-               return BT_STATUS_FAIL;
-       }
+       /* service can have two char with same uuid */
+       for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
+               gattc_char = (hal_gattc_char_t*)l->data;
+               if (gattc_char == NULL)
+                       continue;
 
-       DBG("char path [%s]", gattc_char->chr_path);
-       _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
-       DBG("char uuid [%s]", char_uuid_str);
+               if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
+                       INFO("Found GATT char uuid");
+                       DBG("char path [%s]", gattc_char->chr_path);
+                       _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
+                       DBG("char uuid [%s]", char_uuid_str);
+
+                       /* find descriptor */
+                       gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
+                       if (gattc_desc) {
+                               DBG("desc path [%s]", gattc_desc->desc_path);
+                               _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
+                               DBG("desc uuid [%s]", desc_uuid_str);
+                               break;
+                       }
+               }
+       }
 
-       /* find descriptor */
-       gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
        if (NULL == gattc_desc) {
-               DBG("Failed to get the gatt char");
+               DBG("Failed to get the gatt desc");
                return BT_STATUS_FAIL;
        }
 
-       DBG("desc path [%s]", gattc_desc->desc_path);
-       _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
-       DBG("char uuid [%s]", desc_uuid_str);
-
        g_conn = _bt_hal_get_system_gconn();
        if (NULL == g_conn) {
                 ERR("_bt_gdbus_get_system_gconn returned NULL");
@@ -2020,11 +2251,6 @@ static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *sr
        }
 
        resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
-       if (NULL == resp_data) {
-               ERR("failed to get the memory");
-               return BT_STATUS_FAIL;
-       }
-
        resp_data->conn_id = conn_id;
        memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
        memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
@@ -2079,25 +2305,304 @@ bt_status_t execute_write(int conn_id, int execute)
        return BT_STATUS_UNSUPPORTED;
 }
 
+static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
+{
+       struct hal_ev_gatt_client_watch_notification ev;
+       hal_gatt_resp_data_t *resp_data = user_data;
+
+       DBG("sending the watch register notification event");
+       /* send the event */
+       memset(&ev, 0, sizeof(ev));
+       ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
+       ev.registered = 1;
+       ev.status = resp_data->result;
+
+       ev.is_primary = resp_data->srvc_id.is_primary;
+       ev.inst_id = resp_data->srvc_id.id.inst_id;
+
+       memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
+       memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
+
+       if (!event_cb)
+               ERR("GATT Callback not registered");
+       else
+               event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
+
+       g_free(user_data);
+
+       return FALSE;
+}
+
+static bt_status_t _hal_register_for_notification(int client_if,
+               bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
+               btgatt_gatt_id_t *char_id)
+{
+       int result = BT_STATUS_SUCCESS;
+       GError *error = NULL;
+       GDBusConnection *g_conn;
+       hal_gattc_client_info_t *gattc_client = NULL;
+       hal_gattc_server_info_t * conn_info = NULL;
+       hal_gattc_service_t *gattc_service = NULL;
+       hal_gattc_char_t *gattc_char = NULL;
+       char* char_handle = NULL;
+       char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
+       char char_uuid_str[BT_HAL_UUID_STRING_LEN];
+       hal_gatt_resp_data_t *resp_data;
+
+       DBG("+");
+
+       gattc_client = __bt_find_gatt_client_info(bd_addr);
+       if (gattc_client == NULL) {
+               ERR("failed to get the gatt client info");
+               return BT_STATUS_FAIL;
+       }
+
+       if (gattc_client->client_if != client_if) {
+               ERR("could not find the gatt client for client id[%d]", client_if);
+               return BT_STATUS_FAIL;
+       }
+
+        /* get the connection info */
+       conn_info = __bt_find_gatt_conn_info(bd_addr);
+       if (NULL == conn_info) {
+               ERR("Failed to get the conn_info");
+               return BT_STATUS_FAIL;
+       }
+
+       if (conn_info->inst_id != gattc_client->inst_id) {
+               ERR("could not fild the conn_info");
+               return BT_STATUS_FAIL;
+       }
+
+       /* find service */
+       gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
+       if (NULL == gattc_service) {
+               DBG("Failed to get the gatt service");
+               return BT_STATUS_FAIL;
+       }
+
+       DBG("service path [%s]", gattc_service->svc_path);
+       _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
+       DBG("service uuid [%s]", svc_uuid_str);
+
+
+       /* find characteristic */
+       gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
+       if (NULL == gattc_char) {
+               DBG("Failed to get the gatt char");
+               return BT_STATUS_FAIL;
+       }
+
+       DBG("char path [%s]", gattc_char->chr_path);
+       _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
+       DBG("char uuid [%s]", char_uuid_str);
+
+       char_handle = gattc_char->chr_path;
+
+       g_conn = _bt_hal_get_system_gconn();
+       if (g_conn == NULL) {
+               ERR("conn NULL");
+               return BT_STATUS_FAIL;
+       }
+
+       resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
+
+       DBG("#StartNotify");
+       g_dbus_connection_call_sync(g_conn,
+                       BT_HAL_BLUEZ_NAME,
+                       char_handle,
+                       BT_HAL_GATT_CHAR_INTERFACE,
+                       "StartNotify",
+                       NULL,
+                       NULL,
+                       G_DBUS_CALL_FLAGS_NONE,
+                       BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
+
+       if (error) {
+               g_dbus_error_strip_remote_error(error);
+               ERR("### Watch Failed: %s", error->message);
+               if (g_strrstr(error->message, "Already notifying"))
+                       result = BT_STATUS_SUCCESS;
+               else if (g_strrstr(error->message, "In Progress"))
+                       result = BT_STATUS_BUSY;
+               else if (g_strrstr(error->message, "Operation is not supported"))
+                       result = BT_STATUS_UNSUPPORTED;
+               /*failed because of either Insufficient Authorization or Write Not Permitted */
+               else if (g_strrstr(error->message, "Write not permitted") ||
+                               g_strrstr(error->message, "Operation Not Authorized"))
+                       result = BT_STATUS_AUTH_FAILURE;
+               /* failed because of either Insufficient Authentication,
+                  Insufficient Encryption Key Size, or Insufficient Encryption. */
+               else if (g_strrstr(error->message, "Not paired"))
+                       result = BT_STATUS_NOT_READY;
+               else
+                       result = BT_STATUS_FAIL;
+
+               g_clear_error(&error);
+       }
+
+       resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
+       resp_data->result = result;
+       memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+       memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
+
+       g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
+
+       DBG("-");
+
+       return BT_STATUS_SUCCESS;
+}
+
 /**
  * Register to receive notifications or indications for a given
  * characteristic
  */
-bt_status_t register_for_notification(int client_if,
+bt_status_t btif_register_for_notification(int client_if,
                const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
                btgatt_gatt_id_t *char_id)
 {
        CHECK_BTGATT_INIT();
-       return BT_STATUS_UNSUPPORTED;
+
+       return _hal_register_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
 }
 
+static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
+{
+       struct hal_ev_gatt_client_watch_notification ev;
+       hal_gatt_resp_data_t *resp_data = user_data;
+
+       DBG("sending the watch deregister notification event");
+       /* send the event */
+       memset(&ev, 0, sizeof(ev));
+       ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
+       ev.registered = 0;
+       ev.status = resp_data->result;
+
+       ev.is_primary = resp_data->srvc_id.is_primary;
+       ev.inst_id = resp_data->srvc_id.id.inst_id;
+
+       memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
+       memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
+
+       if (!event_cb)
+               ERR("GATT Callback not registered");
+       else
+               event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
+
+       g_free(user_data);
+
+       return FALSE;
+}
+
+static bt_status_t _hal_deregister_for_notification(int client_if,
+               bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
+               btgatt_gatt_id_t *char_id)
+{
+       int result = BT_STATUS_SUCCESS;
+       GError *error = NULL;
+       GDBusConnection *g_conn;
+       hal_gattc_client_info_t *gattc_client = NULL;
+       hal_gattc_server_info_t * conn_info = NULL;
+       hal_gattc_service_t *gattc_service = NULL;
+       hal_gattc_char_t *gattc_char = NULL;
+       char* char_handle = NULL;
+       char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
+       char char_uuid_str[BT_HAL_UUID_STRING_LEN];
+       hal_gatt_resp_data_t *resp_data;
+
+       DBG("+");
+
+       gattc_client = __bt_find_gatt_client_info(bd_addr);
+       if (gattc_client == NULL) {
+               ERR("failed to get the gatt client info");
+               return BT_STATUS_FAIL;
+       }
+
+       if (gattc_client->client_if != client_if) {
+               ERR("could not find the gatt client for client id[%d]", client_if);
+               return BT_STATUS_FAIL;
+       }
+
+        /* get the connection info */
+       conn_info = __bt_find_gatt_conn_info(bd_addr);
+       if (NULL == conn_info) {
+               ERR("Failed to get the conn_info");
+               return BT_STATUS_FAIL;
+       }
+
+       if (conn_info->inst_id != gattc_client->inst_id) {
+               ERR("could not fild the conn_info");
+               return BT_STATUS_FAIL;
+       }
+
+       /* find service */
+       gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
+       if (NULL == gattc_service) {
+               DBG("Failed to get the gatt service");
+               return BT_STATUS_FAIL;
+       }
+
+       DBG("service path [%s]", gattc_service->svc_path);
+       _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
+       DBG("service uuid [%s]", svc_uuid_str);
+
+
+       /* find characteristic */
+       gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
+       if (NULL == gattc_char) {
+               DBG("Failed to get the gatt char");
+               return BT_STATUS_FAIL;
+       }
+
+       DBG("char path [%s]", gattc_char->chr_path);
+       _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
+       DBG("char uuid [%s]", char_uuid_str);
+
+       char_handle = gattc_char->chr_path;
+
+       g_conn = _bt_hal_get_system_gconn();
+       if (g_conn == NULL) {
+               ERR("conn NULL");
+               return BT_STATUS_FAIL;
+       }
+
+       resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
+
+       DBG("#StartNotify");
+       g_dbus_connection_call_sync(g_conn,
+                       BT_HAL_BLUEZ_NAME,
+                       char_handle,
+                       BT_HAL_GATT_CHAR_INTERFACE,
+                       "StopNotify",
+                       NULL,
+                       NULL,
+                       G_DBUS_CALL_FLAGS_NONE,
+                       BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
+
+       if (error) {
+               ERR("### Watch Failed: %s", error->message);
+               g_clear_error(&error);
+               result = BT_STATUS_FAIL;
+       }
+
+       resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
+       resp_data->result = result;
+       memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+       memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
+
+       g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
+
+       DBG("-");
+
+       return BT_STATUS_SUCCESS;
+}
 /** Deregister a previous request for notifications/indications */
-bt_status_t deregister_for_notification(int client_if,
+bt_status_t btif_deregister_for_notification(int client_if,
                const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
                btgatt_gatt_id_t *char_id)
 {
        CHECK_BTGATT_INIT();
-       return BT_STATUS_UNSUPPORTED;
+       return _hal_deregister_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
 }
 
 /** Request RSSI for a given remote device */
@@ -2298,38 +2803,40 @@ bt_status_t batchscan_read_reports(int client_if, int scan_mode)
 }
 
 const btgatt_client_interface_t btgatt_client_interface = {
-       btif_gattc_register_client,
-       btif_gattc_unregister_client,
-       scan,
-       btif_gattc_client_connect,
-       btif_gattc_client_disconnect,
-       refresh,
-       btif_gattc_client_search_service,
-       get_included_service,
-       btif_gattc_get_characteristic,
-       btif_gattc_get_descriptor,
-       btif_read_characteristic,
-       btif_write_characteristic,
-       btif_read_descriptor,
-       btif_write_descriptor,
-       execute_write,
-       register_for_notification,
-       deregister_for_notification,
-       read_remote_rssi,
-       ota_fw_update,
-       get_device_type,
-       btif_gattc_conn_parameter_update,
-       test_command,
-       configure_mtu,
-       scan_filter_param_setup,
-       scan_filter_add_remove,
-       scan_filter_clear,
-       scan_filter_enable,
-       set_scan_parameters,
-       batchscan_cfg_storage,
-       batchscan_enb_batch_scan,
-       batchscan_dis_batch_scan,
-       batchscan_read_reports
+       .register_client = btif_gattc_register_client,
+       .unregister_client = btif_gattc_unregister_client,
+       .scan = scan,
+       .connect = btif_gattc_client_connect,
+       .disconnect = btif_gattc_client_disconnect,
+       .refresh = refresh,
+       .search_service = btif_gattc_client_search_service,
+       .get_included_service = get_included_service,
+       .get_characteristic = btif_gattc_get_characteristic,
+       .get_descriptor = btif_gattc_get_descriptor,
+       .read_characteristic = btif_read_characteristic,
+       .write_characteristic = btif_write_characteristic,
+       .acquire_write = btif_get_acquire_write_fd,
+       .acquire_notify = btif_get_acquire_notify_fd,
+       .read_descriptor = btif_read_descriptor,
+       .write_descriptor = btif_write_descriptor,
+       .execute_write = execute_write,
+       .register_for_notification = btif_register_for_notification,
+       .deregister_for_notification = btif_deregister_for_notification,
+       .read_remote_rssi = read_remote_rssi,
+       .ota_fw_update = ota_fw_update,
+       .get_device_type = get_device_type,
+       .conn_parameter_update = btif_gattc_conn_parameter_update,
+       .test_command = test_command,
+       .configure_mtu = configure_mtu,
+       .scan_filter_param_setup = scan_filter_param_setup,
+       .scan_filter_add_remove = scan_filter_add_remove,
+       .scan_filter_clear = scan_filter_clear,
+       .scan_filter_enable = scan_filter_enable,
+       .set_scan_parameters = set_scan_parameters,
+       .batchscan_cfg_storage = batchscan_cfg_storage,
+       .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
+       .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
+       .batchscan_read_reports = batchscan_read_reports
 };
 
 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(bt_bdaddr_t *serv_addr)
@@ -2463,11 +2970,6 @@ static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdadd
        }
 
        gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
-       if (gattc_data == NULL) {
-               ERR("Unable to allocate memory");
-               ret = BT_STATUS_NOMEM;
-               goto fail;
-       }
        memcpy(gattc_data->bd_addr.address, bd_addr->address,
                                        BT_HAL_ADDRESS_LENGTH_MAX);
 
@@ -2483,14 +2985,6 @@ static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdadd
                        (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
 
        return ret;
-
-fail:
-       if (device_proxy)
-               g_object_unref(device_proxy);
-
-       g_free(gattc_data);
-
-       return ret;
 }
 
 static bt_status_t _bt_hold_current_advertising()
@@ -2601,11 +3095,6 @@ static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
 
        /*add gatt server connection info*/
        gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
-       if (gatt_conn_info == NULL) {
-               ERR("Failed to allocate memory");
-               goto fail;
-       }
-
        memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
        gatt_conn_info->inst_id = gattc_data->inst_id;
        hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
@@ -2803,3 +3292,88 @@ static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
 
        event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
 }
+
+static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
+               hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
+               char *char_value, int len)
+{
+       struct hal_ev_gatt_client_notify_changed_value ev;
+       hal_gattc_client_info_t *gattc_client = NULL;
+
+       if (!event_cb) {
+               ERR("gatt client callback not registered");
+               return;
+       }
+
+       gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
+       if (NULL == gattc_client) {
+               ERR("failed to get the gatt client info");
+               return ;
+       }
+
+       //send event
+       DBG("sending gatt client connected status  event");
+       memset(&ev, 0, sizeof(ev));
+
+       ev.conn_id = gattc_client->conn_id;
+       ev.inst_id = conn_info->inst_id;
+       ev.is_primary = svc_info->is_primary;
+       memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
+       memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
+
+       memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
+
+       if (len > 0 && (char_value != NULL)) {
+               memcpy(ev.value, char_value, len);
+               ev.len = len;
+       }
+
+       event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
+}
+
+void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
+                                               char *char_value, int len)
+{
+       char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
+       hal_gattc_server_info_t *conn_info = NULL;
+       bt_bdaddr_t bd_addr;
+       GSList *l;
+       GSList *k;
+       hal_gattc_service_t *svc_info = NULL;
+       hal_gattc_char_t *char_info = NULL;
+
+       DBG("+");
+
+       _bt_hal_convert_device_path_to_address(char_handle, device_address);
+       device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
+       DBG("device address:[%s]", device_address);
+       DBG("char handle:[%s]", char_handle);
+
+       _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
+       conn_info =  __bt_find_gatt_conn_info(&bd_addr);
+
+       if (conn_info != NULL) {
+               //find service for notified char path
+               for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
+                       svc_info = (hal_gattc_service_t*)l->data;
+                       if (svc_info == NULL)
+                               continue;
+
+                       /* find characteristic object path */
+                       for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
+                               char_info = (hal_gattc_char_t *)k->data;
+                               if (char_info == NULL)
+                                       continue;
+
+                               if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
+                                       DBG("Found char handle[%s]", char_info->chr_path);
+
+                                       //send event
+                                       _bt_hal_send_value_changed_event(conn_info, svc_info,
+                                                       char_info, char_value, len);
+                                       return;
+                               }
+                       }
+               }
+       }
+}