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