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