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