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