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