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