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