BLE Gatt Client Socket write and notify implementation
[platform/core/connectivity/bluetooth-frwk.git] / bt-service-adaptation / services / gatt / bt-service-gatt.c
index 54bb798..4448648 100644 (file)
@@ -107,6 +107,15 @@ char uuid_list[NUM_UUID][BT_UUID_STRING_MAX] = {"0000b00b-0000-0000-f065-080080f
 
 static int gatt_default_client = -1;
 
+typedef struct {
+       gboolean is_registered;
+       bluetooth_device_address_t addr;
+       unsigned char svc_uuid[BLUETOOTH_UUID_HEX_MAX_LEN];
+       int svc_inst;
+       unsigned char char_uuid[BLUETOOTH_UUID_HEX_MAX_LEN];
+       int char_inst;
+} bt_gatt_notif_reg_info_t;
+
 struct gatt_out_conn_info_t {
        int client_id;                                   /* This value unique identifies a GATT Client instance */
        char *addr;                                      /* Remote GATT Server address */
@@ -244,6 +253,8 @@ static void __bt_handle_client_characteristic_write_data(event_gattc_write_data
 static void __bt_handle_client_descriptor_write_data(event_gattc_write_data *event_data);
 static int __bt_do_unregister_gatt_instance(int instance_id);
 static void __bt_hanlde_le_device_disconnection(event_dev_conn_status_t *event_data);
+static void __bt_handle_client_notification_registered(event_gattc_regdereg_notify_t *event_data,
+               gboolean is_registered);
 
 #endif
 
@@ -1018,6 +1029,29 @@ static void __bt_gatt_handle_pending_request_info(int result,
                        }
                        break;
                }
+               case BT_GATT_WATCH_CHARACTERISTIC: {
+                       bt_gatt_notif_reg_info_t *param = (bt_gatt_notif_reg_info_t*)data;
+                       bluetooth_gatt_client_char_prop_info_t *prop = (bluetooth_gatt_client_char_prop_info_t*)req_info->user_data;
+                       BT_INFO("Request Sender [%s]", req_info->sender);
+                       /* Match both address, service properties &char properties to determine same request */
+                       if (!memcmp(param->addr.addr,
+                                       prop->device_address.addr,
+                                       sizeof(bluetooth_device_address_t)) &&
+                                       !memcmp(param->svc_uuid, prop->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) &&
+                                       param->svc_inst == prop->svc.instance_id &&
+                                       !memcmp(param->char_uuid, prop->characteristic.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) &&
+                                       param->char_inst == prop->characteristic.instance_id) {
+                               BT_INFO("Characteristic Watch Successful: Is registered [%d]",
+                                               param->is_registered);
+                               out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
+                               g_array_append_vals(out_param, param, sizeof(bt_gatt_notif_reg_info_t));
+                               _bt_service_method_return(req_info->context, out_param, result);
+                               g_free(req_info->user_data);
+                               _bt_free_info_from_invocation_list(req_info);
+                               g_array_free(out_param, TRUE);
+                       }
+                       break;
+               }
                case BT_GATT_READ_CHARACTERISTIC:
                case BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE: {
                         bluetooth_gatt_client_char_prop_info_t *param = (bluetooth_gatt_client_char_prop_info_t*)data;
@@ -1094,7 +1128,6 @@ static void __bt_handle_server_instance_registered(event_gatts_register_t *data)
                }
        }
        g_free(uuid_string);
-       g_free(data);
 }
 
 static void __bt_handle_gatt_server_service_added(event_gatts_srvc_prm_t *event)
@@ -1142,7 +1175,6 @@ static void __bt_handle_gatt_server_service_added(event_gatts_srvc_prm_t *event)
                }
        }
 
-       g_free(event);
        g_free(uuid_str);
 }
 
@@ -1184,7 +1216,6 @@ static void __bt_handle_gatt_server_characteristic_added(event_gatts_srvc_charct
        _bt_uuid_to_string(&(event->charctr_uuid), uuid_str);
        BT_INFO("GATT Added Characteristic:  UUID: [%s]", uuid_str);
 
-       g_free(event);
        g_free(uuid_str);
 }
 
@@ -1224,7 +1255,6 @@ static void __bt_handle_gatt_server_descriptor_added(event_gatts_srvc_descr_t* e
        _bt_uuid_to_string(&(event->descrptr_uuid), uuid_str);
        BT_INFO("GATT Added Descriptor:  UUID: [%s]", uuid_str);
 
-       g_free(event);
        g_free(uuid_str);
 }
 
@@ -1256,8 +1286,6 @@ static void __bt_handle_gatt_server_service_started(event_gatts_srvc_t *event)
                        break;
                }
        }
-
-       g_free(event);
 }
 
 static void __bt_handle_gatt_server_service_stopped(event_gatts_srvc_t *event)
@@ -1287,8 +1315,6 @@ static void __bt_handle_gatt_server_service_stopped(event_gatts_srvc_t *event)
                        break;
                }
        }
-
-       g_free(event);
 }
 
 static void __bt_handle_gatt_server_service_deleted(event_gatts_srvc_t *event)
@@ -1318,8 +1344,6 @@ static void __bt_handle_gatt_server_service_deleted(event_gatts_srvc_t *event)
                        break;
                }
        }
-
-       g_free(event);
 }
 
 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info(char *address)
@@ -1391,6 +1415,24 @@ static struct gatt_out_conn_info_t* __bt_find_gatt_outgoing_conn_info(char *addr
        }
        return NULL;
 }
