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