Resolve memory leak in HAL
[platform/core/connectivity/bluetooth-frwk.git] / bt-oal / bluez_hal / src / bt-hal-adapter-dbus-handler.c
1 /*
2  * BLUETOOTH 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 <stdio.h>
23 #include <stdlib.h>
24 #include <stdbool.h>
25 #include <string.h>
26
27 #include <glib.h>
28 #include <gio/gio.h>
29 #include <dlog.h>
30 #include <vconf.h>
31
32 #include "bt-hal.h"
33 #include "bt-hal-log.h"
34 #include "bt-hal-msg.h"
35 #include "bt-hal-utils.h"
36 #include "bt-hal-adapter-le.h"
37 #include "bt-hal-adapter-dbus-handler.h"
38 #include "bt-hal-dbus-common-utils.h"
39
40 #include "bt-internal-types.h"
41
42 #define BT_ENABLE_TIMEOUT 20000 /* 20 seconds */
43 #define BT_CORE_NAME "org.projectx.bt_core"
44 #define BT_CORE_PATH "/org/projectx/bt_core"
45 #define BT_CORE_INTERFACE "org.projectx.btcore"
46
47 static GDBusProxy *core_proxy = NULL;
48 static GDBusConnection *system_conn = NULL;
49 static handle_stack_msg event_cb = NULL;
50
51 handle_stack_msg _bt_get_adapter_event_cb(void)
52 {
53         if (!event_cb)
54                 return event_cb;
55         else
56                 return NULL;
57 }
58
59 GDBusConnection *__bt_hal_get_system_gconn(void)
60 {
61         if (system_conn == NULL)
62                 system_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
63
64         return system_conn;
65 }
66
67 GDBusProxy *_bt_init_core_proxy(void)
68 {       GDBusProxy *proxy;
69         GDBusConnection *conn;
70
71         conn = __bt_hal_get_system_gconn();
72         if (!conn)
73                 return NULL;
74
75         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
76                         NULL,
77                         BT_CORE_NAME,
78                         BT_CORE_PATH,
79                         BT_CORE_INTERFACE,
80                         NULL, NULL);
81
82         if (!proxy)
83                 return NULL;
84
85         core_proxy = proxy;
86
87         return proxy;
88 }
89
90 static GDBusProxy *__bt_get_core_proxy(void)
91 {
92         return (core_proxy) ? core_proxy : _bt_init_core_proxy();
93 }
94
95 /* To send stack event to hal-bluetooth handler */
96 void _bt_hal_dbus_store_stack_msg_cb(handle_stack_msg cb)
97 {
98         event_cb = cb;
99 }
100
101 int _bt_hal_enable_core(void)
102 {
103         DBG("");
104         GDBusProxy *proxy;
105         GVariant *result;
106         GError *error = NULL;
107
108         proxy = __bt_get_core_proxy();
109         if(!proxy)
110                 return BT_HAL_ERROR_INTERNAL;
111
112         /* Clean up the process */
113         result = g_dbus_proxy_call_sync(proxy,
114                                "EnableCore",
115                                NULL,
116                                G_DBUS_CALL_FLAGS_NONE,
117                               -1,
118                               NULL,
119                                &error);
120
121         if (!result) {
122                 if (error != NULL) {
123                         ERR("Bt core call failed(Error: %s)", error->message);
124                         g_clear_error(&error);
125                 } else
126                         ERR("Bt core call failed");
127                 return BT_HAL_ERROR_INTERNAL;
128         }
129
130         g_variant_unref(result);
131         return BT_HAL_ERROR_NONE;
132 }
133
134 static gboolean __bt_hal_send_adapter_event(gpointer user_data)
135 {
136         struct hal_ev_adapter_state_changed ev;
137         gboolean *enable = (gboolean *)user_data;
138
139         if (*enable == TRUE)
140                 ev.state = HAL_POWER_ON;
141         else
142                 ev.state = HAL_POWER_OFF;
143
144         if (!event_cb)
145                 event_cb = _bt_get_adapter_event_cb();
146
147         if (event_cb)
148                 event_cb(HAL_EV_ADAPTER_STATE_CHANGED, &ev, sizeof(ev));
149
150         g_free(enable);
151         return false;
152 }
153
154 static gboolean __bt_hal_send_le_event(gpointer user_data)
155 {
156         struct hal_ev_le_state_changed ev;
157         gboolean *enable = (gboolean *)user_data;
158
159         if (*enable == TRUE)
160                 ev.state = HAL_POWER_ON;
161         else
162                 ev.state = HAL_POWER_OFF;
163
164         if (!event_cb)
165                 event_cb = _bt_get_adapter_event_cb();
166
167         if (event_cb)
168                 event_cb(HAL_EV_LE_STATE_CHANGED, &ev, sizeof(ev));
169
170         g_free(enable);
171         return false;
172
173 }
174
175 int _bt_hal_dbus_enable_adapter(void)
176 {
177         GDBusProxy *proxy;
178         GError *error = NULL;
179         GVariant *result = NULL;
180         unsigned char powered = 0;
181
182         DBG("+");
183
184         int le_value = VCONFKEY_BT_LE_STATUS_OFF;
185         if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &le_value))
186                 ERR("fail to get vconf key!");
187
188         if (_bt_hal_get_adapter_powered_state(&powered) == BT_STATUS_FAIL)
189                 ERR("_bt_hal_get_adapter_powered_state failed");
190
191         /*if LE is enabled and bluez is UP , send event from here and return.*/
192         if ((le_value == VCONFKEY_BT_LE_STATUS_ON) && (powered == 1)) {
193                 gboolean *user_data = g_new0(int, 1);
194                 *user_data = TRUE;
195                 g_idle_add(__bt_hal_send_adapter_event, (gpointer)user_data);
196                 return BT_STATUS_SUCCESS;
197         }
198
199         if (TIZEN_FEATURE_BT_USB_DONGLE && powered == 1) {
200                 gboolean *user_data = g_new0(int, 1);
201                 *user_data = TRUE;
202                 g_idle_add(__bt_hal_send_adapter_event, (gpointer)user_data);
203                 return BT_STATUS_SUCCESS;
204         }
205
206         proxy = __bt_get_core_proxy();
207
208         if (!proxy) {
209                 ERR("_bt_hal_dbus_enable_adapter: Core proxy get failed!!!");
210                 return BT_STATUS_FAIL;
211         }
212
213         _bt_hal_set_adapter_request_state(TRUE);
214         _bt_hal_set_le_request_state(TRUE);
215         result = g_dbus_proxy_call_sync(proxy, "EnableAdapter",
216                         NULL,
217                         G_DBUS_CALL_FLAGS_NONE, BT_ENABLE_TIMEOUT,
218                         NULL, &error);
219         if (error) {
220                 ERR("EnableAdapter failed: %s", error->message);
221                 g_clear_error(&error);
222                 error = NULL;
223                 _bt_hal_set_adapter_request_state(FALSE);
224                 _bt_hal_set_le_request_state(FALSE);
225                 result = g_dbus_proxy_call_sync(proxy,
226                                 "DisableAdapter",
227                                 NULL,
228                                 G_DBUS_CALL_FLAGS_NONE,
229                                 -1,
230                                 NULL,
231                                 &error);
232
233                 if (error != NULL) {
234                         ERR("Bt core call failed(Error: %s)", error->message);
235                         g_clear_error(&error);
236                 }
237                 g_variant_unref(result);
238                 /*Terminate myself*/
239                 /* TODO: Terminate bluetooth service or not, need to check */
240                 /*g_idle_add((GSourceFunc)_bt_terminate_service, NULL);*/
241                 return BT_STATUS_FAIL;
242         }
243
244         g_variant_unref(result);
245         return BT_STATUS_SUCCESS;
246 }
247
248 int _bt_hal_dbus_disable_adapter(void)
249 {
250         GDBusProxy *proxy;
251         GError *error = NULL;
252         GVariant *result = NULL;
253
254         DBG("+");
255         proxy = __bt_get_core_proxy();
256         if (!proxy) {
257                 ERR("_bt_hal_dbus_enable_adapter: Core proxy get failed!!!");
258                 return BT_STATUS_FAIL;
259         }
260
261         result = g_dbus_proxy_call_sync(proxy, "DisableAdapter",
262                         NULL,
263                         G_DBUS_CALL_FLAGS_NONE, -1,
264                         NULL, &error);
265         if (error) {
266                 ERR("DisableAdapter failed: %s", error->message);
267                 g_clear_error(&error);
268                 error = NULL;
269                 g_variant_unref(result);
270                 /*Terminate myself*/
271                 /* TODO: Terminate bluetooth service or not, need to check */
272                 /*g_idle_add((GSourceFunc)_bt_terminate_service, NULL);*/
273                 return BT_STATUS_FAIL;
274         }
275
276         g_variant_unref(result);
277         return BT_STATUS_SUCCESS;
278 }
279
280 int _bt_hal_dbus_recover_adapter(void)
281 {
282         GDBusProxy *proxy;
283         GVariant *result = NULL;
284         GError *error = NULL;
285
286         DBG("+");
287         proxy = __bt_get_core_proxy();
288         if (!proxy) {
289                 ERR("_bt_hal_dbus_recover_adapter: Core proxy get failed!!!");
290                 return BT_STATUS_FAIL;
291         }
292
293         result = g_dbus_proxy_call_sync(proxy, "RecoverAdapter",
294                         NULL,
295                         G_DBUS_CALL_FLAGS_NONE, -1,
296                         NULL, &error);
297         if (error) {
298                 ERR("RecoverAdapter failed: %s", error->message);
299                 g_clear_error(&error);
300                 error = NULL;
301                 return BT_STATUS_FAIL;
302         }
303
304         g_variant_unref(result);
305         return BT_STATUS_SUCCESS;
306 }
307
308 #ifdef TIZEN_BT_HAL
309 int _bt_hal_dbus_enable_le(void)
310 {
311         GDBusProxy *proxy;
312         GError *error = NULL;
313         GVariant *result = NULL;
314         int adapter_value = VCONFKEY_BT_STATUS_OFF;
315         unsigned char powered = 0;
316
317         DBG("+");
318
319         if (vconf_get_int(VCONFKEY_BT_STATUS, &adapter_value) != 0)
320                 ERR("fail to get vconf key!");
321
322         if (_bt_hal_get_adapter_powered_state(&powered) == BT_STATUS_FAIL)
323                 ERR("_bt_hal_get_adapter_powered_state failed");
324
325         if ((adapter_value == VCONFKEY_BT_STATUS_ON) && (powered == 1)) {
326                 gboolean *user_data = g_new0(int, 1);
327                 *user_data = TRUE;
328                 g_idle_add(__bt_hal_send_le_event, (gpointer)user_data);
329                 return BT_STATUS_SUCCESS;
330         }
331
332         proxy = __bt_get_core_proxy();
333
334         if (!proxy) {
335                 DBG("_bt_hal_dbus_enable_le: Core proxy get failed!!!");
336                 return BT_STATUS_FAIL;
337         }
338         _bt_hal_set_le_request_state(TRUE);
339
340         result = g_dbus_proxy_call_sync(proxy, "EnableAdapterLe",
341                         NULL,
342                         G_DBUS_CALL_FLAGS_NONE, BT_ENABLE_TIMEOUT,
343                         NULL, &error);
344         if (error) {
345                 DBG("EnableAdapterLe failed: %s", error->message);
346                 g_clear_error(&error);
347                 error = NULL;
348                 result = g_dbus_proxy_call_sync(proxy,
349                                 "DisableAdapterLe",
350                                 NULL,
351                                 G_DBUS_CALL_FLAGS_NONE,
352                                 -1,
353                                 NULL,
354                                 &error);
355
356                 _bt_hal_set_le_request_state(FALSE);
357                 if (error != NULL) {
358                         DBG("Bt core call failed(Error: %s)", error->message);
359                         g_clear_error(&error);
360                 }
361                 g_variant_unref(result);
362
363                 return BT_STATUS_FAIL;
364         }
365
366         DBG("-");
367         g_variant_unref(result);
368         return BT_STATUS_SUCCESS;
369 }
370
371 int _bt_hal_dbus_disable_le(void)
372 {
373         GDBusProxy *proxy;
374         GError *error = NULL;
375         GVariant *result = NULL;
376         int adapter_value = VCONFKEY_BT_STATUS_OFF;
377
378         DBG("+");
379         if (vconf_get_int(VCONFKEY_BT_STATUS, &adapter_value) != 0)
380                 ERR("fail to get vconf key!");
381
382         if (adapter_value == VCONFKEY_BT_STATUS_ON) {
383                 gboolean *user_data = g_new0(int, 1);
384                 *user_data = FALSE;
385                 g_idle_add(__bt_hal_send_le_event, (gpointer)user_data);
386                 return BT_STATUS_SUCCESS;
387         }
388
389         proxy = __bt_get_core_proxy();
390
391         if (!proxy) {
392                 DBG("_bt_hal_dbus_disable_le: Core proxy get failed!!!");
393                 return BT_STATUS_FAIL;
394         }
395
396         result = g_dbus_proxy_call_sync(proxy, "DisableAdapterLe",
397                         NULL,
398                         G_DBUS_CALL_FLAGS_NONE, -1,
399                         NULL, &error);
400         if (error) {
401                 DBG("DisableAdapter failed: %s", error->message);
402                 g_clear_error(&error);
403                 error = NULL;
404                 g_variant_unref(result);
405                 return BT_STATUS_FAIL;
406         }
407
408
409
410         DBG("-");
411         g_variant_unref(result);
412         return BT_STATUS_SUCCESS;
413 }
414 #endif
415
416 #ifdef TIZEN_BT_HAL
417 int _bt_hal_dbus_reset_adapter(void)
418 {
419         GDBusProxy *proxy;
420         GVariant *result;
421         GError *error = NULL;
422         INFO("+");
423
424         proxy = __bt_get_core_proxy();
425         if (!proxy)
426                 return BT_STATUS_FAIL;
427
428         result = g_dbus_proxy_call_sync(proxy,
429                         "ResetAdapter",
430                         NULL,
431                         G_DBUS_CALL_FLAGS_NONE,
432                         -1,
433                         NULL,
434                         &error);
435
436         if (!result) {
437                 if (error != NULL) {
438                         ERR("Failed to ResetAdapter (Error: %s)", error->message);
439                         g_clear_error(&error);
440                 } else
441                         ERR("Failed to ResetAdapter");
442                 return BT_STATUS_FAIL;
443         }
444
445         g_variant_unref(result);
446         return BT_STATUS_SUCCESS;
447 }
448 #endif
449
450 int _bt_hal_dbus_start_discovery(gboolean is_custom,
451                                         bt_disc_role_type_t role)
452 {
453         GDBusProxy *proxy;
454         GError *error = NULL;
455         GVariant *result;
456         const gchar *disc_type;
457         DBG("Discovery Type: Is Custom : [%s]", is_custom ? "TRUE" : "FALSE");
458
459         proxy = _bt_hal_get_adapter_proxy();
460         if (!proxy) {
461                 DBG("Adapter proxy get failed!!!");
462                 return BT_STATUS_FAIL;
463         }
464
465         if (is_custom) {
466                 if (role == BT_DISC_ROLE_BREDR)
467                         disc_type = "BREDR";
468                 else if (role == BT_DISC_ROLE_LE)
469                         disc_type = "LE";
470                 else if (role == BT_DISC_ROLE_DUAL)
471                         disc_type = "LE_BREDR";
472                 else
473                         return BT_STATUS_PARM_INVALID;
474
475                 result = g_dbus_proxy_call_sync(proxy,
476                                 "StartCustomDiscovery",
477                                 g_variant_new("s", disc_type),
478                                 G_DBUS_CALL_FLAGS_NONE,
479                                 -1,
480                                 NULL,
481                                 &error);
482         } else
483                 result = g_dbus_proxy_call_sync(proxy,
484                                 "StartDiscovery",
485                                 NULL,
486                                 G_DBUS_CALL_FLAGS_NONE,
487                                 -1,
488                                 NULL,
489                                 &error);
490
491         if (!result) {
492                 if (error != NULL) {
493                         ERR("StartDiscovery failed (Error: %s)", error->message);
494                         g_clear_error(&error);
495                 } else
496                         ERR("StartDiscovery failed");
497                 return BT_STATUS_FAIL;
498         }
499
500         /* discovery status will be change in event */
501         DBG("-");
502         g_variant_unref(result);
503         return BT_STATUS_SUCCESS;
504 }
505
506 int _bt_hal_dbus_stop_discovery(void)
507 {
508         GDBusProxy *proxy;
509         GError *error = NULL;
510         GVariant *result;
511         DBG("+");
512
513         proxy = _bt_hal_get_adapter_proxy();
514         if (!proxy) {
515                 DBG("_bt_hal_dbus_stop_discovery: Adapter proxy get failed!!!");
516                 return BT_STATUS_FAIL;
517         }
518
519         result = g_dbus_proxy_call_sync(proxy,
520                         "StopDiscovery",
521                         NULL,
522                         G_DBUS_CALL_FLAGS_NONE,
523                         -1,
524                         NULL,
525                         &error);
526
527         if (!result) {
528                 if (error != NULL) {
529                         ERR("StopDiscovery failed (Error: %s)", error->message);
530                         g_clear_error(&error);
531                 } else
532                         ERR("StopDiscovery failed");
533                 return BT_STATUS_FAIL;
534         }
535
536         /* discovery status will be change in event */
537         DBG("-");
538         g_variant_unref(result);
539         return BT_STATUS_SUCCESS;
540 }
541
542 static gboolean __bt_adapter_all_properties_cb(gpointer user_data)
543 {
544         GVariant *result = user_data;
545         GVariantIter *property_iter;
546         const gchar *key;
547         GVariant *value;
548
549         /* Buffer and propety count management */
550         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
551         struct hal_ev_adapter_props_changed *ev = (void*) buf;
552         size_t size = 0;
553         gchar *address = NULL;
554         gchar *name = NULL;
555         unsigned int cod = 0;
556         gboolean discoverable;
557         gboolean connectable;
558         unsigned int scan_mode = BT_SCAN_MODE_NONE;
559         unsigned int disc_timeout;
560         gchar *version;
561         gboolean is_discovering;
562         gboolean is_le_discovering;
563         uint8_t ipsp_initialized;
564         gboolean powered;
565         uint8_t pairable;
566         unsigned int pairable_timeout;
567         gboolean scan_mode_property_update = FALSE;
568
569         DBG("+");
570
571         memset(buf, 0, sizeof(buf));
572         size = sizeof(*ev);
573         ev->num_props = 0;
574         ev->status = BT_STATUS_SUCCESS;
575
576         DBG("@@Start parsing properties");
577         g_variant_get(result, "(a{sv})", &property_iter);
578         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
579                 if (!g_strcmp0(key, "Address")) {
580                         uint8_t bdaddr[6];
581
582                         address = (gchar *) g_variant_get_string(value, NULL);
583                         DBG("Address [%s]", address);
584                         _bt_hal_convert_addr_string_to_type(bdaddr, address);
585                         size += __bt_insert_hal_properties(buf + size,
586                                         HAL_PROP_ADAPTER_ADDR, sizeof(bdaddr), bdaddr);
587                         ev->num_props++;
588                 } else if (!g_strcmp0(key, "Alias")) {
589                         name = (gchar *) g_variant_get_string(value, NULL);
590                         DBG("Alias [%s]", name);
591                         size += __bt_insert_hal_properties(buf + size,
592                                         HAL_PROP_ADAPTER_NAME, strlen(name) + 1, name);
593                         ev->num_props++;
594                 } else if (!g_strcmp0(key, "Class")) {
595                         cod = g_variant_get_uint32(value);
596                         DBG("Class [%d]", cod);
597                         size += __bt_insert_hal_properties(buf + size,
598                                         HAL_PROP_ADAPTER_CLASS, sizeof(unsigned int), &cod);
599                         ev->num_props++;
600                 } else if (!g_strcmp0(key, "Discoverable")) {
601                         discoverable = g_variant_get_boolean(value);
602                         DBG("Discoverable [%d]", discoverable);
603                         if (discoverable)
604                                 scan_mode = BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
605                         scan_mode_property_update = TRUE;
606                 } else if (!g_strcmp0(key, "DiscoverableTimeout")) {
607                         disc_timeout = g_variant_get_uint32(value);
608                         DBG("Discoverable Timeout [%d]", disc_timeout);
609                         size += __bt_insert_hal_properties(buf + size,
610                                         HAL_PROP_ADAPTER_DISC_TIMEOUT, sizeof(unsigned int), &disc_timeout);
611                         ev->num_props++;
612                 } else if (!g_strcmp0(key, "Connectable")) {
613                         connectable = g_variant_get_boolean(value);
614                         DBG("Connectable [%d]", connectable);
615                         if (scan_mode == BT_SCAN_MODE_NONE)
616                                 scan_mode = BT_SCAN_MODE_CONNECTABLE;
617                         scan_mode_property_update = TRUE;
618                 } else if (!g_strcmp0(key, "Version")) {
619                         version = (gchar *) g_variant_get_string(value, NULL);
620                         DBG("Version [%s]", version);
621                         size += __bt_insert_hal_properties(buf + size,
622                                         HAL_PROP_ADAPTER_VERSION, strlen(version) + 1, version);
623                         ev->num_props++;
624                 } else if (!g_strcmp0(key, "Name")) {
625                         name = (gchar *) g_variant_get_string(value, NULL);
626                         DBG("Name [%s]", name);
627                         size += __bt_insert_hal_properties(buf + size,
628                                         HAL_PROP_ADAPTER_NAME, strlen(name) + 1, name);
629                         ev->num_props++;
630                 } else if (!g_strcmp0(key, "Powered")) {
631                         powered = g_variant_get_boolean(value);
632                         DBG("Powered = [%d]", powered);
633                 } else if (!g_strcmp0(key, "Pairable")) {
634                         pairable = (g_variant_get_boolean(value) ? 1 : 0);
635                         DBG("Pairable [%d]", pairable);
636                         size += __bt_insert_hal_properties(buf + size,
637                                         HAL_PROP_ADAPTER_PAIRABLE, sizeof(uint8_t), &pairable);
638                         ev->num_props++;
639                 } else if (!g_strcmp0(key, "PairableTimeout")) {
640                         pairable_timeout = g_variant_get_uint32(value);
641                         DBG("Pairable Timeout = [%d]", pairable_timeout);
642                         size += __bt_insert_hal_properties(buf + size,
643                                         HAL_PROP_ADAPTER_PAIRABLE_TIMEOUT, sizeof(unsigned int), &pairable_timeout);
644                         ev->num_props++;
645                 } else if (!g_strcmp0(key, "UUIDs")) {
646                         char **uuid_value;
647                         int uuid_count = 0;
648                         gsize size1 = 0;
649                         int i = 0;
650                         size1 = g_variant_get_size(value);
651                         int num_props_tmp = ev->num_props;
652                         if (size1 > 0) {
653                                 uuid_value = (char **)g_variant_get_strv(value, &size1);
654                                 for (i = 0; uuid_value[i] != NULL; i++)
655                                         uuid_count++;
656                                 /* UUID collection */
657                                 uint8_t uuids[HAL_UUID_LEN * uuid_count];
658                                 for (i = 0; uuid_value[i] != NULL; i++) {
659                                         char *uuid_str = NULL;
660                                         uint8_t uuid[HAL_UUID_LEN];
661                                         uuid_str = g_strdup(uuid_value[i]);
662                                         DBG("UUID string [%s]\n", uuid_str);
663                                         _bt_hal_convert_uuid_string_to_type(uuid, uuid_str);
664                                         memcpy(uuids + i * HAL_UUID_LEN, uuid, HAL_UUID_LEN);
665                                         g_free(uuid_str);
666                                 }
667                                 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_UUIDS,
668                                                 (HAL_UUID_LEN * uuid_count),
669                                                 uuids);
670                                 ev->num_props = num_props_tmp + 1;
671                                 g_free(uuid_value);
672                         }
673                 } else if (!g_strcmp0(key, "Discovering")) {
674                         is_discovering = g_variant_get_boolean(value);
675                         DBG("Discovering = [%d]", is_discovering);
676                 } else if (!g_strcmp0(key, "LEDiscovering")) {
677                         is_le_discovering = g_variant_get_boolean(value);
678                         DBG("LE Discovering = [%d]", is_le_discovering);
679                 } else if (!g_strcmp0(key, "Modalias")) {
680                         char *modalias = NULL;
681                         g_variant_get(value, "s", &modalias);
682                         DBG("Adapter ModAlias [%s]", modalias);
683                         size += __bt_insert_hal_properties(buf + size,
684                                         HAL_PROP_ADAPTER_MODALIAS, strlen(modalias) + 1, modalias);
685                         ev->num_props++;
686                         g_free(modalias);
687                 } else if (!g_strcmp0(key, "SupportedLEFeatures")) {
688                         DBG("LE Supported features");
689                         char *name = NULL;
690                         char *val = NULL;
691                         GVariantIter *iter = NULL;
692                         bt_local_le_features_t le_features;
693                         gboolean le_features_present = FALSE;
694
695                         memset(&le_features, 0x00, sizeof(le_features));
696
697                         g_variant_get(value, "as", &iter);
698                         if (iter) {
699                                 while (g_variant_iter_loop(iter, "s", &name)) {
700                                         DBG("name = %s", name);
701                                         g_variant_iter_loop(iter, "s", &val);
702                                         DBG("Value = %s", val);
703                                         _bt_hal_update_le_feature_support(name, val, &le_features);
704                                         le_features_present = TRUE;
705                                 }
706                                 g_variant_iter_free(iter);
707
708                                 if (le_features_present) {
709                                         size += __bt_insert_hal_properties(buf + size,
710                                                         HAL_PROP_ADAPTER_LOCAL_LE_FEAT, sizeof(le_features), &le_features);
711                                         ev->num_props++;
712                                 } else {
713                                         DBG("le supported features values are NOT provided by Stack");
714                                 }
715                         }
716                 } else if (!g_strcmp0(key, "IpspInitStateChanged")) {
717                         ipsp_initialized = (g_variant_get_boolean(value) ? 1 : 0);
718                         DBG("IPSP Initialized = %d", ipsp_initialized);
719                         size += __bt_insert_hal_properties(buf + size,
720                                         HAL_PROP_ADAPTER_IPSP_INITIALIZED, sizeof(uint8_t), &ipsp_initialized);
721                         ev->num_props++;
722                 } else {
723                         ERR("Unhandled Property:[%s]", key);
724                 }
725         }
726
727         if (scan_mode_property_update) {
728                 size += __bt_insert_hal_properties(buf + size,
729                                 HAL_PROP_ADAPTER_SCAN_MODE, sizeof(int), &scan_mode);
730                 ev->num_props++;
731         }
732
733         if (!event_cb)
734                 event_cb = _bt_get_adapter_event_cb();
735         if (!event_cb) {
736                 ERR("event_cb is NULL");
737                 goto done;
738         }
739
740         if (size > 2) {
741                 DBG("Send Adapter properties changed event to HAL user,"
742                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
743                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
744         }
745 done:
746         g_variant_unref(result);
747         g_variant_iter_free(property_iter);
748         return FALSE;
749 }
750
751 static int __bt_hal_dbus_get_all_adapter_properties(void)
752 {
753         GDBusProxy *proxy;
754         GVariant *result;
755         GError *error = NULL;
756
757         DBG("+");
758
759         proxy = _bt_hal_get_adapter_properties_proxy();
760         if (!proxy) {
761                 DBG("Adapter Properties proxy get failed!!!");
762                 return BT_STATUS_FAIL;
763         }
764
765         result = g_dbus_proxy_call_sync(proxy,
766                         "GetAll",
767                         g_variant_new("(s)", BT_HAL_ADAPTER_INTERFACE),
768                         G_DBUS_CALL_FLAGS_NONE,
769                         -1,
770                         NULL,
771                         &error);
772
773         if (!result) {
774                 if (error != NULL) {
775                         ERR("Failed to get all adapter properties (Error: %s)", error->message);
776                         g_clear_error(&error);
777                 } else
778                         ERR("Failed to get all adapter properties");
779                 return BT_STATUS_FAIL;
780         }
781
782         DBG("Got All properties from Bluez Stack!!, time to start parsing");
783         /*
784          * As we need to provide async callback to user from HAL, simply schedule a
785          * callback method which will carry actual result
786          */
787         g_idle_add(__bt_adapter_all_properties_cb, (gpointer)result);
788
789         DBG("-");
790         return BT_STATUS_SUCCESS;
791 }
792
793 int _bt_hal_dbus_get_adapter_properties(void)
794 {
795         DBG("+");
796
797         return __bt_hal_dbus_get_all_adapter_properties();
798 }
799
800 int _bt_hal_get_adapter_powered_state(uint8_t *state)
801 {
802         char *adapter_path = NULL;
803         gboolean powered = FALSE;
804         int ret = BT_STATUS_FAIL;
805
806         /* Check Valid Adapter Path, followed by Adapter Powered state.
807            If any of these fails, adapter will be considered Disabled */
808         adapter_path = _bt_hal_get_adapter_path();
809
810         if (adapter_path == NULL) {
811                 INFO("adapter_path is NULL");
812                 g_free(adapter_path);
813                 *state = 0;
814                 return ret;
815         }
816
817         /* Check Adapter Powered Status */
818         ret = _bt_hal_is_adapter_powered(&powered);
819         if (BT_STATUS_FAIL == ret) {
820                 INFO("Adapter is not powered");
821                 g_free(adapter_path);
822                 *state = 0;
823                 return ret;
824         }
825
826         if (powered)
827                 *state = 1;
828         else
829                 *state = 0;
830
831         return ret;
832 }
833
834 /* Get Discoverable timeout API and callback */
835 static gboolean __bt_adapter_discovery_timeout_cb(gpointer user_data)
836 {
837         /* Buffer and propety count management */
838         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
839         struct hal_ev_adapter_props_changed *ev = (void*) buf;;
840         size_t size = 0;
841         unsigned int *timeout = user_data;
842
843         memset(buf, 0, sizeof(buf));
844         size = sizeof(*ev);
845         ev->num_props = 0;
846         ev->status = BT_STATUS_SUCCESS;
847
848         DBG("Discovery timeout in callback: [%d]", *timeout);
849
850         size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_DISC_TIMEOUT,
851                         sizeof(unsigned int), timeout);
852
853         ev->num_props++;
854         DBG("Timeout value [%d] property Num [%d]", *timeout, ev->num_props);
855
856         if (!event_cb)
857                 event_cb = _bt_get_adapter_event_cb();
858         if (!event_cb) {
859                 ERR("event_cb is NULL");
860                 goto done;
861         }
862
863         if (size > 2) {
864                 DBG("Send Adapter Properties changed event to HAL user,"
865                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
866                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
867         }
868 done:
869         g_free(timeout);
870         return FALSE;
871 }
872
873 int _bt_hal_dbus_get_discovery_timeout(void)
874 {
875         GDBusProxy *proxy;
876         GVariant *result;
877         GVariant *temp;
878         GError *error = NULL;
879         unsigned int *timeout;
880         DBG("+");
881
882         proxy = _bt_hal_get_adapter_properties_proxy();
883         if (!proxy) {
884                 DBG("Adapter Properties proxy get failed!!!");
885                 return BT_STATUS_FAIL;
886         }
887
888         result = g_dbus_proxy_call_sync(proxy,
889                         "Get",
890                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
891                                 "DiscoverableTimeout"),
892                         G_DBUS_CALL_FLAGS_NONE,
893                         -1,
894                         NULL,
895                         &error);
896
897         if (!result) {
898                 if (error != NULL) {
899                         ERR("Failed to get local version (Error: %s)", error->message);
900                         g_clear_error(&error);
901                 } else
902                         ERR("Failed to get local version");
903                 return BT_STATUS_FAIL;
904         }
905
906         timeout = g_malloc0(sizeof(int));
907         if (!timeout) {
908                 ERR("Memory allocation failed");
909                 g_variant_unref(result);
910                 return BT_STATUS_FAIL;
911         }
912
913         g_variant_get(result, "(v)", &temp);
914         *timeout = g_variant_get_uint32(temp);
915         DBG("Timeout value: [%d]", *timeout);
916
917         g_variant_unref(result);
918         g_variant_unref(temp);
919
920         /*
921          * As we need to provide async callback to user from HAL, simply schedule a
922          * callback method which will carry actual result
923          */
924         g_idle_add(__bt_adapter_discovery_timeout_cb, (gpointer) timeout);
925
926         DBG("-");
927         return BT_STATUS_SUCCESS;
928 }
929
930 int _bt_hal_dbus_get_adapter_class(unsigned int *adapter_class)
931 {
932         GDBusProxy *proxy;
933         GVariant *result;
934         GVariant *temp;
935         GError *error = NULL;
936         DBG("+");
937
938         proxy = _bt_hal_get_adapter_properties_proxy();
939         if (!proxy) {
940                 DBG("Adapter Properties proxy get failed!!!");
941                 return BT_STATUS_FAIL;
942         }
943
944         result = g_dbus_proxy_call_sync(proxy,
945                         "Get",
946                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
947                                 "Class"),
948                         G_DBUS_CALL_FLAGS_NONE,
949                         -1,
950                         NULL,
951                         &error);
952
953         if (!result) {
954                 if (error != NULL) {
955                         ERR("Failed to get class (Error: %s)", error->message);
956                         g_clear_error(&error);
957                 } else
958                         ERR("Failed to get class");
959                 return BT_STATUS_FAIL;
960         }
961
962
963         g_variant_get(result, "(v)", &temp);
964         *adapter_class = g_variant_get_uint32(temp);
965         DBG("Class value: [0x%06x]", *adapter_class);
966
967         g_variant_unref(result);
968         g_variant_unref(temp);
969
970         DBG("-");
971         return BT_STATUS_SUCCESS;
972 }
973
974 /* Get Discoverable Mode API and callback */
975 static gboolean __bt_adapter_scan_mode_cb(gpointer user_data)
976 {
977         /* Buffer and propety count management */
978         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
979         struct hal_ev_adapter_props_changed *ev = (void*) buf;;
980         size_t size = 0;
981         int *mode = user_data;
982
983         memset(buf, 0, sizeof(buf));
984         size = sizeof(*ev);
985         ev->num_props = 0;
986         ev->status = BT_STATUS_SUCCESS;
987
988         DBG("Scan mode callback: [%d]", *mode);
989
990         size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_SCAN_MODE,
991                         sizeof(int), mode);
992
993         ev->num_props++;
994         DBG("Scan mode [%d] property Num [%d]", *mode, ev->num_props);
995
996         if (!event_cb)
997                 event_cb = _bt_get_adapter_event_cb();
998         if (!event_cb) {
999                 ERR("event_cb is NULL");
1000                 goto done;
1001         }
1002
1003         if (size > 2) {
1004                 DBG("Send Adapter Properties changed event to HAL user,"
1005                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
1006                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1007         }
1008 done:
1009         g_free(mode);
1010         return FALSE;
1011 }
1012
1013 int _bt_hal_dbus_get_scan_mode(void)
1014 {
1015         GDBusProxy *proxy;
1016         gboolean discoverable;
1017         gboolean connectable;
1018         GVariant *result;
1019         GVariant *temp;
1020         GError *error = NULL;
1021         int *scan_mode;
1022                 ;
1023         DBG("+");
1024
1025         proxy = _bt_hal_get_adapter_properties_proxy();
1026         if (!proxy) {
1027                 DBG("Adapter Properties proxy get failed!!!");
1028                 return BT_STATUS_FAIL;
1029         }
1030
1031         result = g_dbus_proxy_call_sync(proxy,
1032                         "Get",
1033                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1034                                 "Discoverable"),
1035                         G_DBUS_CALL_FLAGS_NONE,
1036                         -1,
1037                         NULL,
1038                         &error);
1039
1040         if (!result) {
1041                 if (error != NULL) {
1042                         ERR("Failed to get discoverable mode (Error: %s)", error->message);
1043                         g_clear_error(&error);
1044                 } else
1045                         ERR("Failed to get discoverable mode");
1046                 return BT_STATUS_FAIL;
1047         }
1048
1049         g_variant_get(result, "(v)", &temp);
1050         discoverable = g_variant_get_boolean(temp);
1051         DBG("discoverable:%d", discoverable);
1052
1053         g_variant_unref(result);
1054         g_variant_unref(temp);
1055
1056         if (!discoverable) {
1057                 result = g_dbus_proxy_call_sync(proxy,
1058                                 "Get",
1059                                 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1060                                         "Connectable"),
1061                                 G_DBUS_CALL_FLAGS_NONE,
1062                                 -1,
1063                                 NULL,
1064                                 &error);
1065                 if (!result) {
1066                         if (error != NULL) {
1067                                 ERR("Failed to get connectable mode (Error: %s)", error->message);
1068                                 g_clear_error(&error);
1069                         } else
1070                                 ERR("Failed to get connectable mode");
1071                         return BT_STATUS_FAIL;
1072                 }
1073
1074                 g_variant_get(result, "(v)", &temp);
1075                 connectable = g_variant_get_boolean(temp);
1076                 DBG("connectable:%d", connectable);
1077
1078                 g_variant_unref(result);
1079                 g_variant_unref(temp);
1080         }
1081
1082         scan_mode = g_malloc0(sizeof(int));
1083         if (!scan_mode) {
1084                 ERR("Memory allocation failed");
1085                 return BT_STATUS_FAIL;
1086         }
1087
1088         if (discoverable)
1089                 *scan_mode = BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
1090         else if (connectable)
1091                 *scan_mode = BT_SCAN_MODE_CONNECTABLE;
1092         else
1093                 *scan_mode = BT_SCAN_MODE_NONE;
1094
1095         /*
1096          * As we need to provide async callback to user from HAL, simply schedule a
1097          * callback method which will carry actual result
1098          */
1099         g_idle_add(__bt_adapter_scan_mode_cb, (gpointer) scan_mode);
1100
1101         DBG("-");
1102         return BT_STATUS_SUCCESS;
1103 }
1104
1105 /* Get Local Version API and callback */
1106 static gboolean __bt_adapter_local_version_cb(gpointer user_data)
1107 {
1108         /* Buffer and propety count management */
1109         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1110         struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1111         size_t size = 0;
1112         char *version = NULL;
1113
1114         memset(buf, 0, sizeof(buf));
1115         size = sizeof(*ev);
1116         ev->num_props = 0;
1117         ev->status = BT_STATUS_SUCCESS;
1118
1119         version = (char*) user_data;
1120         DBG("Local Version in callback: [%s]", version);
1121
1122         size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_VERSION,
1123                         (strlen(version) + 1), version);
1124
1125         ev->num_props++;
1126         DBG("Device version [%s] property Num [%d]", version, ev->num_props);
1127
1128         if (!event_cb)
1129                 event_cb = _bt_get_adapter_event_cb();
1130         if (!event_cb) {
1131                 ERR("event_cb is NULL");
1132                 goto done;
1133         }
1134
1135         if (size > 2) {
1136                 DBG("Send Adapter Properties changed event to HAL user,"
1137                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
1138                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1139         }
1140 done:
1141         g_free(version);
1142         return FALSE;
1143 }
1144
1145 int _bt_hal_dbus_get_local_version(void)
1146 {
1147         GDBusProxy *proxy;
1148         const char *version = NULL;
1149         GVariant *result;
1150         GVariant *temp;
1151         GError *error = NULL;
1152         DBG("+");
1153
1154         proxy = _bt_hal_get_adapter_properties_proxy();
1155         if (!proxy) {
1156                 DBG("Adapter Properties proxy get failed!!!");
1157                 return BT_STATUS_FAIL;
1158         }
1159
1160         result = g_dbus_proxy_call_sync(proxy,
1161                         "Get",
1162                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1163                                 "Version"),
1164                         G_DBUS_CALL_FLAGS_NONE,
1165                         -1,
1166                         NULL,
1167                         &error);
1168
1169         if (!result) {
1170                 if (error != NULL) {
1171                         ERR("Failed to get local version (Error: %s)", error->message);
1172                         g_clear_error(&error);
1173                 } else
1174                         ERR("Failed to get local version");
1175                 return BT_STATUS_FAIL;
1176         }
1177
1178         g_variant_get(result, "(v)", &temp);
1179         version = g_variant_dup_string(temp, NULL);
1180         DBG("Local Version: [%s]", version);
1181
1182         g_variant_unref(result);
1183         g_variant_unref(temp);
1184
1185         /*
1186          * As we need to provide async callback to user from HAL, simply schedule a
1187          * callback method which will carry actual result
1188          */
1189         g_idle_add(__bt_adapter_local_version_cb, (gpointer) version);
1190
1191         DBG("-");
1192         return BT_STATUS_SUCCESS;
1193 }
1194
1195 /* Get Local Name API and callback */
1196 static gboolean __bt_adapter_local_name_cb(gpointer user_data)
1197 {
1198         /* Buffer and propety count management */
1199         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1200         struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1201         size_t size = 0;
1202         char *name = NULL;
1203
1204         memset(buf, 0, sizeof(buf));
1205         size = sizeof(*ev);
1206         ev->num_props = 0;
1207         ev->status = BT_STATUS_SUCCESS;
1208
1209         name = (char*) user_data;
1210         DBG("Local Name in callback: [%s]", name);
1211
1212         size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_NAME,
1213                         strlen(name) + 1, name);
1214
1215         ev->num_props++;
1216         DBG("Device name [%s] property Num [%d]", name, ev->num_props);
1217
1218         if (!event_cb)
1219                 event_cb = _bt_get_adapter_event_cb();
1220         if (!event_cb) {
1221                 ERR("event_cb is NULL");
1222                 goto done;
1223         }
1224
1225         if (size > 2) {
1226                 DBG("Send Adapter Properties changed event to HAL user,"
1227                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
1228                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1229         }
1230 done:
1231         g_free(name);
1232         return FALSE;
1233 }
1234
1235 int _bt_hal_dbus_get_local_name(void)
1236 {
1237         GDBusProxy *proxy;
1238         const char *name = NULL;
1239         GVariant *result;
1240         GVariant *temp;
1241         GError *error = NULL;
1242
1243         proxy = _bt_hal_get_adapter_properties_proxy();
1244         if (!proxy) {
1245                 DBG("Adapter Properties proxy get failed!!!");
1246                 return BT_STATUS_FAIL;
1247         }
1248
1249         result = g_dbus_proxy_call_sync(proxy,
1250                         "Get",
1251                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1252                                 "Alias"),
1253                         G_DBUS_CALL_FLAGS_NONE,
1254                         -1,
1255                         NULL,
1256                         &error);
1257
1258         if (!result) {
1259                 if (error != NULL) {
1260                         ERR("Failed to get local name (Error: %s)", error->message);
1261                         g_clear_error(&error);
1262                 } else
1263                         ERR("Failed to get local name");
1264                 return BT_STATUS_FAIL;
1265         }
1266
1267         g_variant_get(result, "(v)", &temp);
1268         name = g_variant_dup_string(temp, NULL);
1269         DBG("Local Name: [%s]", name);
1270
1271         g_variant_unref(result);
1272         g_variant_unref(temp);
1273
1274         /*
1275          * As we need to provide async callback to user from HAL, simply schedule a
1276          * callback method which will carry actual result
1277          */
1278         g_idle_add(__bt_adapter_local_name_cb, (gpointer) name);
1279
1280         return BT_STATUS_SUCCESS;
1281 }
1282
1283 /* Get Local Address API and callback */
1284 static gboolean __bt_adapter_local_address_cb(gpointer user_data)
1285 {
1286         /* Buffer and propety count management */
1287         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1288         struct hal_ev_adapter_props_changed *ev = (void*) buf;
1289         size_t size = 0;
1290         char * address = NULL;
1291
1292         memset(buf, 0, sizeof(buf));
1293         size = sizeof(*ev);
1294         ev->num_props = 0;
1295         ev->status = BT_STATUS_SUCCESS;
1296
1297         address = (char*) user_data;
1298
1299         uint8_t bdaddr[6];
1300         _bt_hal_convert_addr_string_to_type(bdaddr, address);
1301
1302         size += __bt_insert_hal_properties(buf + size, HAL_PROP_DEVICE_ADDR,
1303                         sizeof(bdaddr), bdaddr);
1304
1305         ev->num_props++;
1306         DBG("Device address [%s] property Num [%d]", address, ev->num_props);
1307
1308         size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_ADDR,
1309                         sizeof(bdaddr), bdaddr);
1310
1311         if (!event_cb)
1312                 event_cb = _bt_get_adapter_event_cb();
1313         if (!event_cb) {
1314                 ERR("event_cb is NULL");
1315                 goto done;
1316         }
1317
1318         if (size > 1) {
1319                 DBG("Send Device found event to HAL user,"
1320                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
1321                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1322         }
1323 done:
1324         g_free(address);
1325         return FALSE;
1326 }
1327
1328 int _bt_hal_dbus_get_local_address(void)
1329 {
1330         GDBusProxy *proxy;
1331         GError *error = NULL;
1332         const char *address;
1333         GVariant *result;
1334         GVariant *temp;
1335
1336         proxy = _bt_hal_get_adapter_properties_proxy();
1337         if (!proxy) {
1338                 DBG("_bt_hal_dbus_get_local_address: Adapter Properties proxy get failed!!!");
1339                 return BT_STATUS_FAIL;
1340         }
1341
1342         result = g_dbus_proxy_call_sync(proxy,
1343                         "Get",
1344                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1345                                 "Address"),
1346                         G_DBUS_CALL_FLAGS_NONE,
1347                         -1,
1348                         NULL,
1349                         &error);
1350
1351         if (!result) {
1352                 ERR("Failed to get local address");
1353                 if (error != NULL) {
1354                         ERR("Failed to get local address (Error: %s)", error->message);
1355                         g_clear_error(&error);
1356                 }
1357                 return BT_STATUS_FAIL;
1358         }
1359
1360         g_variant_get(result, "(v)", &temp);
1361         address = g_variant_dup_string(temp, NULL);
1362
1363         if (address)
1364                 DBG("Address:%s", address);
1365         else
1366                 return BT_STATUS_FAIL;
1367
1368         g_variant_unref(result);
1369         g_variant_unref(temp);
1370
1371         /*
1372          * As we need to provide async callback to user from HAL, simply schedule a
1373          * callback method which will carry actual result
1374          */
1375         g_idle_add(__bt_adapter_local_address_cb, (gpointer) address);
1376
1377         return BT_STATUS_SUCCESS;
1378 }
1379
1380 /* Get Local services API and callback */
1381 static gboolean __bt_adapter_service_uuids_cb(gpointer user_data)
1382 {
1383         GVariant *result = user_data;
1384         GVariant *temp;
1385         GVariantIter *iter = NULL;
1386         gchar *uuid_str;
1387
1388         /* Buffer and propety count management */
1389         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1390         struct hal_ev_adapter_props_changed *ev = (void*) buf;
1391         size_t size = 0;
1392
1393         /* UUID collection */
1394         uint8_t uuids[HAL_UUID_LEN * MAX_UUID_COUNT];
1395         int uuid_count = 0;
1396
1397         memset(buf, 0, sizeof(buf));
1398         size = sizeof(*ev);
1399         ev->num_props = 0;
1400         ev->status = BT_STATUS_SUCCESS;
1401
1402         g_variant_get(result, "(v)", &temp);
1403         g_variant_get(temp, "as", &iter);
1404         if (iter == NULL) {
1405                 ERR("Failed to get UUIDs");
1406                 goto fail;
1407         }
1408
1409         while (g_variant_iter_loop(iter, "s", &uuid_str)) {
1410                 uint8_t uuid[HAL_UUID_LEN];
1411
1412                 DBG("UUID string [%s]\n", uuid_str);
1413                 _bt_hal_convert_uuid_string_to_type(uuid, uuid_str);
1414                 memcpy(uuids + uuid_count * HAL_UUID_LEN, uuid, HAL_UUID_LEN);
1415                 uuid_count++;
1416         }
1417
1418         size += __bt_insert_hal_properties(buf + size,
1419                         HAL_PROP_ADAPTER_UUIDS,
1420                         (HAL_UUID_LEN * uuid_count),
1421                         uuids);
1422         ev->num_props++;
1423
1424         if (!event_cb)
1425                 event_cb = _bt_get_adapter_event_cb();
1426         if (!event_cb) {
1427                 ERR("event_cb is NULL");
1428                 goto done;
1429         }
1430
1431         if (size > 2) {
1432                 DBG("Send Adapter properties changed event to HAL user,"
1433                                 " Num Prop [%d] total size [%zd]", ev->num_props, size);
1434                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1435         }
1436 done:
1437         g_variant_iter_free(iter);
1438         g_variant_unref(result);
1439         g_variant_unref(temp);
1440         return FALSE;
1441 fail:
1442         if (!event_cb)
1443                 event_cb = _bt_get_adapter_event_cb();
1444         if (event_cb) {
1445                 ev->status = BT_STATUS_FAIL;
1446                 ev->num_props = 0;
1447                 DBG("Send Adapter properties changed event to HAL user,"
1448                                 " Num Prop [%d] total size [%zd]", ev->num_props, size);
1449                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1450         }
1451
1452         g_variant_unref(result);
1453         return FALSE;
1454 }
1455
1456 int _bt_hal_dbus_get_adapter_supported_uuids(void)
1457 {
1458         GDBusProxy *proxy;
1459         GError *error = NULL;
1460         GVariant *result;
1461
1462         proxy = _bt_hal_get_adapter_properties_proxy();
1463         if (!proxy) {
1464                 DBG("Adapter Properties proxy get failed!!!");
1465                 return BT_STATUS_FAIL;
1466         }
1467
1468         result = g_dbus_proxy_call_sync(proxy,
1469                         "Get",
1470                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1471                                 "UUIDs"),
1472                         G_DBUS_CALL_FLAGS_NONE,
1473                         -1,
1474                         NULL,
1475                         &error);
1476
1477         if (!result) {
1478                 if (error != NULL) {
1479                         ERR("Failed to get UUIDs (Error: %s)", error->message);
1480                         g_clear_error(&error);
1481                 } else
1482                         ERR("Failed to get UUIDs");
1483                 return BT_STATUS_FAIL;
1484         }
1485
1486
1487         DBG("Got All Adaptr service UUID's from Bluez Stack!!, time to start parsing");
1488
1489         /*
1490          * As we need to provide async callback to user from HAL, simply schedule a
1491          * callback method which will carry actual result
1492          */
1493         g_idle_add(__bt_adapter_service_uuids_cb, (gpointer)result);
1494
1495         return BT_STATUS_SUCCESS;
1496 }
1497
1498 static gboolean __is_device_paired(GVariantIter *item_iter)
1499 {
1500         gboolean paired = FALSE;
1501         GVariant *value;
1502         gchar *key;
1503
1504         while (g_variant_iter_loop(item_iter, "{sv}", &key, &value)) {
1505                 if (NULL == key || g_strcmp0(key, "Paired"))
1506                         continue;
1507
1508                 paired = g_variant_get_boolean(value);
1509                 g_variant_unref(value);
1510                 g_free(key);
1511                 break;
1512         }
1513
1514         return paired;
1515 }
1516
1517 static gboolean __bt_adapter_bonded_devices_cb(gpointer user_data)
1518 {
1519         /* Buffer and propety count management */
1520         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1521         uint8_t addresses[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1522         struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1523         size_t size = 0;
1524         size_t count = 0;
1525
1526         GVariant *result = user_data;
1527         GVariantIter *iter;
1528         GVariantIter *interface_iter;
1529         GVariantIter *svc_iter;
1530         char *object_path = NULL;
1531         char *interface_str = NULL;
1532
1533         char device_address[BT_HAL_ADDRESS_STRING_SIZE];
1534         uint8_t bdaddr[BT_HAL_ADDRESS_LENGTH_MAX];
1535
1536         memset(buf, 0, sizeof(buf));
1537         size = sizeof(*ev);
1538         ev->num_props = 0;
1539         ev->status = BT_STATUS_SUCCESS;
1540
1541         INFO("Size [%zd]", size);
1542
1543         /* signature of GetManagedObjects:  a{oa{sa{sv}}} */
1544         g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
1545
1546         /* Parse the signature: {oa{sa{sv}}} */
1547         while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path, &interface_iter)) {
1548                 if (object_path == NULL)
1549                         continue;
1550
1551                 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
1552                                         &interface_str, &svc_iter)) {
1553                         if (g_strcmp0(interface_str, "org.bluez.Device1") == 0) {
1554                                 DBG("Found a device: %s", object_path);
1555                                 if (__is_device_paired(svc_iter)) {
1556                                         _bt_hal_convert_device_path_to_address(object_path, device_address);
1557                                         DBG("Paired Device Address: [%s]", device_address);
1558
1559                                         _bt_hal_convert_addr_string_to_type(bdaddr, device_address);
1560                                         memcpy((addresses + (count * BT_HAL_ADDRESS_LENGTH_MAX)),
1561                                                         bdaddr, BT_HAL_ADDRESS_LENGTH_MAX);
1562                                         count++;
1563                                 }
1564                                 g_variant_iter_free(svc_iter);
1565                                 g_free(interface_str);
1566                                 interface_str = NULL;
1567                                 break;
1568                         }
1569                 }
1570         }
1571
1572         g_variant_iter_free(iter);
1573         g_variant_unref(result);
1574
1575         size += __bt_insert_hal_properties((buf + size),
1576                         HAL_PROP_ADAPTER_BONDED_DEVICES,
1577                         (count * BT_HAL_ADDRESS_LENGTH_MAX), addresses);
1578         ev->num_props++;
1579
1580         if (!event_cb)
1581                 event_cb = _bt_get_adapter_event_cb();
1582         if (!event_cb) {
1583                 ERR("event_cb is NULL");
1584                 goto done;
1585         }
1586
1587         if (size > 2) {
1588                 DBG("Send Adapter properties changed event to HAL user,"
1589                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
1590                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1591         }
1592 done:
1593         return FALSE;
1594 }
1595
1596 int _bt_hal_dbus_get_bonded_devices(void)
1597 {
1598         GDBusProxy *manager_proxy;
1599         GVariant *result = NULL;
1600
1601         manager_proxy = _bt_hal_get_manager_proxy();
1602         if (manager_proxy == NULL)
1603                 return  BT_STATUS_FAIL;
1604
1605         result = g_dbus_proxy_call_sync(manager_proxy, "GetManagedObjects",
1606                         NULL,
1607                         G_DBUS_CALL_FLAGS_NONE,
1608                         -1,
1609                         NULL,
1610                         NULL);
1611         if (!result) {
1612                 ERR("Can't get managed objects");
1613                 return BT_STATUS_FAIL;
1614         }
1615
1616         /*
1617          * As we need to provide async callback to user from HAL, simply schedule a
1618          * callback method which will carry actual result
1619          */
1620         g_idle_add(__bt_adapter_bonded_devices_cb, (gpointer) result);
1621
1622         return BT_STATUS_SUCCESS;
1623 }
1624
1625 int _bt_hal_dbus_get_adapter_property(bt_property_type_t property_type)
1626 {
1627         DBG("property_type: %d", property_type);
1628
1629         switch (property_type) {
1630         case BT_PROPERTY_BDADDR:
1631                 return _bt_hal_dbus_get_local_address();
1632         case BT_PROPERTY_BDNAME:
1633                 return _bt_hal_dbus_get_local_name();
1634         case BT_PROPERTY_VERSION:
1635                 return _bt_hal_dbus_get_local_version();
1636         case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
1637                 return _bt_hal_dbus_get_discovery_timeout();
1638         case BT_PROPERTY_ADAPTER_SCAN_MODE:
1639                 return _bt_hal_dbus_get_scan_mode();
1640         case BT_PROPERTY_CLASS_OF_DEVICE:
1641                 return BT_STATUS_UNSUPPORTED;
1642         case BT_PROPERTY_UUIDS:
1643                 return _bt_hal_dbus_get_adapter_supported_uuids();
1644         case BT_PROPERTY_ADAPTER_BONDED_DEVICES:
1645                 return _bt_hal_dbus_get_bonded_devices();
1646         default:
1647                 return BT_STATUS_UNSUPPORTED;
1648         }
1649 }
1650
1651 static int __bt_hal_dbus_set_local_name(void *data)
1652 {
1653         GDBusProxy *proxy;
1654         const char *name = data;
1655         GVariant *result;
1656         GError *error = NULL;
1657
1658         DBG("Local Name: [%s]", name);
1659         proxy = _bt_hal_get_adapter_properties_proxy();
1660         if (!proxy) {
1661                 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1662                 return BT_STATUS_FAIL;
1663         }
1664
1665         result = g_dbus_proxy_call_sync(proxy,
1666                         "Set",
1667                         g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1668                                 "Alias", g_variant_new("s", name)),
1669                         G_DBUS_CALL_FLAGS_NONE,
1670                         -1,
1671                         NULL,
1672                         &error);
1673         if (!result) {
1674                 if (error != NULL) {
1675                         ERR("Failed to set local name (Error: %s)", error->message);
1676                         g_clear_error(&error);
1677                 } else
1678                         ERR("Failed to set local name");
1679                 return BT_STATUS_FAIL;
1680         }
1681         g_variant_unref(result);
1682
1683         return BT_STATUS_SUCCESS;
1684 }
1685
1686 static int __bt_hal_dbus_set_scan_mode(void *data)
1687 {
1688         GDBusProxy *proxy;
1689         int *mode = data;
1690         GVariant *result;
1691         GError *error = NULL;
1692         gboolean pg_scan;
1693         gboolean inq_scan;
1694
1695         DBG("Scan mode: [%d]", *mode);
1696         proxy = _bt_hal_get_adapter_properties_proxy();
1697         if (!proxy) {
1698                 DBG("Adapter Properties proxy get failed!!!");
1699                 return BT_STATUS_FAIL;
1700         }
1701
1702         switch (*mode) {
1703         case BT_SCAN_MODE_NONE:
1704                 pg_scan = FALSE;
1705                 inq_scan = FALSE;
1706                 break;
1707         case BT_SCAN_MODE_CONNECTABLE:
1708                 pg_scan = TRUE;
1709                 inq_scan = FALSE;
1710                 break;
1711         case BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
1712                 pg_scan = TRUE;
1713                 inq_scan = TRUE;
1714                 break;
1715         default:
1716                 ERR("Invalid scan mode");
1717                 return BT_STATUS_FAIL;
1718         }
1719
1720         result = g_dbus_proxy_call_sync(proxy,
1721                         "Set",
1722                         g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1723                                 "Connectable", g_variant_new("b", pg_scan)),
1724                         G_DBUS_CALL_FLAGS_NONE,
1725                         -1,
1726                         NULL,
1727                         &error);
1728         if (!result) {
1729                 if (error != NULL) {
1730                         ERR("Failed to set connectable property (Error: %s)", error->message);
1731                         g_clear_error(&error);
1732                 } else
1733                         ERR("Failed to set connectable property");
1734                 return BT_STATUS_FAIL;
1735         }
1736         g_variant_unref(result);
1737
1738         result = g_dbus_proxy_call_sync(proxy,
1739                         "Set",
1740                         g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE, "Discoverable",
1741                                 g_variant_new("b", inq_scan)),
1742                         G_DBUS_CALL_FLAGS_NONE,
1743                         -1,
1744                         NULL,
1745                         &error);
1746         if (!result) {
1747                 if (error != NULL) {
1748                         ERR("Failed to set Discoverable property (Error: %s)", error->message);
1749                         g_clear_error(&error);
1750                 } else
1751                         ERR("Failed to set Discoverable property");
1752                 return BT_STATUS_FAIL;
1753         }
1754         g_variant_unref(result);
1755
1756         return BT_STATUS_SUCCESS;
1757 }
1758
1759 static int __bt_hal_dbus_set_discovery_timeout(void *data)
1760 {
1761         GDBusProxy *proxy;
1762         unsigned int *timeout = data;
1763         GVariant *result;
1764         GError *error = NULL;
1765
1766         DBG("Discovery Timeout: [%d]", *timeout);
1767         proxy = _bt_hal_get_adapter_properties_proxy();
1768         if (!proxy) {
1769                 DBG("Adapter Properties proxy get failed!!!");
1770                 return BT_STATUS_FAIL;
1771         }
1772
1773         result = g_dbus_proxy_call_sync(proxy,
1774                         "Set",
1775                         g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1776                                 "DiscoverableTimeout", g_variant_new("u", *timeout)),
1777                         G_DBUS_CALL_FLAGS_NONE,
1778                         -1,
1779                         NULL,
1780                         &error);
1781         if (!result) {
1782                 if (error != NULL) {
1783                         ERR("Failed to set DiscoverableTimeout property (Error: %s)", error->message);
1784                         g_clear_error(&error);
1785                 } else
1786                         ERR("Failed to set DiscoverableTimeout property");
1787                 return BT_STATUS_FAIL;
1788         }
1789         g_variant_unref(result);
1790
1791         return BT_STATUS_SUCCESS;
1792 }
1793
1794 /* Set Adapter Properties */
1795 int _bt_hal_dbus_set_adapter_property(const bt_property_t *property)
1796 {
1797         int result;
1798
1799         if (property == NULL || property->val == NULL) {
1800                 ERR("Invalid parameters received");
1801                 return BT_STATUS_FAIL;
1802         }
1803
1804         switch (property->type) {
1805         case BT_PROPERTY_BDNAME:
1806                 result =  __bt_hal_dbus_set_local_name(property->val);
1807                 break;
1808         case BT_PROPERTY_ADAPTER_SCAN_MODE:
1809                 result =  __bt_hal_dbus_set_scan_mode(property->val);
1810                 break;
1811         case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
1812                 result =  __bt_hal_dbus_set_discovery_timeout(property->val);
1813                 break;
1814         default:
1815                 result = BT_STATUS_UNSUPPORTED;
1816         }
1817
1818         return result;
1819 }