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