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