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