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