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