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