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