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