81b28d71e1b2a5aa8ad2745362b288f4eb563f3f
[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                 g_free(conn_mtu);
2751                 return BT_STATUS_FAIL;
2752         }
2753
2754         gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2755         if (gattc_client == NULL) {
2756                 INFO("GATT client conn info not found");
2757                 g_free(conn_mtu);
2758                 return BT_STATUS_FAIL;
2759         }
2760
2761         _bt_hal_convert_addr_type_to_string(device_address,
2762                                 (unsigned char *)gattc_client->bd_addr.address);
2763
2764         device_path = _bt_hal_get_device_object_path(device_address);
2765         if (device_path == NULL) {
2766                 ERR("device_path NULL : [%s]", device_address);
2767                 g_free(conn_mtu);
2768                 return BT_STATUS_FAIL;
2769         }
2770
2771         device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2772                         NULL, BT_HAL_BLUEZ_NAME,
2773                         device_path, BT_HAL_DEVICE_INTERFACE,  NULL, NULL);
2774
2775         g_free(device_path);
2776         if (NULL == device_proxy) {
2777                 ERR("device_proxy returned NULL");
2778                 g_free(conn_mtu);
2779                 return BT_STATUS_FAIL;
2780         }
2781
2782         conn_mtu->conn_id = conn_id;
2783         conn_mtu->mtu = mtu;
2784
2785         g_dbus_proxy_call(device_proxy, "RequestAttMtu",
2786                         g_variant_new("(q)", mtu),
2787                         G_DBUS_CALL_FLAGS_NONE,
2788                         BT_HAL_MAX_DBUS_TIMEOUT,
2789                         NULL,
2790                         (GAsyncReadyCallback)__bt_request_att_mtu_device_cb,
2791                         conn_mtu);
2792
2793         return BT_STATUS_SUCCESS;
2794 }
2795
2796 /** MTU Exchange request from client */
2797 static bt_status_t configure_mtu(int conn_id, int mtu)
2798 {
2799         CHECK_BTGATT_INIT();
2800
2801         return __hal_configure_mtu(conn_id, mtu);
2802 }
2803
2804 /** Setup scan filter params */
2805 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2806                 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2807                 int rssi_low_thres, int dely_mode, int found_timeout,
2808                 int lost_timeout, int found_timeout_cnt)
2809 {
2810         GDBusProxy *proxy;
2811         GError *error = NULL;
2812         GVariant *ret, *param;
2813         CHECK_BTGATT_INIT();
2814
2815         proxy = _bt_hal_get_adapter_proxy();
2816
2817         if (proxy == NULL)
2818                 return BT_STATUS_FAIL;
2819
2820         param = g_variant_new("(iiiiiiiiiiii)",
2821                                 client_if,
2822                                 action,
2823                                 filt_index,
2824                                 feat_seln,
2825                                 list_logic_type,
2826                                 filt_logic_type,
2827                                 rssi_high_thres,
2828                                 rssi_low_thres,
2829                                 dely_mode,
2830                                 found_timeout,
2831                                 lost_timeout,
2832                                 found_timeout_cnt);
2833         ret = g_dbus_proxy_call_sync(proxy, "scan_filter_param_setup",
2834                         param, G_DBUS_CALL_FLAGS_NONE,
2835                         -1, NULL, &error);
2836
2837         if (error) {
2838                 ERR("scan_filter_param_setup Fail: %s", error->message);
2839                 g_clear_error(&error);
2840                 return BT_STATUS_FAIL;
2841         }
2842
2843         if (ret)
2844                 g_variant_unref(ret);
2845
2846         return BT_STATUS_SUCCESS;
2847 }
2848
2849 /** Configure a scan filter condition */
2850 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2851                 int filt_index, int company_id,
2852                 int company_id_mask, const bt_uuid_t *p_uuid,
2853                 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2854                 char addr_type, int data_len, char* p_data, int mask_len,
2855                 char* p_mask)
2856 {
2857         GDBusProxy *proxy;
2858         GError *error = NULL;
2859         GVariant *ret, *param;
2860         GVariant *arr_uuid_param = NULL, *arr_uuid_mask_param = NULL;
2861         GVariant *arr_data_param = NULL, *arr_data_mask_param = NULL;
2862         GArray *arr_uuid = NULL;
2863         GArray *arr_uuid_mask = NULL;
2864         GArray *arr_data = NULL;
2865         GArray *arr_data_mask = NULL;
2866         CHECK_BTGATT_INIT();
2867
2868         proxy = _bt_hal_get_adapter_proxy();
2869
2870         if (proxy == NULL)
2871                 return BT_STATUS_FAIL;
2872
2873         if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS) {
2874
2875                 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2876
2877                 _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
2878
2879                 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS being added\nRemote Device Address is [%s]", address);
2880
2881                 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2882                                 NULL, 0, TRUE, NULL, NULL);
2883                 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2884                                 NULL, 0, TRUE, NULL, NULL);
2885                 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2886                                 NULL, 0, TRUE, NULL, NULL);
2887                 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2888                                 NULL, 0, TRUE, NULL, NULL);
2889
2890                 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2891                                         client_if,      // client_if
2892                                         action,      // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2893                                         BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS,        // filter_type
2894                                         filt_index,       // filter_index
2895                                         company_id,      // company_id
2896                                         company_id_mask,      // company_id_mask
2897                                         arr_uuid_param, // p_uuid
2898                                         arr_uuid_mask_param,    // p_uuid_mask
2899                                         address,        // string
2900                                         addr_type,      // address_type
2901                                         arr_data_param, // p_data
2902                                         arr_data_mask_param);   // p_mask
2903
2904                 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2905                                 param, G_DBUS_CALL_FLAGS_NONE,
2906                                 -1, NULL, &error);
2907
2908                 if (error) {
2909                         ERR("scan_filter_add_remove Fail: %s", error->message);
2910                         g_clear_error(&error);
2911                         return BT_STATUS_FAIL;
2912                 }
2913
2914                 if (ret)
2915                         g_variant_unref(ret);
2916
2917                 return BT_STATUS_SUCCESS;
2918         }
2919
2920         if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_NAME) {
2921
2922                 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_NAME being added\nRemote Device Name is %s", p_data);
2923                 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2924                                 NULL, 0, TRUE, NULL, NULL);
2925                 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2926                                 NULL, 0, TRUE, NULL, NULL);
2927                 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2928                                 NULL, 0, TRUE, NULL, NULL);
2929                 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2930                                 NULL, 0, TRUE, NULL, NULL);
2931
2932                 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2933                                         client_if,      // client_if
2934                                         action,      // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2935                                         BT_SCAN_FILTER_FEATURE_DEVICE_NAME,   // filter_type
2936                                         filt_index,       // filter_index
2937                                         company_id,      // company_id
2938                                         company_id_mask,      // company_id_mask
2939                                         arr_uuid_param, // p_uuid
2940                                         arr_uuid_mask_param,    // p_uuid_mask
2941                                         p_data,    // string
2942                                         addr_type,      // address_type
2943                                         arr_data_param, // p_data
2944                                         arr_data_mask_param);
2945
2946                 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2947                                 param, G_DBUS_CALL_FLAGS_NONE,
2948                                 -1, NULL, &error);
2949
2950                 if (error) {
2951                         ERR("scan_filter_add_remove Fail: %s", error->message);
2952                         g_clear_error(&error);
2953                         return BT_STATUS_FAIL;
2954                 }
2955
2956                 if (ret)
2957                         g_variant_unref(ret);
2958
2959                 return BT_STATUS_SUCCESS;
2960         }
2961
2962         if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_UUID) {
2963
2964                 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
2965                 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
2966
2967                 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
2968                 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
2969
2970                 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2971                                 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
2972                 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2973                                 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
2974                 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2975                                 NULL, 0, TRUE, NULL, NULL);
2976                 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2977                                 NULL, 0, TRUE, NULL, NULL);
2978
2979                 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2980                                         client_if,      // client_if
2981                                         action,      // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2982                                         BT_SCAN_FILTER_FEATURE_SERVICE_UUID,  // filter_type
2983                                         filt_index,       // filter_index
2984                                         company_id,      // company_id
2985                                         company_id_mask,      // company_id_mask
2986                                         arr_uuid_param, // p_uuid
2987                                         arr_uuid_mask_param,    // p_uuid_mask
2988                                         "",   // string
2989                                         addr_type,      // address_type
2990                                         arr_data_param, // p_data
2991                                         arr_data_mask_param);
2992
2993                 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2994                                 param, G_DBUS_CALL_FLAGS_NONE,
2995                                 -1, NULL, &error);
2996
2997                 if (error) {
2998                         ERR("scan_filter_add_remove Fail: %s", error->message);
2999                         g_clear_error(&error);
3000                         return BT_STATUS_FAIL;
3001                 }
3002
3003                 if (ret)
3004                         g_variant_unref(ret);
3005
3006                 g_array_free(arr_uuid, TRUE);
3007                 g_array_free(arr_uuid_mask, TRUE);
3008
3009                 return BT_STATUS_SUCCESS;
3010         }
3011
3012         if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID) {
3013
3014                 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3015                 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3016
3017                 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3018                 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3019
3020                 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3021                                 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3022                 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3023                                 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3024                 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3025                                 NULL, 0, TRUE, NULL, NULL);
3026                 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3027                                 NULL, 0, TRUE, NULL, NULL);
3028
3029                 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3030                                         client_if,      // client_if
3031                                         action,      // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3032                                         BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID,     // filter_type
3033                                         filt_index,       // filter_index
3034                                         company_id,      // company_id
3035                                         company_id_mask,      // company_id_mask
3036                                         arr_uuid_param, // p_uuid
3037                                         arr_uuid_mask_param,    // p_uuid_mask
3038                                         "",   // string
3039                                         addr_type,      // address_type
3040                                         arr_data_param, // p_data
3041                                         arr_data_mask_param);
3042
3043                 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3044                                 G_DBUS_CALL_FLAGS_NONE,
3045                                 -1, NULL, &error);
3046
3047                 if (error) {
3048                         ERR("scan_filter_add_remove Fail: %s", error->message);
3049                         g_clear_error(&error);
3050                         return BT_STATUS_FAIL;
3051                 }
3052
3053                 if (ret)
3054                         g_variant_unref(ret);
3055
3056                 g_array_free(arr_uuid, TRUE);
3057                 g_array_free(arr_uuid_mask, TRUE);
3058
3059                 return BT_STATUS_SUCCESS;
3060         }
3061
3062         if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_DATA) {
3063
3064                 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3065                 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3066
3067                 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3068                 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3069
3070                 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3071                                 NULL, 0, TRUE, NULL, NULL);
3072                 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3073                                 NULL, 0, TRUE, NULL, NULL);
3074                 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3075                                 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3076                                 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3077                                 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3078
3079                 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3080                                         client_if,      // client_if
3081                                         action,      // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3082                                         BT_SCAN_FILTER_FEATURE_SERVICE_DATA,  // filter_type
3083                                         filt_index,       // filter_index
3084                                         company_id,      // company_id
3085                                         company_id_mask,      // company_id_mask
3086                                         arr_uuid_param, // p_uuid
3087                                         arr_uuid_mask_param,    // p_uuid_mask
3088                                         "",   // string
3089                                         addr_type,      // address_type
3090                                         arr_data_param, // p_data
3091                                         arr_data_mask_param);
3092
3093                 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3094                                 G_DBUS_CALL_FLAGS_NONE,
3095                                 -1, NULL, &error);
3096
3097                 if (error) {
3098                         ERR("scan_filter_add_remove Fail: %s", error->message);
3099                         g_clear_error(&error);
3100                         return BT_STATUS_FAIL;
3101                 }
3102
3103                 if (ret)
3104                         g_variant_unref(ret);
3105
3106                 g_array_free(arr_data, TRUE);
3107                 g_array_free(arr_data_mask, TRUE);
3108
3109                 return BT_STATUS_SUCCESS;
3110         }
3111
3112         if (filt_type == BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA) {
3113
3114                 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3115                 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3116
3117                 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3118                 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3119
3120                 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3121                                 NULL, 0, TRUE, NULL, NULL);
3122                 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3123                                 NULL, 0, TRUE, NULL, NULL);
3124                 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3125                                 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3126                 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3127                                 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3128
3129                 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3130                                         client_if,      // client_if
3131                                         action,      // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3132                                         BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA,     // filter_type
3133                                         filt_index,       // filter_index
3134                                         company_id,        // company_id
3135                                         company_id_mask, // company_id_mask
3136                                         arr_uuid_param, // p_uuid
3137                                         arr_uuid_mask_param,    // p_uuid_mask
3138                                         "",   // string
3139                                         addr_type,      // address_type
3140                                         arr_data_param, // p_data
3141                                         arr_data_mask_param);
3142
3143                 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3144                                 G_DBUS_CALL_FLAGS_NONE,
3145                                 -1, NULL, &error);
3146
3147                 if (error) {
3148                         ERR("scan_filter_add_remove Fail: %s", error->message);
3149                         g_clear_error(&error);
3150                         return BT_STATUS_FAIL;
3151                 }
3152
3153                 if (ret)
3154                         g_variant_unref(ret);
3155
3156                 g_array_free(arr_data, TRUE);
3157                 g_array_free(arr_data_mask, TRUE);
3158
3159                 return BT_STATUS_SUCCESS;
3160         }
3161
3162         return BT_STATUS_UNSUPPORTED;
3163 }
3164
3165 /** Clear all scan filter conditions for specific filter index*/
3166 bt_status_t scan_filter_clear(int client_if, int filt_index)
3167 {
3168         GDBusProxy *proxy;
3169         GError *error = NULL;
3170         GVariant *ret;
3171         CHECK_BTGATT_INIT();
3172
3173         proxy = _bt_hal_get_adapter_proxy();
3174         if (proxy == NULL)
3175                 return BT_STATUS_FAIL;
3176
3177         ret = g_dbus_proxy_call_sync(proxy, "scan_filter_clear",
3178                                 g_variant_new("(ii)", client_if, filt_index),
3179                                 G_DBUS_CALL_FLAGS_NONE,
3180                                 -1, NULL, &error);
3181
3182         if (error) {
3183                 ERR("scan_filter_clear Fail: %s", error->message);
3184                 g_clear_error(&error);
3185                 return BT_STATUS_FAIL;
3186         }
3187         if (ret)
3188                 g_variant_unref(ret);
3189         return BT_STATUS_SUCCESS;
3190 }
3191
3192 /** Enable / disable scan filter feature*/
3193 bt_status_t scan_filter_enable(int client_if, bool enable)
3194 {
3195         GDBusProxy *proxy;
3196         GError *error = NULL;
3197         GVariant *ret;
3198         CHECK_BTGATT_INIT();
3199
3200         proxy = _bt_hal_get_adapter_proxy();
3201         if (proxy == NULL)
3202                 return BT_STATUS_FAIL;
3203
3204         ret = g_dbus_proxy_call_sync(proxy, "scan_filter_enable",
3205                                 g_variant_new("(ib)", client_if, enable),
3206                                 G_DBUS_CALL_FLAGS_NONE,
3207                                 -1, NULL, &error);
3208
3209         if (error) {
3210                 ERR("scan_filter_enable Fail: %s", error->message);
3211                 g_clear_error(&error);
3212                 return BT_STATUS_FAIL;
3213         }
3214         g_variant_unref(ret);
3215
3216         return BT_STATUS_SUCCESS;
3217 }
3218
3219 /** Sets the LE scan interval and window in units of N*0.625 msec */
3220 #ifdef TIZEN_BT_HAL
3221 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
3222 {
3223         int ret;
3224
3225         CHECK_BTGATT_INIT();
3226
3227         le_scan_type = scan_type;
3228         ret = _bt_hal_adapter_le_set_scan_parameters(
3229                         scan_type, scan_interval, scan_window);
3230         return ret;
3231 }
3232 #else
3233 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
3234 {
3235         CHECK_BTGATT_INIT();
3236         return BT_STATUS_UNSUPPORTED;
3237 }
3238 #endif
3239
3240 /* Configure the batchscan storage */
3241 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
3242                 int batch_scan_trunc_max, int batch_scan_notify_threshold)
3243 {
3244         CHECK_BTGATT_INIT();
3245         return BT_STATUS_UNSUPPORTED;
3246 }
3247
3248 /* Enable batchscan */
3249 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
3250                 int scan_interval, int scan_window, int addr_type, int discard_rule)
3251 {
3252         CHECK_BTGATT_INIT();
3253         return BT_STATUS_UNSUPPORTED;
3254 }
3255
3256 /* Disable batchscan */
3257 bt_status_t batchscan_dis_batch_scan(int client_if)
3258 {
3259         CHECK_BTGATT_INIT();
3260         return BT_STATUS_UNSUPPORTED;
3261 }
3262
3263 /* Read out batchscan reports */
3264 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
3265 {
3266         CHECK_BTGATT_INIT();
3267         return BT_STATUS_UNSUPPORTED;
3268 }
3269
3270 const btgatt_client_interface_t btgatt_client_interface = {
3271         .register_client = btif_gattc_register_client,
3272         .unregister_client = btif_gattc_unregister_client,
3273         .scan = scan,
3274         .connect = btif_gattc_client_connect,
3275         .disconnect = btif_gattc_client_disconnect,
3276         .refresh = refresh,
3277         .search_service = btif_gattc_client_search_service,
3278         .get_included_service = get_included_service,
3279         .get_characteristic = btif_gattc_get_characteristic,
3280         .get_descriptor = btif_gattc_get_descriptor,
3281         .read_characteristic = btif_read_characteristic,
3282         .write_characteristic = btif_write_characteristic,
3283         .acquire_write = btif_get_acquire_write_fd,
3284         .acquire_notify = btif_get_acquire_notify_fd,
3285         .read_descriptor = btif_read_descriptor,
3286         .write_descriptor = btif_write_descriptor,
3287         .execute_write = execute_write,
3288         .register_for_notification = btif_register_for_notification,
3289         .deregister_for_notification = btif_deregister_for_notification,
3290         .read_remote_rssi = read_remote_rssi,
3291         .ota_fw_update = ota_fw_update,
3292         .get_device_type = get_device_type,
3293         .conn_parameter_update = btif_gattc_conn_parameter_update,
3294         .test_command = test_command,
3295         .configure_mtu = configure_mtu,
3296         .scan_filter_param_setup = scan_filter_param_setup,
3297         .scan_filter_add_remove = scan_filter_add_remove,
3298         .scan_filter_clear = scan_filter_clear,
3299         .scan_filter_enable = scan_filter_enable,
3300         .set_scan_parameters = set_scan_parameters,
3301         .batchscan_cfg_storage = batchscan_cfg_storage,
3302         .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
3303         .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
3304         .batchscan_read_reports = batchscan_read_reports,
3305         .add_connection_info = btif_gattc_add_connection_info,
3306 };
3307
3308 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr)
3309 {
3310         GSList *l;
3311         hal_gattc_server_info_t *info = NULL;
3312
3313         for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3314                 info = (hal_gattc_server_info_t*)l->data;
3315                 if (info == NULL)
3316                         continue;
3317
3318                 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3319                         return info;
3320                 }
3321
3322         return NULL;
3323 }
3324
3325 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
3326 {
3327         GSList *l;
3328         hal_gattc_client_info_t *info = NULL;
3329
3330         for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3331                 info = (hal_gattc_client_info_t*)l->data;
3332                 if (info == NULL)
3333                         continue;
3334
3335                 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3336                         return info;
3337                 }
3338
3339         return NULL;
3340 }
3341
3342 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
3343 {
3344         GSList *l;
3345         hal_gattc_client_info_t *info = NULL;
3346
3347         for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3348                 info = (hal_gattc_client_info_t*)l->data;
3349                 if (info == NULL)
3350                         continue;
3351
3352                 if (info->conn_id == conn_id)
3353                         return info;
3354                 }
3355
3356         return NULL;
3357 }
3358
3359 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int  conn_id)
3360 {
3361         GSList *l;
3362         hal_gattc_server_info_t *info = NULL;
3363         hal_gattc_client_info_t *gattc_client = NULL;
3364
3365         gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
3366         if (gattc_client == NULL) {
3367                 ERR("GATT client conn info not found");
3368                 return NULL;
3369         }
3370
3371         for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3372                 info = (hal_gattc_server_info_t*)l->data;
3373                 if (info == NULL)
3374                         continue;
3375
3376                 if ((info->inst_id == gattc_client->inst_id) &&
3377                         !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
3378                         return info;
3379                 }
3380         }
3381         return NULL;
3382 }
3383
3384 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
3385                 gboolean auto_connect)
3386 {
3387         char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3388         gchar *device_path = NULL;
3389         GDBusProxy *device_proxy = NULL;
3390         GDBusConnection *conn;
3391         int ret = BT_STATUS_SUCCESS;
3392         hal_gattc_client_info_t *gattc_data;
3393
3394         if (NULL == bd_addr) {
3395                 ERR("bd_addr is NULL");
3396                 return BT_STATUS_PARM_INVALID;
3397         }
3398
3399         conn = _bt_hal_get_system_gconn();
3400         if (NULL == conn) {
3401                 ERR("_bt_gdbus_get_system_gconn returned NULL");
3402                 return BT_STATUS_FAIL;
3403         }
3404
3405         _bt_hal_convert_addr_type_to_string(device_address,
3406                         (unsigned char *)bd_addr->address);
3407         device_path = _bt_hal_get_device_object_path(device_address);
3408         if (device_path == NULL) {
3409                 ERR("device_path NULL : [%s]", device_address);
3410                 ret = BT_STATUS_FAIL;
3411                 return ret;
3412         }
3413
3414         device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3415                         NULL, BT_HAL_BLUEZ_NAME,
3416                         device_path, BT_HAL_DEVICE_INTERFACE,  NULL, NULL);
3417         g_free(device_path);
3418         if (NULL == device_proxy) {
3419                 ERR("device_proxy returned NULL");
3420                 return BT_STATUS_FAIL;
3421         }
3422
3423         gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
3424         memcpy(gattc_data->bd_addr.address, bd_addr->address,
3425                                         BT_HAL_ADDRESS_LENGTH_MAX);
3426
3427         DBG("ConnectLE [%s]", device_address);
3428
3429         gattc_data->client_if = client_if;
3430
3431         g_dbus_proxy_call(device_proxy, "ConnectLE",
3432                         g_variant_new("(b)", auto_connect),
3433                         G_DBUS_CALL_FLAGS_NONE,
3434                         BT_HAL_MAX_DBUS_TIMEOUT,
3435                         NULL,
3436                         (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
3437
3438         return ret;
3439 }
3440
3441 static bt_status_t _bt_hold_current_advertising()
3442 {
3443         int ret = BT_STATUS_FAIL;
3444         gboolean is_advertising = FALSE;
3445         DBG("+");
3446
3447         is_advertising = _bt_hal_is_advertising_in_slot(0);
3448         if (is_advertising) {
3449                 DBG("+ Stop current advertising");
3450
3451                 ret = _bt_hal_enable_advertising(0, 0, FALSE, FALSE);
3452                 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3453         }
3454
3455         return ret;
3456 }
3457
3458 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3459 {
3460         DBG("+ start current advertising");
3461
3462         _bt_hal_enable_advertising(0, 0, TRUE, FALSE);
3463
3464         return FALSE;
3465 }
3466
3467 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3468 {
3469         DBG("Try to initiate pending LE connection");
3470
3471         pending_le_conn_timer_id = 0;
3472
3473         __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3474                         &pending_le_conn_info->bd_addr,
3475                         pending_le_conn_info->auto_connect);
3476
3477         g_free(pending_le_conn_info);
3478         pending_le_conn_info = NULL;
3479
3480         return FALSE;
3481 }
3482
3483 static int __hal_generate_conn_id()
3484 {
3485          return ++bt_conn_id;
3486 }
3487
3488 static int __hal_generate_server_instance_id()
3489 {
3490         return ++bt_inst_id;
3491 }
3492
3493 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3494                 gpointer user_data)
3495 {
3496         GError *g_error = NULL;
3497         GVariant *reply = NULL;
3498         hal_gattc_client_info_t *gattc_data  = user_data;
3499         int result = BT_STATUS_SUCCESS;
3500         struct hal_ev_gatt_client_connected ev;
3501         hal_gattc_server_info_t *gatt_conn_info = NULL;
3502
3503         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3504         g_object_unref(proxy);
3505         if (reply == NULL) {
3506                 ERR("Connect LE Dbus Call Error");
3507                 if (g_error) {
3508                         ERR("Error: %s\n", g_error->message);
3509                         g_clear_error(&g_error);
3510                 }
3511                 result = BT_STATUS_FAIL;
3512         }
3513         g_variant_unref(reply);
3514
3515         if (NULL == gattc_data) {
3516                 ERR("gattc_data is NULL");
3517                 return;
3518         }
3519
3520         /*send fail event*/
3521         if (result == BT_STATUS_FAIL) {
3522                 memset(&ev, 0, sizeof(ev));
3523                 ev.conn_id = -1;
3524                 ev.status = result;
3525                 ev.client_if = gattc_data->client_if;
3526                 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3527                                                 BT_HAL_ADDRESS_LENGTH_MAX);
3528
3529                 if (!event_cb) {
3530                         ERR("gatt client callback not registered");
3531                 } else {
3532                         DBG("sending gatt client connected event");
3533                         event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3534                 }
3535
3536                 goto fail;
3537         }
3538
3539         DBG("LE connected. Adding the gattc server/client conn info in list");
3540         gattc_data->conn_id = __hal_generate_conn_id() ;
3541         gattc_data->inst_id = __hal_generate_server_instance_id();
3542
3543         hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3544
3545         /*add gatt server connection info*/
3546         gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3547         memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3548         gatt_conn_info->conn_id = gattc_data->conn_id;
3549         gatt_conn_info->inst_id = gattc_data->inst_id;
3550         hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3551
3552         return;
3553
3554 fail:
3555         /*remove conn_info*/
3556         if (gattc_data)
3557                 g_free(gattc_data);
3558 }
3559
3560 static void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3561 {
3562         g_free(desc_info->desc_path);
3563         g_free(desc_info);
3564 }
3565
3566 static void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3567 {
3568         GSList *l = NULL;
3569         hal_gattc_desc_t *desc_info = NULL;
3570         for (l = char_info->gatt_list_descs; l != NULL; ) {
3571                 desc_info = l->data;
3572                 l = g_slist_next(l);
3573                 if (desc_info == NULL)
3574                         continue;
3575                 /* Remove descriptor element */
3576                 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3577                 __hal_gattc_free_desc_info(desc_info);
3578         }
3579         g_slist_free(char_info->gatt_list_descs);
3580         g_free(char_info->chr_path);
3581         g_free(char_info);
3582 }
3583
3584 static void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3585 {
3586         GSList *l = NULL;
3587         hal_gattc_char_t *char_info = NULL;
3588         for (l = svc_info->gatt_list_chars; l != NULL; ) {
3589                 char_info = l->data;
3590                 l = g_slist_next(l);
3591                 if (char_info == NULL)
3592                         continue;
3593                 /* Remove characteristic element */
3594                 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3595                 __hal_gattc_free_char_info(char_info);
3596         }
3597         g_slist_free(svc_info->gatt_list_chars);
3598         g_free(svc_info->svc_path);
3599         g_free(svc_info);
3600 }
3601
3602 static void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3603 {
3604         GSList *l = NULL;
3605         hal_gattc_service_t *svc_info = NULL;
3606
3607         DBG("+");
3608
3609         for (l = conn_info->gatt_list_services; l != NULL; ) {
3610                 svc_info = (hal_gattc_service_t *)l->data;
3611                 l = g_slist_next(l);
3612                 if (svc_info == NULL)
3613                         continue;
3614                 /* Remove service element */
3615                 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3616                 __hal_gattc_free_svc_info(svc_info);
3617         }
3618         g_slist_free(conn_info->gatt_list_services);
3619         g_free(conn_info);
3620 }
3621
3622 gboolean _bt_hal_check_gattc_is_existing(const char *address)
3623 {
3624         bt_bdaddr_t bd_addr;
3625         _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3626         if (__bt_find_gatt_client_info(&bd_addr) != NULL)
3627                 return TRUE;
3628         else
3629                 return FALSE;
3630 }
3631
3632 void _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3633 {
3634         int result = BT_STATUS_SUCCESS;
3635         struct hal_ev_gatt_client_connected ev;
3636         hal_gattc_server_info_t *conn_info = NULL;
3637         bt_bdaddr_t bd_addr;
3638         int event;
3639         hal_gattc_client_info_t *gattc_client = NULL;
3640         int inst_id = -1;
3641
3642
3643         DBG("+ connected device address [%s]", address);
3644
3645         event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3646                                 HAL_EV_GATT_CLIENT_DISCONNECTED;
3647
3648         _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3649         /* find the gatt client info */
3650         gattc_client = __bt_find_gatt_client_info(&bd_addr);
3651         if (NULL == gattc_client) {
3652                 ERR("Fail to get gatt client info");
3653                 return;
3654         }
3655
3656         //send event
3657         memset(&ev, 0, sizeof(ev));
3658         ev.conn_id = gattc_client->conn_id;
3659         ev.status = result;
3660         ev.client_if = gattc_client->client_if;
3661         memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3662                                 BT_HAL_ADDRESS_LENGTH_MAX);
3663
3664         if (!event_cb) {
3665                 ERR("gatt client callback not registered");
3666         } else {
3667                 event_cb(event, (void *)&ev, sizeof(ev));
3668         }
3669
3670         if (!gatt_connected) {
3671                 inst_id = gattc_client->inst_id;
3672
3673                 /* remove the gatt client info from the client list also*/
3674                 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3675                 g_free(gattc_client);
3676
3677                 //find the connected server info
3678                 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3679                 if (NULL == conn_info) {
3680                         ERR("Fail to get gatt server info");
3681                         return;
3682                 }
3683
3684                 if (inst_id != conn_info->inst_id) {
3685                         ERR("server instance is different");
3686                         return;
3687                 }
3688
3689                 //remove gatt conn info from the server list
3690                 DBG("remove the server conn_info from list after gatt disconnection");
3691                 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3692                 __hal_clean_gattc_server_info(conn_info);
3693         }
3694
3695         DBG("-");
3696 }
3697
3698 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3699                                                 const char* uuid_str, int inst_id)
3700 {
3701         struct hal_ev_gatt_client_search_result ev;
3702
3703          if (!event_cb) {
3704                 ERR("gatt client callback not registered");
3705                 return;
3706         }
3707
3708         DBG("Send service searching result. [%s] conn_id[%d]", uuid_str, conn_id);
3709
3710         memset(&ev, 0, sizeof(ev));
3711         ev.conn_id = conn_id;
3712         ev.inst_id = inst_id;
3713         ev.is_primary = is_primary;
3714         _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3715
3716         event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3717 }
3718
3719 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3720 {
3721         struct hal_ev_gatt_client_search_complete ev;
3722
3723          if (!event_cb) {
3724                 ERR("gatt client callback not registered");
3725                 return;
3726         }
3727
3728         DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
3729
3730
3731         memset(&ev, 0, sizeof(ev));
3732         ev.conn_id = conn_id;
3733         ev.status = status;
3734
3735         event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
3736 }
3737
3738 static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
3739                 hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
3740                 char *char_value, int len)
3741 {
3742         struct hal_ev_gatt_client_notify_changed_value ev;
3743         hal_gattc_client_info_t *gattc_client = NULL;
3744
3745         if (!event_cb) {
3746                 ERR("gatt client callback not registered");
3747                 return;
3748         }
3749
3750         gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
3751         if (NULL == gattc_client) {
3752                 ERR("failed to get the gatt client info");
3753                 return ;
3754         }
3755
3756         //send event
3757         DBG("sending gatt client connected status  event");
3758         memset(&ev, 0, sizeof(ev));
3759
3760         ev.conn_id = gattc_client->conn_id;
3761         ev.inst_id = conn_info->inst_id;
3762         ev.is_primary = svc_info->is_primary;
3763         memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
3764         memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
3765
3766         memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3767
3768         if (len > 0 && (char_value != NULL)) {
3769                 memcpy(ev.value, char_value, len);
3770                 ev.len = len;
3771         }
3772
3773         event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
3774 }
3775
3776 void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
3777                                                 char *char_value, int len)
3778 {
3779         char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3780         hal_gattc_server_info_t *conn_info = NULL;
3781         bt_bdaddr_t bd_addr;
3782         GSList *l;
3783         GSList *k;
3784         hal_gattc_service_t *svc_info = NULL;
3785         hal_gattc_char_t *char_info = NULL;
3786
3787         DBG("+");
3788
3789         _bt_hal_convert_device_path_to_address(char_handle, device_address);
3790         device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
3791         DBG("device address:[%s]", device_address);
3792         DBG("char handle:[%s]", char_handle);
3793
3794         _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
3795         conn_info =  __bt_find_gatt_conn_info(&bd_addr);
3796
3797         if (conn_info != NULL) {
3798                 //find service for notified char path
3799                 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
3800                         svc_info = (hal_gattc_service_t*)l->data;
3801                         if (svc_info == NULL)
3802                                 continue;
3803
3804                         /* find characteristic object path */
3805                         for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
3806                                 char_info = (hal_gattc_char_t *)k->data;
3807                                 if (char_info == NULL)
3808                                         continue;
3809
3810                                 if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
3811                                         DBG("Found char handle[%s]", char_info->chr_path);
3812
3813                                         //send event
3814                                         _bt_hal_send_value_changed_event(conn_info, svc_info,
3815                                                         char_info, char_value, len);
3816                                         return;
3817                                 }
3818                         }
3819                 }
3820         }
3821 }
3822
3823 static bt_status_t __hal_gattc_get_service_info(hal_gattc_server_info_t *server_info, const char *service_path)
3824 {
3825         GDBusConnection *g_conn = NULL;
3826         GDBusProxy *properties_proxy = NULL;
3827         GVariant *result = NULL;
3828         GError *error = NULL;
3829         GVariantIter *property_iter = NULL;
3830         const gchar *key = NULL;
3831         GVariant *value = NULL;
3832         const char *uuid_str = NULL;
3833         gsize len = 0;
3834         gboolean is_primary = FALSE;
3835         GVariantIter *char_iter = NULL;
3836         const char *char_handle = NULL;
3837         GPtrArray *gp_char_array = NULL;
3838
3839         if (service_path == NULL) {
3840                 ERR("service_path is NULL");
3841                 return BT_STATUS_FAIL;
3842         }
3843
3844         DBG("service_path: %s", service_path);
3845
3846         g_conn = _bt_hal_get_system_gconn();
3847         if (g_conn == NULL) {
3848                 ERR("g_conn is NULL");
3849                 return BT_STATUS_FAIL;
3850         }
3851
3852         properties_proxy = g_dbus_proxy_new_sync(g_conn,
3853                         G_DBUS_PROXY_FLAGS_NONE, NULL,
3854                         BT_HAL_BLUEZ_NAME,
3855                         service_path,
3856                         BT_HAL_PROPERTIES_INTERFACE,
3857                         NULL, &error);
3858         if (properties_proxy == NULL) {
3859                 ERR("properties_proxy is NULL");
3860                 return BT_STATUS_FAIL;
3861         }
3862
3863         result = g_dbus_proxy_call_sync(properties_proxy,
3864                         "GetAll",
3865                         g_variant_new("(s)", BT_HAL_GATT_SERVICE_INTERFACE),
3866                         G_DBUS_CALL_FLAGS_NONE,
3867                         -1, NULL, &error);
3868         if (result == NULL) {
3869                 if (error != NULL) {
3870                         ERR("Fail to get properties (Error: %s)", error->message);
3871                         g_clear_error(&error);
3872                 } else {
3873                         ERR("Fail to get properties");
3874                 }
3875                 g_object_unref(properties_proxy);
3876                 return BT_STATUS_FAIL;
3877         }
3878
3879         g_variant_get(result, "(a{sv})", &property_iter);
3880
3881         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
3882                 if (g_strcmp0(key, "UUID") == 0) {
3883                         uuid_str = g_variant_get_string(value, &len);
3884                 } else if (g_strcmp0(key, "Primary") == 0) {
3885                         is_primary = g_variant_get_boolean(value);
3886                 } else if (g_strcmp0(key, "Characteristics") == 0) {
3887                         g_variant_get(value, "ao", &char_iter);
3888                         if (char_iter != NULL) {
3889                                 gp_char_array = g_ptr_array_new();
3890                                 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
3891                                         DBG("char_handle: %s", char_handle);
3892                                         g_ptr_array_add(gp_char_array, (gpointer)char_handle);
3893                                 }
3894                                 g_variant_iter_free(char_iter);
3895                         }
3896                 }
3897         }
3898
3899         if (uuid_str == NULL || gp_char_array == NULL) {
3900                 ERR("uuid_str and gp_char_array should be set");
3901                 goto done;
3902         }
3903
3904         /* Create new service */
3905         _gattc_create_new_service(server_info, is_primary, uuid_str, service_path, gp_char_array);
3906
3907 done:
3908         g_variant_iter_free(property_iter);
3909         g_variant_unref(result);
3910         g_object_unref(properties_proxy);
3911
3912         return BT_STATUS_SUCCESS;
3913 }
3914
3915 static void __bt_hal_gattc_get_uuid_from_path(const char *path, char **service_uuid)
3916 {
3917         GDBusConnection *conn = NULL;
3918         GDBusProxy *proxy = NULL;
3919         GError *err = NULL;
3920         GVariant *ret = NULL;
3921         GVariant *value = NULL;
3922
3923         conn = _bt_hal_get_system_gconn();
3924         if (conn == NULL) {
3925                 ERR("_bt_gdbus_get_system_gconn returned NULL");
3926                 return;
3927         }
3928
3929         proxy = g_dbus_proxy_new_sync(conn,
3930                         G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
3931                         BT_HAL_BLUEZ_NAME, path, BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
3932         if (proxy == NULL) {
3933                 ERR("device_proxy returned NULL");
3934                 return;
3935         }
3936
3937         ret = g_dbus_proxy_call_sync(proxy, "Get",
3938                         g_variant_new("(ss)", BT_HAL_GATT_SERVICE_INTERFACE, "UUID"),
3939                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
3940         if (err) {
3941                 ERR("DBus Error : %s", err->message);
3942                 g_clear_error(&err);
3943         } else {
3944                 g_variant_get(ret, "(v)", &value);
3945                 *service_uuid = g_variant_dup_string(value, NULL);
3946                 g_variant_unref(value);
3947                 g_variant_unref(ret);
3948         }
3949
3950         if (proxy)
3951                 g_object_unref(proxy);
3952
3953         return;
3954 }
3955
3956 void _bt_hal_handle_gattc_service_changed_event(gboolean is_added, const char *path)
3957 {
3958         struct hal_ev_gatt_client_service_changed ev = {0, };
3959         char address[BT_HAL_ADDRESS_STRING_SIZE];
3960         hal_gattc_server_info_t *server_info = NULL;
3961         hal_gattc_service_t *service = NULL;
3962         GSList *list = NULL;
3963         char *uuid_str = NULL;
3964
3965         _bt_hal_convert_device_path_to_address(path, address);
3966         _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
3967         server_info = __bt_find_gatt_conn_info((bt_bdaddr_t *)ev.bdaddr);
3968         if (server_info == NULL) {
3969                 ERR("service_info is NULL");
3970                 return;
3971         }
3972
3973         if (is_added) {
3974                 /* Get service UUID from path */
3975                 __bt_hal_gattc_get_uuid_from_path(path, &uuid_str);
3976                 if (uuid_str) {
3977                         DBG("conn_id(%d) GATT Service(%s) Added", server_info->conn_id, uuid_str);
3978                         _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3979                         g_free(uuid_str);
3980                 } else {
3981                         ERR("uuid_str is NULL");
3982                         return;
3983                 }
3984
3985                 /* Create new service and append into the list */
3986                 __hal_gattc_get_service_info(server_info, path);
3987         } else {
3988                 /* Find service UUID from path */
3989                 for (list = server_info->gatt_list_services; list; list = g_slist_next(list)) {
3990                         service = (hal_gattc_service_t *)list->data;
3991                         if (service == NULL)
3992                                 continue;
3993
3994                         if (g_strcmp0(service->svc_path, path) == 0) {
3995                                 memcpy(ev.uuid, service->svc_uuid.uu, sizeof(bt_uuid_t));
3996                                 uuid_str = g_malloc0(BT_HAL_UUID_STRING_LEN);
3997                                 _bt_hal_convert_uuid_type_to_string(uuid_str, ev.uuid);
3998                                 DBG("conn_id(%d) GATT Service(%s) Removed", server_info->conn_id, uuid_str);
3999
4000                                 /* Remove service info in list */
4001                                 server_info->gatt_list_services = g_slist_remove(server_info->gatt_list_services, service);
4002                                 __hal_gattc_free_svc_info(service);
4003                                 break;
4004                         }
4005                 }
4006
4007                 if (uuid_str) {
4008                         g_free(uuid_str);
4009                 } else {
4010                         ERR("uuid_str is NULL");
4011                         return;
4012                 }
4013         }
4014
4015         /* Send GATT Client service changed event */
4016         ev.change_type = is_added;
4017         ev.conn_id = server_info->conn_id;
4018         ev.inst_id = server_info->inst_id;
4019         event_cb(HAL_EV_GATT_CLIENT_SERVICE_CHANGED, (void *)&ev, sizeof(ev));
4020 }