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