f0c82ecda918c0cdee4bddcc0bc2fe008c92a0d1
[platform/core/connectivity/bluetooth-frwk.git] / bt-oal / bluez_hal / src / bt-hal-gatt-client.c
1 /*
2  * BLUETOOOTH HAL
3  *
4  * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:  Anupam Roy <anupam.r@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *              http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <hardware/bluetooth.h>
23 #include <hardware/bt_gatt.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <dlog.h>
29 #include <gio/gio.h>
30 #include <glib.h>
31 #include <gio/gunixfdlist.h>
32
33
34 #include "bt-hal-log.h"
35 #include "bt-hal-msg.h"
36 #include "bt-hal-event-receiver.h"
37 #include "bt-hal-adapter-le.h"
38
39 #include "bt-hal-gatt-client.h"
40 #include "bt-hal-dbus-common-utils.h"
41 #include "bt-hal-utils.h"
42
43 /************************************************************************************
44  **  Static variables
45  ************************************************************************************/
46 extern const btgatt_callbacks_t *bt_gatt_callbacks;
47 #define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
48 {\
49         ERR("%s: BTGATT not initialized", __FUNCTION__);\
50         return BT_STATUS_NOT_READY;\
51 } else {\
52         DBG("%s", __FUNCTION__);\
53 }
54
55 #ifdef TIZEN_BT_HAL
56 int le_scan_type = BT_GATTC_LE_SCAN_TYPE_PASSIVE;
57 #endif
58
59 static handle_stack_msg event_cb = NULL;
60
61 #define GATT_SERV_INTERFACE             "org.bluez.GattService1"
62 #define MAX_HAL_OBJECT_PATH_LEN         100
63
64 typedef enum {
65         HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST = 0x01,
66         HAL_GATT_CHARACTERISTIC_PROPERTY_READ = 0x02,
67         HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE = 0x04,
68         HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE = 0x08,
69         HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY = 0x10,
70         HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE = 0x20,
71         HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE = 0x40,
72         HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE = 0x80,
73         HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES = 0x100,
74         HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ = 0x200,
75         HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE = 0x400,
76         HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ = 0x800,
77         HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE = 0x1000,
78         HAL_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS = 0xffff,
79 } bt_gatt_characteristic_property_t;
80
81
82 typedef enum {
83         HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE = 1,
84         HAL_GATT_WRITE_TYPE_WRITE ,
85 } hal_gatt_write_type_t;
86
87
88 typedef enum {
89         HAL_GATT_PROPERTY_BROADCAST = 0x01,  /**< Broadcast property */
90         HAL_GATT_PROPERTY_READ = 0x02,  /**< Read property */
91         HAL_GATT_PROPERTY_WRITE_WITHOUT_RESPONSE = 0x04,  /**< Write without response property */
92         HAL_GATT_PROPERTY_WRITE = 0x08,  /**< Write property */
93         HAL_GATT_PROPERTY_NOTIFY = 0x10,  /**< Notify property */
94         HAL_GATT_PROPERTY_INDICATE = 0x20,  /**< Indicate property */
95         HAL_GATT_PROPERTY_AUTHENTICATED_SIGNED_WRITES = 0x40,  /**< Authenticated signed writes property */
96         HAL_GATT_PROPERTY_EXTENDED_PROPERTIES = 0x80,  /**< Extended properties */
97 } hal_gatt_property_e;
98
99 typedef struct {
100         int client_if;
101         bt_bdaddr_t bd_addr;
102         gboolean auto_connect;
103 } bt_pending_le_conn_info_s;
104
105 typedef struct {
106         char *desc_path;
107         bt_uuid_t desc_uuid;
108 } hal_gattc_desc_t;
109
110 typedef struct {
111         char *chr_path;
112         bt_uuid_t chr_uuid;
113         unsigned int permission;
114         GSList *gatt_list_descs;
115 } hal_gattc_char_t;
116
117 typedef struct {
118         gchar *svc_path;
119         bt_uuid_t svc_uuid;
120         int is_primary;
121         GSList *gatt_list_chars;
122 } hal_gattc_service_t;
123
124 typedef struct {
125         bt_bdaddr_t bd_addr;    /*remote server address*/
126         int conn_id;
127         int inst_id;            /*server instance id*/
128         gboolean is_gatt_connected;             /*status for GattConnected signal*/
129         GSList *gatt_list_services;
130 } hal_gattc_server_info_t;
131
132 /* Linked List of connected GATT server */
133 static GSList *hal_gattc_server_info_list = NULL;
134
135 typedef struct {
136         int client_if;
137         bt_bdaddr_t bd_addr;    /*remote server address*/
138         int conn_id;
139         int inst_id;
140         gboolean is_gatt_connected;             /*status for GattConnected signal*/
141 } hal_gattc_client_info_t;
142
143 /* Linked list of connected GATT client connection */
144 static GSList * hal_gattc_client_info_list = NULL;
145
146 static bt_pending_le_conn_info_s *pending_le_conn_info = NULL;
147 static guint pending_le_conn_timer_id = 0;
148 static int bt_conn_id = 0;
149 static int bt_inst_id = 0;
150
151 /* Should match the range with bt-service-gatt.c's MAX_APPS_SUPPORTED */
152 /* TODO: Adjust MAX Client after modifying MAX app handle logic */
153 #define BT_GATTC_CL_MAX 11
154
155 static int assigned_if = 0;
156 static gboolean client_if_used[BT_GATTC_CL_MAX];
157
158 typedef struct {
159         int conn_id;
160         int result;
161         btgatt_srvc_id_t srvc_id;
162         btgatt_gatt_id_t char_id;
163         btgatt_gatt_id_t desc_id;
164 } hal_gatt_resp_data_t;
165
166 typedef struct {
167         int client_if;
168         bt_uuid_t app_uuid;
169 } hal_gatt_client_app;
170
171 static GSList * hal_gattc_client_app_list = NULL;
172
173 struct conn_mtu_s {
174         int conn_id;
175         int mtu;
176 };
177
178 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
179                 gboolean auto_connect);
180 static bt_status_t _bt_hold_current_advertising();
181 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data);
182 static gboolean __bt_connect_le_timer_cb(gpointer user_data);
183 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
184                 gpointer user_data);
185 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int  conn_id);
186 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
187                                                 const char* uuid_str, int inst_id);
188 static void _bt_hal_send_search_service_complete_event(int conn_id, int status);
189 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr);
190 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
191 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id);
192
193 void _bt_hal_gatt_client_init(void)
194 {
195         assigned_if = 0;
196         memset(client_if_used, 0x00, sizeof(client_if_used));
197 }
198
199 static int __bt_hal_gatt_assign_if(void)
200 {
201         int index;
202
203         index = assigned_if + 1;
204
205         if (index >= BT_GATTC_CL_MAX)
206                 index = 1;
207
208         while (client_if_used[index] == TRUE) {
209                 if (index == assigned_if) {
210                         /* No available ID */
211                         ERR("All interface ID is used");
212                         return -1;
213                 }
214
215                 index++;
216
217                 if (index >= BT_GATTC_CL_MAX)
218                         index = 1;
219         }
220
221         assigned_if = index;
222         client_if_used[index] = TRUE;
223
224         return assigned_if;
225 }
226
227 static void __bt_hal_gatt_delete_if(int client_if)
228 {
229         if (client_if >= BT_GATTC_CL_MAX || client_if < 0)
230                 return;
231
232         client_if_used[client_if] = FALSE;
233 }
234
235
236 /* To send stack event to hal-av handler */
237 void _bt_hal_register_gatt_client_handler_cb(handle_stack_msg cb)
238 {
239         event_cb = cb;
240 }
241
242 void _bt_hal_unregister_gatt_client_handler_cb(void)
243 {
244         event_cb = NULL;
245 }
246
247 #ifdef TIZEN_BT_HAL
248 int _bt_hal_gatt_client_get_le_scan_type(void)
249 {
250         return le_scan_type;
251 }
252 #endif
253
254 static gboolean __bt_hal_register_client_cb(gpointer user_data)
255 {
256         struct hal_ev_gatt_client_registered ev;
257         hal_gatt_client_app *client_info = user_data;
258
259         /* Prepare to send AV connecting event */
260         memset(&ev, 0, sizeof(ev));
261         ev.status = BT_STATUS_SUCCESS;
262         ev.client_if = client_info->client_if;
263         memcpy(ev.app_uuid, client_info->app_uuid.uu, sizeof(ev.app_uuid));
264
265         if (!event_cb)
266                 ERR("GATT Callback not registered");
267         else {
268                 DBG("GATT client registered, client_if: [%d]", client_info->client_if);
269                 event_cb(HAL_EV_GATT_CLIENT_REGISTERED, (void *)&ev, sizeof(ev));
270         }
271
272         g_free(user_data);
273         return FALSE;
274 }
275
276 static hal_gatt_client_app *__hal_gattc_add_client_app(bt_uuid_t *app_uuid)
277 {
278         GSList *l;
279         int client_if = 0;
280         hal_gatt_client_app *info = NULL;
281         hal_gatt_client_app *gattc_app = NULL;
282
283         //check if client app is already registered
284         for (l = hal_gattc_client_app_list; l != NULL; l = g_slist_next(l)) {
285                 info = (hal_gatt_client_app*)l->data;
286                 if (info == NULL)
287                         continue;
288
289                 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
290                         DBG("gatt client app already registered");
291                         return info;
292                 }
293         }
294
295         client_if = __bt_hal_gatt_assign_if();
296         if (client_if == -1) {
297                 ERR("Fail to allocate the client if");
298                 return NULL;
299         }
300
301         DBG("adding the gatt client app");
302
303         //add client app
304         gattc_app = g_malloc0(sizeof(hal_gatt_client_app));
305         gattc_app->client_if = client_if;
306         memcpy(&gattc_app->app_uuid, app_uuid, sizeof(bt_uuid_t));
307
308         hal_gattc_client_app_list = g_slist_append(hal_gattc_client_app_list, gattc_app);
309
310         return gattc_app;
311 }
312
313 static bt_status_t __hal_gattc_register_client_app(bt_uuid_t *app_uuid)
314 {
315         hal_gatt_client_app *gattc_app = NULL;
316         hal_gatt_client_app *client_app_info = NULL;
317
318         /* add gatt client in list */
319         gattc_app = __hal_gattc_add_client_app(app_uuid);
320         if (gattc_app == NULL) {
321                 ERR("Failed to register gatt client app");
322                 return BT_STATUS_FAIL;
323         }
324
325         /*send event */
326         client_app_info = g_malloc0(sizeof(hal_gatt_client_app));
327         client_app_info->client_if = gattc_app->client_if;
328         memcpy(&client_app_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
329         g_idle_add(__bt_hal_register_client_cb, (gpointer)client_app_info);
330
331         DBG("registered client client_if [%d]", client_app_info->client_if);
332
333         return BT_STATUS_SUCCESS;
334 }
335
336 /** Registers a GATT client application with the stack */
337 bt_status_t btif_gattc_register_client(bt_uuid_t *uuid)
338 {
339         CHECK_BTGATT_INIT();
340
341         return __hal_gattc_register_client_app(uuid);
342 }
343
344 bt_status_t btif_gattc_add_connection_info(const bt_bdaddr_t *bd_addr, int conn_id, int server_inst_id)
345 {
346         hal_gattc_client_info_t *client_info = NULL;
347         hal_gattc_server_info_t *server_info = NULL;
348
349         /* Add client connection info in list */
350         client_info = g_malloc0(sizeof(hal_gattc_client_info_t));
351         client_info->client_if = -1;
352         memcpy(client_info->bd_addr.address, bd_addr->address, BT_HAL_ADDRESS_LENGTH_MAX);
353         client_info->conn_id = conn_id;
354         client_info->inst_id = server_inst_id;
355         hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, client_info);
356         DBG("Added client connection info in list");
357
358         /* Add server connection info in list */
359         server_info = __bt_find_gatt_conn_info(bd_addr);
360         if (server_info == NULL) {
361                 server_info = g_malloc0(sizeof(hal_gattc_server_info_t));
362                 memcpy(server_info->bd_addr.address, bd_addr->address, BT_HAL_ADDRESS_LENGTH_MAX);
363                 server_info->conn_id = conn_id;
364                 server_info->inst_id = server_inst_id;
365                 server_info->is_gatt_connected = TRUE;
366                 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, server_info);
367                 DBG("Added server connection info in list");
368         }
369
370         return BT_STATUS_SUCCESS;
371 }
372
373 bt_status_t __hal_gattc_unregister_client(int client_if)
374 {
375         GSList *l;
376         hal_gatt_client_app *info = NULL;
377
378         DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
379
380         /* remove the gatt client app */
381         for (l = hal_gattc_client_app_list; l != NULL; ) {
382                 info = (hal_gatt_client_app*)l->data;
383                 l = g_slist_next(l);
384
385                 if (info == NULL)
386                         continue;
387
388                 if (info->client_if == client_if) {
389                         DBG("gatt client app found");
390
391                         __bt_hal_gatt_delete_if(client_if);
392
393                         hal_gattc_client_app_list = g_slist_remove(hal_gattc_client_app_list, info);
394                         g_free(info);
395                 }
396         }
397
398         DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
399         return BT_STATUS_SUCCESS;
400 }
401
402 /** Unregister a client application from the stack */
403 bt_status_t btif_gattc_unregister_client(int client_if)
404 {
405         CHECK_BTGATT_INIT();
406
407         return __hal_gattc_unregister_client(client_if);
408 }
409
410 /** Start or stop LE device scanning */
411 bt_status_t scan(int client_if, bool start)
412 {
413         int ret;
414
415         CHECK_BTGATT_INIT();
416
417         if (start)
418                 ret = _bt_hal_adapter_le_start_scan();
419         else
420                 ret = _bt_hal_adapter_le_stop_scan();
421
422         return ret;
423 }
424
425 /** Create a connection to a remote LE or dual-mode device */
426 bt_status_t btif_gattc_client_connect(int client_if, const bt_bdaddr_t *bd_addr,
427                 bool is_direct)
428 {
429         int ret = BT_STATUS_SUCCESS;
430
431         CHECK_BTGATT_INIT();
432
433         if (NULL == bd_addr)
434                 return BT_STATUS_PARM_INVALID;
435
436         ret = _bt_hold_current_advertising();
437         if (ret == BT_STATUS_SUCCESS) {
438                 DBG("Current advertising is held");
439                 pending_le_conn_info = g_malloc0(sizeof(bt_pending_le_conn_info_s));
440                 pending_le_conn_info->client_if = client_if;
441                 memcpy(pending_le_conn_info->bd_addr.address, bd_addr->address,
442                                 BT_HAL_ADDRESS_LENGTH_MAX);
443                 pending_le_conn_info->auto_connect = is_direct;
444
445                 pending_le_conn_timer_id =
446                         g_timeout_add(1000, __bt_connect_le_timer_cb, NULL);
447
448                 return BT_STATUS_SUCCESS;
449         } else {
450                 ERR("advertising is not stopped");
451         }
452
453         return __bt_connect_le_device_internal(client_if, bd_addr, is_direct);
454 }
455
456
457 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
458                 gpointer user_data)
459 {
460         GError *g_error = NULL;
461         GVariant *reply = NULL;
462         hal_gattc_client_info_t *gatt_conn_info  = user_data;
463         int result = BT_STATUS_SUCCESS;
464         struct hal_ev_gatt_client_connected ev;
465
466         DBG("+");
467
468         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
469         g_object_unref(proxy);
470         if (reply == NULL) {
471                 ERR("Connect LE Dbus Call Error");
472                 if (g_error) {
473                         ERR("Error: %s\n", g_error->message);
474                         g_clear_error(&g_error);
475                 }
476                 result = BT_STATUS_FAIL;
477         }
478         g_variant_unref(reply);
479
480         if (NULL == gatt_conn_info) {
481                 ERR("server_data is NULL");
482                 return;
483         }
484
485         /*send fail event*/
486         if (result == BT_STATUS_FAIL) {
487                 memset(&ev, 0, sizeof(ev));
488                 ev.conn_id = gatt_conn_info->conn_id;
489                 ev.status = result;
490                 ev.client_if = gatt_conn_info->client_if;
491                 memcpy(ev.bdaddr, gatt_conn_info->bd_addr.address,
492                                                 BT_HAL_ADDRESS_LENGTH_MAX);
493
494                 if (!event_cb) {
495                         ERR("gatt client callback not registered");
496                 } else {
497                         DBG("sending gatt client disconnected event");
498                         event_cb(HAL_EV_GATT_CLIENT_DISCONNECTED, (void *)&ev, sizeof(ev));
499                 }
500         }
501
502         /*remove conn_info*/
503         if (gatt_conn_info)
504                 g_free(gatt_conn_info);
505
506         DBG("-");
507 }
508
509 bt_status_t _hal_gattc_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
510                         int conn_id)
511 {
512         char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
513         gchar *device_path;
514         GDBusProxy *device_proxy;
515         GDBusConnection *conn;
516         int ret = BT_STATUS_SUCCESS;
517         hal_gattc_client_info_t *gattc_data;
518
519         if (NULL == bd_addr) {
520                 ERR("bd_addr is NULL");
521                 return BT_STATUS_PARM_INVALID;
522         }
523
524         conn = _bt_hal_get_system_gconn();
525         if (NULL == conn) {
526                 ERR("_bt_gdbus_get_system_gconn returned NULL");
527                 return BT_STATUS_FAIL;
528         }
529
530         _bt_hal_convert_addr_type_to_string(device_address,
531                         (unsigned char *)bd_addr->address);
532         device_path = _bt_hal_get_device_object_path(device_address);
533         if (device_path == NULL) {
534                 DBG("device_path NULL");
535                 ret =  BT_STATUS_FAIL;
536                 return ret;
537         }
538
539         ERR("device_path:%s", device_path);
540
541         device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
542                         NULL, BT_HAL_BLUEZ_NAME,
543                         device_path, BT_HAL_DEVICE_INTERFACE,  NULL, NULL);
544         g_free(device_path);
545         if (NULL == device_proxy) {
546                 ERR("device_proxy returned NULL");
547                 return BT_STATUS_FAIL;
548         }
549
550         gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
551         memcpy(gattc_data->bd_addr.address, bd_addr->address,
552                         BT_HAL_ADDRESS_LENGTH_MAX);
553         gattc_data->client_if = client_if;
554         gattc_data->conn_id = conn_id;
555
556         DBG("DisconnectLE [%s]", device_address);
557
558         g_dbus_proxy_call(device_proxy, "DisconnectLE",
559                         NULL,
560                         G_DBUS_CALL_FLAGS_NONE,
561                         BT_HAL_MAX_DBUS_TIMEOUT,
562                         NULL,
563                         (GAsyncReadyCallback)__le_disconnection_req_cb, gattc_data);
564         return ret;
565 }
566
567 /** Disconnect a remote device or cancel a pending connection */
568 bt_status_t btif_gattc_client_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
569                 int conn_id)
570 {
571         CHECK_BTGATT_INIT();
572
573         return _hal_gattc_disconnect(client_if, bd_addr, conn_id);
574 }
575
576 /** Clear the attribute cache for a given device */
577 bt_status_t refresh(int client_if, const bt_bdaddr_t *bd_addr)
578 {
579         CHECK_BTGATT_INIT();
580         return BT_STATUS_UNSUPPORTED;
581 }
582
583 static hal_gattc_service_t* _gattc_find_service_from_uuid(hal_gattc_server_info_t *conn_info, bt_uuid_t *svc_uuid)
584 {
585         GSList *l;
586         hal_gattc_service_t *info = NULL;
587
588         for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
589                 info = (hal_gattc_service_t*)l->data;
590                 if (info == NULL)
591                         continue;
592
593                 if (!memcmp(&info->svc_uuid, svc_uuid, sizeof(bt_uuid_t)))
594                         return info;
595                 }
596
597         return NULL;
598 }
599
600
601 static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid,
602                                 bt_gatt_characteristic_property_t prop)
603 {
604         GSList *l;
605         hal_gattc_char_t *info = NULL;
606
607         for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
608                 info = (hal_gattc_char_t*)l->data;
609                 if (info == NULL)
610                         continue;
611
612                 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
613                         (info->permission & prop)) {
614                         return info;
615                 }
616         }
617         return NULL;
618 }
619
620 static hal_gattc_char_t* _gattc_find_char_from_uuid_for_notify(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid)
621 {
622         GSList *l;
623         hal_gattc_char_t *info = NULL;
624
625         for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
626                 info = (hal_gattc_char_t*)l->data;
627                 if (info == NULL)
628                         continue;
629
630                 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
631                         ((info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) ||
632                                 (info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE))) {
633                         return info;
634                 }
635         }
636         return NULL;
637 }
638
639 static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char, bt_uuid_t *desc_uuid)
640 {
641         GSList *l;
642         hal_gattc_desc_t *info = NULL;
643
644         for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
645                 info = (hal_gattc_desc_t*)l->data;
646                 if (info == NULL)
647                         continue;
648
649                 if (!memcmp(&info->desc_uuid, desc_uuid, sizeof(bt_uuid_t)))
650                         return info;
651                 }
652         return NULL;
653 }
654
655
656 static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
657                 const char *uuid_str, const char *object_path, int is_primary)
658 {
659         hal_gattc_service_t *gattc_service = NULL;
660
661         gattc_service = g_malloc0(sizeof(hal_gattc_service_t));
662         gattc_service->svc_path = g_strdup(object_path);
663         _bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str);
664         gattc_service->is_primary = is_primary;
665
666         conn_info->gatt_list_services = g_slist_append(conn_info->gatt_list_services, gattc_service);
667         INFO("Toatal svc [%d] Added [%s] [%s]", g_slist_length(conn_info->gatt_list_services), object_path + 15, uuid_str);
668
669         return gattc_service;
670 }
671
672 static void _hal_gattc_add_characteristic(hal_gattc_service_t *gatt_svc, char *char_handle)
673 {
674         hal_gattc_char_t *gattc_char = NULL;
675
676         gattc_char = g_malloc0(sizeof(hal_gattc_char_t));
677         gattc_char->chr_path = g_strdup(char_handle);
678
679         DBG("svc path: [%s]", gatt_svc->svc_path);
680         DBG("char path: [%s]", gattc_char->chr_path);
681
682         gatt_svc->gatt_list_chars = g_slist_append(gatt_svc->gatt_list_chars, gattc_char);
683 }
684
685 static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboolean is_primary,
686                 const char* uuid_str, const char *object_path, GPtrArray *gp_char_array)
687 {
688         hal_gattc_service_t* gatt_svc = NULL;
689         int i;
690         gchar *gp_char_path = NULL;
691
692         /* add the service */
693         gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary);
694         if (gatt_svc == NULL) {
695                 ERR("Failed to add service");
696                 return;
697         }
698
699         /* add the characteristic */
700         for (i = 0; i < gp_char_array->len; i++) {
701                 gp_char_path = g_ptr_array_index(gp_char_array, i);
702                 _hal_gattc_add_characteristic(gatt_svc, gp_char_path);
703         }
704
705         g_ptr_array_free(gp_char_array, TRUE);
706 }
707
708 static void _hal_gattc_add_descriptor(hal_gattc_char_t *gattc_char, char *desc_path)
709 {
710         hal_gattc_desc_t *gattc_desc = NULL;
711
712         gattc_desc = g_malloc0(sizeof(hal_gattc_desc_t));
713         gattc_desc->desc_path = g_strdup(desc_path);
714
715         gattc_char->gatt_list_descs = g_slist_append(gattc_char->gatt_list_descs, gattc_desc);
716 }
717
718 static void _hal_gattc_update_char_property(hal_gattc_char_t *gattc_char, const char* char_uuid_str,
719                 GPtrArray *gp_desc_array, unsigned int char_permission)
720 {
721         gchar *gp_desc_path = NULL;
722         int i;
723
724         if (char_uuid_str == NULL) {
725                 DBG("char_uuid_str is NULL");
726                 return;
727         }
728
729         //update the char uuid
730         _bt_hal_convert_uuid_string_to_type(gattc_char->chr_uuid.uu, char_uuid_str);
731
732         //update char permission
733         gattc_char->permission = char_permission;
734
735         //add the descriptor
736         for (i = 0; i < gp_desc_array->len; i++) {
737                 gp_desc_path = g_ptr_array_index(gp_desc_array, i);
738                 _hal_gattc_add_descriptor(gattc_char, gp_desc_path);
739         }
740 }
741
742 static void _hal_gattc_update_desc_property(hal_gattc_desc_t *gattc_desc, const char* desc_uuid_str)
743 {
744         if (desc_uuid_str == NULL) {
745                 DBG("char_uuid_str is NULL");
746                 return;
747         }
748
749         //update the descriptor uuid
750         DBG("desc UUID: [%s] ", desc_uuid_str);
751         DBG("desc path: [%s]", gattc_desc->desc_path);
752
753         _bt_hal_convert_uuid_string_to_type(gattc_desc->desc_uuid.uu, desc_uuid_str);
754 }
755
756 static void browse_service_char(int conn_id)
757 {
758         hal_gattc_server_info_t *conn_info = NULL;
759         GSList *l;
760         GSList *k;
761         GSList *m;
762         hal_gattc_service_t *svc_info = NULL;
763         hal_gattc_char_t *char_info = NULL;
764         hal_gattc_desc_t *desc_info = NULL;
765
766         conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
767         if (conn_info == NULL) {
768                 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
769                 return;
770         }
771
772         for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
773                 svc_info = (hal_gattc_service_t*)l->data;
774                 if (svc_info == NULL)
775                         continue;
776
777                 /* find characteristic object path */
778                 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
779                         char_info = (hal_gattc_char_t *)k->data;
780                         if (char_info == NULL)
781                                 continue;
782
783                         /* descriptor */
784                         for (m = char_info->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
785                                 desc_info = (hal_gattc_desc_t *)m->data;
786                                 if (desc_info == NULL)
787                                         continue;
788                         }
789                 }
790         }
791 }
792
793
794
795 /**
796  * Enumerate all GATT services on a connected device.
797  * Optionally, the results can be filtered for a given UUID.
798  */
799 static bt_status_t _gattc_client_search_service(int conn_id)
800 {
801         CHECK_BTGATT_INIT();
802
803         GVariant *result = NULL;
804         GVariantIter *iter;
805         GVariantIter *svc_iter;
806         GVariantIter *interface_iter;
807         char *object_path = NULL;
808         char *interface_str = NULL;
809         const gchar *key = NULL;
810         GVariant *value = NULL;
811         GPtrArray *gp_array  = NULL;
812         char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
813         char temp_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
814         int ret = BT_STATUS_FAIL;
815         int idx = 0;
816         const gchar *uuid_str = NULL;
817         gsize len = 0;
818         hal_gattc_server_info_t *conn_info = NULL;
819         gboolean is_primary = FALSE;
820         int svc_count = 0;
821
822         char *char_handle = NULL;
823         GVariantIter *char_iter = NULL;
824         GPtrArray *gp_char_array  = NULL;
825
826         conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
827         if (NULL == conn_info) {
828                 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
829                 return BT_STATUS_FAIL;
830         }
831
832 #if 0
833         // TODO: This logic is not able to handle in case service-added event is coming unexpectedly.
834         /* Check the service info is stored */
835         if (g_slist_length(conn_info->gatt_list_services) > 0) {
836                 GSList *l = NULL;
837                 hal_gattc_service_t *svc_info = NULL;
838                 char svc_uuid_str[BT_HAL_UUID_STRING_LEN] = {0, };
839                 DBG("Send event from service info list");
840                 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
841                         svc_info = l->data;
842                         if (svc_info == NULL)
843                                 continue;
844                         _bt_hal_convert_uuid_type_to_string(svc_uuid_str, svc_info->svc_uuid.uu);
845                         _bt_hal_send_search_service_result_event(conn_id,
846                                         svc_info->is_primary, svc_uuid_str, conn_info->inst_id);
847                 }
848                 _bt_hal_send_search_service_complete_event(conn_id, BT_STATUS_SUCCESS);
849                 return BT_STATUS_SUCCESS;
850         } else {
851                 DBG("No stored service, request to bluez");
852         }
853 #endif
854
855         _bt_hal_convert_addr_type_to_string(device_address,
856                         (unsigned char *)conn_info->bd_addr.address);
857
858         result = _bt_hal_get_managed_objects();
859         if (result == NULL)
860                 return ret;
861
862         gp_array = g_ptr_array_new();
863         g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
864
865         while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
866                                 &interface_iter)) {
867                 if (object_path == NULL)
868                         continue;
869
870                 _bt_hal_convert_device_path_to_address(object_path, temp_address);
871
872                 if (g_strcmp0(temp_address, device_address) != 0)
873                         continue;
874
875                 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
876                                         &interface_str, &svc_iter)) {
877                         if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
878                                 continue;
879
880                         DBG("[%d] Object Path : %s", idx++, object_path);
881                         /* for characteristic */
882                         gp_char_array = g_ptr_array_new();
883                         while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
884                                 if (g_strcmp0(key, "Primary") == 0) {
885                                         is_primary = g_variant_get_boolean(value);
886                                         if (is_primary) {
887                                                 g_ptr_array_add(gp_array, (gpointer)object_path);
888                                                 svc_count++;
889                                         }
890                                 } else if (g_strcmp0(key, "UUID") == 0) {
891                                         uuid_str = g_variant_get_string(value, &len);
892                                 } else if (g_strcmp0(key, "Characteristics") == 0) {
893                                         g_variant_get(value, "ao", &char_iter);
894                                         if (char_iter != NULL) {
895                                                 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
896                                                         g_ptr_array_add(gp_char_array, (gpointer)char_handle);
897                                                 }
898                                         }
899                                 }
900                         }
901
902                         if (uuid_str) {
903                                 _bt_hal_send_search_service_result_event(conn_id, is_primary,
904                                                 uuid_str, conn_info->inst_id);
905
906                                 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
907                         }
908                 }
909         }
910
911         if (gp_array->len == 0 || svc_count == 0) {
912                 ERR("gp_array is NULL");
913                 ret = BT_STATUS_FAIL;
914         } else {
915                 ret = BT_STATUS_SUCCESS;
916         }
917
918         browse_service_char(conn_id);
919         /* send search service complete event */
920         _bt_hal_send_search_service_complete_event(conn_id, ret);
921
922         g_ptr_array_free(gp_array, TRUE);
923         g_variant_iter_free(iter);
924         g_variant_unref(result);
925         DBG("-");
926         return ret;
927 }
928
929 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
930 {
931         if (NULL == filter_uuid) {
932                 DBG("Browse all the services");
933                 return _gattc_client_search_service(conn_id);
934         } else {
935                 DBG("TODO implement it");
936                 return BT_STATUS_UNSUPPORTED;
937         }
938 }
939 /**
940  * Enumerate included services for a given service.
941  * Set start_incl_srvc_id to NULL to get the first included service.
942  */
943 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
944                 btgatt_srvc_id_t *start_incl_srvc_id)
945 {
946         CHECK_BTGATT_INIT();
947         return BT_STATUS_UNSUPPORTED;
948 }
949
950 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
951                 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
952 {
953         struct hal_ev_gatt_client_char_search_result  ev;
954
955          if (!event_cb) {
956                 ERR("gatt client callback not registered");
957                 return;
958         }
959
960         memset(&ev, 0, sizeof(ev));
961         ev.conn_id = conn_id;
962         ev.inst_id = svc_id->id.inst_id;
963         ev.is_primary = svc_id->is_primary;
964         ev.status = status;
965         memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
966
967         if (status == BT_STATUS_SUCCESS) {
968                 /* building char uuid */
969                 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
970                 ev.char_prop = char_prop;
971         }
972
973         DBG("sending the char search event.  conn_id[%d] status[%d]", conn_id, status);
974         event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
975 }
976
977 static int _hal_get_permission_flag(char *permission)
978 {
979         int ret = 0;
980
981         if (NULL == permission) {
982                 ERR("gatt permission is NULL");
983                 return ret;
984         }
985
986         if (!g_strcmp0(permission, "broadcast"))
987                 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
988         else if (!g_strcmp0(permission, "read"))
989                 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
990         else if (!g_strcmp0(permission, "write-without-response"))
991                 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
992         else if (!g_strcmp0(permission, "write"))
993                 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
994         else if (!g_strcmp0(permission, "notify"))
995                 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
996         else if (!g_strcmp0(permission, "indicate"))
997                 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
998         else if (!g_strcmp0(permission, "authenticated-signed-writes"))
999                 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
1000         else if (!g_strcmp0(permission, "reliable-write"))
1001                 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
1002         else if (!g_strcmp0(permission, "writable-auxiliaries"))
1003                 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
1004         else if (!g_strcmp0(permission, "encrypt-read"))
1005                 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1006         else if (!g_strcmp0(permission, "encrypt-write"))
1007                 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1008         else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
1009                 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1010         else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
1011                 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1012
1013         return ret;
1014 }
1015
1016 static void __hal_convert_permission_flag_to_str(unsigned int permission)
1017 {
1018         char perm[200] = { 0, };
1019
1020         if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
1021                 g_strlcat(perm, "broadcast ", sizeof(perm));
1022         if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_READ)
1023                 g_strlcat(perm, "read ", sizeof(perm));
1024         if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
1025                 g_strlcat(perm, "write-without-response ", sizeof(perm));
1026         if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE)
1027                 g_strlcat(perm, "write ", sizeof(perm));
1028         if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
1029                 g_strlcat(perm, "notify ", sizeof(perm));
1030         if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
1031                 g_strlcat(perm, "indicate ", sizeof(perm));
1032         if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
1033                 g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
1034         if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
1035                 g_strlcat(perm, "reliable-write ", sizeof(perm));
1036         if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
1037                 g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
1038         if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
1039                 g_strlcat(perm, "encrypt-read ", sizeof(perm));
1040         if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
1041                 g_strlcat(perm, "encrypt-write ", sizeof(perm));
1042         if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
1043                 g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
1044         if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
1045                 g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
1046
1047         DBG("permission [0x%04x] : %s\n", permission, perm);
1048         return;
1049 }
1050
1051 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
1052 {
1053         GDBusProxy *properties_proxy = NULL;
1054         GError *error = NULL;
1055         GVariant *value = NULL;
1056         GVariant *result = NULL;
1057         GDBusConnection *g_conn;
1058         const gchar *key;
1059         char *char_desc_handle = NULL;
1060         gsize len;
1061         GVariantIter *property_iter;
1062         GVariantIter *char_desc_iter;
1063         char* char_handle = NULL;
1064         gchar *char_uuid_str = NULL;
1065         GPtrArray *gp_desc_array  = NULL;
1066         GVariantIter *char_perm_iter;
1067         gchar* permission;
1068         unsigned int char_permission = 0 ;
1069
1070         if (gattc_char->chr_path == NULL) {
1071                 DBG("char path is NULL");
1072                  return BT_STATUS_FAIL;
1073         }
1074         char_handle = gattc_char->chr_path;
1075
1076         g_conn = _bt_hal_get_system_gconn();
1077         if (NULL == g_conn) {
1078                  ERR("_bt_gdbus_get_system_gconn returned NULL");
1079                 return BT_STATUS_FAIL;
1080         }
1081
1082         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1083                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1084                         BT_HAL_BLUEZ_NAME,
1085                         char_handle,
1086                         BT_HAL_PROPERTIES_INTERFACE,
1087                         NULL, &error);
1088
1089         if (properties_proxy == NULL) {
1090                 ERR("properties_proxy returned NULL");
1091                 return BT_STATUS_FAIL;
1092         }
1093
1094         result = g_dbus_proxy_call_sync(properties_proxy,
1095                         "GetAll",
1096                         g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1097                         G_DBUS_CALL_FLAGS_NONE,
1098                         -1,
1099                         NULL,
1100                         &error);
1101         if (!result) {
1102                 if (error != NULL) {
1103                         ERR("Fail to get properties (Error: %s)", error->message);
1104                         g_clear_error(&error);
1105                 } else
1106                         ERR("Fail to get properties");
1107                 g_object_unref(properties_proxy);
1108                 return BT_STATUS_FAIL;
1109         }
1110
1111         gp_desc_array = g_ptr_array_new();
1112
1113         g_variant_get(result, "(a{sv})", &property_iter);
1114
1115         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1116                 if (!g_strcmp0(key, "UUID")) {
1117                         char_uuid_str = g_variant_dup_string(value, &len);
1118                         INFO("%s [%s]", char_handle + 37, char_uuid_str);
1119                 } else if (!g_strcmp0(key, "Flags")) {
1120                         g_variant_get(value, "as", &char_perm_iter);
1121                                 char_permission = 0x00;
1122
1123                         while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1124                                 char_permission |= _hal_get_permission_flag(permission);
1125                         }
1126                         __hal_convert_permission_flag_to_str(char_permission);
1127                         g_variant_iter_free(char_perm_iter);
1128                 } else if (!g_strcmp0(key, "Descriptors")) {
1129                         g_variant_get(value, "ao", &char_desc_iter);
1130                         while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
1131                                 g_ptr_array_add(gp_desc_array, (gpointer)char_desc_handle);
1132                         }
1133                         g_variant_iter_free(char_desc_iter);
1134                 }
1135         }
1136
1137         _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1138
1139         g_free(char_uuid_str);
1140         g_variant_iter_free(property_iter);
1141         g_variant_unref(result);
1142         g_object_unref(properties_proxy);
1143         g_ptr_array_free(gp_desc_array, TRUE);
1144
1145         return BT_STATUS_SUCCESS;
1146 }
1147
1148 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1149                 btgatt_srvc_id_t *srvc_id)
1150 {
1151         hal_gattc_server_info_t * conn_info = NULL;
1152         hal_gattc_service_t *gattc_service = NULL;
1153         GSList *l;
1154         hal_gattc_char_t *gattc_char = NULL;
1155         char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1156         int status = BT_STATUS_FAIL;
1157
1158         conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1159         if (NULL == conn_info) {
1160                 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1161                 return BT_STATUS_FAIL;
1162         }
1163
1164         /* find service */
1165         gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1166         if (NULL == gattc_service) {
1167                 ERR("Failed to get the gatt service");
1168                 return BT_STATUS_FAIL;
1169         }
1170
1171         _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1172         INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1173
1174         /* find characteristic object path */
1175         for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1176                 gattc_char = (hal_gattc_char_t *)l->data;
1177                 status = _hal_gattc_get_characteristic_info(gattc_char);
1178
1179                 /* send event */
1180                 if (BT_STATUS_SUCCESS == status) {
1181                         _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1182                                         &gattc_char->chr_uuid, gattc_char->permission);
1183                 }
1184         }
1185
1186         status = BT_STATUS_FAIL;
1187         _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1188
1189         browse_service_char(conn_id);
1190         /* retrive uuid for characteristic and object path for descriptor */
1191
1192         return BT_STATUS_SUCCESS;
1193 }
1194
1195 /**
1196  * Enumerate characteristics for a given service.
1197  * Set start_char_id to NULL to get the first characteristic.
1198  */
1199 bt_status_t btif_gattc_get_characteristic(int conn_id,
1200                 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1201 {
1202         CHECK_BTGATT_INIT();
1203
1204         if (start_char_id == NULL) {
1205                 DBG("Get all the characteristics");
1206                 return _gattc_get_all_characteristic(conn_id, srvc_id);
1207
1208         } else {
1209                 DBG("TBD Get specific characteristics");
1210                 return BT_STATUS_UNSUPPORTED;
1211         }
1212 }
1213
1214 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1215 {
1216         GDBusProxy *properties_proxy = NULL;
1217         GError *error = NULL;
1218         GVariant *value = NULL;
1219         GVariant *result = NULL;
1220         GDBusConnection *g_conn;
1221         const gchar *key;
1222         gsize len;
1223         GVariantIter *property_iter;
1224         char* desc_handle = NULL;
1225         const gchar *desc_uuid_str = NULL;
1226
1227         if (gattc_desc->desc_path == NULL) {
1228                 DBG("desc path is NULL");
1229                 return BT_STATUS_FAIL;
1230         }
1231         desc_handle = gattc_desc->desc_path;
1232
1233         g_conn = _bt_hal_get_system_gconn();
1234         if (NULL == g_conn) {
1235                 ERR("_bt_gdbus_get_system_gconn returned NULL");
1236                 return BT_STATUS_FAIL;
1237         }
1238
1239         properties_proxy = g_dbus_proxy_new_sync(g_conn,
1240                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1241                         BT_HAL_BLUEZ_NAME,
1242                         desc_handle,
1243                         BT_HAL_PROPERTIES_INTERFACE,
1244                         NULL, &error);
1245
1246         if (properties_proxy == NULL) {
1247                 ERR("properties_proxy returned NULL");
1248                 return BT_STATUS_FAIL;
1249         }
1250
1251         result = g_dbus_proxy_call_sync(properties_proxy,
1252                         "GetAll",
1253                         g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1254                         G_DBUS_CALL_FLAGS_NONE,
1255                         -1,
1256                         NULL,
1257                         &error);
1258         if (!result) {
1259                 if (error != NULL) {
1260                         ERR("Fail to get properties (Error: %s)", error->message);
1261                         g_clear_error(&error);
1262                 } else
1263                         ERR("Fail to get properties");
1264                 g_object_unref(properties_proxy);
1265                 return BT_STATUS_FAIL;
1266         }
1267
1268         g_variant_get(result, "(a{sv})", &property_iter);
1269
1270         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1271                 if (!g_strcmp0(key, "UUID")) {
1272                         desc_uuid_str = g_variant_get_string(value, &len);
1273                         _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1274
1275                         g_free((gchar *)key);
1276                         g_variant_unref(value);
1277                         break;
1278                 }
1279         }
1280
1281         g_variant_iter_free(property_iter);
1282         g_variant_unref(result);
1283         g_object_unref(properties_proxy);
1284
1285         return BT_STATUS_SUCCESS;
1286 }
1287
1288 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1289                 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1290 {
1291         struct hal_ev_gatt_client_desc_search_result  ev;
1292
1293         if (!event_cb) {
1294                 ERR("gatt client callback not registered");
1295                 return;
1296         }
1297
1298         memset(&ev, 0, sizeof(ev));
1299         ev.conn_id = conn_id;
1300         ev.inst_id = svc_id->id.inst_id;
1301         ev.is_primary = svc_id->is_primary;
1302         ev.status = status;
1303
1304         memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1305         memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1306
1307         if (status == BT_STATUS_SUCCESS) {
1308                 /* building desc uuid */
1309                 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1310         }
1311
1312         DBG("sending the desc search event. conn_id[%d] status[%d]", conn_id, status);
1313
1314         event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1315 }
1316
1317 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1318                 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1319 {
1320         hal_gattc_server_info_t * conn_info = NULL;
1321         hal_gattc_service_t *gattc_service = NULL;
1322         GSList *l;
1323         GSList *m;
1324         hal_gattc_char_t *gattc_char = NULL;
1325         hal_gattc_desc_t *gattc_desc = NULL;
1326         char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1327         char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1328         int status = BT_STATUS_FAIL;
1329
1330         conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1331         if (NULL == conn_info) {
1332                 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1333                 return BT_STATUS_FAIL;
1334         }
1335
1336         /* find service */
1337         gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1338         if (NULL == gattc_service) {
1339                 ERR("Failed to get the gatt service");
1340                 return BT_STATUS_FAIL;
1341         }
1342
1343         _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1344         INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1345
1346         /* find characteristics */
1347         /* a service can have two char with same uuid */
1348         for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1349                 gattc_char = (hal_gattc_char_t*)l->data;
1350                 if (gattc_char == NULL)
1351                         continue;
1352
1353                 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1354                         _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1355                         INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1356
1357                         /* get descriptor uuid */
1358                         for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1359                                 gattc_desc = (hal_gattc_desc_t *)m->data;
1360                                 if (gattc_desc == NULL)
1361                                         continue;
1362
1363                                 status = _hal_gattc_get_descriptor_info(gattc_desc);
1364
1365                                 /* send event */
1366                                 if (BT_STATUS_SUCCESS == status) {
1367                                         _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1368                                                         char_id, &gattc_desc->desc_uuid);
1369                                 }
1370                         }
1371                 }
1372         }
1373
1374         status = BT_STATUS_FAIL;
1375         _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1376
1377         browse_service_char(conn_id);
1378         /* retrive uuid for characteristic and object path for descriptor */
1379
1380         return BT_STATUS_SUCCESS;
1381 }
1382
1383 /**
1384  * Enumerate descriptors for a given characteristic.
1385  * Set start_descr_id to NULL to get the first descriptor.
1386  */
1387 bt_status_t btif_gattc_get_descriptor(int conn_id,
1388                 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1389                 btgatt_gatt_id_t *start_descr_id)
1390 {
1391         CHECK_BTGATT_INIT();
1392
1393         if (start_descr_id == NULL) {
1394                 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1395         } else {
1396                 DBG("TBD Get specific descriptor");
1397                 return BT_STATUS_UNSUPPORTED;
1398         }
1399 }
1400
1401 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1402 {
1403         struct hal_ev_gatt_client_read_data  ev;
1404
1405         if (!event_cb) {
1406                 ERR("gatt client callback not registered");
1407                 return;
1408         }
1409
1410         memset(&ev, 0, sizeof(ev));
1411         ev.conn_id = resp_data->conn_id;
1412         ev.inst_id = resp_data->srvc_id.id.inst_id;
1413         ev.is_primary = resp_data->srvc_id.is_primary;
1414         ev.status = result;
1415
1416         memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1417         memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1418
1419         ev.len = len;
1420         if (len > 0) {
1421                 /* building the char read value */
1422                 memcpy(ev.value, value, len);
1423         }
1424
1425         DBG("sending gatt client charac read event. conn_id[%d] status[%d]", resp_data->conn_id, result);
1426
1427         event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1428 }
1429
1430 static void __hal_internal_read_char_cb(GObject *source_object,
1431                 GAsyncResult *res, gpointer user_data)
1432 {
1433         GError *error = NULL;
1434         GDBusConnection *system_gconn = NULL;
1435         GVariant *value;
1436         GVariantIter *iter;
1437         GByteArray *gp_byte_array = NULL;
1438         guint8 g_byte;
1439         hal_gatt_resp_data_t *resp_data = user_data;
1440         int result = BT_STATUS_SUCCESS;
1441
1442         system_gconn = _bt_hal_get_system_gconn();
1443         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1444
1445         if (error) {
1446                 ERR("Read Characteristic dbus failed Error:[%s]", error->message);
1447
1448                 //send failed event
1449                 result  = BT_STATUS_FAIL;
1450                 __hal_send_char_read_event(resp_data, result, NULL, 0);
1451                 g_clear_error(&error);
1452                 g_free(resp_data);
1453                 return;
1454         }
1455
1456         gp_byte_array = g_byte_array_new();
1457         g_variant_get(value, "(ay)", &iter);
1458
1459         while (g_variant_iter_loop(iter, "y", &g_byte))
1460                 g_byte_array_append(gp_byte_array, &g_byte, 1);
1461
1462
1463         //send value  event
1464         __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1465
1466         g_free(resp_data);
1467
1468         g_byte_array_free(gp_byte_array, TRUE);
1469         g_variant_iter_free(iter);
1470         g_variant_unref(value);
1471
1472 }
1473
1474 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1475                 btgatt_gatt_id_t *char_id, int auth_req)
1476 {
1477         GDBusConnection *g_conn;
1478         hal_gatt_resp_data_t *resp_data;
1479         hal_gattc_service_t *gattc_service = NULL;
1480         GVariantBuilder *builder = NULL;
1481         guint16 offset = 0;
1482         hal_gattc_server_info_t * conn_info = NULL;
1483         hal_gattc_char_t *gattc_char = NULL;
1484         char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1485         char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1486         char* char_handle = NULL;
1487
1488         /* get the connection info */
1489         conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1490         if (NULL == conn_info) {
1491                 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1492                 return BT_STATUS_FAIL;
1493         }
1494
1495         /* find service */
1496         gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1497         if (NULL == gattc_service) {
1498                 ERR("Failed to get the gatt service");
1499                 return BT_STATUS_FAIL;
1500         }
1501
1502         _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1503
1504         /* find characteristic */
1505         gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1506                         HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1507         if (NULL == gattc_char) {
1508                 ERR("Failed to get the gatt char");
1509                 return BT_STATUS_FAIL;
1510         }
1511
1512         _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1513         INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1514
1515         g_conn = _bt_hal_get_system_gconn();
1516         if (NULL == g_conn) {
1517                 ERR("_bt_gdbus_get_system_gconn returned NULL");
1518                 return BT_STATUS_FAIL;
1519         }
1520
1521         resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1522         resp_data->conn_id = conn_id;
1523         memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1524         memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1525
1526         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1527
1528         /*offset*/
1529         g_variant_builder_add(builder, "{sv}", "offset",
1530                         g_variant_new("q", offset));
1531
1532         char_handle = gattc_char->chr_path;
1533
1534         g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1535                         "ReadValue", g_variant_new("(a{sv})", builder),
1536                         G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1537                         (GAsyncReadyCallback)__hal_internal_read_char_cb,
1538                         (gpointer)resp_data);
1539         g_variant_builder_unref(builder);
1540
1541         return BT_STATUS_SUCCESS;
1542 }
1543
1544 /** Read a characteristic on a remote device */
1545 bt_status_t btif_read_characteristic(int conn_id,
1546                 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1547                 int auth_req)
1548 {
1549         CHECK_BTGATT_INIT();
1550
1551         return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1552 }
1553
1554 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1555 {
1556         struct hal_ev_gatt_client_write_result  ev;
1557
1558          if (!event_cb) {
1559                 ERR("gatt client callback not registered");
1560                 return;
1561         }
1562
1563         memset(&ev, 0, sizeof(ev));
1564         ev.conn_id = resp_data->conn_id;
1565         ev.inst_id = resp_data->srvc_id.id.inst_id;
1566         ev.is_primary = resp_data->srvc_id.is_primary;
1567         ev.status = result;
1568
1569         memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1570         memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1571
1572         DBG("sending gatt client charac write event. conn_id[%d] status[%d]", resp_data->conn_id, result);
1573
1574         event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1575 }
1576
1577 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1578                 GAsyncResult *res, gpointer user_data)
1579 {
1580         GError *error = NULL;
1581         GDBusConnection *system_gconn = NULL;
1582         GVariant *value;
1583         hal_gatt_resp_data_t *resp_data = user_data;
1584         int result = BT_STATUS_SUCCESS;
1585
1586         DBG("+");
1587
1588         system_gconn = _bt_hal_get_system_gconn();
1589         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1590
1591         if (error) {
1592                 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1593
1594                 result  = BT_STATUS_FAIL;
1595                 //send failed event
1596                 __hal_send_char_write_event(resp_data, result);
1597                 g_clear_error(&error);
1598                 g_free(resp_data);
1599                 return;
1600         }
1601
1602         //send write value  event
1603         __hal_send_char_write_event(resp_data, result);
1604
1605         g_free(resp_data);
1606         g_variant_unref(value);
1607
1608         DBG("-");
1609 }
1610
1611 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1612 {
1613         switch (type) {
1614         case HAL_GATT_WRITE_TYPE_WRITE:
1615                 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1616                 break;
1617         case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1618                 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1619                 break;
1620         default:
1621                 ERR("Unknow write type : %d", type);
1622                 return BT_STATUS_FAIL;
1623         }
1624
1625         return BT_STATUS_SUCCESS;
1626 }
1627
1628
1629 static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
1630 {
1631         GDBusConnection *conn;
1632         GVariantBuilder *builder = NULL;
1633         guint16 offset = 0;
1634         GError *err = NULL;
1635         GVariant *value;
1636         gint32 idx;
1637         guint16 att_mtu;
1638         GUnixFDList *fd_list = NULL;
1639
1640         conn = _bt_hal_get_system_gconn();
1641         if (NULL == conn) {
1642                 ERR("_bt_gdbus_get_system_gconn returned NULL");
1643                 return BT_STATUS_FAIL;
1644         }
1645
1646         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1647         //val = g_variant_new("ay", builder1);
1648
1649         g_variant_builder_add(builder, "{sv}", "offset",
1650         g_variant_new("q", offset));
1651
1652         value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1653                         "AcquireWrite", g_variant_new("(a{sv})", builder),
1654                         G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1655                         NULL, &fd_list, NULL, &err);
1656         if (err != NULL) {
1657                 g_dbus_error_strip_remote_error(err);
1658                 ERR("Error: %s", err->message);
1659                 g_error_free(err);
1660                 g_variant_builder_unref(builder);
1661                 return BT_STATUS_FAIL;
1662         }
1663
1664         g_variant_get(value, "(hq)", &idx, &att_mtu);
1665         *fd = g_unix_fd_list_get(fd_list, idx, NULL);
1666
1667         INFO("Acquired Write fd %d,  index %d, mtu %d", *fd, idx, att_mtu);
1668         *mtu = att_mtu;
1669
1670         g_object_unref(fd_list);
1671         g_variant_unref(value);
1672         g_variant_builder_unref(builder);
1673
1674         return BT_STATUS_SUCCESS;
1675 }
1676
1677 static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
1678 {
1679         GDBusConnection *conn;
1680         GVariantBuilder *builder = NULL;
1681         guint16 offset = 0;
1682         GError *err = NULL;
1683         GVariant *value;
1684         gint32 idx, notify_fd;
1685         guint16 att_mtu;
1686         GUnixFDList *fd_list = NULL;
1687
1688         conn = _bt_hal_get_system_gconn();
1689
1690         if (NULL == conn) {
1691                 ERR("_bt_gdbus_get_system_gconn returned NULL");
1692                 return BT_STATUS_FAIL;
1693         }
1694
1695
1696         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1697
1698
1699         g_variant_builder_add(builder, "{sv}", "offset",
1700                 g_variant_new("q", offset));
1701
1702         value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1703                 "AcquireNotify", g_variant_new("(a{sv})", builder),
1704                 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1705                 NULL, &fd_list, NULL, &err);
1706         if (err != NULL) {
1707                 g_dbus_error_strip_remote_error(err);
1708                 ERR("Error: %s", err->message);
1709                 g_error_free(err);
1710                 g_variant_builder_unref(builder);
1711                 return BT_STATUS_FAIL;
1712         }
1713
1714         g_variant_get(value, "(hq)", &idx, &att_mtu);
1715         notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
1716         *mtu = att_mtu;
1717
1718         INFO("Acquired Notify fd %d, mtu %d", notify_fd, *mtu);
1719
1720         *fd = notify_fd;
1721
1722         g_object_unref(fd_list);
1723         g_variant_unref(value);
1724         g_variant_builder_unref(builder);
1725
1726         return BT_STATUS_SUCCESS;
1727 }
1728
1729
1730 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1731                 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1732 {
1733         GVariant *val, *options;
1734         GVariantBuilder *builder1;
1735         GVariantBuilder *builder2;
1736         GDBusConnection *g_conn;
1737         guint16 offset = 0;
1738         int i = 0;
1739         hal_gatt_resp_data_t  *resp_data;
1740         hal_gattc_service_t *gattc_service = NULL;
1741         hal_gattc_server_info_t * conn_info = NULL;
1742         hal_gattc_char_t *gattc_char = NULL;
1743         char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1744         char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1745         char* char_handle = NULL;
1746         bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1747         int ret = BT_STATUS_SUCCESS;
1748
1749         ret = __hal_get_write_prop(write_type, &write_prop);
1750         if (BT_STATUS_FAIL == ret) {
1751                 DBG("received invalid  write type:[%d] ", write_type);
1752                 return BT_STATUS_FAIL;
1753         }
1754
1755         /* get the connection info */
1756         conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1757         if (NULL == conn_info) {
1758                 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1759                 return BT_STATUS_FAIL;
1760         }
1761
1762         /* find service */
1763         gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1764         if (NULL == gattc_service) {
1765                 ERR("Failed to get the gatt service");
1766                 return BT_STATUS_FAIL;
1767         }
1768
1769         _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1770         DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1771
1772         /* find characteristic */
1773         gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1774         if (NULL == gattc_char) {
1775                 ERR("Failed to get the gatt char");
1776                 return BT_STATUS_FAIL;
1777         }
1778
1779         _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1780         DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1781
1782         g_conn = _bt_hal_get_system_gconn();
1783         if (NULL == g_conn) {
1784                  ERR("_bt_gdbus_get_system_gconn returned NULL");
1785                 return BT_STATUS_FAIL;
1786         }
1787
1788         resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1789         resp_data->conn_id = conn_id;
1790         memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1791         memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1792
1793         char_handle = gattc_char->chr_path;
1794
1795         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1796
1797         for (i = 0; i < length; i++)
1798                 g_variant_builder_add(builder1, "y", value[i]);
1799
1800         val = g_variant_new("ay", builder1);
1801
1802         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1803         /*offset*/
1804         g_variant_builder_add(builder2, "{sv}", "offset",
1805                         g_variant_new_uint16(offset));
1806
1807         options = g_variant_new("a{sv}", builder2);
1808
1809         g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1810                         "WriteValuebyType",
1811                         g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1812                         NULL,
1813                         G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1814                         (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1815                         (gpointer)resp_data);
1816
1817         g_variant_builder_unref(builder1);
1818         g_variant_builder_unref(builder2);
1819
1820         return BT_STATUS_SUCCESS;
1821 }
1822
1823 bt_status_t btif_get_acquire_write_fd(int conn_id,
1824                 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1825                 int auth_req, int *fd, int*mtu)
1826 {
1827         CHECK_BTGATT_INIT();
1828
1829         hal_gattc_service_t *gattc_service = NULL;
1830         hal_gattc_server_info_t * conn_info = NULL;
1831         hal_gattc_char_t *gattc_char = NULL;
1832         char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1833
1834         bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1835         int ret = BT_STATUS_SUCCESS;
1836
1837         DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1838
1839         /* get the connection info */
1840         conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1841         if (NULL == conn_info) {
1842                 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1843                 return BT_STATUS_FAIL;
1844         }
1845
1846         /* find service */
1847         gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1848         if (NULL == gattc_service) {
1849                 ERR("Failed to get the gatt service");
1850                 return BT_STATUS_FAIL;
1851         }
1852
1853         gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1854         if (NULL == gattc_char) {
1855                 ERR("Failed to get the gatt char");
1856                 return BT_STATUS_FAIL;
1857         }
1858
1859         _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1860         INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1861
1862         ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
1863         if (ret != BT_STATUS_SUCCESS)
1864                 return ret;
1865
1866         return ret;
1867 }
1868
1869 bt_status_t btif_get_acquire_notify_fd(int conn_id,
1870                 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
1871 {
1872         CHECK_BTGATT_INIT();
1873
1874         hal_gattc_service_t *gattc_service = NULL;
1875         hal_gattc_server_info_t * conn_info = NULL;
1876         hal_gattc_char_t *gattc_char = NULL;
1877         char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1878
1879         bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1880         int ret = BT_STATUS_SUCCESS;
1881
1882         DBG("svc isntance id [%d]", srvc_id->id.inst_id);
1883
1884         /* get the connection info */
1885         conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1886         if (NULL == conn_info) {
1887                 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1888                 return BT_STATUS_FAIL;
1889         }
1890
1891         /* find service */
1892         gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1893         if (NULL == gattc_service) {
1894                 ERR("Failed to get the gatt service");
1895                 return BT_STATUS_FAIL;
1896         }
1897
1898         gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1899         if (NULL == gattc_char) {
1900                 ERR("Failed to get the gatt char");
1901                 return BT_STATUS_FAIL;
1902         }
1903
1904         _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1905         INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1906
1907         ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
1908         if (ret != BT_STATUS_SUCCESS)
1909                 return ret;
1910
1911         return ret;
1912 }
1913
1914
1915 /** Write a remote characteristic */
1916 bt_status_t btif_write_characteristic(int conn_id,
1917                 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1918                 int write_type, int len, int auth_req,
1919                 char* p_value)
1920 {
1921         CHECK_BTGATT_INIT();
1922
1923         DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1924         return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1925                                 len, auth_req, p_value);
1926 }
1927
1928 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1929 {
1930         struct hal_ev_gatt_client_read_data  ev;
1931
1932          if (!event_cb) {
1933                 ERR("gatt client callback not registered");
1934                 return;
1935         }
1936
1937         memset(&ev, 0, sizeof(ev));
1938         ev.conn_id = resp_data->conn_id;
1939         ev.inst_id = resp_data->srvc_id.id.inst_id;
1940         ev.is_primary = resp_data->srvc_id.is_primary;
1941         ev.status = result;
1942
1943         memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1944         memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1945         memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1946
1947         ev.len = len;
1948         if (len > 0) {
1949                 /* building the desc read value */
1950                 memcpy(ev.value, value, len);
1951         }
1952
1953         DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
1954
1955         event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
1956 }
1957
1958 static void __hal_internal_read_desc_cb(GObject *source_object,
1959                 GAsyncResult *res, gpointer user_data)
1960 {
1961         GError *error = NULL;
1962         GDBusConnection *system_gconn = NULL;
1963         GVariant *value;
1964         GVariantIter *iter;
1965         GByteArray *gp_byte_array = NULL;
1966         guint8 g_byte;
1967         hal_gatt_resp_data_t *resp_data = user_data;
1968         int result = BT_STATUS_SUCCESS;
1969         int i;
1970
1971         DBG("+");
1972
1973         system_gconn = _bt_hal_get_system_gconn();
1974         value = g_dbus_connection_call_finish(system_gconn, res, &error);
1975
1976         if (error) {
1977                 ERR("Read descriptor dbus failed Error:[%s]", error->message);
1978
1979                 //send failed event
1980                 result  = BT_STATUS_FAIL;
1981                 __hal_send_desc_read_event(resp_data, result, NULL, 0);
1982                 g_clear_error(&error);
1983                 g_free(resp_data);
1984                 return;
1985         }
1986
1987         gp_byte_array = g_byte_array_new();
1988         g_variant_get(value, "(ay)", &iter);
1989
1990         while (g_variant_iter_loop(iter, "y", &g_byte))
1991                 g_byte_array_append(gp_byte_array, &g_byte, 1);
1992
1993         //print the value
1994         DBG("value is");
1995         for (i = 0; i < gp_byte_array->len; i++)
1996                 DBG("%02x", gp_byte_array->data[i]);
1997
1998         //send value  event
1999         __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
2000
2001         g_free(resp_data);
2002
2003         g_byte_array_free(gp_byte_array, TRUE);
2004         g_variant_iter_free(iter);
2005         g_variant_unref(value);
2006
2007         DBG("-");
2008 }
2009
2010 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2011                 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
2012 {
2013         GDBusConnection *g_conn;
2014         hal_gatt_resp_data_t *resp_data;
2015         hal_gattc_service_t *gattc_service = NULL;
2016         GVariantBuilder *builder = NULL;
2017         guint16 offset = 0;
2018         hal_gattc_server_info_t * conn_info = NULL;
2019         hal_gattc_char_t *gattc_char = NULL;
2020         char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2021         char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2022         char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2023         char* desc_handle = NULL;
2024         GSList *l;
2025
2026         hal_gattc_desc_t *gattc_desc = NULL;
2027
2028         /* get the connection info */
2029         conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2030         if (NULL == conn_info) {
2031                 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2032                 return BT_STATUS_FAIL;
2033         }
2034
2035         /* find service */
2036         gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2037         if (NULL == gattc_service) {
2038                 ERR("Failed to get the gatt service");
2039                 return BT_STATUS_FAIL;
2040         }
2041
2042         _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2043         DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2044
2045         /* find characteristic */
2046         /* service can have two char with same uuid */
2047         for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2048                 gattc_char = (hal_gattc_char_t*)l->data;
2049                 if (gattc_char == NULL)
2050                         continue;
2051
2052                 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2053                         _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2054                         DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2055
2056                         /* find descriptor */
2057                         gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
2058                         if (gattc_desc) {
2059                                 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2060                                 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2061                                 break;
2062                         }
2063                 }
2064         }
2065
2066         if (NULL == gattc_desc) {
2067                 ERR("Failed to get the gatt desc");
2068                 return BT_STATUS_FAIL;
2069         }
2070
2071         g_conn = _bt_hal_get_system_gconn();
2072         if (NULL == g_conn) {
2073                  ERR("_bt_gdbus_get_system_gconn returned NULL");
2074                 return BT_STATUS_FAIL;
2075         }
2076
2077         resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2078         resp_data->conn_id = conn_id;
2079         memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2080         memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2081         memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
2082
2083         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2084
2085         /*offset*/
2086         g_variant_builder_add(builder, "{sv}", "offset",
2087                         g_variant_new("q", offset));
2088
2089         desc_handle = gattc_desc->desc_path;
2090
2091         DBG("calling desc read value");
2092
2093         g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2094                         "ReadValue", g_variant_new("(a{sv})", builder),
2095                         G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2096                         (GAsyncReadyCallback)__hal_internal_read_desc_cb,
2097                         (gpointer)resp_data);
2098         g_variant_builder_unref(builder);
2099
2100         return BT_STATUS_SUCCESS;
2101 }
2102
2103 /** Read the descriptor for a given characteristic */
2104 bt_status_t btif_read_descriptor(int conn_id,
2105                 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2106                 btgatt_gatt_id_t *descr_id, int auth_req)
2107 {
2108         CHECK_BTGATT_INIT();
2109
2110         return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
2111 }
2112
2113 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
2114 {
2115         struct hal_ev_gatt_client_write_result  ev;
2116
2117          if (!event_cb) {
2118                 ERR("gatt client callback not registered");
2119                 return;
2120         }
2121
2122         memset(&ev, 0, sizeof(ev));
2123         ev.conn_id = resp_data->conn_id;
2124         ev.inst_id = resp_data->srvc_id.id.inst_id;
2125         ev.is_primary = resp_data->srvc_id.is_primary;
2126         ev.status = result;
2127
2128         memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2129         memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2130         memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
2131
2132         DBG("sending gatt client charac write event. conn_id[%d] status[%d]", resp_data->conn_id, result);
2133
2134         event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
2135 }
2136
2137 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
2138                 GAsyncResult *res, gpointer user_data)
2139 {
2140         GError *error = NULL;
2141         GDBusConnection *system_gconn = NULL;
2142         GVariant *value;
2143         hal_gatt_resp_data_t *resp_data = user_data;
2144         int result = BT_STATUS_SUCCESS;
2145
2146         DBG("+");
2147
2148         system_gconn = _bt_hal_get_system_gconn();
2149         value = g_dbus_connection_call_finish(system_gconn, res, &error);
2150
2151         if (error) {
2152                 ERR("write descriptor dbus failed Error: [%s]", error->message);
2153
2154                 //send failed event
2155                 result  = BT_STATUS_FAIL;
2156                 __hal_send_desc_write_event(resp_data, result);
2157                 g_clear_error(&error);
2158                 g_free(resp_data);
2159                 return;
2160         }
2161
2162         //send write value  event
2163         __hal_send_desc_write_event(resp_data, result);
2164
2165         g_free(resp_data);
2166         g_variant_unref(value);
2167
2168         DBG("-");
2169 }
2170
2171 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2172                                 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
2173                                 int write_type, int length, int auth_req, char* value)
2174 {
2175         GVariant *val, *options;
2176         GVariantBuilder *builder1;
2177         GVariantBuilder *builder2;
2178         GDBusConnection *g_conn;
2179         guint16 offset = 0;
2180         int i = 0;
2181         hal_gatt_resp_data_t  *resp_data;
2182         hal_gattc_service_t *gattc_service = NULL;
2183         hal_gattc_server_info_t * conn_info = NULL;
2184         hal_gattc_char_t *gattc_char = NULL;
2185         hal_gattc_desc_t *gattc_desc = NULL;
2186         char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2187         char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2188         char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2189         char* desc_handle = NULL;
2190         bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
2191         int ret = BT_STATUS_SUCCESS;
2192         GSList *l;
2193
2194         DBG("+");
2195
2196         ret = __hal_get_write_prop(write_type, &write_prop);
2197         if (BT_STATUS_FAIL == ret) {
2198                 ERR("received invalid  write type:[%d] ", write_type);
2199                 return BT_STATUS_FAIL;
2200         }
2201
2202         /* get the connection info */
2203         conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2204         if (NULL == conn_info) {
2205                 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2206                 return BT_STATUS_FAIL;
2207         }
2208
2209         /* find service */
2210         gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2211         if (NULL == gattc_service) {
2212                 ERR("Failed to get the gatt service");
2213                 return BT_STATUS_FAIL;
2214         }
2215
2216         _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2217         DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2218
2219         /* find characteristic */
2220         /* service can have two char with same uuid */
2221         for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2222                 gattc_char = (hal_gattc_char_t*)l->data;
2223                 if (gattc_char == NULL)
2224                         continue;
2225
2226                 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2227                         _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2228                         DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2229
2230                         /* find descriptor */
2231                         gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2232                         if (gattc_desc) {
2233                                 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2234                                 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2235                                 break;
2236                         }
2237                 }
2238         }
2239
2240         if (NULL == gattc_desc) {
2241                 ERR("Failed to get the gatt desc");
2242                 return BT_STATUS_FAIL;
2243         }
2244
2245         g_conn = _bt_hal_get_system_gconn();
2246         if (NULL == g_conn) {
2247                  ERR("_bt_gdbus_get_system_gconn returned NULL");
2248                 return BT_STATUS_FAIL;
2249         }
2250
2251         resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2252         resp_data->conn_id = conn_id;
2253         memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2254         memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2255         memcpy(&resp_data->desc_id, descr_id, sizeof(btgatt_gatt_id_t));
2256
2257         desc_handle = gattc_desc->desc_path;
2258
2259         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2260
2261         for (i = 0; i < length; i++)
2262                 g_variant_builder_add(builder1, "y", value[i]);
2263
2264         val = g_variant_new("ay", builder1);
2265
2266         builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2267         /*offset*/
2268         g_variant_builder_add(builder2, "{sv}", "offset",
2269                         g_variant_new_uint16(offset));
2270
2271         options = g_variant_new("a{sv}", builder2);
2272
2273         g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2274                         "WriteValue",
2275                         g_variant_new("(@ay@a{sv})", val, options),
2276                         NULL,
2277                         G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2278                         (GAsyncReadyCallback)__hal_bluetooth_internal_desc_write_cb,
2279                         (gpointer)resp_data);
2280
2281         g_variant_builder_unref(builder1);
2282         g_variant_builder_unref(builder2);
2283
2284         return BT_STATUS_SUCCESS;
2285 }
2286
2287 /** Write a remote descriptor for a given characteristic */
2288 bt_status_t btif_write_descriptor(int conn_id,
2289                 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2290                 btgatt_gatt_id_t *descr_id, int write_type, int len,
2291                 int auth_req, char* p_value)
2292 {
2293         CHECK_BTGATT_INIT();
2294
2295         return _hal_write_descriptor_value(conn_id, srvc_id, char_id, descr_id, write_type,
2296                         len, auth_req, p_value);
2297 }
2298
2299 /** Execute a prepared write operation */
2300 bt_status_t execute_write(int conn_id, int execute)
2301 {
2302         CHECK_BTGATT_INIT();
2303         return BT_STATUS_UNSUPPORTED;
2304 }
2305
2306 static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
2307 {
2308         struct hal_ev_gatt_client_watch_notification ev;
2309         hal_gatt_resp_data_t *resp_data = user_data;
2310
2311         DBG("sending the watch register notification event");
2312         /* send the event */
2313         memset(&ev, 0, sizeof(ev));
2314         ev.conn_id = resp_data->conn_id;
2315         ev.registered = 1;
2316         ev.status = resp_data->result;
2317
2318         ev.is_primary = resp_data->srvc_id.is_primary;
2319         ev.inst_id = resp_data->srvc_id.id.inst_id;
2320
2321         memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2322         memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2323
2324         if (!event_cb)
2325                 ERR("GATT Callback not registered");
2326         else
2327                 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2328
2329         g_free(user_data);
2330
2331         return FALSE;
2332 }
2333
2334 static bt_status_t _hal_register_for_notification(int conn_id,
2335                 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2336                 btgatt_gatt_id_t *char_id)
2337 {
2338         int result = BT_STATUS_SUCCESS;
2339         GError *error = NULL;
2340         GDBusConnection *g_conn;
2341         hal_gattc_client_info_t *gattc_client = NULL;
2342         hal_gattc_server_info_t * conn_info = NULL;
2343         hal_gattc_service_t *gattc_service = NULL;
2344         hal_gattc_char_t *gattc_char = NULL;
2345         char* char_handle = NULL;
2346         char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2347         char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2348         hal_gatt_resp_data_t *resp_data;
2349
2350         DBG("+");
2351
2352         gattc_client = __bt_find_gatt_client_info(bd_addr);
2353         if (gattc_client == NULL) {
2354                 ERR("failed to get the gatt client info");
2355                 return BT_STATUS_FAIL;
2356         }
2357
2358         if (gattc_client->conn_id != conn_id) {
2359                 ERR("could not find the gatt client for client id[%d]", conn_id);
2360                 return BT_STATUS_FAIL;
2361         }
2362
2363          /* get the connection info */
2364         conn_info = __bt_find_gatt_conn_info(bd_addr);
2365         if (NULL == conn_info) {
2366                 ERR("Failed to get the conn_info");
2367                 return BT_STATUS_FAIL;
2368         }
2369
2370         if (conn_info->inst_id != gattc_client->inst_id) {
2371                 ERR("could not fild the conn_info");
2372                 return BT_STATUS_FAIL;
2373         }
2374
2375         /* find service */
2376         gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2377         if (NULL == gattc_service) {
2378                 ERR("Failed to get the gatt service");
2379                 return BT_STATUS_FAIL;
2380         }
2381
2382         _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2383         DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2384
2385
2386         /* find characteristic */
2387         gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2388         if (NULL == gattc_char) {
2389                 ERR("Failed to get the gatt char");
2390                 return BT_STATUS_FAIL;
2391         }
2392
2393         _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2394         DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2395
2396         char_handle = gattc_char->chr_path;
2397
2398         g_conn = _bt_hal_get_system_gconn();
2399         if (g_conn == NULL) {
2400                 ERR("conn NULL");
2401                 return BT_STATUS_FAIL;
2402         }
2403
2404         resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2405
2406         INFO_C("### Request StartNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2407
2408         g_dbus_connection_call_sync(g_conn,
2409                         BT_HAL_BLUEZ_NAME,
2410                         char_handle,
2411                         BT_HAL_GATT_CHAR_INTERFACE,
2412                         "StartNotify",
2413                         NULL,
2414                         NULL,
2415                         G_DBUS_CALL_FLAGS_NONE,
2416                         BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2417
2418         if (error) {
2419                 g_dbus_error_strip_remote_error(error);
2420                 ERR("### StartNotify Failed: %s", error->message);
2421                 if (g_strrstr(error->message, "Already notifying"))
2422                         result = BT_STATUS_SUCCESS;
2423                 else if (g_strrstr(error->message, "In Progress"))
2424                         result = BT_STATUS_BUSY;
2425                 else if (g_strrstr(error->message, "Operation is not supported"))
2426                         result = BT_STATUS_UNSUPPORTED;
2427                 /*failed because of either Insufficient Authorization or Write Not Permitted */
2428                 else if (g_strrstr(error->message, "Write not permitted") ||
2429                                 g_strrstr(error->message, "Operation Not Authorized"))
2430                         result = BT_STATUS_AUTH_FAILURE;
2431                 /* failed because of either Insufficient Authentication,
2432                    Insufficient Encryption Key Size, or Insufficient Encryption. */
2433                 else if (g_strrstr(error->message, "Not paired"))
2434                         result = BT_STATUS_NOT_READY;
2435                 else
2436                         result = BT_STATUS_FAIL;
2437
2438                 g_clear_error(&error);
2439         }
2440
2441         resp_data->conn_id = gattc_client->conn_id;
2442         resp_data->result = result;
2443         memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2444         memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2445
2446         g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2447
2448         DBG("-");
2449
2450         return BT_STATUS_SUCCESS;
2451 }
2452
2453 /**
2454  * Register to receive notifications or indications for a given
2455  * characteristic
2456  */
2457 bt_status_t btif_register_for_notification(int conn_id,
2458                 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2459                 btgatt_gatt_id_t *char_id)
2460 {
2461         CHECK_BTGATT_INIT();
2462
2463         return _hal_register_for_notification(conn_id, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2464 }
2465
2466 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2467 {
2468         struct hal_ev_gatt_client_watch_notification ev;
2469         hal_gatt_resp_data_t *resp_data = user_data;
2470
2471         DBG("sending the watch deregister notification event");
2472         /* send the event */
2473         memset(&ev, 0, sizeof(ev));
2474         ev.conn_id = resp_data->conn_id;
2475         ev.registered = 0;
2476         ev.status = resp_data->result;
2477
2478         ev.is_primary = resp_data->srvc_id.is_primary;
2479         ev.inst_id = resp_data->srvc_id.id.inst_id;
2480
2481         memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2482         memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2483
2484         if (!event_cb)
2485                 ERR("GATT Callback not registered");
2486         else
2487                 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2488
2489         g_free(user_data);
2490
2491         return FALSE;
2492 }
2493
2494 static bt_status_t _hal_deregister_for_notification(int conn_id,
2495                 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2496                 btgatt_gatt_id_t *char_id)
2497 {
2498         int result = BT_STATUS_SUCCESS;
2499         GError *error = NULL;
2500         GDBusConnection *g_conn;
2501         hal_gattc_client_info_t *gattc_client = NULL;
2502         hal_gattc_server_info_t * conn_info = NULL;
2503         hal_gattc_service_t *gattc_service = NULL;
2504         hal_gattc_char_t *gattc_char = NULL;
2505         char* char_handle = NULL;
2506         char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2507         char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2508         hal_gatt_resp_data_t *resp_data;
2509
2510         DBG("+");
2511
2512         gattc_client = __bt_find_gatt_client_info(bd_addr);
2513         if (gattc_client == NULL) {
2514                 ERR("failed to get the gatt client info");
2515                 return BT_STATUS_FAIL;
2516         }
2517
2518         if (gattc_client->conn_id != conn_id) {
2519                 ERR("could not find the gatt client for client id[%d]", conn_id);
2520                 return BT_STATUS_FAIL;
2521         }
2522
2523          /* get the connection info */
2524         conn_info = __bt_find_gatt_conn_info(bd_addr);
2525         if (NULL == conn_info) {
2526                 ERR("Failed to get the conn_info");
2527                 return BT_STATUS_FAIL;
2528         }
2529
2530         if (conn_info->inst_id != gattc_client->inst_id) {
2531                 ERR("could not fild the conn_info");
2532                 return BT_STATUS_FAIL;
2533         }
2534
2535         /* find service */
2536         gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2537         if (NULL == gattc_service) {
2538                 ERR("Failed to get the gatt service");
2539                 return BT_STATUS_FAIL;
2540         }
2541
2542         _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2543         DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2544
2545
2546         /* find characteristic */
2547         gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2548         if (NULL == gattc_char) {
2549                 ERR("Failed to get the gatt char");
2550                 return BT_STATUS_FAIL;
2551         }
2552
2553         _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2554         DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2555
2556         char_handle = gattc_char->chr_path;
2557
2558         g_conn = _bt_hal_get_system_gconn();
2559         if (g_conn == NULL) {
2560                 ERR("conn NULL");
2561                 return BT_STATUS_FAIL;
2562         }
2563
2564         resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2565
2566         INFO("### Request StopNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2567         g_dbus_connection_call_sync(g_conn,
2568                         BT_HAL_BLUEZ_NAME,
2569                         char_handle,
2570                         BT_HAL_GATT_CHAR_INTERFACE,
2571                         "StopNotify",
2572                         NULL,
2573                         NULL,
2574                         G_DBUS_CALL_FLAGS_NONE,
2575                         BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2576
2577         if (error) {
2578                 ERR("### StopNotify Failed: %s", error->message);
2579                 g_clear_error(&error);
2580                 result = BT_STATUS_FAIL;
2581         }
2582
2583         resp_data->conn_id = gattc_client->conn_id;
2584         resp_data->result = result;
2585         memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2586         memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2587
2588         g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2589
2590         DBG("-");
2591
2592         return BT_STATUS_SUCCESS;
2593 }
2594 /** Deregister a previous request for notifications/indications */
2595 bt_status_t btif_deregister_for_notification(int conn_id,
2596                 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2597                 btgatt_gatt_id_t *char_id)
2598 {
2599         CHECK_BTGATT_INIT();
2600         return _hal_deregister_for_notification(conn_id, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2601 }
2602
2603 /** Request RSSI for a given remote device */
2604 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2605 {
2606         CHECK_BTGATT_INIT();
2607         return BT_STATUS_UNSUPPORTED;
2608 }
2609
2610 /** OTA firmware download */
2611 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2612 {
2613         CHECK_BTGATT_INIT();
2614         return BT_STATUS_UNSUPPORTED;
2615 }
2616
2617 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2618 int get_device_type(const bt_bdaddr_t *bd_addr)
2619 {
2620         CHECK_BTGATT_INIT();
2621         return BT_STATUS_UNSUPPORTED;
2622 }
2623
2624 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2625                         int min_int, int max_int, int latency, int timeout)
2626 {
2627         gchar *device_path = NULL;
2628         GError *error = NULL;
2629         GDBusProxy *device_proxy = NULL;
2630         GDBusConnection *conn;
2631         GVariant *reply;
2632         int ret = BT_STATUS_SUCCESS;
2633         char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2634
2635         INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2636                         min_int, max_int, latency, timeout);
2637
2638         conn = _bt_hal_get_system_gconn();
2639         if (conn == NULL) {
2640                 ERR("conn NULL");
2641                 return BT_STATUS_FAIL;
2642         }
2643
2644         _bt_hal_convert_addr_type_to_string(device_address,
2645                                 (unsigned char *)bd_addr->address);
2646         device_path = _bt_hal_get_device_object_path(device_address);
2647
2648         if (device_path == NULL) {
2649                 ERR("device_path NULL : [%s]", device_address);
2650                 return BT_STATUS_FAIL;
2651         }
2652
2653         device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2654                         NULL, BT_HAL_BLUEZ_NAME,
2655                         device_path, BT_HAL_DEVICE_INTERFACE,  NULL, NULL);
2656
2657         g_free(device_path);
2658         if (NULL == device_proxy) {
2659                 ERR("device_proxy returned NULL");
2660                 return BT_STATUS_FAIL;
2661         }
2662
2663         INFO("Request LeConnUpdate");
2664         reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2665                         g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2666                         G_DBUS_CALL_FLAGS_NONE,
2667                         -1,
2668                         NULL,
2669                         &error);
2670
2671         g_object_unref(device_proxy);
2672         if (reply == NULL) {
2673                 if (error) {
2674                         ERR("Error %s[%s]", error->message, device_address);
2675                         if (g_strrstr(error->message, "In Progress"))
2676                                 ret = BT_STATUS_SUCCESS;
2677                         else
2678                                 ret = BT_STATUS_FAIL;
2679                         g_error_free(error);
2680                         return ret;
2681                 }
2682         }
2683         g_variant_unref(reply);
2684
2685         DBG("LE Connection parameter Updated");
2686         return ret;
2687 }
2688
2689 /** Request a connection parameter update */
2690 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2691 {
2692         CHECK_BTGATT_INIT();
2693
2694         return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2695 }
2696
2697 /** Test mode interface */
2698 bt_status_t test_command(int command, btgatt_test_params_t* params)
2699 {
2700         CHECK_BTGATT_INIT();
2701         return BT_STATUS_UNSUPPORTED;
2702 }
2703
2704 static void __bt_request_att_mtu_device_cb(GDBusProxy *proxy, GAsyncResult *res,
2705                                                         gpointer user_data)
2706 {
2707         GError *g_error = NULL;
2708         GVariant *reply = NULL;
2709         int result = BT_STATUS_SUCCESS;
2710         struct hal_ev_gatt_client_mtu_exchange_completed  ev;
2711         struct conn_mtu_s *conn_mtu = (struct conn_mtu_s *)user_data;
2712
2713         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2714         g_object_unref(proxy);
2715         if (reply == NULL) {
2716                 ERR("Connect LE Dbus Call Error");
2717                 if (g_error) {
2718                         ERR("Error occured in RequestAttMtu [%s]", g_error->message);
2719                         g_clear_error(&g_error);
2720                 }
2721                 result = BT_STATUS_FAIL;
2722         }
2723         g_variant_unref(reply);
2724
2725         memset(&ev, 0, sizeof(ev));
2726         ev.status = result;
2727         ev.mtu = conn_mtu->mtu;
2728         ev.conn_id = conn_mtu->conn_id;
2729
2730         if (!event_cb) {
2731                 ERR("gatt client callback not registered");
2732         } else {
2733                 DBG("sending gatt client MTU exchange completed event");
2734                 event_cb(HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED  , (void *)&ev, sizeof(ev));
2735         }
2736
2737         g_free(conn_mtu);
2738 }
2739
2740
2741 static bt_status_t __hal_configure_mtu(int conn_id, int mtu)
2742 {
2743         gchar *device_path = NULL;
2744         GDBusProxy *device_proxy = NULL;
2745         GDBusConnection *conn;
2746         hal_gattc_client_info_t *gattc_client = NULL;
2747         char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2748         struct conn_mtu_s *conn_mtu = g_malloc0(sizeof(struct conn_mtu_s));
2749
2750         conn = _bt_hal_get_system_gconn();
2751         if (conn == NULL) {
2752                 ERR("conn NULL");
2753                 g_free(conn_mtu);
2754                 return BT_STATUS_FAIL;
2755         }
2756
2757         gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2758         if (gattc_client == NULL) {
2759                 INFO("GATT client conn info not found");
2760                 g_free(conn_mtu);
2761                 return BT_STATUS_FAIL;
2762         }
2763
2764         _bt_hal_convert_addr_type_to_string(device_address,
2765                                 (unsigned char *)gattc_client->bd_addr.address);
2766
2767         device_path = _bt_hal_get_device_object_path(device_address);
2768         if (device_path == NULL) {
2769                 ERR("device_path NULL : [%s]", device_address);
2770                 g_free(conn_mtu);
2771                 return BT_STATUS_FAIL;
2772         }
2773
2774         device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2775                         NULL, BT_HAL_BLUEZ_NAME,
2776                         device_path, BT_HAL_DEVICE_INTERFACE,  NULL, NULL);
2777
2778         g_free(device_path);
2779         if (NULL == device_proxy) {
2780                 ERR("device_proxy returned NULL");
2781                 g_free(conn_mtu);
2782                 return BT_STATUS_FAIL;
2783         }
2784
2785         conn_mtu->conn_id = conn_id;
2786         conn_mtu->mtu = mtu;
2787
2788         g_dbus_proxy_call(device_proxy, "RequestAttMtu",
2789                         g_variant_new("(q)", mtu),
2790                         G_DBUS_CALL_FLAGS_NONE,
2791                         BT_HAL_MAX_DBUS_TIMEOUT,
2792                         NULL,
2793                         (GAsyncReadyCallback)__bt_request_att_mtu_device_cb,
2794                         conn_mtu);
2795
2796         return BT_STATUS_SUCCESS;
2797 }
2798
2799 /** MTU Exchange request from client */
2800 static bt_status_t configure_mtu(int conn_id, int mtu)
2801 {
2802         CHECK_BTGATT_INIT();
2803
2804         return __hal_configure_mtu(conn_id, mtu);
2805 }
2806
2807 /** Setup scan filter params */
2808 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2809                 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2810                 int rssi_low_thres, int dely_mode, int found_timeout,
2811                 int lost_timeout, int found_timeout_cnt)
2812 {
2813         GDBusProxy *proxy;
2814         GError *error = NULL;
2815         GVariant *ret, *param;
2816         CHECK_BTGATT_INIT();
2817
2818         proxy = _bt_hal_get_adapter_proxy();
2819
2820         if (proxy == NULL)
2821                 return BT_STATUS_FAIL;
2822
2823         param = g_variant_new("(iiiiiiiiiiii)",
2824                                 client_if,
2825                                 action,
2826                                 filt_index,
2827                                 feat_seln,
2828                                 list_logic_type,
2829                                 filt_logic_type,
2830                                 rssi_high_thres,
2831                                 rssi_low_thres,
2832                                 dely_mode,
2833                                 found_timeout,
2834                                 lost_timeout,
2835                                 found_timeout_cnt);
2836         ret = g_dbus_proxy_call_sync(proxy, "scan_filter_param_setup",
2837                         param, G_DBUS_CALL_FLAGS_NONE,
2838                         -1, NULL, &error);
2839
2840         if (error) {
2841                 ERR("scan_filter_param_setup Fail: %s", error->message);
2842                 g_clear_error(&error);
2843                 return BT_STATUS_FAIL;
2844         }
2845
2846         if (ret)
2847                 g_variant_unref(ret);
2848
2849         return BT_STATUS_SUCCESS;
2850 }
2851
2852 /** Configure a scan filter condition */
2853 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2854                 int filt_index, int company_id,
2855                 int company_id_mask, const bt_uuid_t *p_uuid,
2856                 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2857                 char addr_type, int data_len, char* p_data, int mask_len,
2858                 char* p_mask)
2859 {
2860         GDBusProxy *proxy;
2861         GError *error = NULL;
2862         GVariant *ret, *param;
2863         GVariant *arr_uuid_param = NULL, *arr_uuid_mask_param = NULL;
2864         GVariant *arr_data_param = NULL, *arr_data_mask_param = NULL;
2865         GArray *arr_uuid = NULL;
2866         GArray *arr_uuid_mask = NULL;
2867         GArray *arr_data = NULL;
2868         GArray *arr_data_mask = NULL;
2869         CHECK_BTGATT_INIT();
2870
2871         proxy = _bt_hal_get_adapter_proxy();
2872
2873         if (proxy == NULL)
2874                 return BT_STATUS_FAIL;
2875
2876         if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS) {
2877
2878                 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2879
2880                 _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
2881
2882                 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS being added\nRemote Device Address is [%s]", address);
2883
2884                 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2885                                 NULL, 0, TRUE, NULL, NULL);
2886                 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2887                                 NULL, 0, TRUE, NULL, NULL);
2888                 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2889                                 NULL, 0, TRUE, NULL, NULL);
2890                 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2891                                 NULL, 0, TRUE, NULL, NULL);
2892
2893                 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2894                                         client_if,      // client_if
2895                                         action,      // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2896                                         BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS,        // filter_type
2897                                         filt_index,       // filter_index
2898                                         company_id,      // company_id
2899                                         company_id_mask,      // company_id_mask
2900                                         arr_uuid_param, // p_uuid
2901                                         arr_uuid_mask_param,    // p_uuid_mask
2902                                         address,        // string
2903                                         addr_type,      // address_type
2904                                         arr_data_param, // p_data
2905                                         arr_data_mask_param);   // p_mask
2906
2907                 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2908                                 param, G_DBUS_CALL_FLAGS_NONE,
2909                                 -1, NULL, &error);
2910
2911                 if (error) {
2912                         ERR("scan_filter_add_remove Fail: %s", error->message);
2913                         g_clear_error(&error);
2914                         return BT_STATUS_FAIL;
2915                 }
2916
2917                 if (ret)
2918                         g_variant_unref(ret);
2919
2920                 return BT_STATUS_SUCCESS;
2921         }
2922
2923         if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_NAME) {
2924
2925                 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_NAME being added\nRemote Device Name is %s", p_data);
2926                 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2927                                 NULL, 0, TRUE, NULL, NULL);
2928                 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2929                                 NULL, 0, TRUE, NULL, NULL);
2930                 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2931                                 NULL, 0, TRUE, NULL, NULL);
2932                 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2933                                 NULL, 0, TRUE, NULL, NULL);
2934
2935                 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2936                                         client_if,      // client_if
2937                                         action,      // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2938                                         BT_SCAN_FILTER_FEATURE_DEVICE_NAME,   // filter_type
2939                                         filt_index,       // filter_index
2940                                         company_id,      // company_id
2941                                         company_id_mask,      // company_id_mask
2942                                         arr_uuid_param, // p_uuid
2943                                         arr_uuid_mask_param,    // p_uuid_mask
2944                                         p_data,    // string
2945                                         addr_type,      // address_type
2946                                         arr_data_param, // p_data
2947                                         arr_data_mask_param);
2948
2949                 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2950                                 param, G_DBUS_CALL_FLAGS_NONE,
2951                                 -1, NULL, &error);
2952
2953                 if (error) {
2954                         ERR("scan_filter_add_remove Fail: %s", error->message);
2955                         g_clear_error(&error);
2956                         return BT_STATUS_FAIL;
2957                 }
2958
2959                 if (ret)
2960                         g_variant_unref(ret);
2961
2962                 return BT_STATUS_SUCCESS;
2963         }
2964
2965         if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_UUID) {
2966
2967                 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
2968                 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
2969
2970                 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
2971                 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
2972
2973                 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2974                                 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
2975                 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2976                                 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
2977                 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2978                                 NULL, 0, TRUE, NULL, NULL);
2979                 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2980                                 NULL, 0, TRUE, NULL, NULL);
2981
2982                 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2983                                         client_if,      // client_if
2984                                         action,      // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2985                                         BT_SCAN_FILTER_FEATURE_SERVICE_UUID,  // filter_type
2986                                         filt_index,       // filter_index
2987                                         company_id,      // company_id
2988                                         company_id_mask,      // company_id_mask
2989                                         arr_uuid_param, // p_uuid
2990                                         arr_uuid_mask_param,    // p_uuid_mask
2991                                         "",   // string
2992                                         addr_type,      // address_type
2993                                         arr_data_param, // p_data
2994                                         arr_data_mask_param);
2995
2996                 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2997                                 param, G_DBUS_CALL_FLAGS_NONE,
2998                                 -1, NULL, &error);
2999
3000                 if (error) {
3001                         ERR("scan_filter_add_remove Fail: %s", error->message);
3002                         g_clear_error(&error);
3003                         return BT_STATUS_FAIL;
3004                 }
3005
3006                 if (ret)
3007                         g_variant_unref(ret);
3008
3009                 g_array_free(arr_uuid, TRUE);
3010                 g_array_free(arr_uuid_mask, TRUE);
3011
3012                 return BT_STATUS_SUCCESS;
3013         }
3014
3015         if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID) {
3016
3017                 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3018                 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3019
3020                 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3021                 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3022
3023                 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3024                                 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3025                 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3026                                 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3027                 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3028                                 NULL, 0, TRUE, NULL, NULL);
3029                 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3030                                 NULL, 0, TRUE, NULL, NULL);
3031
3032                 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3033                                         client_if,      // client_if
3034                                         action,      // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3035                                         BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID,     // filter_type
3036                                         filt_index,       // filter_index
3037                                         company_id,      // company_id
3038                                         company_id_mask,      // company_id_mask
3039                                         arr_uuid_param, // p_uuid
3040                                         arr_uuid_mask_param,    // p_uuid_mask
3041                                         "",   // string
3042                                         addr_type,      // address_type
3043                                         arr_data_param, // p_data
3044                                         arr_data_mask_param);
3045
3046                 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3047                                 G_DBUS_CALL_FLAGS_NONE,
3048                                 -1, NULL, &error);
3049
3050                 if (error) {
3051                         ERR("scan_filter_add_remove Fail: %s", error->message);
3052                         g_clear_error(&error);
3053                         return BT_STATUS_FAIL;
3054                 }
3055
3056                 if (ret)
3057                         g_variant_unref(ret);
3058
3059                 g_array_free(arr_uuid, TRUE);
3060                 g_array_free(arr_uuid_mask, TRUE);
3061
3062                 return BT_STATUS_SUCCESS;
3063         }
3064
3065         if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_DATA) {
3066
3067                 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3068                 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3069
3070                 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3071                 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3072
3073                 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3074                                 NULL, 0, TRUE, NULL, NULL);
3075                 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3076                                 NULL, 0, TRUE, NULL, NULL);
3077                 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3078                                 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3079                                 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3080                                 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3081
3082                 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3083                                         client_if,      // client_if
3084                                         action,      // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3085                                         BT_SCAN_FILTER_FEATURE_SERVICE_DATA,  // filter_type
3086                                         filt_index,       // filter_index
3087                                         company_id,      // company_id
3088                                         company_id_mask,      // company_id_mask
3089                                         arr_uuid_param, // p_uuid
3090                                         arr_uuid_mask_param,    // p_uuid_mask
3091                                         "",   // string
3092                                         addr_type,      // address_type
3093                                         arr_data_param, // p_data
3094                                         arr_data_mask_param);
3095
3096                 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3097                                 G_DBUS_CALL_FLAGS_NONE,
3098                                 -1, NULL, &error);
3099
3100                 if (error) {
3101                         ERR("scan_filter_add_remove Fail: %s", error->message);
3102                         g_clear_error(&error);
3103                         return BT_STATUS_FAIL;
3104                 }
3105
3106                 if (ret)
3107                         g_variant_unref(ret);
3108
3109                 g_array_free(arr_data, TRUE);
3110                 g_array_free(arr_data_mask, TRUE);
3111
3112                 return BT_STATUS_SUCCESS;
3113         }
3114
3115         if (filt_type == BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA) {
3116
3117                 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3118                 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3119
3120                 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3121                 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3122
3123                 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3124                                 NULL, 0, TRUE, NULL, NULL);
3125                 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3126                                 NULL, 0, TRUE, NULL, NULL);
3127                 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3128                                 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3129                 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3130                                 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3131
3132                 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3133                                         client_if,      // client_if
3134                                         action,      // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3135                                         BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA,     // filter_type
3136                                         filt_index,       // filter_index
3137                                         company_id,        // company_id
3138                                         company_id_mask, // company_id_mask
3139                                         arr_uuid_param, // p_uuid
3140                                         arr_uuid_mask_param,    // p_uuid_mask
3141                                         "",   // string
3142                                         addr_type,      // address_type
3143                                         arr_data_param, // p_data
3144                                         arr_data_mask_param);
3145
3146                 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3147                                 G_DBUS_CALL_FLAGS_NONE,
3148                                 -1, NULL, &error);
3149
3150                 if (error) {
3151                         ERR("scan_filter_add_remove Fail: %s", error->message);
3152                         g_clear_error(&error);
3153                         return BT_STATUS_FAIL;
3154                 }
3155
3156                 if (ret)
3157                         g_variant_unref(ret);
3158
3159                 g_array_free(arr_data, TRUE);
3160                 g_array_free(arr_data_mask, TRUE);
3161
3162                 return BT_STATUS_SUCCESS;
3163         }
3164
3165         return BT_STATUS_UNSUPPORTED;
3166 }
3167
3168 /** Clear all scan filter conditions for specific filter index*/
3169 bt_status_t scan_filter_clear(int client_if, int filt_index)
3170 {
3171         GDBusProxy *proxy;
3172         GError *error = NULL;
3173         GVariant *ret;
3174         CHECK_BTGATT_INIT();
3175
3176         proxy = _bt_hal_get_adapter_proxy();
3177         if (proxy == NULL)
3178                 return BT_STATUS_FAIL;
3179
3180         ret = g_dbus_proxy_call_sync(proxy, "scan_filter_clear",
3181                                 g_variant_new("(ii)", client_if, filt_index),
3182                                 G_DBUS_CALL_FLAGS_NONE,
3183                                 -1, NULL, &error);
3184
3185         if (error) {
3186                 ERR("scan_filter_clear Fail: %s", error->message);
3187                 g_clear_error(&error);
3188                 return BT_STATUS_FAIL;
3189         }
3190         if (ret)
3191                 g_variant_unref(ret);
3192         return BT_STATUS_SUCCESS;
3193 }
3194
3195 /** Enable / disable scan filter feature*/
3196 bt_status_t scan_filter_enable(int client_if, bool enable)
3197 {
3198         GDBusProxy *proxy;
3199         GError *error = NULL;
3200         GVariant *ret;
3201         CHECK_BTGATT_INIT();
3202
3203         proxy = _bt_hal_get_adapter_proxy();
3204         if (proxy == NULL)
3205                 return BT_STATUS_FAIL;
3206
3207         ret = g_dbus_proxy_call_sync(proxy, "scan_filter_enable",
3208                                 g_variant_new("(ib)", client_if, enable),
3209                                 G_DBUS_CALL_FLAGS_NONE,
3210                                 -1, NULL, &error);
3211
3212         if (error) {
3213                 ERR("scan_filter_enable Fail: %s", error->message);
3214                 g_clear_error(&error);
3215                 return BT_STATUS_FAIL;
3216         }
3217         g_variant_unref(ret);
3218
3219         return BT_STATUS_SUCCESS;
3220 }
3221
3222 /** Sets the LE scan interval and window in units of N*0.625 msec */
3223 #ifdef TIZEN_BT_HAL
3224 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
3225 {
3226         int ret;
3227
3228         CHECK_BTGATT_INIT();
3229
3230         le_scan_type = scan_type;
3231         ret = _bt_hal_adapter_le_set_scan_parameters(
3232                         scan_type, scan_interval, scan_window);
3233         return ret;
3234 }
3235 #else
3236 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
3237 {
3238         CHECK_BTGATT_INIT();
3239         return BT_STATUS_UNSUPPORTED;
3240 }
3241 #endif
3242
3243 /* Configure the batchscan storage */
3244 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
3245                 int batch_scan_trunc_max, int batch_scan_notify_threshold)
3246 {
3247         CHECK_BTGATT_INIT();
3248         return BT_STATUS_UNSUPPORTED;
3249 }
3250
3251 /* Enable batchscan */
3252 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
3253                 int scan_interval, int scan_window, int addr_type, int discard_rule)
3254 {
3255         CHECK_BTGATT_INIT();
3256         return BT_STATUS_UNSUPPORTED;
3257 }
3258
3259 /* Disable batchscan */
3260 bt_status_t batchscan_dis_batch_scan(int client_if)
3261 {
3262         CHECK_BTGATT_INIT();
3263         return BT_STATUS_UNSUPPORTED;
3264 }
3265
3266 /* Read out batchscan reports */
3267 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
3268 {
3269         CHECK_BTGATT_INIT();
3270         return BT_STATUS_UNSUPPORTED;
3271 }
3272
3273 const btgatt_client_interface_t btgatt_client_interface = {
3274         .register_client = btif_gattc_register_client,
3275         .unregister_client = btif_gattc_unregister_client,
3276         .scan = scan,
3277         .connect = btif_gattc_client_connect,
3278         .disconnect = btif_gattc_client_disconnect,
3279         .refresh = refresh,
3280         .search_service = btif_gattc_client_search_service,
3281         .get_included_service = get_included_service,
3282         .get_characteristic = btif_gattc_get_characteristic,
3283         .get_descriptor = btif_gattc_get_descriptor,
3284         .read_characteristic = btif_read_characteristic,
3285         .write_characteristic = btif_write_characteristic,
3286         .acquire_write = btif_get_acquire_write_fd,
3287         .acquire_notify = btif_get_acquire_notify_fd,
3288         .read_descriptor = btif_read_descriptor,
3289         .write_descriptor = btif_write_descriptor,
3290         .execute_write = execute_write,
3291         .register_for_notification = btif_register_for_notification,
3292         .deregister_for_notification = btif_deregister_for_notification,
3293         .read_remote_rssi = read_remote_rssi,
3294         .ota_fw_update = ota_fw_update,
3295         .get_device_type = get_device_type,
3296         .conn_parameter_update = btif_gattc_conn_parameter_update,
3297         .test_command = test_command,
3298         .configure_mtu = configure_mtu,
3299         .scan_filter_param_setup = scan_filter_param_setup,
3300         .scan_filter_add_remove = scan_filter_add_remove,
3301         .scan_filter_clear = scan_filter_clear,
3302         .scan_filter_enable = scan_filter_enable,
3303         .set_scan_parameters = set_scan_parameters,
3304         .batchscan_cfg_storage = batchscan_cfg_storage,
3305         .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
3306         .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
3307         .batchscan_read_reports = batchscan_read_reports,
3308         .add_connection_info = btif_gattc_add_connection_info,
3309 };
3310
3311 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr)
3312 {
3313         GSList *l;
3314         hal_gattc_server_info_t *info = NULL;
3315
3316         for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3317                 info = (hal_gattc_server_info_t*)l->data;
3318                 if (info == NULL)
3319                         continue;
3320
3321                 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3322                         return info;
3323                 }
3324
3325         return NULL;
3326 }
3327
3328 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
3329 {
3330         GSList *l;
3331         hal_gattc_client_info_t *info = NULL;
3332
3333         for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3334                 info = (hal_gattc_client_info_t*)l->data;
3335                 if (info == NULL)
3336                         continue;
3337
3338                 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3339                         return info;
3340                 }
3341
3342         return NULL;
3343 }
3344
3345 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
3346 {
3347         GSList *l;
3348         hal_gattc_client_info_t *info = NULL;
3349
3350         for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3351                 info = (hal_gattc_client_info_t*)l->data;
3352                 if (info == NULL)
3353                         continue;
3354
3355                 if (info->conn_id == conn_id)
3356                         return info;
3357                 }
3358
3359         return NULL;
3360 }
3361
3362 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int  conn_id)
3363 {
3364         GSList *l;
3365         hal_gattc_server_info_t *info = NULL;
3366         hal_gattc_client_info_t *gattc_client = NULL;
3367
3368         gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
3369         if (gattc_client == NULL) {
3370                 ERR("GATT client conn info not found");
3371                 return NULL;
3372         }
3373
3374         for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3375                 info = (hal_gattc_server_info_t*)l->data;
3376                 if (info == NULL)
3377                         continue;
3378
3379                 if ((info->inst_id == gattc_client->inst_id) &&
3380                         !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
3381                         return info;
3382                 }
3383         }
3384         return NULL;
3385 }
3386
3387 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
3388                 gboolean auto_connect)
3389 {
3390         char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3391         gchar *device_path = NULL;
3392         GDBusProxy *device_proxy = NULL;
3393         GDBusConnection *conn;
3394         int ret = BT_STATUS_SUCCESS;
3395         hal_gattc_client_info_t *gattc_data;
3396
3397         if (NULL == bd_addr) {
3398                 ERR("bd_addr is NULL");
3399                 return BT_STATUS_PARM_INVALID;
3400         }
3401
3402         conn = _bt_hal_get_system_gconn();
3403         if (NULL == conn) {
3404                 ERR("_bt_gdbus_get_system_gconn returned NULL");
3405                 return BT_STATUS_FAIL;
3406         }
3407
3408         _bt_hal_convert_addr_type_to_string(device_address,
3409                         (unsigned char *)bd_addr->address);
3410         device_path = _bt_hal_get_device_object_path(device_address);
3411         if (device_path == NULL) {
3412                 ERR("device_path NULL : [%s]", device_address);
3413                 ret = BT_STATUS_FAIL;
3414                 return ret;
3415         }
3416
3417         device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3418                         NULL, BT_HAL_BLUEZ_NAME,
3419                         device_path, BT_HAL_DEVICE_INTERFACE,  NULL, NULL);
3420         g_free(device_path);
3421         if (NULL == device_proxy) {
3422                 ERR("device_proxy returned NULL");
3423                 return BT_STATUS_FAIL;
3424         }
3425
3426         gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
3427         memcpy(gattc_data->bd_addr.address, bd_addr->address,
3428                                         BT_HAL_ADDRESS_LENGTH_MAX);
3429
3430         DBG("ConnectLE [%s]", device_address);
3431
3432         gattc_data->client_if = client_if;
3433
3434         g_dbus_proxy_call(device_proxy, "ConnectLE",
3435                         g_variant_new("(b)", auto_connect),
3436                         G_DBUS_CALL_FLAGS_NONE,
3437                         BT_HAL_MAX_DBUS_TIMEOUT,
3438                         NULL,
3439                         (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
3440
3441         return ret;
3442 }
3443
3444 static bt_status_t _bt_hold_current_advertising()
3445 {
3446         int ret = BT_STATUS_FAIL;
3447         gboolean is_advertising = FALSE;
3448         DBG("+");
3449
3450         is_advertising = _bt_hal_is_advertising_in_slot(0);
3451         if (is_advertising) {
3452                 DBG("+ Stop current advertising");
3453
3454                 ret = _bt_hal_enable_advertising(0, 0, FALSE, FALSE);
3455                 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3456         }
3457
3458         return ret;
3459 }
3460
3461 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3462 {
3463         DBG("+ start current advertising");
3464
3465         _bt_hal_enable_advertising(0, 0, TRUE, FALSE);
3466
3467         return FALSE;
3468 }
3469
3470 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3471 {
3472         DBG("Try to initiate pending LE connection");
3473
3474         pending_le_conn_timer_id = 0;
3475
3476         __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3477                         &pending_le_conn_info->bd_addr,
3478                         pending_le_conn_info->auto_connect);
3479
3480         g_free(pending_le_conn_info);
3481         pending_le_conn_info = NULL;
3482
3483         return FALSE;
3484 }
3485
3486 static int __hal_generate_conn_id()
3487 {
3488          return ++bt_conn_id;
3489 }
3490
3491 static int __hal_generate_server_instance_id()
3492 {
3493         return ++bt_inst_id;
3494 }
3495
3496 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3497                 gpointer user_data)
3498 {
3499         GError *g_error = NULL;
3500         GVariant *reply = NULL;
3501         hal_gattc_client_info_t *gattc_data  = user_data;
3502         int result = BT_STATUS_SUCCESS;
3503         struct hal_ev_gatt_client_connected ev;
3504         hal_gattc_server_info_t *gatt_conn_info = NULL;
3505
3506         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3507         g_object_unref(proxy);
3508         if (reply == NULL) {
3509                 ERR("Connect LE Dbus Call Error");
3510                 if (g_error) {
3511                         ERR("Error: %s\n", g_error->message);
3512                         g_clear_error(&g_error);
3513                 }
3514                 result = BT_STATUS_FAIL;
3515         }
3516         g_variant_unref(reply);
3517
3518         if (NULL == gattc_data) {
3519                 ERR("gattc_data is NULL");
3520                 return;
3521         }
3522
3523         /*send fail event*/
3524         if (result == BT_STATUS_FAIL) {
3525                 memset(&ev, 0, sizeof(ev));
3526                 ev.conn_id = -1;
3527                 ev.status = result;
3528                 ev.client_if = gattc_data->client_if;
3529                 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3530                                                 BT_HAL_ADDRESS_LENGTH_MAX);
3531
3532                 if (!event_cb) {
3533                         ERR("gatt client callback not registered");
3534                 } else {
3535                         DBG("sending gatt client connected event");
3536                         event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3537                 }
3538
3539                 goto fail;
3540         }
3541
3542         DBG("LE connected. Adding the gattc server/client conn info in list");
3543         gattc_data->conn_id = __hal_generate_conn_id() ;
3544         gattc_data->inst_id = __hal_generate_server_instance_id();
3545
3546         hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3547
3548         /*add gatt server connection info*/
3549         gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3550         memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3551         gatt_conn_info->conn_id = gattc_data->conn_id;
3552         gatt_conn_info->inst_id = gattc_data->inst_id;
3553         hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3554
3555         return;
3556
3557 fail:
3558         /*remove conn_info*/
3559         if (gattc_data)
3560                 g_free(gattc_data);
3561 }
3562
3563 static void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3564 {
3565         g_free(desc_info->desc_path);
3566         g_free(desc_info);
3567 }
3568
3569 static void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3570 {
3571         GSList *l = NULL;
3572         hal_gattc_desc_t *desc_info = NULL;
3573         for (l = char_info->gatt_list_descs; l != NULL; ) {
3574                 desc_info = l->data;
3575                 l = g_slist_next(l);
3576                 if (desc_info == NULL)
3577                         continue;
3578                 /* Remove descriptor element */
3579                 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3580                 __hal_gattc_free_desc_info(desc_info);
3581         }
3582         g_slist_free(char_info->gatt_list_descs);
3583         g_free(char_info->chr_path);
3584         g_free(char_info);
3585 }
3586
3587 static void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3588 {
3589         GSList *l = NULL;
3590         hal_gattc_char_t *char_info = NULL;
3591         for (l = svc_info->gatt_list_chars; l != NULL; ) {
3592                 char_info = l->data;
3593                 l = g_slist_next(l);
3594                 if (char_info == NULL)
3595                         continue;
3596                 /* Remove characteristic element */
3597                 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3598                 __hal_gattc_free_char_info(char_info);
3599         }
3600         g_slist_free(svc_info->gatt_list_chars);
3601         g_free(svc_info->svc_path);
3602         g_free(svc_info);
3603 }
3604
3605 static void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3606 {
3607         GSList *l = NULL;
3608         hal_gattc_service_t *svc_info = NULL;
3609
3610         DBG("+");
3611
3612         for (l = conn_info->gatt_list_services; l != NULL; ) {
3613                 svc_info = (hal_gattc_service_t *)l->data;
3614                 l = g_slist_next(l);
3615                 if (svc_info == NULL)
3616                         continue;
3617                 /* Remove service element */
3618                 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3619                 __hal_gattc_free_svc_info(svc_info);
3620         }
3621         g_slist_free(conn_info->gatt_list_services);
3622         g_free(conn_info);
3623 }
3624
3625 gboolean _bt_hal_check_gattc_is_existing(const char *address)
3626 {
3627         bt_bdaddr_t bd_addr;
3628         _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3629         if (__bt_find_gatt_client_info(&bd_addr) != NULL)
3630                 return TRUE;
3631         else
3632                 return FALSE;
3633 }
3634
3635 void _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3636 {
3637         int result = BT_STATUS_SUCCESS;
3638         struct hal_ev_gatt_client_connected ev;
3639         hal_gattc_server_info_t *conn_info = NULL;
3640         bt_bdaddr_t bd_addr;
3641         int event;
3642         hal_gattc_client_info_t *gattc_client = NULL;
3643         int inst_id = -1;
3644
3645         event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3646                                 HAL_EV_GATT_CLIENT_DISCONNECTED;
3647
3648         _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3649         /* find the gatt client info */
3650         gattc_client = __bt_find_gatt_client_info(&bd_addr);
3651         if (NULL == gattc_client) {
3652                 ERR("Fail to get gatt client info");
3653                 return;
3654         }
3655
3656         gattc_client->is_gatt_connected = gatt_connected;
3657
3658         //send event
3659         memset(&ev, 0, sizeof(ev));
3660         ev.conn_id = gattc_client->conn_id;
3661         ev.status = result;
3662         ev.client_if = gattc_client->client_if;
3663         memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3664                                 BT_HAL_ADDRESS_LENGTH_MAX);
3665
3666         if (!event_cb) {
3667                 ERR("gatt client callback not registered");
3668         } else {
3669                 event_cb(event, (void *)&ev, sizeof(ev));
3670         }
3671
3672         if (!gatt_connected) {
3673                 inst_id = gattc_client->inst_id;
3674
3675                 /* remove the gatt client info from the client list also*/
3676                 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3677                 g_free(gattc_client);
3678
3679                 //find the connected server info
3680                 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3681                 if (NULL == conn_info) {
3682                         ERR("Fail to get gatt server info");
3683                         return;
3684                 }
3685
3686                 if (inst_id != conn_info->inst_id) {
3687                         ERR("server instance is different");
3688                         return;
3689                 }
3690
3691                 //remove gatt conn info from the server list
3692                 DBG("remove the server conn_info from list after gatt disconnection");
3693                 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3694                 __hal_clean_gattc_server_info(conn_info);
3695         }
3696 }
3697
3698 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3699                                                 const char* uuid_str, int inst_id)
3700 {
3701         struct hal_ev_gatt_client_search_result ev;
3702
3703          if (!event_cb) {
3704                 ERR("gatt client callback not registered");
3705                 return;
3706         }
3707
3708         DBG("Send service searching result. [%s] conn_id[%d]", uuid_str, conn_id);
3709
3710         memset(&ev, 0, sizeof(ev));
3711         ev.conn_id = conn_id;
3712         ev.inst_id = inst_id;
3713         ev.is_primary = is_primary;
3714         _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3715
3716         event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3717 }
3718
3719 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3720 {
3721         struct hal_ev_gatt_client_search_complete ev;
3722
3723          if (!event_cb) {
3724                 ERR("gatt client callback not registered");
3725                 return;
3726         }
3727
3728         DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
3729
3730
3731         memset(&ev, 0, sizeof(ev));
3732         ev.conn_id = conn_id;
3733         ev.status = status;
3734
3735         event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
3736 }
3737
3738 static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
3739                 hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
3740                 char *char_value, int len)
3741 {
3742         struct hal_ev_gatt_client_notify_changed_value ev;
3743         hal_gattc_client_info_t *gattc_client = NULL;
3744
3745         if (!event_cb) {
3746                 ERR("gatt client callback not registered");
3747                 return;
3748         }
3749
3750         gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
3751         if (NULL == gattc_client) {
3752                 ERR("failed to get the gatt client info");
3753                 return ;
3754         }
3755
3756         //send event
3757         DBG("sending gatt client connected status  event");
3758         memset(&ev, 0, sizeof(ev));
3759
3760         ev.conn_id = gattc_client->conn_id;
3761         ev.inst_id = conn_info->inst_id;
3762         ev.is_primary = svc_info->is_primary;
3763         memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
3764         memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
3765
3766         memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3767
3768         if (len > 0 && (char_value != NULL)) {
3769                 memcpy(ev.value, char_value, len);
3770                 ev.len = len;
3771         }
3772
3773         event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
3774 }
3775
3776 void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
3777                                                 char *char_value, int len)
3778 {
3779         char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3780         hal_gattc_server_info_t *conn_info = NULL;
3781         bt_bdaddr_t bd_addr;
3782         GSList *l;
3783         GSList *k;
3784         hal_gattc_service_t *svc_info = NULL;
3785         hal_gattc_char_t *char_info = NULL;
3786
3787         DBG("+");
3788
3789         _bt_hal_convert_device_path_to_address(char_handle, device_address);
3790         device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
3791         DBG("device address:[%s]", device_address);
3792         DBG("char handle:[%s]", char_handle);
3793
3794         _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
3795         conn_info =  __bt_find_gatt_conn_info(&bd_addr);
3796
3797         if (conn_info != NULL) {
3798                 //find service for notified char path
3799                 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
3800                         svc_info = (hal_gattc_service_t*)l->data;
3801                         if (svc_info == NULL)
3802                                 continue;
3803
3804                         /* find characteristic object path */
3805                         for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
3806                                 char_info = (hal_gattc_char_t *)k->data;
3807                                 if (char_info == NULL)
3808                                         continue;
3809
3810                                 if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
3811                                         DBG("Found char handle[%s]", char_info->chr_path);
3812
3813                                         //send event
3814                                         _bt_hal_send_value_changed_event(conn_info, svc_info,
3815                                                         char_info, char_value, len);
3816                                         return;
3817                                 }
3818                         }
3819                 }
3820         }
3821 }
3822
3823 static bt_status_t __hal_gattc_get_service_info(hal_gattc_server_info_t *server_info, const char *service_path)
3824 {
3825         GDBusConnection *g_conn = NULL;
3826         GDBusProxy *properties_proxy = NULL;
3827         GVariant *result = NULL;
3828         GError *error = NULL;
3829         GVariantIter *property_iter = NULL;
3830         const gchar *key = NULL;
3831         GVariant *value = NULL;
3832         const char *uuid_str = NULL;
3833         gsize len = 0;
3834         gboolean is_primary = FALSE;
3835         GVariantIter *char_iter = NULL;
3836         const char *char_handle = NULL;
3837         GPtrArray *gp_char_array = NULL;
3838
3839         if (service_path == NULL) {
3840                 ERR("service_path is NULL");
3841                 return BT_STATUS_FAIL;
3842         }
3843
3844         DBG("service_path: %s", service_path);
3845
3846         g_conn = _bt_hal_get_system_gconn();
3847         if (g_conn == NULL) {
3848                 ERR("g_conn is NULL");
3849                 return BT_STATUS_FAIL;
3850         }
3851
3852         properties_proxy = g_dbus_proxy_new_sync(g_conn,
3853                         G_DBUS_PROXY_FLAGS_NONE, NULL,
3854                         BT_HAL_BLUEZ_NAME,
3855                         service_path,
3856                         BT_HAL_PROPERTIES_INTERFACE,
3857                         NULL, &error);
3858         if (properties_proxy == NULL) {
3859                 ERR("properties_proxy is NULL");
3860                 return BT_STATUS_FAIL;
3861         }
3862
3863         result = g_dbus_proxy_call_sync(properties_proxy,
3864                         "GetAll",
3865                         g_variant_new("(s)", BT_HAL_GATT_SERVICE_INTERFACE),
3866                         G_DBUS_CALL_FLAGS_NONE,
3867                         -1, NULL, &error);
3868         if (result == NULL) {
3869                 if (error != NULL) {
3870                         ERR("Fail to get properties (Error: %s)", error->message);
3871                         g_clear_error(&error);
3872                 } else {
3873                         ERR("Fail to get properties");
3874                 }
3875                 g_object_unref(properties_proxy);
3876                 return BT_STATUS_FAIL;
3877         }
3878
3879         g_variant_get(result, "(a{sv})", &property_iter);
3880
3881         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
3882                 if (g_strcmp0(key, "UUID") == 0) {
3883                         uuid_str = g_variant_get_string(value, &len);
3884                 } else if (g_strcmp0(key, "Primary") == 0) {
3885                         is_primary = g_variant_get_boolean(value);
3886                 } else if (g_strcmp0(key, "Characteristics") == 0) {
3887                         g_variant_get(value, "ao", &char_iter);
3888                         if (char_iter != NULL) {
3889                                 gp_char_array = g_ptr_array_new();
3890                                 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
3891                                         DBG("char_handle: %s", char_handle);
3892                                         g_ptr_array_add(gp_char_array, (gpointer)char_handle);
3893                                 }
3894                                 g_variant_iter_free(char_iter);
3895                         }
3896                 }
3897         }
3898
3899         if (uuid_str == NULL || gp_char_array == NULL) {
3900                 ERR("uuid_str and gp_char_array should be set");
3901                 goto done;
3902         }
3903
3904         /* Create new service */
3905         _gattc_create_new_service(server_info, is_primary, uuid_str, service_path, gp_char_array);
3906
3907 done:
3908         g_variant_iter_free(property_iter);
3909         g_variant_unref(result);
3910         g_object_unref(properties_proxy);
3911
3912         return BT_STATUS_SUCCESS;
3913 }
3914
3915 static void __bt_hal_gattc_get_uuid_from_path(const char *path, char **service_uuid)
3916 {
3917         GDBusConnection *conn = NULL;
3918         GDBusProxy *proxy = NULL;
3919         GError *err = NULL;
3920         GVariant *ret = NULL;
3921         GVariant *value = NULL;
3922
3923         conn = _bt_hal_get_system_gconn();
3924         if (conn == NULL) {
3925                 ERR("_bt_gdbus_get_system_gconn returned NULL");
3926                 return;
3927         }
3928
3929         proxy = g_dbus_proxy_new_sync(conn,
3930                         G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
3931                         BT_HAL_BLUEZ_NAME, path, BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
3932         if (proxy == NULL) {
3933                 ERR("device_proxy returned NULL");
3934                 return;
3935         }
3936
3937         ret = g_dbus_proxy_call_sync(proxy, "Get",
3938                         g_variant_new("(ss)", BT_HAL_GATT_SERVICE_INTERFACE, "UUID"),
3939                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
3940         if (err) {
3941                 ERR("DBus Error : %s", err->message);
3942                 g_clear_error(&err);
3943         } else {
3944                 g_variant_get(ret, "(v)", &value);
3945                 *service_uuid = g_variant_dup_string(value, NULL);
3946                 g_variant_unref(value);
3947                 g_variant_unref(ret);
3948         }
3949
3950         if (proxy)
3951                 g_object_unref(proxy);
3952
3953         return;
3954 }
3955
3956 void _bt_hal_handle_gattc_service_changed_event(gboolean is_added, const char *path)
3957 {
3958         struct hal_ev_gatt_client_service_changed ev = {0, };
3959         char address[BT_HAL_ADDRESS_STRING_SIZE];
3960         hal_gattc_server_info_t *server_info = NULL;
3961         hal_gattc_client_info_t *gattc_client = NULL;
3962         hal_gattc_service_t *service = NULL;
3963         GSList *list = NULL;
3964         char *uuid_str = NULL;
3965
3966         _bt_hal_convert_device_path_to_address(path, address);
3967         _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
3968         server_info = __bt_find_gatt_conn_info((bt_bdaddr_t *)ev.bdaddr);
3969         if (server_info == NULL) {
3970                 ERR("server_info is NULL");
3971                 return;
3972         }
3973
3974         gattc_client = __bt_find_gatt_client_info((bt_bdaddr_t *)ev.bdaddr);
3975         if (gattc_client == NULL) {
3976                 ERR("gattc_client is NULL");
3977                 return;
3978         }
3979
3980         if (server_info->is_gatt_connected == FALSE && gattc_client->is_gatt_connected == FALSE) {
3981                 DBG("GattConnected signal is not received yet. Just skip [%d %d]",
3982                         server_info->is_gatt_connected, gattc_client->is_gatt_connected);
3983                 return;
3984         }
3985
3986         if (is_added) {
3987                 /* Get service UUID from path */
3988                 __bt_hal_gattc_get_uuid_from_path(path, &uuid_str);
3989                 if (uuid_str) {
3990                         DBG("conn_id(%d) GATT Service(%s) Added", server_info->conn_id, uuid_str);
3991                         _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3992                         g_free(uuid_str);
3993                 } else {
3994                         ERR("uuid_str is NULL");
3995                         return;
3996                 }
3997
3998                 /* Create new service and append into the list */
3999                 __hal_gattc_get_service_info(server_info, path);
4000         } else {
4001                 /* Find service UUID from path */
4002                 for (list = server_info->gatt_list_services; list; list = g_slist_next(list)) {
4003                         service = (hal_gattc_service_t *)list->data;
4004                         if (service == NULL)
4005                                 continue;
4006
4007                         if (g_strcmp0(service->svc_path, path) == 0) {
4008                                 memcpy(ev.uuid, service->svc_uuid.uu, sizeof(bt_uuid_t));
4009                                 uuid_str = g_malloc0(BT_HAL_UUID_STRING_LEN);
4010                                 _bt_hal_convert_uuid_type_to_string(uuid_str, ev.uuid);
4011                                 DBG("conn_id(%d) GATT Service(%s) Removed", server_info->conn_id, uuid_str);
4012
4013                                 /* Remove service info in list */
4014                                 server_info->gatt_list_services = g_slist_remove(server_info->gatt_list_services, service);
4015                                 __hal_gattc_free_svc_info(service);
4016                                 break;
4017                         }
4018                 }
4019
4020                 if (uuid_str) {
4021                         g_free(uuid_str);
4022                 } else {
4023                         ERR("uuid_str is NULL");
4024                         return;
4025                 }
4026         }
4027
4028         /* Send GATT Client service changed event */
4029         ev.change_type = is_added;
4030         ev.conn_id = server_info->conn_id;
4031         ev.inst_id = server_info->inst_id;
4032         event_cb(HAL_EV_GATT_CLIENT_SERVICE_CHANGED, (void *)&ev, sizeof(ev));
4033 }