+
+static struct gatt_server_info_t *__bt_find_remote_gatt_server_info_from_client_if(int client_if)
+{
+       GSList *l;
+       struct gatt_server_info_t *info = NULL;
+
+       for (l = gatt_server_info_list; l != NULL; l = g_slist_next(l)) {
+               info = (struct gatt_server_info_t*)l->data;
+               if (info == NULL)
+                       continue;
+
+               if (info->client_id == client_if) {
+                       BT_INFO("Remote GATT server found addr[%s]", info->addr);
+                       return info;
+               }
+       }
+       return NULL;
+}
 #endif
 
 
@@ -1402,6 +1444,7 @@ static void __bt_handle_gatt_server_connection_state(event_gatts_conn_t *event)
        int result = BLUETOOTH_ERROR_NONE;
        struct gatt_client_info_t *conn_info = NULL;
        bluetooth_device_address_t dev_addr;
+       GVariant *param = NULL;
 
        char *address = g_malloc0(BT_ADDRESS_STRING_SIZE);
 
@@ -1423,14 +1466,14 @@ static void __bt_handle_gatt_server_connection_state(event_gatts_conn_t *event)
 
        if (!conn_info) {
                BT_INFO("Conn Info absent: But no need to Send Local GATT Server Connected event to apps");
-#if 0
+
                param = g_variant_new("(is)", result, address);
 
                /* Send event to application */
                _bt_send_event(BT_DEVICE_EVENT,
                                BLUETOOTH_EVENT_GATT_SERVER_CONNECTED, /* Local device is GATT server */
                                param);
-#endif
+
                /* Save Connection info */
                conn_info = g_new0(struct gatt_client_info_t, 1);
                conn_info->addr = g_strdup(address);
@@ -1450,8 +1493,8 @@ static void __bt_handle_gatt_server_disconnection_state(event_gatts_conn_t *even
        int result = BLUETOOTH_ERROR_NONE;
        struct gatt_client_info_t *conn_info = NULL;
        bluetooth_device_address_t dev_addr;
-
-       char *address = g_malloc0(BT_ADDRESS_STRING_SIZE);
+       GVariant *param = NULL;
+       char address[BT_ADDRESS_STRING_SIZE];
 
        memcpy(dev_addr.addr, event->address.addr, 6);
 
@@ -1481,21 +1524,19 @@ static void __bt_handle_gatt_server_disconnection_state(event_gatts_conn_t *even
        conn_info = __bt_find_remote_gatt_client_info(address);
        if (conn_info) {
                BT_INFO("No need to Send Local GATT Server Disconnected event to apps, just remove remote client info");
-#if 0
+
                param = g_variant_new("(is)", result, address);
                /* Send event to application */
                _bt_send_event(BT_DEVICE_EVENT,
                                BLUETOOTH_EVENT_GATT_SERVER_DISCONNECTED, /* Local device is GATT server */
                                param);
-#endif
+
                /* Remove info from List */
                gatt_client_info_list = g_slist_remove(gatt_client_info_list, conn_info);
                BT_INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
                g_free(conn_info->addr);
                g_free(conn_info);
        }
-
-       g_free(address);
 }
 #else
 
@@ -1612,6 +1653,75 @@ static void __bt_handle_gatt_server_disconnection_state(event_gatts_conn_t *even
 }
 #endif
 
+
+static void __bt_handle_gatt_server_acquire_write_requested(event_gatts_srvc_acquire_attr_t *event)
+{
+       GVariant *param = NULL;
+       int result = BLUETOOTH_ERROR_NONE;
+       struct gatt_server_req_info *req_info = NULL;
+       bluetooth_device_address_t dev_addr;
+       char  adress[BT_ADDRESS_STRING_SIZE] = {'/0',};
+
+       BT_INFO("GATT Server ACQUIRE  Write Req Connection ID: [%d]", event->attr_trans.conn_id);
+       BT_INFO("GATT Server  ACQUIRE Write Req Transaction ID:[%d]", event->attr_trans.trans_id);
+       BT_INFO("GATT Server ACQUIRE Write Req Attribute Handle: [%d]", event->attr_trans.attr_handle);
+
+       //adress = g_malloc0(BT_ADDRESS_STRING_SIZE);
+       memcpy(dev_addr.addr, event->address.addr, 6);
+
+       req_info = g_new0(struct gatt_server_req_info, 1);
+       req_info->request_id = event->attr_trans.trans_id;
+       req_info->attribute_handle = event->attr_trans.attr_handle;
+       req_info->connection_id = event->attr_trans.conn_id;
+       req_info->request_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
+       gatt_server_requests = g_slist_append(gatt_server_requests, req_info);
+
+       _bt_convert_addr_type_to_string(adress,
+                       (unsigned char *)dev_addr.addr);
+
+       param = g_variant_new("(iiiiiis)", result,
+                       event->attr_trans.conn_id,
+                       event->attr_trans.trans_id,
+                       event->attr_trans.attr_handle,
+                       event->mtu, event->attr_trans.offset, adress);
+       BT_INFO("GATT Server ACQUIRE Write Req Attribute remote adress : [%s]", adress);
+
+       _bt_send_event(BT_GATT_SERVER_EVENT,
+                       BLUETOOTH_EVENT_GATT_SERVER_ACQUIRE_WRITE,
+                       param);
+
+}
+
+static void __bt_handle_gatt_server_acquire_notify_requested(event_gatts_srvc_acquire_attr_t *event)
+{
+       GVariant *param = NULL;
+       int result = BLUETOOTH_ERROR_NONE;
+       struct gatt_server_req_info *req_info = NULL;
+
+       BT_INFO("GATT Server ACQUIRE  Notify Req Connection ID: [%d]", event->attr_trans.conn_id);
+       BT_INFO("GATT Server ACQUIRE Notify  Req Transaction ID:[%d]", event->attr_trans.trans_id);
+       BT_INFO("GATT Server ACQUIRE Notify Req Attribute Handle: [%d]", event->attr_trans.attr_handle);
+
+       req_info = g_new0(struct gatt_server_req_info, 1);
+       req_info->request_id = event->attr_trans.trans_id;
+       req_info->attribute_handle = event->attr_trans.attr_handle;
+       req_info->connection_id = event->attr_trans.conn_id;
+       req_info->request_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
+       gatt_server_requests = g_slist_append(gatt_server_requests, req_info);
+
+       param = g_variant_new("(iiiiii)", result,
+                       event->attr_trans.conn_id,
+                       event->attr_trans.trans_id,
+                       event->attr_trans.attr_handle,
+                       event->mtu, event->attr_trans.offset);
+
+       BT_INFO("GATT Server ACQUIRE Notify  Req Attribute : ");
+
+        _bt_send_event(BT_GATT_SERVER_EVENT,
+                                BLUETOOTH_EVENT_GATT_SERVER_ACQUIRE_NOTIFY,
+                                param);
+}
+
 static void __bt_handle_gatt_server_write_requested(event_gatts_srvc_write_attr_t *event)
 {
        char *address;
@@ -1638,7 +1748,6 @@ static void __bt_handle_gatt_server_write_requested(event_gatts_srvc_write_attr_
 
        if (event->length <= 0) {
                BT_INFO("GATT Server write requested, but length of attr value is 0");
-               g_free(event);
                return;
        }
 
@@ -1689,7 +1798,6 @@ static void __bt_handle_gatt_server_write_requested(event_gatts_srvc_write_attr_
                         BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
                        param);
 
-       g_free(event);
        g_free(write_val);
 }
 
@@ -1740,8 +1848,6 @@ static void __bt_handle_gatt_server_read_requested(event_gatts_srvc_read_attr_t
        _bt_send_event(BT_GATT_SERVER_EVENT,
                        BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
                        param);
-
-       g_free(event);
 }
 
 static void __bt_handle_gatt_server_indicate_confirmed(event_gatts_ind_cnfrm_t *event)
@@ -1789,7 +1895,6 @@ static void __bt_handle_gatt_server_indicate_confirmed(event_gatts_ind_cnfrm_t *
                        param);
 
        BT_INFO("Received Indication confirm for client number [%d]", recvd);
-       g_free(event);
        g_free(address);
 }
 
@@ -1826,7 +1931,6 @@ static void __bt_handle_gatt_server_notification_changed(event_gatts_notif_t *ev
                        BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
                        param);
 
-       g_free(event);
        g_free(address);
 }
 
@@ -1841,7 +1945,6 @@ static void __bt_handle_gatt_mtu_changed_event(event_gatts_mtu_changed_t *event)
        conn_info = __bt_find_remote_gatt_client_info_from_conn_id(event->conn_id);
        if (conn_info == NULL) {
                BT_ERR("Cant find connection Information");
-               g_free(event);
                return;
        }
        BT_INFO("Got connection Info GATT client [%s] MTU Size [%d]",
@@ -1857,7 +1960,6 @@ static void __bt_handle_gatt_mtu_changed_event(event_gatts_mtu_changed_t *event)
        _bt_send_event(BT_GATT_SERVER_EVENT,
                        BLUETOOTH_EVENT_GATT_ATT_MTU_CHANGED,
                        param);
-       g_free(event);
 }
 
 static void __bt_gatt_event_handler(int event_type, gpointer event_data)
@@ -1866,87 +1968,83 @@ static void __bt_gatt_event_handler(int event_type, gpointer event_data)
        switch (event_type) {
                case OAL_EVENT_BLE_SERVER_INSTANCE_INITIALISED: {
                BT_INFO("OAL Event: Server Instance Registered");
-               event_gatts_register_t* event = g_memdup(event_data, sizeof(event_gatts_register_t));
                /* GATT Server Registered event is handled in MAIN thread context */
-               __bt_handle_server_instance_registered(event);
+               __bt_handle_server_instance_registered((event_gatts_register_t *)event_data);
                break;
                                                                }
        case OAL_EVENT_GATTS_SERVICE_ADDED: {
                BT_INFO("OAL Event: GATT Service added");
-               event_gatts_srvc_prm_t *service_parm = g_memdup(event_data, sizeof(event_gatts_srvc_prm_t));
-               __bt_handle_gatt_server_service_added(service_parm);
+               __bt_handle_gatt_server_service_added((event_gatts_srvc_prm_t *)event_data);
                break;
        }
        case OAL_EVENT_GATTS_CHARACTERISTIC_ADDED: {
                BT_INFO("OAL Event: GATT characteristic added");
-               event_gatts_srvc_charctr_t *char_parm = g_memdup(event_data, sizeof(event_gatts_srvc_charctr_t));
-               __bt_handle_gatt_server_characteristic_added(char_parm);
+               __bt_handle_gatt_server_characteristic_added((event_gatts_srvc_charctr_t *)event_data);
                break;
        }
        case OAL_EVENT_GATTS_DESCRIPTOR_ADDED: {
                BT_INFO("OAL Event: GATT descriptor added");
-               event_gatts_srvc_descr_t *desc_parm = g_memdup(event_data, sizeof(event_gatts_srvc_descr_t));
-               __bt_handle_gatt_server_descriptor_added(desc_parm);
+               __bt_handle_gatt_server_descriptor_added((event_gatts_srvc_descr_t *)event_data);
                break;
        }
        case OAL_EVENT_GATTS_SERVICE_STARTED: {
                BT_INFO("OAL Event: GATT Service started");
-               event_gatts_srvc_t *svc_started = g_memdup(event_data, sizeof(event_gatts_srvc_t));
-               __bt_handle_gatt_server_service_started(svc_started);
+               __bt_handle_gatt_server_service_started((event_gatts_srvc_t *)event_data);
                break;
        }
        case OAL_EVENT_GATTS_SERVICE_STOPED: {
                BT_INFO("OAL Event: GATT Service stopped");
-               event_gatts_srvc_t *svc_stopped = g_memdup(event_data, sizeof(event_gatts_srvc_t));
-               __bt_handle_gatt_server_service_stopped(svc_stopped);
+               __bt_handle_gatt_server_service_stopped((event_gatts_srvc_t *)event_data);
                break;
        }
        case OAL_EVENT_GATTS_SERVICE_DELETED: {
                BT_INFO("OAL Event: GATT Service deleted");
-               event_gatts_srvc_t *svc_deleted = g_memdup(event_data, sizeof(event_gatts_srvc_t));
-               __bt_handle_gatt_server_service_deleted(svc_deleted);
+               __bt_handle_gatt_server_service_deleted((event_gatts_srvc_t *) event_data);
                break;
        }
        case OAL_EVENT_GATTS_CONNECTION_COMPLETED: {
                BT_INFO("OAL Event: GATT Server Connected");
-               event_gatts_conn_t* event = g_memdup(event_data, sizeof(event_gatts_conn_t));
-               __bt_handle_gatt_server_connection_state(event);
+               __bt_handle_gatt_server_connection_state((event_gatts_conn_t *)event_data);
                break;
        }
        case OAL_EVENT_GATTS_DISCONNECTION_COMPLETED: {
                BT_INFO("OAL Event: GATT Server Disconnected");
-               event_gatts_conn_t* event = g_memdup(event_data, sizeof(event_gatts_conn_t));
-               __bt_handle_gatt_server_disconnection_state(event);
+               __bt_handle_gatt_server_disconnection_state((event_gatts_conn_t *)event_data);
                break;
        }
        case OAL_EVENT_GATTS_REQUEST_READ: {
                BT_INFO("OAL Event: GATT Server Read Request");
-               event_gatts_srvc_read_attr_t *read_req = g_memdup(event_data, sizeof(event_gatts_srvc_read_attr_t));
-               __bt_handle_gatt_server_read_requested(read_req);
+               __bt_handle_gatt_server_read_requested((event_gatts_srvc_read_attr_t *)event_data);
                break;
        }
        case OAL_EVENT_GATTS_REQUEST_WRITE: {
                BT_INFO("OAL Event: GATT Server Write Request");
-               event_gatts_srvc_write_attr_t *write_req = g_memdup(event_data, sizeof(event_gatts_srvc_write_attr_t));
-               __bt_handle_gatt_server_write_requested(write_req);
+               __bt_handle_gatt_server_write_requested((event_gatts_srvc_write_attr_t *)event_data);
+               break;
+       }
+       case OAL_EVENT_GATTS_REQUEST_ACQUIRE_WRITE: {
+               BT_INFO("OAL Event: GATT Server Acquire  Write Request");
+               __bt_handle_gatt_server_acquire_write_requested((event_gatts_srvc_acquire_attr_t*)event_data);
+               break;
+       }
+       case OAL_EVENT_GATTS_REQUEST_ACQUIRE_NOTIFY: {
+               BT_INFO("OAL Event: GATT ServerAcquire Notify  Request");
+               __bt_handle_gatt_server_acquire_notify_requested((event_gatts_srvc_acquire_attr_t*)event_data);
                break;
        }
        case OAL_EVENT_GATTS_IND_CONFIRM: {
                BT_INFO("OAL Event: GATT Server Indication confirmed");
-               event_gatts_ind_cnfrm_t *parm = g_memdup(event_data, sizeof(event_gatts_ind_cnfrm_t));
-               __bt_handle_gatt_server_indicate_confirmed(parm);
+               __bt_handle_gatt_server_indicate_confirmed((event_gatts_ind_cnfrm_t *)event_data);
                break;
        }
        case OAL_EVENT_GATTS_NOTIFICATION: { /* Tizen Platform Specific */
                BT_INFO("OAL Event: GATT Server DisConnected");
-               event_gatts_notif_t* notif = g_memdup(event_data, sizeof(event_gatts_notif_t));
-               __bt_handle_gatt_server_notification_changed(notif);
+               __bt_handle_gatt_server_notification_changed((event_gatts_notif_t *)event_data);
                break;
        }
        case OAL_EVENT_GATTS_MTU_CHANGED: {
                BT_INFO("OAL Event: GATT Server MTU changed event callback");
-               event_gatts_mtu_changed_t *mtu_changed = g_memdup(event_data, sizeof(event_gatts_mtu_changed_t));
-               __bt_handle_gatt_mtu_changed_event(mtu_changed);
+               __bt_handle_gatt_mtu_changed_event((event_gatts_mtu_changed_t *)event_data);
                break;
        }
 #ifdef TIZEN_GATT_CLIENT
@@ -2008,6 +2106,17 @@ static void __bt_gatt_event_handler(int event_type, gpointer event_data)
        case OAL_EVENT_DEVICE_LE_DISCONNECTED: {
                BT_INFO("OAL Event: LE device disconnected");
                __bt_hanlde_le_device_disconnection((event_dev_conn_status_t *)event_data);
+               break;
+       }
+       case OAL_EVENT_GATTC_NOTIFICATION_REGISTERED: {
+               BT_INFO("OAL Event: GATT Client Notification Registered");
+               __bt_handle_client_notification_registered((event_gattc_regdereg_notify_t *) event_data, TRUE);
+               break;
+       }
+       case OAL_EVENT_GATTC_NOTIFICATION_DEREGISTERED: {
+               BT_INFO("OAL Event: GATT Client Notification Registered");
+               __bt_handle_client_notification_registered((event_gattc_regdereg_notify_t *) event_data, FALSE);
+               break;
        }
 #endif
        default:
@@ -2207,6 +2316,43 @@ int _bt_gatt_server_send_response(char *sender, bluetooth_gatt_att_data_t *data,
        return BLUETOOTH_ERROR_NONE;
 }
 
+int _bt_gatt_server_acquire_send_response(char *sender, bluetooth_gatt_server_acquire_response_params_t *param ,       void *fd_list)
+{
+       BT_CHECK_PARAMETER(sender, return);
+       BT_CHECK_PARAMETER(param, return);
+       struct gatt_server_req_info *req_info = NULL;
+       int ret = OAL_STATUS_SUCCESS;
+
+
+       BT_INFO("GATT acquire Server Response: Req Type [%d] req_id [%d] fd  [%d] mtu[%d]",
+                       param->req_type, param->request_id,
+                        param->fd,
+                       param->mtu);
+
+       /* Search for matching Request in List */
+       req_info = __bt_gatt_server_find_request_info(param->request_id, param->req_type);
+       if (!req_info) {
+               BT_ERR("GATT acquire Server Req Info not found for current response..return Error");
+               return BLUETOOTH_ERROR_NOT_IN_OPERATION;
+       }
+
+       ret = gatt_send_response_acquire(req_info->connection_id, param->request_id, 0, param->fd, param->mtu, fd_list);
+
+       if (ret != OAL_STATUS_SUCCESS) {
+               BT_ERR("ret: %d", ret);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       BT_INFO("GATT acquire Server Response successfully sent");
+       /* Remove GATT server request from list */
+       gatt_server_requests = g_slist_remove(gatt_server_requests, req_info);
+       g_free(req_info->addr);
+
+       return BLUETOOTH_ERROR_NONE;
+}
+
+
+
 int _bt_gatt_server_send_indication(char *sender, bluetooth_device_address_t *dev_addr,
                bluetooth_gatt_att_data_t *data,
                bluetooth_gatt_server_indication_params_t *param)
@@ -2327,17 +2473,6 @@ int _bt_get_att_mtu(bluetooth_device_address_t *address,
 }
 
 #ifdef TIZEN_GATT_CLIENT
-static void __bt_convert_byte_ordering(char *data, int data_len,
-               char *converted_data)
-{
-       int i, j;
-       char temp[BLUETOOTH_UUID_HEX_MAX_LEN];
-
-       memcpy(&temp, data, data_len);
-       for (i = 0, j = data_len - 1; i < data_len; i++, j--)
-               converted_data[i] = temp[j];
-}
-
 /* GATT Client utility static functions */
 static bt_gatt_service_info_list_t * __bt_get_service_info_list(int conn_id)
 {
@@ -2639,14 +2774,17 @@ static void __bt_build_descriptor_browse_info(int conn_id,
        memcpy(&info->char_uuid, char_info->uuid, BLUETOOTH_UUID_HEX_MAX_LEN);
        info->char_inst_id = char_info->inst_id;
 
+       /* Fill property of the parent characteristic of this descriptor */
+       info->char_props_map = char_info->props;
+
+       info->count = g_slist_length(char_info->descs);
+       BT_INFO("Total count of Descriptors [%d]", info->count);
+
        if (!char_info->descs) {
                BT_ERR("No Descriptors browsed for address [%s]", conn_info->addr);
                return;
        }
 
-       info->count = g_slist_length(char_info->descs);
-       BT_INFO("Total count of Descriptors [%d]", info->count);
-
        for (l = char_info->descs; l != NULL; l = g_slist_next(l)) {
                desc_info = (bt_gatt_descriptor_info_t*)l->data;
                if (desc_info == NULL)
@@ -2662,8 +2800,6 @@ static void __bt_build_descriptor_browse_info(int conn_id,
                /* Fill instance ID of Descriptor */
                info->inst_id[count] = desc_info->inst_id;
 
-               /* Fill property of the parent characteristic of this descriptor */
-               info->char_props_map = char_info->props;
 
                /* Increment count of Descriptor browsed */
                count++;
@@ -2933,6 +3069,7 @@ static void __bt_handle_client_disconnected(event_gattc_conn_t *event_data)
                        __bt_gatt_handle_pending_request_info(result, BT_CONNECT_LE,
                                        address, BT_ADDRESS_STRING_SIZE);
                        BT_ERR("Failed to connect Local GATT Remote addr[%s]", address);
+                       g_free(address);
                        return;
                }
        } else {
@@ -3155,7 +3292,8 @@ static void __bt_handle_client_characteristic_search_result(
                        svc_info->chars = g_slist_append(svc_info->chars, char_info);
                } else {
                        /* If found, then return */
-                       BT_INFO("Characteristic browsed is already presesnt");
+                       BT_INFO("update char property as Characteristic browsed is already present");
+                       char_info->props |= event_data->char_prop;
                }
        } else {
                /* If Not success: Means Charc browse is completed  */
@@ -3285,6 +3423,7 @@ Note: Even in case of failure, address, handles and result code should be return
        if (event_data->uuid_status.conn_status.status != OAL_STATUS_SUCCESS)
                result = BLUETOOTH_ERROR_INTERNAL;
        else {
+               BT_ERR("read data len is [%d]", event_data->data_len);
                if (event_data->data_len > 0) {
                        /* DEBUG */
                        for (i = 0; i < event_data->data_len; i++)
@@ -3298,42 +3437,49 @@ Note: Even in case of failure, address, handles and result code should be return
                                        read_val,
                                        event_data->data_len,
                                        TRUE, NULL, NULL);
-                       /* SVC uuid */
-                       svc_uuid = g_memdup(&event_data->uuid_status.srvc_id.id.uuid.uuid[0], uuid_len);
-
-                       data_svc_uuid = g_variant_new_from_data(
-                                       G_VARIANT_TYPE_BYTESTRING,
-                                       svc_uuid,
-                                       16,
-                                       TRUE, NULL, NULL);
-
-                       /* Char uuid */
-                       char_uuid = g_memdup(&event_data->uuid_status.char_id.uuid.uuid[0], uuid_len);
-
-                       data_char_uuid = g_variant_new_from_data(
-                                       G_VARIANT_TYPE_BYTESTRING,
-                                       char_uuid,
-                                       16,
-                                       TRUE, NULL, NULL);
-                       param = g_variant_new("(isn@ayin@ayin@ay)", result,
-                                       conn_info->addr,
-                                       16,
-                                       data_svc_uuid,
-                                       event_data->uuid_status.srvc_id.id.inst_id,
-                                       16,
-                                       data_char_uuid,
-                                       event_data->uuid_status.char_id.inst_id,
-                                       event_data->data_len,
-                                       data);
-
-                       /* Send Event */
-                       _bt_send_event(BT_GATT_CLIENT_EVENT,
-                                       BLUETOOTH_EVENT_GATT_READ_CHAR,
-                                       param);
                } else {
                        BT_ERR("Characteristic Read success, but no data!!!");
-                       result = BLUETOOTH_ERROR_INTERNAL;
+
+                       data = g_variant_new_from_data(
+                                       G_VARIANT_TYPE_BYTESTRING,
+                                       NULL,
+                                       0,
+                                       FALSE, NULL, NULL);
                }
+
+               /* SVC uuid */
+               svc_uuid = g_memdup(&event_data->uuid_status.srvc_id.id.uuid.uuid[0], uuid_len);
+
+               data_svc_uuid = g_variant_new_from_data(
+                               G_VARIANT_TYPE_BYTESTRING,
+                               svc_uuid,
+                               16,
+                               TRUE, NULL, NULL);
+
+               /* Char uuid */
+               char_uuid = g_memdup(&event_data->uuid_status.char_id.uuid.uuid[0], uuid_len);
+
+               data_char_uuid = g_variant_new_from_data(
+                               G_VARIANT_TYPE_BYTESTRING,
+                               char_uuid,
+                               16,
+                               TRUE, NULL, NULL);
+
+               param = g_variant_new("(isn@ayin@ayin@ay)", result,
+                               conn_info->addr,
+                               16,
+                               data_svc_uuid,
+                               event_data->uuid_status.srvc_id.id.inst_id,
+                               16,
+                               data_char_uuid,
+                               event_data->uuid_status.char_id.inst_id,
+                               event_data->data_len,
+                               data);
+
+               /* Send Event */
+               _bt_send_event(BT_GATT_CLIENT_EVENT,
+                               BLUETOOTH_EVENT_GATT_READ_CHAR,
+                               param);
        }
        /* Send DBUS return */
        __bt_gatt_handle_pending_request_info(result,
@@ -3402,6 +3548,7 @@ static void __bt_handle_client_descriptor_read_data(
        if (event_data->uuid_status.conn_status.status != OAL_STATUS_SUCCESS)
                result = BLUETOOTH_ERROR_INTERNAL;
        else {
+               BT_INFO("desc data len:", event_data->data_len);
                if (event_data->data_len > 0) {
                        /* DEBUG */
                        for (i = 0; i < event_data->data_len; i++)
@@ -3415,55 +3562,60 @@ static void __bt_handle_client_descriptor_read_data(
                                        read_val,
                                        event_data->data_len,
                                        TRUE, NULL, NULL);
-                       /* SVC uuid */
-                       svc_uuid = g_memdup(&event_data->uuid_status.srvc_id.id.uuid.uuid[0], uuid_len);
-
-                       data_svc_uuid = g_variant_new_from_data(
-                                       G_VARIANT_TYPE_BYTESTRING,
-                                       svc_uuid,
-                                       16,
-                                       TRUE, NULL, NULL);
-
-                       /* Char uuid */
-                       char_uuid = g_memdup(&event_data->uuid_status.char_id.uuid.uuid[0], uuid_len);
-
-                       data_char_uuid = g_variant_new_from_data(
-                                       G_VARIANT_TYPE_BYTESTRING,
-                                       char_uuid,
-                                       16,
-                                       TRUE, NULL, NULL);
-
-                       /* Desc uuid */
-                       desc_uuid = g_memdup(&event_data->uuid_status.descr_id.uuid.uuid[0], uuid_len);
+               } else {
+                       BT_INFO("Descriptor Read success, but no data!!!");
 
-                       data_desc_uuid = g_variant_new_from_data(
+                       data = g_variant_new_from_data(
                                        G_VARIANT_TYPE_BYTESTRING,
-                                       desc_uuid,
-                                       16,
-                                       TRUE, NULL, NULL);
-
-                       param = g_variant_new("(isn@ayin@ayin@ayin@ay)", result,
-                                       conn_info->addr,
-                                       uuid_len,
-                                       data_svc_uuid,
-                                       event_data->uuid_status.srvc_id.id.inst_id,
-                                       16,
-                                       data_char_uuid,
-                                       event_data->uuid_status.char_id.inst_id,
-                                       16,
-                                       data_desc_uuid,
-                                       event_data->uuid_status.descr_id.inst_id,
-                                       event_data->data_len,
-                                       data);
-
-                       /* Send Event */
-                       _bt_send_event(BT_GATT_CLIENT_EVENT,
+                                       NULL,
+                                       0,
+                                       FALSE, NULL, NULL);
+               }
+               /* SVC uuid */
+               svc_uuid = g_memdup(&event_data->uuid_status.srvc_id.id.uuid.uuid[0], uuid_len);
+
+               data_svc_uuid = g_variant_new_from_data(
+                               G_VARIANT_TYPE_BYTESTRING,
+                               svc_uuid,
+                               16,
+                               TRUE, NULL, NULL);
+
+               /* Char uuid */
+               char_uuid = g_memdup(&event_data->uuid_status.char_id.uuid.uuid[0], uuid_len);
+
+               data_char_uuid = g_variant_new_from_data(
+                               G_VARIANT_TYPE_BYTESTRING,
+                               char_uuid,
+                               16,
+                               TRUE, NULL, NULL);
+
+               /* Desc uuid */
+               desc_uuid = g_memdup(&event_data->uuid_status.descr_id.uuid.uuid[0], uuid_len);
+
+               data_desc_uuid = g_variant_new_from_data(
+                               G_VARIANT_TYPE_BYTESTRING,
+                               desc_uuid,
+                               16,
+                               TRUE, NULL, NULL);
+
+               param = g_variant_new("(isn@ayin@ayin@ayin@ay)", result,
+                               conn_info->addr,
+                               uuid_len,
+                               data_svc_uuid,
+                               event_data->uuid_status.srvc_id.id.inst_id,
+                               16,
+                               data_char_uuid,
+                               event_data->uuid_status.char_id.inst_id,
+                               16,
+                               data_desc_uuid,
+                               event_data->uuid_status.descr_id.inst_id,
+                               event_data->data_len,
+                               data);
+
+               /* Send Event */
+               _bt_send_event(BT_GATT_CLIENT_EVENT,
                                        BLUETOOTH_EVENT_GATT_READ_DESC,
                                        param);
-               } else {
-                       BT_ERR("Descriptor Read success, but no data!!!");
-                       result = BLUETOOTH_ERROR_INTERNAL;
-               }
        }
        BT_INFO("Send DBUS rpely for GATT Read Descriptor");
        /* Send DBUS return */
@@ -3699,8 +3851,60 @@ static void __bt_hanlde_le_device_disconnection(event_dev_conn_status_t *event_d
 
        __bt_gatt_handle_pending_request_info(result, BT_CONNECT_LE, address,
                                                 BT_ADDRESS_STRING_SIZE);
+       g_free(address);
 }
 
+static void __bt_handle_client_notification_registered(
+               event_gattc_regdereg_notify_t *event_data,
+               gboolean is_registered)
+{
+       int result = BLUETOOTH_ERROR_NONE;
+       struct gatt_server_info_t *conn_info = NULL;
+       bt_gatt_notif_reg_info_t notif_info;
+       BT_INFO("+");
+
+       memset(&notif_info, 0x00, sizeof(bt_gatt_notif_reg_info_t));
+
+       BT_INFO("Client Interface [%d] status [%d]",
+                       event_data->client_if,
+                       event_data->status);
+
+       /* Extract Address from conn_id of event data */
+       conn_info = __bt_find_remote_gatt_server_info_from_client_if(
+                       event_data->client_if);
+
+       if (!conn_info) {
+               BT_INFO("Connection Info is not present, return");
+               return;
+       }
+       BT_INFO("Notification Registered for addr [%s]",
+                       conn_info->addr);
+
+
+       /* Fill svc informations in buffer */
+       memcpy(&notif_info.svc_uuid,
+                       event_data->srvc_id.id.uuid.uuid, BLUETOOTH_UUID_HEX_MAX_LEN);
+       notif_info.svc_inst = event_data->srvc_id.id.inst_id;
+
+       /* Fill char in buffer */
+       memcpy(&notif_info.char_uuid,
+                       event_data->char_id.uuid.uuid, BLUETOOTH_UUID_HEX_MAX_LEN);
+       notif_info.char_inst = event_data->char_id.inst_id;
+
+       /* Fill remote device address */
+       _bt_convert_addr_string_to_type(notif_info.addr.addr, conn_info->addr);
+
+       notif_info.is_registered = is_registered;
+
+       if (event_data->status != OAL_STATUS_SUCCESS)
+               result = BLUETOOTH_ERROR_INTERNAL;
+
+       /* Send DBUS Return for BT_GATT_WATCH_CHARACTERISTIC */
+       __bt_gatt_handle_pending_request_info(result,
+                       BT_GATT_WATCH_CHARACTERISTIC,
+                       &notif_info,
+                       sizeof(bt_gatt_notif_reg_info_t));
+}
 
 
 gboolean _bt_is_remote_gatt_device_connected(bluetooth_device_address_t *address)
@@ -4083,6 +4287,100 @@ int _bt_gatt_read_descriptor_value(
        return BLUETOOTH_ERROR_NONE;
 }
 
+/*acquire Notify*/
+int _bt_gatt_acquire_notify(bluetooth_gatt_client_char_prop_info_t *chr, int *fd, int *mtu)
+{
+       struct gatt_server_info_t *conn_info = NULL;
+       oal_gatt_srvc_id_t srvc_id;
+       oal_gatt_id_t char_id;
+       int ret = OAL_STATUS_SUCCESS;
+       char *addr;
+
+       BT_CHECK_PARAMETER(chr, return);
+
+       BT_INFO("+");
+
+       addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE);
+       _bt_convert_addr_type_to_string(addr, chr->device_address.addr);
+
+       /* Check if remote GATT Server is connected or not */
+       conn_info = __bt_find_remote_gatt_server_info(addr);
+       if (conn_info) {
+               BT_INFO("GATT Server [%s] is connected, conn Id [%d]",
+                               conn_info->addr, conn_info->connection_id);
+       } else {
+               BT_ERR("GATT Server is not yet connected..");
+               g_free(addr);
+               return BLUETOOTH_ERROR_NOT_CONNECTED;
+       }
+
+       srvc_id.is_prmry = TRUE;
+       srvc_id.id.inst_id = chr->svc.instance_id;
+       memcpy(srvc_id.id.uuid.uuid, chr->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN);
+
+       char_id.inst_id = chr->characteristic.instance_id;
+       memcpy(char_id.uuid.uuid, chr->characteristic.uuid, BLUETOOTH_UUID_HEX_MAX_LEN);
+
+               ret = gattc_acquire_notify(conn_info->connection_id, &srvc_id, &char_id, fd, mtu);
+
+       if (ret != OAL_STATUS_SUCCESS) {
+               BT_ERR("ret: %d", ret);
+               g_free(addr);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+       BT_INFO("GATT characterstics FD [%d]  mtu[%d]", *fd, *mtu);
+       g_free(addr);
+       return BLUETOOTH_ERROR_NONE;
+}
+
+/*acquire Write*/
+int _bt_gatt_acquire_write(bluetooth_gatt_client_char_prop_info_t *chr, int *fd, int *mtu)
+{
+
+       struct gatt_server_info_t *conn_info = NULL;
+       oal_gatt_srvc_id_t srvc_id;
+       oal_gatt_id_t char_id;
+       int ret = OAL_STATUS_SUCCESS;
+       char *addr;
+
+       BT_CHECK_PARAMETER(chr, return);
+
+       BT_INFO("+");
+
+       addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE);
+       _bt_convert_addr_type_to_string(addr, chr->device_address.addr);
+
+       /* Check if remote GATT Server is connected or not */
+       conn_info = __bt_find_remote_gatt_server_info(addr);
+       if (conn_info) {
+               BT_INFO("GATT Server [%s] is connected, conn Id [%d]",
+                               conn_info->addr, conn_info->connection_id);
+       } else {
+               BT_ERR("GATT Server is not yet connected..");
+               g_free(addr);
+               return BLUETOOTH_ERROR_NOT_CONNECTED;
+       }
+
+       srvc_id.is_prmry = TRUE;
+       srvc_id.id.inst_id = chr->svc.instance_id;
+       memcpy(srvc_id.id.uuid.uuid, chr->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN);
+
+       char_id.inst_id = chr->characteristic.instance_id;
+       memcpy(char_id.uuid.uuid, chr->characteristic.uuid, BLUETOOTH_UUID_HEX_MAX_LEN);
+
+               ret = gattc_acquire_write(conn_info->connection_id, &srvc_id, &char_id,
+                                       OAL_GATT_AUTH_REQ_NONE, fd, mtu);
+       if (ret != OAL_STATUS_SUCCESS) {
+               BT_ERR("ret: %d", ret);
+               g_free(addr);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+       BT_INFO("GATT characterstics FD [%d]  mtu [%d]", *fd, *mtu);
+       g_free(addr);
+       return BLUETOOTH_ERROR_NONE;
+
+}
+
 
 /* Write Characteristic */
 int _bt_gatt_write_characteristic_value_by_type(
@@ -4241,6 +4539,62 @@ int _bt_gatt_write_descriptor_value_by_type(
        return BLUETOOTH_ERROR_NONE;
 }
 
+int _bt_gatt_watch_characteristic(
+               bluetooth_gatt_client_char_prop_info_t *chr,
+               int client_id,
+               gboolean is_notify)
+{
+       struct gatt_server_info_t *conn_info = NULL;
+       oal_gatt_srvc_id_t srvc_id;
+       oal_gatt_id_t char_id;
+       int ret = OAL_STATUS_SUCCESS;
+       char *addr;
+
+       BT_CHECK_PARAMETER(chr, return);
+
+       BT_INFO("Client ID [%d] Is Notify [%d]", client_id, is_notify);
+
+       addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE);
+       _bt_convert_addr_type_to_string(addr, chr->device_address.addr);
+
+       /* Check if remote GATT Server is connected or not */
+       conn_info = __bt_find_remote_gatt_server_info(addr);
+       if (conn_info) {
+               BT_INFO("GATT Server [%s] is connected, conn Id [%d]",
+                               conn_info->addr, conn_info->connection_id);
+       } else {
+               BT_ERR("GATT Server is not yet connected..");
+               g_free(addr);
+               return BLUETOOTH_ERROR_NOT_CONNECTED;
+       }
+       srvc_id.is_prmry = TRUE;
+       srvc_id.id.inst_id = chr->svc.instance_id;
+       memcpy(srvc_id.id.uuid.uuid, chr->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN);
+
+       char_id.inst_id = chr->characteristic.instance_id;
+       memcpy(char_id.uuid.uuid, chr->characteristic.uuid, BLUETOOTH_UUID_HEX_MAX_LEN);
+
+       /* Register or unregister Notification characteristic */
+       if (is_notify)
+               ret = gattc_register_for_notification(conn_info->client_id,
+                               (bt_address_t*)&(chr->device_address),
+                               &srvc_id, &char_id);
+       else
+               ret = gattc_deregister_for_notification(conn_info->client_id,
+                               (bt_address_t*)&(chr->device_address),
+                               &srvc_id, &char_id);
+
+       BT_INFO("Result[%d]", ret);
+       if (ret != OAL_STATUS_SUCCESS) {
+               BT_ERR("ret: %d", ret);
+               g_free(addr);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+       g_free(addr);
+       return BLUETOOTH_ERROR_NONE;
+}
+
+
 int _bt_disconnect_le_device(bluetooth_device_address_t *address,
                int client_id)
 {