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