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