Merge "Handle the pin code request in case of peripheral" 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
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 int _bt_hal_enable_core(void)
105 {
106         DBG("");
107         GDBusProxy *proxy;
108         GVariant *result;
109         GError *error = NULL;
110
111         proxy = __bt_get_core_proxy();
112         if(!proxy)
113                 return BT_HAL_ERROR_INTERNAL;
114
115         /* Clean up the process */
116         result = g_dbus_proxy_call_sync(proxy,
117                                "EnableCore",
118                                NULL,
119                                G_DBUS_CALL_FLAGS_NONE,
120                               -1,
121                               NULL,
122                                &error);
123
124         if (!result) {
125                 if (error != NULL) {
126                         ERR("Bt core call failed(Error: %s)", error->message);
127                         g_clear_error(&error);
128                 } else
129                         ERR("Bt core call failed");
130                 return BT_HAL_ERROR_INTERNAL;
131         }
132
133         g_variant_unref(result);
134         return BT_HAL_ERROR_NONE;
135 }
136
137 static gboolean __bt_hal_send_adapter_event(gpointer user_data)
138 {
139         struct hal_ev_adapter_state_changed ev;
140         gboolean *enable = (gboolean *)user_data;
141
142         if (*enable == TRUE)
143                 ev.state = HAL_POWER_ON;
144         else
145                 ev.state = HAL_POWER_OFF;
146
147         if (!event_cb)
148                 event_cb = _bt_get_adapter_event_cb();
149
150         if (event_cb)
151                 event_cb(HAL_EV_ADAPTER_STATE_CHANGED, &ev, sizeof(ev));
152
153         g_free(enable);
154         return false;
155 }
156
157 static gboolean __bt_hal_send_le_event(gpointer user_data)
158 {
159         struct hal_ev_le_state_changed ev;
160         gboolean *enable = (gboolean *)user_data;
161
162         if (*enable == TRUE)
163                 ev.state = HAL_POWER_ON;
164         else
165                 ev.state = HAL_POWER_OFF;
166
167         if (!event_cb)
168                 event_cb = _bt_get_adapter_event_cb();
169
170         if (event_cb)
171                 event_cb(HAL_EV_LE_STATE_CHANGED, &ev, sizeof(ev));
172
173         g_free(enable);
174         return false;
175
176 }
177
178 int _bt_hal_dbus_enable_adapter(void)
179 {
180         GDBusProxy *proxy;
181         GError *error = NULL;
182         GVariant *result = NULL;
183         unsigned char powered = 0;
184
185         DBG("+");
186
187         int le_value = VCONFKEY_BT_LE_STATUS_OFF;
188         if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &le_value))
189                 ERR("fail to get vconf key!");
190
191         if (_bt_hal_get_adapter_powered_state(&powered) == BT_STATUS_FAIL)
192                 ERR("_bt_hal_get_adapter_powered_state failed");
193
194         /*if LE is enabled and bluez is UP , send event from here and return.*/
195         if ((le_value == VCONFKEY_BT_LE_STATUS_ON) && (powered == 1)) {
196                 gboolean *user_data = g_new0(int, 1);
197                 *user_data = TRUE;
198                 g_idle_add(__bt_hal_send_adapter_event, (gpointer)user_data);
199                 return BT_STATUS_SUCCESS;
200         }
201         proxy = __bt_get_core_proxy();
202
203         if (!proxy) {
204                 DBG("_bt_hal_dbus_enable_adapter: Core proxy get failed!!!");
205                 return BT_STATUS_FAIL;
206         }
207
208         _bt_hal_set_adapter_request_state(TRUE);
209         _bt_hal_set_le_request_state(TRUE);
210         result = g_dbus_proxy_call_sync(proxy, "EnableAdapter",
211                         NULL,
212                         G_DBUS_CALL_FLAGS_NONE, BT_ENABLE_TIMEOUT,
213                         NULL, &error);
214         if (error) {
215                 DBG("EnableAdapter failed: %s", error->message);
216                 g_clear_error(&error);
217                 error = NULL;
218                 _bt_hal_set_adapter_request_state(FALSE);
219                 _bt_hal_set_le_request_state(FALSE);
220                 result = g_dbus_proxy_call_sync(proxy,
221                                 "DisableAdapter",
222                                 NULL,
223                                 G_DBUS_CALL_FLAGS_NONE,
224                                 -1,
225                                 NULL,
226                                 &error);
227
228                 if (error != NULL) {
229                         DBG("Bt core call failed(Error: %s)", error->message);
230                         g_clear_error(&error);
231                 }
232                 g_variant_unref(result);
233                 /*Terminate myself*/
234                 /* TODO: Terminate bluetooth service or not, need to check */
235                 /*g_idle_add((GSourceFunc)_bt_terminate_service, NULL);*/
236                 return BT_STATUS_FAIL;
237         }
238
239         DBG("-");
240         g_variant_unref(result);
241         return BT_STATUS_SUCCESS;
242 }
243
244 int _bt_hal_dbus_disable_adapter(void)
245 {
246         GDBusProxy *proxy;
247         GError *error = NULL;
248         GVariant *result = NULL;
249
250         DBG("+");
251         proxy = __bt_get_core_proxy();
252
253         if (!proxy) {
254                 DBG("_bt_hal_dbus_enable_adapter: Core proxy get failed!!!");
255                 return BT_STATUS_FAIL;
256         }
257
258         result = g_dbus_proxy_call_sync(proxy, "DisableAdapter",
259                         NULL,
260                         G_DBUS_CALL_FLAGS_NONE, -1,
261                         NULL, &error);
262         if (error) {
263                 DBG("DisableAdapter failed: %s", error->message);
264                 g_clear_error(&error);
265                 error = NULL;
266                 g_variant_unref(result);
267                 /*Terminate myself*/
268                 /* TODO: Terminate bluetooth service or not, need to check */
269                 /*g_idle_add((GSourceFunc)_bt_terminate_service, NULL);*/
270                 return BT_STATUS_FAIL;
271         }
272
273         DBG("-");
274         g_variant_unref(result);
275         return BT_STATUS_SUCCESS;
276 }
277
278 int _bt_hal_dbus_recover_adapter(void)
279 {
280         GDBusProxy *proxy;
281         GVariant *result = NULL;
282         GError *error = NULL;
283
284         DBG("+");
285         proxy = __bt_get_core_proxy();
286
287         if (!proxy) {
288                 DBG("_bt_hal_dbus_recover_adapter: Core proxy get failed!!!");
289                 return BT_STATUS_FAIL;
290         }
291
292         result = g_dbus_proxy_call_sync(proxy, "RecoverAdapter",
293                         NULL,
294                         G_DBUS_CALL_FLAGS_NONE, -1,
295                         NULL, &error);
296         if (error) {
297                 DBG("RecoverAdapter failed: %s", error->message);
298                 g_clear_error(&error);
299                 error = NULL;
300                 return BT_STATUS_FAIL;
301         }
302
303         DBG("-");
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         return FALSE;
748 }
749
750 static int __bt_hal_dbus_get_all_adapter_properties(void)
751 {
752         GDBusProxy *proxy;
753         GVariant *result;
754         GError *error = NULL;
755
756         DBG("+");
757
758         proxy = _bt_hal_get_adapter_properties_proxy();
759         if (!proxy) {
760                 DBG("Adapter Properties proxy get failed!!!");
761                 return BT_STATUS_FAIL;
762         }
763
764         result = g_dbus_proxy_call_sync(proxy,
765                         "GetAll",
766                         g_variant_new("(s)", BT_HAL_ADAPTER_INTERFACE),
767                         G_DBUS_CALL_FLAGS_NONE,
768                         -1,
769                         NULL,
770                         &error);
771
772         if (!result) {
773                 if (error != NULL) {
774                         ERR("Failed to get all adapter properties (Error: %s)", error->message);
775                         g_clear_error(&error);
776                 } else
777                         ERR("Failed to get all adapter properties");
778                 return BT_STATUS_FAIL;
779         }
780
781         DBG("Got All properties from Bluez Stack!!, time to start parsing");
782         /*
783          * As we need to provide async callback to user from HAL, simply schedule a
784          * callback method which will carry actual result
785          */
786         g_idle_add(__bt_adapter_all_properties_cb, (gpointer)result);
787
788         DBG("-");
789         return BT_STATUS_SUCCESS;
790 }
791
792 int _bt_hal_dbus_get_adapter_properties(void)
793 {
794         DBG("+");
795
796         return __bt_hal_dbus_get_all_adapter_properties();
797 }
798
799 int _bt_hal_get_adapter_powered_state(uint8_t *state)
800 {
801         char *adapter_path = NULL;
802         gboolean powered = FALSE;
803         int ret = BT_STATUS_FAIL;
804
805         /* Check Valid Adapter Path, followed by Adapter Powered state.
806            If any of these fails, adapter will be considered Disabled */
807         adapter_path = _bt_hal_get_adapter_path();
808
809         if (adapter_path == NULL) {
810                 INFO("Adapter is not powered");
811                 g_free(adapter_path);
812                 *state = 0;
813                 return ret;
814         }
815
816         /* Check Adapter Powered Status */
817         ret = _bt_hal_is_adapter_powered(&powered);
818         if (BT_STATUS_FAIL == ret) {
819                 INFO("Adapter is not powered");
820                 g_free(adapter_path);
821                 *state = 0;
822                 return ret;
823         }
824
825         if (powered)
826                 *state = 1;
827         else
828                 *state = 0;
829
830         return ret;
831 }
832
833 /* Get Discoverable timeout API and callback */
834 static gboolean __bt_adapter_discovery_timeout_cb(gpointer user_data)
835 {
836         /* Buffer and propety count management */
837         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
838         struct hal_ev_adapter_props_changed *ev = (void*) buf;;
839         size_t size = 0;
840         unsigned int *timeout = user_data;
841
842         memset(buf, 0, sizeof(buf));
843         size = sizeof(*ev);
844         ev->num_props = 0;
845         ev->status = BT_STATUS_SUCCESS;
846
847         DBG("Discovery timeout in callback: [%d]", *timeout);
848
849         size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_DISC_TIMEOUT,
850                         sizeof(unsigned int), timeout);
851
852         ev->num_props++;
853         DBG("Timeout value [%d] property Num [%d]", *timeout, ev->num_props);
854
855         if (!event_cb)
856                 event_cb = _bt_get_adapter_event_cb();
857         if (!event_cb) {
858                 ERR("event_cb is NULL");
859                 goto done;
860         }
861
862         if (size > 2) {
863                 DBG("Send Adapter Properties changed event to HAL user,"
864                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
865                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
866         }
867 done:
868         g_free(timeout);
869         return FALSE;
870 }
871
872 int _bt_hal_dbus_get_discovery_timeout(void)
873 {
874         GDBusProxy *proxy;
875         GVariant *result;
876         GVariant *temp;
877         GError *error = NULL;
878         unsigned int *timeout;
879         DBG("+");
880
881         proxy = _bt_hal_get_adapter_properties_proxy();
882         if (!proxy) {
883                 DBG("Adapter Properties proxy get failed!!!");
884                 return BT_STATUS_FAIL;
885         }
886
887         result = g_dbus_proxy_call_sync(proxy,
888                         "Get",
889                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
890                                 "DiscoverableTimeout"),
891                         G_DBUS_CALL_FLAGS_NONE,
892                         -1,
893                         NULL,
894                         &error);
895
896         if (!result) {
897                 if (error != NULL) {
898                         ERR("Failed to get local version (Error: %s)", error->message);
899                         g_clear_error(&error);
900                 } else
901                         ERR("Failed to get local version");
902                 return BT_STATUS_FAIL;
903         }
904
905         timeout = g_malloc0(sizeof(int));
906         if (!timeout) {
907                 ERR("Memory allocation failed");
908                 g_variant_unref(result);
909                 return BT_STATUS_FAIL;
910         }
911
912         g_variant_get(result, "(v)", &temp);
913         *timeout = g_variant_get_uint32(temp);
914         DBG("Timeout value: [%d]", *timeout);
915
916         g_variant_unref(result);
917         g_variant_unref(temp);
918
919         /*
920          * As we need to provide async callback to user from HAL, simply schedule a
921          * callback method which will carry actual result
922          */
923         g_idle_add(__bt_adapter_discovery_timeout_cb, (gpointer) timeout);
924
925         DBG("-");
926         return BT_STATUS_SUCCESS;
927 }
928
929 int _bt_hal_dbus_get_adapter_class(unsigned int *adapter_class)
930 {
931         GDBusProxy *proxy;
932         GVariant *result;
933         GVariant *temp;
934         GError *error = NULL;
935         DBG("+");
936
937         proxy = _bt_hal_get_adapter_properties_proxy();
938         if (!proxy) {
939                 DBG("Adapter Properties proxy get failed!!!");
940                 return BT_STATUS_FAIL;
941         }
942
943         result = g_dbus_proxy_call_sync(proxy,
944                         "Get",
945                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
946                                 "Class"),
947                         G_DBUS_CALL_FLAGS_NONE,
948                         -1,
949                         NULL,
950                         &error);
951
952         if (!result) {
953                 if (error != NULL) {
954                         ERR("Failed to get class (Error: %s)", error->message);
955                         g_clear_error(&error);
956                 } else
957                         ERR("Failed to get class");
958                 return BT_STATUS_FAIL;
959         }
960
961
962         g_variant_get(result, "(v)", &temp);
963         *adapter_class = g_variant_get_uint32(temp);
964         DBG("Class value: [0x%06x]", *adapter_class);
965
966         g_variant_unref(result);
967         g_variant_unref(temp);
968
969         DBG("-");
970         return BT_STATUS_SUCCESS;
971 }
972
973 /* Get Discoverable Mode API and callback */
974 static gboolean __bt_adapter_scan_mode_cb(gpointer user_data)
975 {
976         /* Buffer and propety count management */
977         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
978         struct hal_ev_adapter_props_changed *ev = (void*) buf;;
979         size_t size = 0;
980         int *mode = user_data;
981
982         memset(buf, 0, sizeof(buf));
983         size = sizeof(*ev);
984         ev->num_props = 0;
985         ev->status = BT_STATUS_SUCCESS;
986
987         DBG("Scan mode callback: [%d]", *mode);
988
989         size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_SCAN_MODE,
990                         sizeof(int), mode);
991
992         ev->num_props++;
993         DBG("Scan mode [%d] property Num [%d]", *mode, ev->num_props);
994
995         if (!event_cb)
996                 event_cb = _bt_get_adapter_event_cb();
997         if (!event_cb) {
998                 ERR("event_cb is NULL");
999                 goto done;
1000         }
1001
1002         if (size > 2) {
1003                 DBG("Send Adapter Properties changed event to HAL user,"
1004                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
1005                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1006         }
1007 done:
1008         g_free(mode);
1009         return FALSE;
1010 }
1011
1012 int _bt_hal_dbus_get_scan_mode(void)
1013 {
1014         GDBusProxy *proxy;
1015         gboolean discoverable;
1016         gboolean connectable;
1017         GVariant *result;
1018         GVariant *temp;
1019         GError *error = NULL;
1020         int *scan_mode;
1021                 ;
1022         DBG("+");
1023
1024         proxy = _bt_hal_get_adapter_properties_proxy();
1025         if (!proxy) {
1026                 DBG("Adapter Properties proxy get failed!!!");
1027                 return BT_STATUS_FAIL;
1028         }
1029
1030         result = g_dbus_proxy_call_sync(proxy,
1031                         "Get",
1032                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1033                                 "Discoverable"),
1034                         G_DBUS_CALL_FLAGS_NONE,
1035                         -1,
1036                         NULL,
1037                         &error);
1038
1039         if (!result) {
1040                 if (error != NULL) {
1041                         ERR("Failed to get discoverable mode (Error: %s)", error->message);
1042                         g_clear_error(&error);
1043                 } else
1044                         ERR("Failed to get discoverable mode");
1045                 return BT_STATUS_FAIL;
1046         }
1047
1048         g_variant_get(result, "(v)", &temp);
1049         discoverable = g_variant_get_boolean(temp);
1050         DBG("discoverable:%d", discoverable);
1051
1052         g_variant_unref(result);
1053         g_variant_unref(temp);
1054
1055         if (!discoverable) {
1056                 result = g_dbus_proxy_call_sync(proxy,
1057                                 "Get",
1058                                 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1059                                         "Connectable"),
1060                                 G_DBUS_CALL_FLAGS_NONE,
1061                                 -1,
1062                                 NULL,
1063                                 &error);
1064                 if (!result) {
1065                         if (error != NULL) {
1066                                 ERR("Failed to get connectable mode (Error: %s)", error->message);
1067                                 g_clear_error(&error);
1068                         } else
1069                                 ERR("Failed to get connectable mode");
1070                         return BT_STATUS_FAIL;
1071                 }
1072
1073                 g_variant_get(result, "(v)", &temp);
1074                 connectable = g_variant_get_boolean(temp);
1075                 DBG("connectable:%d", connectable);
1076
1077                 g_variant_unref(result);
1078                 g_variant_unref(temp);
1079         }
1080
1081         scan_mode = g_malloc0(sizeof(int));
1082         if (!scan_mode) {
1083                 ERR("Memory allocation failed");
1084                 return BT_STATUS_FAIL;
1085         }
1086
1087         if (discoverable)
1088                 *scan_mode = BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
1089         else if (connectable)
1090                 *scan_mode = BT_SCAN_MODE_CONNECTABLE;
1091         else
1092                 *scan_mode = BT_SCAN_MODE_NONE;
1093
1094         /*
1095          * As we need to provide async callback to user from HAL, simply schedule a
1096          * callback method which will carry actual result
1097          */
1098         g_idle_add(__bt_adapter_scan_mode_cb, (gpointer) scan_mode);
1099
1100         DBG("-");
1101         return BT_STATUS_SUCCESS;
1102 }
1103
1104 /* Get Local Version API and callback */
1105 static gboolean __bt_adapter_local_version_cb(gpointer user_data)
1106 {
1107         /* Buffer and propety count management */
1108         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1109         struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1110         size_t size = 0;
1111         char *version = NULL;
1112
1113         memset(buf, 0, sizeof(buf));
1114         size = sizeof(*ev);
1115         ev->num_props = 0;
1116         ev->status = BT_STATUS_SUCCESS;
1117
1118         version = (char*) user_data;
1119         DBG("Local Version in callback: [%s]", version);
1120
1121         size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_VERSION,
1122                         (strlen(version) + 1), version);
1123
1124         ev->num_props++;
1125         DBG("Device version [%s] property Num [%d]", version, ev->num_props);
1126
1127         if (!event_cb)
1128                 event_cb = _bt_get_adapter_event_cb();
1129         if (!event_cb) {
1130                 ERR("event_cb is NULL");
1131                 goto done;
1132         }
1133
1134         if (size > 2) {
1135                 DBG("Send Adapter Properties changed event to HAL user,"
1136                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
1137                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1138         }
1139 done:
1140         g_free(version);
1141         return FALSE;
1142 }
1143
1144 int _bt_hal_dbus_get_local_version(void)
1145 {
1146         GDBusProxy *proxy;
1147         const char *version = NULL;
1148         GVariant *result;
1149         GVariant *temp;
1150         GError *error = NULL;
1151         DBG("+");
1152
1153         proxy = _bt_hal_get_adapter_properties_proxy();
1154         if (!proxy) {
1155                 DBG("Adapter Properties proxy get failed!!!");
1156                 return BT_STATUS_FAIL;
1157         }
1158
1159         result = g_dbus_proxy_call_sync(proxy,
1160                         "Get",
1161                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1162                                 "Version"),
1163                         G_DBUS_CALL_FLAGS_NONE,
1164                         -1,
1165                         NULL,
1166                         &error);
1167
1168         if (!result) {
1169                 if (error != NULL) {
1170                         ERR("Failed to get local version (Error: %s)", error->message);
1171                         g_clear_error(&error);
1172                 } else
1173                         ERR("Failed to get local version");
1174                 return BT_STATUS_FAIL;
1175         }
1176
1177         g_variant_get(result, "(v)", &temp);
1178         version = g_variant_dup_string(temp, NULL);
1179         DBG("Local Version: [%s]", version);
1180
1181         g_variant_unref(result);
1182         g_variant_unref(temp);
1183
1184         /*
1185          * As we need to provide async callback to user from HAL, simply schedule a
1186          * callback method which will carry actual result
1187          */
1188         g_idle_add(__bt_adapter_local_version_cb, (gpointer) version);
1189
1190         DBG("-");
1191         return BT_STATUS_SUCCESS;
1192 }
1193
1194 /* Get Local Name API and callback */
1195 static gboolean __bt_adapter_local_name_cb(gpointer user_data)
1196 {
1197         /* Buffer and propety count management */
1198         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1199         struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1200         size_t size = 0;
1201         char *name = NULL;
1202
1203         memset(buf, 0, sizeof(buf));
1204         size = sizeof(*ev);
1205         ev->num_props = 0;
1206         ev->status = BT_STATUS_SUCCESS;
1207
1208         name = (char*) user_data;
1209         DBG("Local Name in callback: [%s]", name);
1210
1211         size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_NAME,
1212                         strlen(name) + 1, name);
1213
1214         ev->num_props++;
1215         DBG("Device name [%s] property Num [%d]", name, ev->num_props);
1216
1217         if (!event_cb)
1218                 event_cb = _bt_get_adapter_event_cb();
1219         if (!event_cb) {
1220                 ERR("event_cb is NULL");
1221                 goto done;
1222         }
1223
1224         if (size > 2) {
1225                 DBG("Send Adapter Properties changed event to HAL user,"
1226                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
1227                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1228         }
1229 done:
1230         g_free(name);
1231         return FALSE;
1232 }
1233
1234 int _bt_hal_dbus_get_local_name(void)
1235 {
1236         GDBusProxy *proxy;
1237         const char *name = NULL;
1238         GVariant *result;
1239         GVariant *temp;
1240         GError *error = NULL;
1241         DBG("+");
1242
1243         proxy = _bt_hal_get_adapter_properties_proxy();
1244         if (!proxy) {
1245                 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1246                 return BT_STATUS_FAIL;
1247         }
1248
1249         result = g_dbus_proxy_call_sync(proxy,
1250                         "Get",
1251                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1252                                 "Alias"),
1253                         G_DBUS_CALL_FLAGS_NONE,
1254                         -1,
1255                         NULL,
1256                         &error);
1257
1258         if (!result) {
1259                 if (error != NULL) {
1260                         ERR("Failed to get local name (Error: %s)", error->message);
1261                         g_clear_error(&error);
1262                 } else
1263                         ERR("Failed to get local name");
1264                 return BT_STATUS_FAIL;
1265         }
1266
1267         g_variant_get(result, "(v)", &temp);
1268         name = g_variant_dup_string(temp, NULL);
1269         DBG("Local Name: [%s]", name);
1270
1271         g_variant_unref(result);
1272         g_variant_unref(temp);
1273
1274         /*
1275          * As we need to provide async callback to user from HAL, simply schedule a
1276          * callback method which will carry actual result
1277          */
1278         g_idle_add(__bt_adapter_local_name_cb, (gpointer) name);
1279
1280         DBG("-");
1281         return BT_STATUS_SUCCESS;
1282 }
1283
1284 /* Get Local Address API and callback */
1285 static gboolean __bt_adapter_local_address_cb(gpointer user_data)
1286 {
1287         /* Buffer and propety count management */
1288         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1289         struct hal_ev_adapter_props_changed *ev = (void*) buf;
1290         size_t size = 0;
1291         char * address = NULL;
1292
1293         memset(buf, 0, sizeof(buf));
1294         size = sizeof(*ev);
1295         ev->num_props = 0;
1296         ev->status = BT_STATUS_SUCCESS;
1297
1298         address = (char*) user_data;
1299
1300         uint8_t bdaddr[6];
1301         _bt_hal_convert_addr_string_to_type(bdaddr, address);
1302
1303         size += __bt_insert_hal_properties(buf + size, HAL_PROP_DEVICE_ADDR,
1304                         sizeof(bdaddr), bdaddr);
1305
1306         ev->num_props++;
1307         DBG("Device address [%s] property Num [%d]", address, ev->num_props);
1308
1309         size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_ADDR,
1310                         sizeof(bdaddr), bdaddr);
1311
1312         if (!event_cb)
1313                 event_cb = _bt_get_adapter_event_cb();
1314         if (!event_cb) {
1315                 ERR("event_cb is NULL");
1316                 goto done;
1317         }
1318
1319         if (size > 1) {
1320                 DBG("Send Device found event to HAL user,"
1321                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
1322                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1323         }
1324 done:
1325         g_free(address);
1326         return FALSE;
1327 }
1328
1329 int _bt_hal_dbus_get_local_address(void)
1330 {
1331         GDBusProxy *proxy;
1332         GError *error = NULL;
1333         const char *address;
1334         GVariant *result;
1335         GVariant *temp;
1336
1337         DBG("+");
1338
1339         proxy = _bt_hal_get_adapter_properties_proxy();
1340         if (!proxy) {
1341                 DBG("_bt_hal_dbus_get_local_address: Adapter Properties proxy get failed!!!");
1342                 return BT_STATUS_FAIL;
1343         }
1344
1345         result = g_dbus_proxy_call_sync(proxy,
1346                         "Get",
1347                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1348                                 "Address"),
1349                         G_DBUS_CALL_FLAGS_NONE,
1350                         -1,
1351                         NULL,
1352                         &error);
1353
1354         if (!result) {
1355                 ERR("Failed to get local address");
1356                 if (error != NULL) {
1357                         ERR("Failed to get local address (Error: %s)", error->message);
1358                         g_clear_error(&error);
1359                 }
1360                 return BT_STATUS_FAIL;
1361         }
1362
1363         g_variant_get(result, "(v)", &temp);
1364         address = g_variant_dup_string(temp, NULL);
1365
1366         if (address)
1367                 DBG("Address:%s", address);
1368         else
1369                 return BT_STATUS_FAIL;
1370
1371         g_variant_unref(result);
1372         g_variant_unref(temp);
1373
1374         /*
1375          * As we need to provide async callback to user from HAL, simply schedule a
1376          * callback method which will carry actual result
1377          */
1378         g_idle_add(__bt_adapter_local_address_cb, (gpointer) address);
1379
1380         DBG("-");
1381         return BT_STATUS_SUCCESS;
1382 }
1383
1384 /* Get Local services API and callback */
1385 static gboolean __bt_adapter_service_uuids_cb(gpointer user_data)
1386 {
1387         GVariant *result = user_data;
1388         GVariant *temp;
1389         GVariantIter *iter = NULL;
1390         gchar *uuid_str;
1391
1392         /* Buffer and propety count management */
1393         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1394         struct hal_ev_adapter_props_changed *ev = (void*) buf;
1395         size_t size = 0;
1396
1397         /* UUID collection */
1398         uint8_t uuids[HAL_UUID_LEN * MAX_UUID_COUNT];
1399         int uuid_count = 0;
1400
1401         memset(buf, 0, sizeof(buf));
1402         size = sizeof(*ev);
1403         ev->num_props = 0;
1404         ev->status = BT_STATUS_SUCCESS;
1405
1406         g_variant_get(result, "(v)", &temp);
1407         g_variant_get(temp, "as", &iter);
1408         if (iter == NULL) {
1409                 ERR("Failed to get UUIDs");
1410                 goto fail;
1411         }
1412
1413         while (g_variant_iter_loop(iter, "s", &uuid_str)) {
1414                 uint8_t uuid[HAL_UUID_LEN];
1415
1416                 DBG("UUID string [%s]\n", uuid_str);
1417                 _bt_hal_convert_uuid_string_to_type(uuid, uuid_str);
1418                 memcpy(uuids + uuid_count * HAL_UUID_LEN, uuid, HAL_UUID_LEN);
1419                 uuid_count++;
1420         }
1421
1422         size += __bt_insert_hal_properties(buf + size,
1423                         HAL_PROP_ADAPTER_UUIDS,
1424                         (HAL_UUID_LEN * uuid_count),
1425                         uuids);
1426         ev->num_props++;
1427
1428         if (!event_cb)
1429                 event_cb = _bt_get_adapter_event_cb();
1430         if (!event_cb) {
1431                 ERR("event_cb is NULL");
1432                 goto done;
1433         }
1434
1435         if (size > 2) {
1436                 DBG("Send Adapter properties changed event to HAL user,"
1437                                 " Num Prop [%d] total size [%zd]", ev->num_props, size);
1438                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1439         }
1440 done:
1441         g_variant_iter_free(iter);
1442         g_variant_unref(result);
1443         g_variant_unref(temp);
1444         return FALSE;
1445 fail:
1446         if (!event_cb)
1447                 event_cb = _bt_get_adapter_event_cb();
1448         if (event_cb) {
1449                 ev->status = BT_STATUS_FAIL;
1450                 ev->num_props = 0;
1451                 DBG("Send Adapter properties changed event to HAL user,"
1452                                 " Num Prop [%d] total size [%zd]", ev->num_props, size);
1453                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1454         }
1455
1456         g_variant_unref(result);
1457         return FALSE;
1458 }
1459
1460 int _bt_hal_dbus_get_adapter_supported_uuids(void)
1461 {
1462         GDBusProxy *proxy;
1463         GError *error = NULL;
1464         GVariant *result;
1465
1466         DBG("+");
1467
1468         proxy = _bt_hal_get_adapter_properties_proxy();
1469
1470         if (!proxy) {
1471                 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1472                 return BT_STATUS_FAIL;
1473         }
1474
1475         result = g_dbus_proxy_call_sync(proxy,
1476                         "Get",
1477                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1478                                 "UUIDs"),
1479                         G_DBUS_CALL_FLAGS_NONE,
1480                         -1,
1481                         NULL,
1482                         &error);
1483
1484         if (!result) {
1485                 if (error != NULL) {
1486                         ERR("Failed to get UUIDs (Error: %s)", error->message);
1487                         g_clear_error(&error);
1488                 } else
1489                         ERR("Failed to get UUIDs");
1490                 return BT_STATUS_FAIL;
1491         }
1492
1493
1494         DBG("Got All Adaptr service UUID's from Bluez Stack!!, time to start parsing");
1495
1496         /*
1497          * As we need to provide async callback to user from HAL, simply schedule a
1498          * callback method which will carry actual result
1499          */
1500         g_idle_add(__bt_adapter_service_uuids_cb, (gpointer)result);
1501
1502         DBG("-");
1503         return BT_STATUS_SUCCESS;
1504 }
1505
1506 static gboolean __is_device_paired(GVariantIter *item_iter)
1507 {
1508         gboolean paired = FALSE;
1509         GVariant *value;
1510         gchar *key;
1511
1512         while (g_variant_iter_loop(item_iter, "{sv}", &key, &value)) {
1513                 if (NULL == key || g_strcmp0(key, "Paired"))
1514                         continue;
1515
1516                 paired = g_variant_get_boolean(value);
1517                 g_variant_unref(value);
1518                 g_free(key);
1519                 break;
1520         }
1521
1522         return paired;
1523 }
1524
1525 static gboolean __bt_adapter_bonded_devices_cb(gpointer user_data)
1526 {
1527         /* Buffer and propety count management */
1528         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1529         uint8_t addresses[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1530         struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1531         size_t size = 0;
1532         size_t count = 0;
1533
1534         GVariant *result = user_data;
1535         GVariantIter *iter;
1536         GVariantIter *interface_iter;
1537         GVariantIter *svc_iter;
1538         char *object_path = NULL;
1539         char *interface_str = NULL;
1540
1541         char device_address[BT_HAL_ADDRESS_STRING_SIZE];
1542         uint8_t bdaddr[BT_HAL_ADDRESS_LENGTH_MAX];
1543
1544         memset(buf, 0, sizeof(buf));
1545         size = sizeof(*ev);
1546         ev->num_props = 0;
1547         ev->status = BT_STATUS_SUCCESS;
1548
1549         INFO("Size [%zd]", size);
1550
1551         /* signature of GetManagedObjects:  a{oa{sa{sv}}} */
1552         g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
1553
1554         /* Parse the signature: {oa{sa{sv}}} */
1555         while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path, &interface_iter)) {
1556                 if (object_path == NULL)
1557                         continue;
1558
1559                 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
1560                                         &interface_str, &svc_iter)) {
1561                         if (g_strcmp0(interface_str, "org.bluez.Device1") == 0) {
1562                                 DBG("Found a device: %s", object_path);
1563                                 if (__is_device_paired(svc_iter)) {
1564                                         _bt_hal_convert_device_path_to_address(object_path, device_address);
1565                                         DBG("Paired Device Address: [%s]", device_address);
1566
1567                                         _bt_hal_convert_addr_string_to_type(bdaddr, device_address);
1568                                         memcpy((addresses + (count * BT_HAL_ADDRESS_LENGTH_MAX)),
1569                                                         bdaddr, BT_HAL_ADDRESS_LENGTH_MAX);
1570                                         count++;
1571                                 }
1572                                 g_variant_iter_free(svc_iter);
1573                                 g_free(interface_str);
1574                                 interface_str = NULL;
1575                                 break;
1576                         }
1577                 }
1578         }
1579
1580         g_variant_iter_free(iter);
1581         g_variant_unref(result);
1582
1583         size += __bt_insert_hal_properties((buf + size),
1584                         HAL_PROP_ADAPTER_BONDED_DEVICES,
1585                         (count * BT_HAL_ADDRESS_LENGTH_MAX), addresses);
1586         ev->num_props++;
1587
1588         if (!event_cb)
1589                 event_cb = _bt_get_adapter_event_cb();
1590         if (!event_cb) {
1591                 ERR("event_cb is NULL");
1592                 goto done;
1593         }
1594
1595         if (size > 2) {
1596                 DBG("Send Adapter properties changed event to HAL user,"
1597                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
1598                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1599         }
1600 done:
1601         return FALSE;
1602 }
1603
1604 int _bt_hal_dbus_get_bonded_devices(void)
1605 {
1606         GDBusProxy *manager_proxy;
1607         GVariant *result = NULL;
1608
1609         DBG("+");
1610
1611         manager_proxy = _bt_hal_get_manager_proxy();
1612         if (manager_proxy == NULL)
1613                 return  BT_STATUS_FAIL;
1614
1615         result = g_dbus_proxy_call_sync(manager_proxy, "GetManagedObjects",
1616                         NULL,
1617                         G_DBUS_CALL_FLAGS_NONE,
1618                         -1,
1619                         NULL,
1620                         NULL);
1621         if (!result) {
1622                 ERR("Can't get managed objects");
1623                 return BT_STATUS_FAIL;
1624         }
1625
1626         /*
1627          * As we need to provide async callback to user from HAL, simply schedule a
1628          * callback method which will carry actual result
1629          */
1630         g_idle_add(__bt_adapter_bonded_devices_cb, (gpointer) result);
1631
1632         DBG("-");
1633         return BT_STATUS_SUCCESS;
1634 }
1635
1636 int _bt_hal_dbus_get_adapter_property(bt_property_type_t property_type)
1637 {
1638         DBG("+");
1639
1640         INFO("property_type: %d", property_type);
1641
1642         switch (property_type) {
1643         case BT_PROPERTY_BDADDR:
1644                 return _bt_hal_dbus_get_local_address();
1645         case BT_PROPERTY_BDNAME:
1646                 return _bt_hal_dbus_get_local_name();
1647         case BT_PROPERTY_VERSION:
1648                 return _bt_hal_dbus_get_local_version();
1649         case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
1650                 return _bt_hal_dbus_get_discovery_timeout();
1651         case BT_PROPERTY_ADAPTER_SCAN_MODE:
1652                 return _bt_hal_dbus_get_scan_mode();
1653         case BT_PROPERTY_CLASS_OF_DEVICE:
1654                 return BT_STATUS_UNSUPPORTED;
1655         case BT_PROPERTY_UUIDS:
1656                 return _bt_hal_dbus_get_adapter_supported_uuids();
1657         case BT_PROPERTY_ADAPTER_BONDED_DEVICES:
1658                 return _bt_hal_dbus_get_bonded_devices();
1659         default:
1660                 return BT_STATUS_UNSUPPORTED;
1661         }
1662
1663         DBG("-");
1664 }
1665
1666 static int __bt_hal_dbus_set_local_name(void *data)
1667 {
1668         GDBusProxy *proxy;
1669         const char *name = data;
1670         GVariant *result;
1671         GError *error = NULL;
1672
1673         DBG("+");
1674         DBG("Local Name: [%s]", name);
1675         proxy = _bt_hal_get_adapter_properties_proxy();
1676         if (!proxy) {
1677                 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1678                 return BT_STATUS_FAIL;
1679         }
1680
1681         result = g_dbus_proxy_call_sync(proxy,
1682                         "Set",
1683                         g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1684                                 "Alias", g_variant_new("s", name)),
1685                         G_DBUS_CALL_FLAGS_NONE,
1686                         -1,
1687                         NULL,
1688                         &error);
1689         if (!result) {
1690                 if (error != NULL) {
1691                         ERR("Failed to set local name (Error: %s)", error->message);
1692                         g_clear_error(&error);
1693                 } else
1694                         ERR("Failed to set local name");
1695                 return BT_STATUS_FAIL;
1696         }
1697         g_variant_unref(result);
1698
1699         DBG("-");
1700         return BT_STATUS_SUCCESS;
1701 }
1702
1703 static int __bt_hal_dbus_set_scan_mode(void *data)
1704 {
1705         GDBusProxy *proxy;
1706         int *mode = data;
1707         GVariant *result;
1708         GError *error = NULL;
1709         gboolean pg_scan;
1710         gboolean inq_scan;
1711
1712         DBG("+");
1713         DBG("Scan mode: [%d]", *mode);
1714         proxy = _bt_hal_get_adapter_properties_proxy();
1715         if (!proxy) {
1716                 DBG("Adapter Properties proxy get failed!!!");
1717                 return BT_STATUS_FAIL;
1718         }
1719
1720         switch (*mode) {
1721         case BT_SCAN_MODE_NONE:
1722                 pg_scan = FALSE;
1723                 inq_scan = FALSE;
1724                 break;
1725         case BT_SCAN_MODE_CONNECTABLE:
1726                 pg_scan = TRUE;
1727                 inq_scan = FALSE;
1728                 break;
1729         case BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
1730                 pg_scan = TRUE;
1731                 inq_scan = TRUE;
1732                 break;
1733         default:
1734                 ERR("Invalid scan mode");
1735                 return BT_STATUS_FAIL;
1736         }
1737
1738         result = g_dbus_proxy_call_sync(proxy,
1739                         "Set",
1740                         g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1741                                 "Connectable", g_variant_new("b", pg_scan)),
1742                         G_DBUS_CALL_FLAGS_NONE,
1743                         -1,
1744                         NULL,
1745                         &error);
1746         if (!result) {
1747                 if (error != NULL) {
1748                         ERR("Failed to set connectable property (Error: %s)", error->message);
1749                         g_clear_error(&error);
1750                 } else
1751                         ERR("Failed to set connectable property");
1752                 return BT_STATUS_FAIL;
1753         }
1754         g_variant_unref(result);
1755
1756         result = g_dbus_proxy_call_sync(proxy,
1757                         "Set",
1758                         g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE, "Discoverable",
1759                                 g_variant_new("b", inq_scan)),
1760                         G_DBUS_CALL_FLAGS_NONE,
1761                         -1,
1762                         NULL,
1763                         &error);
1764         if (!result) {
1765                 if (error != NULL) {
1766                         ERR("Failed to set Discoverable property (Error: %s)", error->message);
1767                         g_clear_error(&error);
1768                 } else
1769                         ERR("Failed to set Discoverable property");
1770                 return BT_STATUS_FAIL;
1771         }
1772         g_variant_unref(result);
1773
1774         DBG("-");
1775         return BT_STATUS_SUCCESS;
1776 }
1777
1778 static int __bt_hal_dbus_set_discovery_timeout(void *data)
1779 {
1780         GDBusProxy *proxy;
1781         unsigned int *timeout = data;
1782         GVariant *result;
1783         GError *error = NULL;
1784
1785
1786         DBG("+");
1787
1788         DBG("Discovery Timeout: [%d]", *timeout);
1789         proxy = _bt_hal_get_adapter_properties_proxy();
1790         if (!proxy) {
1791                 DBG("Adapter Properties proxy get failed!!!");
1792                 return BT_STATUS_FAIL;
1793         }
1794
1795         result = g_dbus_proxy_call_sync(proxy,
1796                         "Set",
1797                         g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1798                                 "DiscoverableTimeout", g_variant_new("u", *timeout)),
1799                         G_DBUS_CALL_FLAGS_NONE,
1800                         -1,
1801                         NULL,
1802                         &error);
1803         if (!result) {
1804                 if (error != NULL) {
1805                         ERR("Failed to set DiscoverableTimeout property (Error: %s)", error->message);
1806                         g_clear_error(&error);
1807                 } else
1808                         ERR("Failed to set DiscoverableTimeout property");
1809                 return BT_STATUS_FAIL;
1810         }
1811         g_variant_unref(result);
1812
1813         DBG("-");
1814         return BT_STATUS_SUCCESS;
1815 }
1816
1817 /* Set Adapter Properties */
1818 int _bt_hal_dbus_set_adapter_property(const bt_property_t *property)
1819 {
1820         int result;
1821
1822         DBG("");
1823
1824         if (property == NULL || property->val == NULL) {
1825                 ERR("Invalid parameters received");
1826                 return BT_STATUS_FAIL;
1827         }
1828
1829         switch (property->type) {
1830         case BT_PROPERTY_BDNAME:
1831                 result =  __bt_hal_dbus_set_local_name(property->val);
1832                 break;
1833         case BT_PROPERTY_ADAPTER_SCAN_MODE:
1834                 result =  __bt_hal_dbus_set_scan_mode(property->val);
1835                 break;
1836         case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
1837                 result =  __bt_hal_dbus_set_discovery_timeout(property->val);
1838                 break;
1839         default:
1840                 result = BT_STATUS_UNSUPPORTED;
1841         }
1842
1843         DBG("Result= [%d]", result);
1844         return result;
1845 }