Merge "Implement get_att_mtu logic in hal gatt client" 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         struct hal_ev_discovery_state_changed ev;
512         DBG("+");
513
514         memset(&ev, 0, sizeof(ev));
515
516         proxy = _bt_hal_get_adapter_proxy();
517         if (!proxy) {
518                 DBG("_bt_hal_dbus_stop_discovery: Adapter proxy get failed!!!");
519                 return BT_STATUS_FAIL;
520         }
521
522         result = g_dbus_proxy_call_sync(proxy,
523                         "StopDiscovery",
524                         NULL,
525                         G_DBUS_CALL_FLAGS_NONE,
526                         -1,
527                         NULL,
528                         &error);
529
530         if (!result) {
531                 if (error != NULL) {
532                         ERR("StopDiscovery failed (Error: %s)", error->message);
533                         g_clear_error(&error);
534                 } else
535                         ERR("StopDiscovery failed");
536                 return BT_STATUS_FAIL;
537         }
538
539         /* Stop success */
540         ev.state = HAL_DISCOVERY_STATE_STOPPED;
541
542         if (!event_cb)
543                 event_cb = _bt_hal_get_stack_message_handler();
544         if (event_cb) {
545                 DBG("Sending HAL_EV_DISCOVERY_STATE_CHANGED event");
546                 event_cb(HAL_EV_DISCOVERY_STATE_CHANGED, (void*)&ev, sizeof(ev));
547         }
548
549         /* discovery status will be change in event */
550         DBG("-");
551         g_variant_unref(result);
552         return BT_STATUS_SUCCESS;
553 }
554
555 int _bt_hal_dbus_get_energy_info(uint32_t *tx_time, uint32_t *rx_time,
556                                         uint32_t *idle_time, uint32_t *energy_used)
557 {
558         GDBusProxy *proxy;
559         GError *error = NULL;
560         GVariant *result;
561
562         if (!tx_time || !rx_time || !idle_time || !energy_used) {
563                 ERR("Invalid parameter");
564                 return BT_STATUS_FAIL;
565         }
566
567         proxy = _bt_hal_get_adapter_proxy();
568         if (!proxy) {
569                 DBG("_bt_hal_dbus_get_energy_info: Adapter proxy get failed!!!");
570                 return BT_STATUS_FAIL;
571         }
572
573         result = g_dbus_proxy_call_sync(proxy,
574                         "GetEnergyInfo",
575                         NULL,
576                         G_DBUS_CALL_FLAGS_NONE,
577                         -1,
578                         NULL,
579                         &error);
580
581         if (!result) {
582                 if (error != NULL) {
583                         ERR("GetEnergyInfo failed (Error: %s)", error->message);
584                         g_clear_error(&error);
585                 } else {
586                         ERR("GetEnergyInfo failed");
587                 }
588                 return BT_STATUS_FAIL;
589         }
590
591         g_variant_get(result, "(uuuu)", tx_time, rx_time, idle_time, energy_used);
592
593         DBG("Tx time: %d, Rx time: %d, Idle time: %d", *tx_time, *rx_time, *idle_time);
594
595         g_variant_unref(result);
596         return BT_STATUS_SUCCESS;
597 }
598
599 int _bt_hal_dbus_get_profile_connected_devices(const char *profile_uuid)
600 {
601         GDBusConnection *conn;
602         GDBusProxy *manager_proxy;
603         GVariant *result = NULL;
604         GVariant *result1 = NULL;
605         GVariantIter *iter = NULL;
606         GError *error = NULL;
607         char *object_path = NULL;
608         GVariantIter *interface_iter;
609         char *interface_str = NULL;
610         GDBusProxy *device_proxy = NULL;
611         gboolean is_connected = FALSE;
612         struct hal_ev_adapter_profile_connected_devices ev;
613
614         DBG("Get Profile Connected Devices. UUID: %s", profile_uuid);
615         memset(&ev, 0, sizeof(ev));
616
617         conn = __bt_hal_get_system_gconn();
618         if (conn == NULL)
619                 return BT_STATUS_FAIL;
620
621         manager_proxy = _bt_hal_get_manager_proxy();
622         if (manager_proxy == NULL)
623                 return  BT_STATUS_FAIL;
624
625         result = g_dbus_proxy_call_sync(manager_proxy, "GetManagedObjects",
626                         NULL,
627                         G_DBUS_CALL_FLAGS_NONE,
628                         -1,
629                         NULL,
630                         &error);
631
632         if (!result) {
633                 if (error != NULL) {
634                         ERR("GetManagedObjects failed (Error: %s)", error->message);
635                         g_clear_error(&error);
636                         error = NULL;
637                 } else
638                         ERR("GetManagedObjects failed");
639                 return BT_STATUS_FAIL;
640         }
641
642         /* signature of GetManagedObjects:  a{oa{sa{sv}}} */
643         g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
644
645         /* Parse the signature:  oa{sa{sv}}} */
646         while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path, &interface_iter)) {
647                 if (object_path == NULL)
648                         continue;
649
650                 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
651                                         &interface_str, NULL)) {
652                         if (g_strcmp0(interface_str, "org.bluez.Device1") == 0) {
653                                 DBG("Found a device: %s", object_path);
654                                 g_free(interface_str);
655
656                                 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
657                                                 NULL, BT_HAL_BLUEZ_NAME,
658                                                 object_path, BT_HAL_DEVICE_INTERFACE,  NULL, NULL);
659
660                                 if (device_proxy == NULL) {
661                                         DBG("Device don't have this service");
662                                         break;
663                                 }
664
665                                 result1 = g_dbus_proxy_call_sync(device_proxy, "IsConnectedProfile",
666                                                 g_variant_new("(s)", profile_uuid),
667                                                 G_DBUS_CALL_FLAGS_NONE,
668                                                 -1,
669                                                 NULL,
670                                                 &error);
671
672                                 if (result1 == NULL) {
673                                         if (error) {
674                                                 ERR("Error occured in Proxy call [%s]", error->message);
675                                                 g_error_free(error);
676                                                 error = NULL;
677                                         }
678                                         g_object_unref(device_proxy);
679                                         break;
680                                 }
681                                 g_variant_get(result1, "(b)", &is_connected);
682
683                                 if (is_connected == TRUE) {
684                                         char address[BT_HAL_ADDRESS_STRING_SIZE];
685                                         _bt_hal_convert_device_path_to_address(object_path, address);
686                                         DBG("Address: %s", address);
687                                         if (ev.count >= 10) {
688                                                 INFO("Too many address");
689                                                 break;
690                                         }
691                                         _bt_hal_convert_addr_string_to_type(ev.bdaddr_list[ev.count], address);
692                                         ev.count++;
693                                 }
694
695                                 g_variant_unref(result1);
696                                 g_object_unref(device_proxy);
697                                 break;
698                         }
699                 }
700         }
701
702         if (!event_cb)
703                 event_cb = _bt_hal_get_stack_message_handler();
704         if (event_cb) {
705                 DBG("Sending HAL_EV_ADAPTER_PROFILE_CONNECTED_DEVICES event");
706                 event_cb(HAL_EV_ADAPTER_PROFILE_CONNECTED_DEVICES, (void *)&ev, sizeof(ev));
707         }
708
709         g_variant_unref(result);
710         g_variant_iter_free(iter);
711
712         DBG("-");
713         return BT_STATUS_SUCCESS;
714 }
715
716 static gboolean __bt_adapter_all_properties_cb(gpointer user_data)
717 {
718         GVariant *result = user_data;
719         GVariantIter *property_iter;
720         const gchar *key;
721         GVariant *value;
722
723         /* Buffer and propety count management */
724         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
725         struct hal_ev_adapter_props_changed *ev = (void*) buf;
726         size_t size = 0;
727         gchar *address = NULL;
728         gchar *name = NULL;
729         unsigned int cod = 0;
730         gboolean discoverable;
731         gboolean connectable;
732         unsigned int scan_mode = BT_SCAN_MODE_NONE;
733         unsigned int disc_timeout;
734         gchar *version;
735         gboolean is_discovering;
736         gboolean is_le_discovering;
737         uint8_t ipsp_initialized;
738         gboolean powered;
739         uint8_t pairable;
740         unsigned int pairable_timeout;
741         gboolean scan_mode_property_update = FALSE;
742
743         DBG("+");
744
745         memset(buf, 0, sizeof(buf));
746         size = sizeof(*ev);
747         ev->num_props = 0;
748         ev->status = BT_STATUS_SUCCESS;
749
750         DBG("@@Start parsing properties");
751         g_variant_get(result, "(a{sv})", &property_iter);
752         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
753                 if (!g_strcmp0(key, "Address")) {
754                         uint8_t bdaddr[6];
755
756                         address = (gchar *) g_variant_get_string(value, NULL);
757                         DBG("Address [%s]", address);
758                         _bt_hal_convert_addr_string_to_type(bdaddr, address);
759                         size += __bt_insert_hal_properties(buf + size,
760                                         HAL_PROP_ADAPTER_ADDR, sizeof(bdaddr), bdaddr);
761                         ev->num_props++;
762                 } else if (!g_strcmp0(key, "Alias")) {
763                         name = (gchar *) g_variant_get_string(value, NULL);
764                         DBG("Alias [%s]", name);
765                         size += __bt_insert_hal_properties(buf + size,
766                                         HAL_PROP_ADAPTER_NAME, strlen(name) + 1, name);
767                         ev->num_props++;
768                 } else if (!g_strcmp0(key, "Class")) {
769                         cod = g_variant_get_uint32(value);
770                         DBG("Class [%d]", cod);
771                         size += __bt_insert_hal_properties(buf + size,
772                                         HAL_PROP_ADAPTER_CLASS, sizeof(unsigned int), &cod);
773                         ev->num_props++;
774                 } else if (!g_strcmp0(key, "Discoverable")) {
775                         discoverable = g_variant_get_boolean(value);
776                         DBG("Discoverable [%d]", discoverable);
777                         if (discoverable)
778                                 scan_mode = BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
779                         scan_mode_property_update = TRUE;
780                 } else if (!g_strcmp0(key, "DiscoverableTimeout")) {
781                         disc_timeout = g_variant_get_uint32(value);
782                         DBG("Discoverable Timeout [%d]", disc_timeout);
783                         size += __bt_insert_hal_properties(buf + size,
784                                         HAL_PROP_ADAPTER_DISC_TIMEOUT, sizeof(unsigned int), &disc_timeout);
785                         ev->num_props++;
786                 } else if (!g_strcmp0(key, "Connectable")) {
787                         connectable = g_variant_get_boolean(value);
788                         DBG("Connectable [%d]", connectable);
789                         if (scan_mode == BT_SCAN_MODE_NONE)
790                                 scan_mode = BT_SCAN_MODE_CONNECTABLE;
791                         scan_mode_property_update = TRUE;
792                 } else if (!g_strcmp0(key, "Version")) {
793                         version = (gchar *) g_variant_get_string(value, NULL);
794                         DBG("Version [%s]", version);
795                         size += __bt_insert_hal_properties(buf + size,
796                                         HAL_PROP_ADAPTER_VERSION, strlen(version) + 1, version);
797                         ev->num_props++;
798                 } else if (!g_strcmp0(key, "Name")) {
799                         name = (gchar *) g_variant_get_string(value, NULL);
800                         DBG("Name [%s]", name);
801                         size += __bt_insert_hal_properties(buf + size,
802                                         HAL_PROP_ADAPTER_NAME, strlen(name) + 1, name);
803                         ev->num_props++;
804                 } else if (!g_strcmp0(key, "Powered")) {
805                         powered = g_variant_get_boolean(value);
806                         DBG("Powered = [%d]", powered);
807                 } else if (!g_strcmp0(key, "Pairable")) {
808                         pairable = (g_variant_get_boolean(value) ? 1 : 0);
809                         DBG("Pairable [%d]", pairable);
810                         size += __bt_insert_hal_properties(buf + size,
811                                         HAL_PROP_ADAPTER_PAIRABLE, sizeof(uint8_t), &pairable);
812                         ev->num_props++;
813                 } else if (!g_strcmp0(key, "PairableTimeout")) {
814                         pairable_timeout = g_variant_get_uint32(value);
815                         DBG("Pairable Timeout = [%d]", pairable_timeout);
816                         size += __bt_insert_hal_properties(buf + size,
817                                         HAL_PROP_ADAPTER_PAIRABLE_TIMEOUT, sizeof(unsigned int), &pairable_timeout);
818                         ev->num_props++;
819                 } else if (!g_strcmp0(key, "UUIDs")) {
820                         char **uuid_value;
821                         int uuid_count = 0;
822                         gsize size1 = 0;
823                         int i = 0;
824                         size1 = g_variant_get_size(value);
825                         int num_props_tmp = ev->num_props;
826                         if (size1 > 0) {
827                                 uuid_value = (char **)g_variant_get_strv(value, &size1);
828                                 for (i = 0; uuid_value[i] != NULL; i++)
829                                         uuid_count++;
830                                 /* UUID collection */
831                                 uint8_t uuids[HAL_UUID_LEN * uuid_count];
832                                 for (i = 0; uuid_value[i] != NULL; i++) {
833                                         char *uuid_str = NULL;
834                                         uint8_t uuid[HAL_UUID_LEN];
835                                         uuid_str = g_strdup(uuid_value[i]);
836                                         DBG("UUID string [%s]\n", uuid_str);
837                                         _bt_hal_convert_uuid_string_to_type(uuid, uuid_str);
838                                         memcpy(uuids + i * HAL_UUID_LEN, uuid, HAL_UUID_LEN);
839                                         g_free(uuid_str);
840                                 }
841                                 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_UUIDS,
842                                                 (HAL_UUID_LEN * uuid_count),
843                                                 uuids);
844                                 ev->num_props = num_props_tmp + 1;
845                                 g_free(uuid_value);
846                         }
847                 } else if (!g_strcmp0(key, "Discovering")) {
848                         is_discovering = g_variant_get_boolean(value);
849                         DBG("Discovering = [%d]", is_discovering);
850                 } else if (!g_strcmp0(key, "LEDiscovering")) {
851                         is_le_discovering = g_variant_get_boolean(value);
852                         DBG("LE Discovering = [%d]", is_le_discovering);
853                 } else if (!g_strcmp0(key, "Modalias")) {
854                         char *modalias = NULL;
855                         g_variant_get(value, "s", &modalias);
856                         DBG("Adapter ModAlias [%s]", modalias);
857                         size += __bt_insert_hal_properties(buf + size,
858                                         HAL_PROP_ADAPTER_MODALIAS, strlen(modalias) + 1, modalias);
859                         ev->num_props++;
860                         g_free(modalias);
861                 } else if (!g_strcmp0(key, "SupportedLEFeatures")) {
862                         DBG("LE Supported features");
863                         char *name = NULL;
864                         char *val = NULL;
865                         GVariantIter *iter = NULL;
866                         bt_local_le_features_t le_features;
867                         gboolean le_features_present = FALSE;
868
869                         memset(&le_features, 0x00, sizeof(le_features));
870
871                         g_variant_get(value, "as", &iter);
872                         if (iter) {
873                                 while (g_variant_iter_loop(iter, "s", &name)) {
874                                         DBG("name = %s", name);
875                                         g_variant_iter_loop(iter, "s", &val);
876                                         DBG("Value = %s", val);
877                                         _bt_hal_update_le_feature_support(name, val, &le_features);
878                                         le_features_present = TRUE;
879                                 }
880                                 g_free(val);
881                                 g_variant_iter_free(iter);
882
883                                 if (le_features_present) {
884                                         size += __bt_insert_hal_properties(buf + size,
885                                                         HAL_PROP_ADAPTER_LOCAL_LE_FEAT, sizeof(le_features), &le_features);
886                                         ev->num_props++;
887                                 } else {
888                                         DBG("le supported features values are NOT provided by Stack");
889                                 }
890                         }
891                 } else if (!g_strcmp0(key, "IpspInitStateChanged")) {
892                         ipsp_initialized = (g_variant_get_boolean(value) ? 1 : 0);
893                         DBG("IPSP Initialized = %d", ipsp_initialized);
894                         size += __bt_insert_hal_properties(buf + size,
895                                         HAL_PROP_ADAPTER_IPSP_INITIALIZED, sizeof(uint8_t), &ipsp_initialized);
896                         ev->num_props++;
897                 } else {
898                         ERR("Unhandled Property:[%s]", key);
899                 }
900         }
901
902         if (scan_mode_property_update) {
903                 size += __bt_insert_hal_properties(buf + size,
904                                 HAL_PROP_ADAPTER_SCAN_MODE, sizeof(int), &scan_mode);
905                 ev->num_props++;
906         }
907
908         if (!event_cb)
909                 event_cb = _bt_get_adapter_event_cb();
910         if (!event_cb) {
911                 ERR("event_cb is NULL");
912                 goto done;
913         }
914
915         if (size > 2) {
916                 DBG("Send Adapter properties changed event to HAL user,"
917                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
918                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
919         }
920 done:
921         g_variant_unref(result);
922         g_variant_iter_free(property_iter);
923         return FALSE;
924 }
925
926 static int __bt_hal_dbus_get_all_adapter_properties(void)
927 {
928         GDBusProxy *proxy;
929         GVariant *result;
930         GError *error = NULL;
931
932         DBG("+");
933
934         proxy = _bt_hal_get_adapter_properties_proxy();
935         if (!proxy) {
936                 DBG("Adapter Properties proxy get failed!!!");
937                 return BT_STATUS_FAIL;
938         }
939
940         result = g_dbus_proxy_call_sync(proxy,
941                         "GetAll",
942                         g_variant_new("(s)", BT_HAL_ADAPTER_INTERFACE),
943                         G_DBUS_CALL_FLAGS_NONE,
944                         -1,
945                         NULL,
946                         &error);
947
948         if (!result) {
949                 if (error != NULL) {
950                         ERR("Failed to get all adapter properties (Error: %s)", error->message);
951                         g_clear_error(&error);
952                 } else
953                         ERR("Failed to get all adapter properties");
954                 return BT_STATUS_FAIL;
955         }
956
957         DBG("Got All properties from Bluez Stack!!, time to start parsing");
958         /*
959          * As we need to provide async callback to user from HAL, simply schedule a
960          * callback method which will carry actual result
961          */
962         g_idle_add(__bt_adapter_all_properties_cb, (gpointer)result);
963
964         DBG("-");
965         return BT_STATUS_SUCCESS;
966 }
967
968 int _bt_hal_dbus_get_adapter_properties(void)
969 {
970         DBG("+");
971
972         return __bt_hal_dbus_get_all_adapter_properties();
973 }
974
975 int _bt_hal_get_adapter_powered_state(uint8_t *state)
976 {
977         char *adapter_path = NULL;
978         gboolean powered = FALSE;
979         int ret = BT_STATUS_FAIL;
980
981         /* Check Valid Adapter Path, followed by Adapter Powered state.
982            If any of these fails, adapter will be considered Disabled */
983         adapter_path = _bt_hal_get_adapter_path();
984
985         if (adapter_path == NULL) {
986                 INFO("adapter_path is NULL");
987                 g_free(adapter_path);
988                 *state = 0;
989                 return ret;
990         }
991
992         /* Check Adapter Powered Status */
993         ret = _bt_hal_is_adapter_powered(&powered);
994         if (BT_STATUS_FAIL == ret) {
995                 INFO("Adapter is not powered");
996                 g_free(adapter_path);
997                 *state = 0;
998                 return ret;
999         }
1000
1001         g_free(adapter_path);
1002
1003         if (powered)
1004                 *state = 1;
1005         else
1006                 *state = 0;
1007
1008         return ret;
1009 }
1010
1011 /* Get Discoverable timeout API and callback */
1012 static gboolean __bt_adapter_discovery_timeout_cb(gpointer user_data)
1013 {
1014         /* Buffer and propety count management */
1015         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1016         struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1017         size_t size = 0;
1018         unsigned int *timeout = user_data;
1019
1020         memset(buf, 0, sizeof(buf));
1021         size = sizeof(*ev);
1022         ev->num_props = 0;
1023         ev->status = BT_STATUS_SUCCESS;
1024
1025         DBG("Discovery timeout in callback: [%d]", *timeout);
1026
1027         size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_DISC_TIMEOUT,
1028                         sizeof(unsigned int), timeout);
1029
1030         ev->num_props++;
1031         DBG("Timeout value [%d] property Num [%d]", *timeout, ev->num_props);
1032
1033         if (!event_cb)
1034                 event_cb = _bt_get_adapter_event_cb();
1035         if (!event_cb) {
1036                 ERR("event_cb is NULL");
1037                 goto done;
1038         }
1039
1040         if (size > 2) {
1041                 DBG("Send Adapter Properties changed event to HAL user,"
1042                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
1043                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1044         }
1045 done:
1046         g_free(timeout);
1047         return FALSE;
1048 }
1049
1050 int _bt_hal_dbus_get_discovery_timeout(void)
1051 {
1052         GDBusProxy *proxy;
1053         GVariant *result;
1054         GVariant *temp;
1055         GError *error = NULL;
1056         unsigned int *timeout;
1057         DBG("+");
1058
1059         proxy = _bt_hal_get_adapter_properties_proxy();
1060         if (!proxy) {
1061                 DBG("Adapter Properties proxy get failed!!!");
1062                 return BT_STATUS_FAIL;
1063         }
1064
1065         result = g_dbus_proxy_call_sync(proxy,
1066                         "Get",
1067                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1068                                 "DiscoverableTimeout"),
1069                         G_DBUS_CALL_FLAGS_NONE,
1070                         -1,
1071                         NULL,
1072                         &error);
1073
1074         if (!result) {
1075                 if (error != NULL) {
1076                         ERR("Failed to get local version (Error: %s)", error->message);
1077                         g_clear_error(&error);
1078                 } else
1079                         ERR("Failed to get local version");
1080                 return BT_STATUS_FAIL;
1081         }
1082
1083         timeout = g_malloc0(sizeof(int));
1084         if (!timeout) {
1085                 ERR("Memory allocation failed");
1086                 g_variant_unref(result);
1087                 return BT_STATUS_FAIL;
1088         }
1089
1090         g_variant_get(result, "(v)", &temp);
1091         *timeout = g_variant_get_uint32(temp);
1092         DBG("Timeout value: [%d]", *timeout);
1093
1094         g_variant_unref(result);
1095         g_variant_unref(temp);
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_discovery_timeout_cb, (gpointer) timeout);
1102
1103         DBG("-");
1104         return BT_STATUS_SUCCESS;
1105 }
1106
1107 int _bt_hal_dbus_get_adapter_class(unsigned int *adapter_class)
1108 {
1109         GDBusProxy *proxy;
1110         GVariant *result;
1111         GVariant *temp;
1112         GError *error = NULL;
1113         DBG("+");
1114
1115         proxy = _bt_hal_get_adapter_properties_proxy();
1116         if (!proxy) {
1117                 DBG("Adapter Properties proxy get failed!!!");
1118                 return BT_STATUS_FAIL;
1119         }
1120
1121         result = g_dbus_proxy_call_sync(proxy,
1122                         "Get",
1123                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1124                                 "Class"),
1125                         G_DBUS_CALL_FLAGS_NONE,
1126                         -1,
1127                         NULL,
1128                         &error);
1129
1130         if (!result) {
1131                 if (error != NULL) {
1132                         ERR("Failed to get class (Error: %s)", error->message);
1133                         g_clear_error(&error);
1134                 } else
1135                         ERR("Failed to get class");
1136                 return BT_STATUS_FAIL;
1137         }
1138
1139
1140         g_variant_get(result, "(v)", &temp);
1141         *adapter_class = g_variant_get_uint32(temp);
1142         DBG("Class value: [0x%06x]", *adapter_class);
1143
1144         g_variant_unref(result);
1145         g_variant_unref(temp);
1146
1147         DBG("-");
1148         return BT_STATUS_SUCCESS;
1149 }
1150
1151 /* Get Discoverable Mode API and callback */
1152 static gboolean __bt_adapter_scan_mode_cb(gpointer user_data)
1153 {
1154         /* Buffer and propety count management */
1155         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1156         struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1157         size_t size = 0;
1158         int *mode = user_data;
1159
1160         memset(buf, 0, sizeof(buf));
1161         size = sizeof(*ev);
1162         ev->num_props = 0;
1163         ev->status = BT_STATUS_SUCCESS;
1164
1165         DBG("Scan mode callback: [%d]", *mode);
1166
1167         size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_SCAN_MODE,
1168                         sizeof(int), mode);
1169
1170         ev->num_props++;
1171         DBG("Scan mode [%d] property Num [%d]", *mode, ev->num_props);
1172
1173         if (!event_cb)
1174                 event_cb = _bt_get_adapter_event_cb();
1175         if (!event_cb) {
1176                 ERR("event_cb is NULL");
1177                 goto done;
1178         }
1179
1180         if (size > 2) {
1181                 DBG("Send Adapter Properties changed event to HAL user,"
1182                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
1183                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1184         }
1185 done:
1186         g_free(mode);
1187         return FALSE;
1188 }
1189
1190 int _bt_hal_dbus_get_scan_mode(void)
1191 {
1192         GDBusProxy *proxy;
1193         gboolean discoverable = FALSE;
1194         gboolean connectable = FALSE;
1195         GVariant *result;
1196         GVariant *temp;
1197         GError *error = NULL;
1198         int *scan_mode;
1199                 ;
1200         DBG("+");
1201
1202         proxy = _bt_hal_get_adapter_properties_proxy();
1203         if (!proxy) {
1204                 DBG("Adapter Properties proxy get failed!!!");
1205                 return BT_STATUS_FAIL;
1206         }
1207
1208         result = g_dbus_proxy_call_sync(proxy,
1209                         "Get",
1210                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1211                                 "Discoverable"),
1212                         G_DBUS_CALL_FLAGS_NONE,
1213                         -1,
1214                         NULL,
1215                         &error);
1216
1217         if (!result) {
1218                 if (error != NULL) {
1219                         ERR("Failed to get discoverable mode (Error: %s)", error->message);
1220                         g_clear_error(&error);
1221                 } else
1222                         ERR("Failed to get discoverable mode");
1223                 return BT_STATUS_FAIL;
1224         }
1225
1226         g_variant_get(result, "(v)", &temp);
1227         discoverable = g_variant_get_boolean(temp);
1228         DBG("discoverable:%d", discoverable);
1229
1230         g_variant_unref(result);
1231         g_variant_unref(temp);
1232
1233         if (!discoverable) {
1234                 result = g_dbus_proxy_call_sync(proxy,
1235                                 "Get",
1236                                 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1237                                         "Connectable"),
1238                                 G_DBUS_CALL_FLAGS_NONE,
1239                                 -1,
1240                                 NULL,
1241                                 &error);
1242                 if (!result) {
1243                         if (error != NULL) {
1244                                 ERR("Failed to get connectable mode (Error: %s)", error->message);
1245                                 g_clear_error(&error);
1246                         } else
1247                                 ERR("Failed to get connectable mode");
1248                         return BT_STATUS_FAIL;
1249                 }
1250
1251                 g_variant_get(result, "(v)", &temp);
1252                 connectable = g_variant_get_boolean(temp);
1253                 DBG("connectable:%d", connectable);
1254
1255                 g_variant_unref(result);
1256                 g_variant_unref(temp);
1257         }
1258
1259         scan_mode = g_malloc0(sizeof(int));
1260         if (!scan_mode) {
1261                 ERR("Memory allocation failed");
1262                 return BT_STATUS_FAIL;
1263         }
1264
1265         if (discoverable)
1266                 *scan_mode = BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
1267         else if (connectable)
1268                 *scan_mode = BT_SCAN_MODE_CONNECTABLE;
1269         else
1270                 *scan_mode = BT_SCAN_MODE_NONE;
1271
1272         /*
1273          * As we need to provide async callback to user from HAL, simply schedule a
1274          * callback method which will carry actual result
1275          */
1276         g_idle_add(__bt_adapter_scan_mode_cb, (gpointer) scan_mode);
1277
1278         DBG("-");
1279         return BT_STATUS_SUCCESS;
1280 }
1281
1282 /* Get Local Version API and callback */
1283 static gboolean __bt_adapter_local_version_cb(gpointer user_data)
1284 {
1285         /* Buffer and propety count management */
1286         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1287         struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1288         size_t size = 0;
1289         char *version = NULL;
1290
1291         memset(buf, 0, sizeof(buf));
1292         size = sizeof(*ev);
1293         ev->num_props = 0;
1294         ev->status = BT_STATUS_SUCCESS;
1295
1296         version = (char*) user_data;
1297         DBG("Local Version in callback: [%s]", version);
1298
1299         size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_VERSION,
1300                         (strlen(version) + 1), version);
1301
1302         ev->num_props++;
1303         DBG("Device version [%s] property Num [%d]", version, ev->num_props);
1304
1305         if (!event_cb)
1306                 event_cb = _bt_get_adapter_event_cb();
1307         if (!event_cb) {
1308                 ERR("event_cb is NULL");
1309                 goto done;
1310         }
1311
1312         if (size > 2) {
1313                 DBG("Send Adapter Properties changed event to HAL user,"
1314                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
1315                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1316         }
1317 done:
1318         g_free(version);
1319         return FALSE;
1320 }
1321
1322 int _bt_hal_dbus_get_local_version(void)
1323 {
1324         GDBusProxy *proxy;
1325         const char *version = NULL;
1326         GVariant *result;
1327         GVariant *temp;
1328         GError *error = NULL;
1329         DBG("+");
1330
1331         proxy = _bt_hal_get_adapter_properties_proxy();
1332         if (!proxy) {
1333                 DBG("Adapter Properties proxy get failed!!!");
1334                 return BT_STATUS_FAIL;
1335         }
1336
1337         result = g_dbus_proxy_call_sync(proxy,
1338                         "Get",
1339                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1340                                 "Version"),
1341                         G_DBUS_CALL_FLAGS_NONE,
1342                         -1,
1343                         NULL,
1344                         &error);
1345
1346         if (!result) {
1347                 if (error != NULL) {
1348                         ERR("Failed to get local version (Error: %s)", error->message);
1349                         g_clear_error(&error);
1350                 } else
1351                         ERR("Failed to get local version");
1352                 return BT_STATUS_FAIL;
1353         }
1354
1355         g_variant_get(result, "(v)", &temp);
1356         version = g_variant_dup_string(temp, NULL);
1357         DBG("Local Version: [%s]", version);
1358
1359         g_variant_unref(result);
1360         g_variant_unref(temp);
1361
1362         /*
1363          * As we need to provide async callback to user from HAL, simply schedule a
1364          * callback method which will carry actual result
1365          */
1366         g_idle_add(__bt_adapter_local_version_cb, (gpointer) version);
1367
1368         DBG("-");
1369         return BT_STATUS_SUCCESS;
1370 }
1371
1372 /* Get Local Name API and callback */
1373 static gboolean __bt_adapter_local_name_cb(gpointer user_data)
1374 {
1375         /* Buffer and propety count management */
1376         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1377         struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1378         size_t size = 0;
1379         char *name = NULL;
1380
1381         memset(buf, 0, sizeof(buf));
1382         size = sizeof(*ev);
1383         ev->num_props = 0;
1384         ev->status = BT_STATUS_SUCCESS;
1385
1386         name = (char*) user_data;
1387         DBG("Local Name in callback: [%s]", name);
1388
1389         size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_NAME,
1390                         strlen(name) + 1, name);
1391
1392         ev->num_props++;
1393         DBG("Device name [%s] property Num [%d]", name, ev->num_props);
1394
1395         if (!event_cb)
1396                 event_cb = _bt_get_adapter_event_cb();
1397         if (!event_cb) {
1398                 ERR("event_cb is NULL");
1399                 goto done;
1400         }
1401
1402         if (size > 2) {
1403                 DBG("Send Adapter Properties changed event to HAL user,"
1404                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
1405                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1406         }
1407 done:
1408         g_free(name);
1409         return FALSE;
1410 }
1411
1412 int _bt_hal_dbus_get_local_name(void)
1413 {
1414         GDBusProxy *proxy;
1415         const char *name = NULL;
1416         GVariant *result;
1417         GVariant *temp;
1418         GError *error = NULL;
1419
1420         proxy = _bt_hal_get_adapter_properties_proxy();
1421         if (!proxy) {
1422                 DBG("Adapter Properties proxy get failed!!!");
1423                 return BT_STATUS_FAIL;
1424         }
1425
1426         result = g_dbus_proxy_call_sync(proxy,
1427                         "Get",
1428                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1429                                 "Alias"),
1430                         G_DBUS_CALL_FLAGS_NONE,
1431                         -1,
1432                         NULL,
1433                         &error);
1434
1435         if (!result) {
1436                 if (error != NULL) {
1437                         ERR("Failed to get local name (Error: %s)", error->message);
1438                         g_clear_error(&error);
1439                 } else
1440                         ERR("Failed to get local name");
1441                 return BT_STATUS_FAIL;
1442         }
1443
1444         g_variant_get(result, "(v)", &temp);
1445         name = g_variant_dup_string(temp, NULL);
1446         DBG("Local Name: [%s]", name);
1447
1448         g_variant_unref(result);
1449         g_variant_unref(temp);
1450
1451         /*
1452          * As we need to provide async callback to user from HAL, simply schedule a
1453          * callback method which will carry actual result
1454          */
1455         g_idle_add(__bt_adapter_local_name_cb, (gpointer) name);
1456
1457         return BT_STATUS_SUCCESS;
1458 }
1459
1460 /* Get Local Address API and callback */
1461 static gboolean __bt_adapter_local_address_cb(gpointer user_data)
1462 {
1463         /* Buffer and propety count management */
1464         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1465         struct hal_ev_adapter_props_changed *ev = (void*) buf;
1466         size_t size = 0;
1467         char * address = NULL;
1468
1469         memset(buf, 0, sizeof(buf));
1470         size = sizeof(*ev);
1471         ev->num_props = 0;
1472         ev->status = BT_STATUS_SUCCESS;
1473
1474         address = (char*) user_data;
1475
1476         uint8_t bdaddr[6];
1477         _bt_hal_convert_addr_string_to_type(bdaddr, address);
1478
1479         size += __bt_insert_hal_properties(buf + size, HAL_PROP_DEVICE_ADDR,
1480                         sizeof(bdaddr), bdaddr);
1481
1482         ev->num_props++;
1483         DBG("Device address [%s] property Num [%d]", address, ev->num_props);
1484
1485         size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_ADDR,
1486                         sizeof(bdaddr), bdaddr);
1487
1488         if (!event_cb)
1489                 event_cb = _bt_get_adapter_event_cb();
1490         if (!event_cb) {
1491                 ERR("event_cb is NULL");
1492                 goto done;
1493         }
1494
1495         if (size > 1) {
1496                 DBG("Send Device found event to HAL user,"
1497                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
1498                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1499         }
1500 done:
1501         g_free(address);
1502         return FALSE;
1503 }
1504
1505 int _bt_hal_dbus_get_local_address(void)
1506 {
1507         GDBusProxy *proxy;
1508         GError *error = NULL;
1509         const char *address;
1510         GVariant *result;
1511         GVariant *temp;
1512
1513         proxy = _bt_hal_get_adapter_properties_proxy();
1514         if (!proxy) {
1515                 DBG("_bt_hal_dbus_get_local_address: Adapter Properties proxy get failed!!!");
1516                 return BT_STATUS_FAIL;
1517         }
1518
1519         result = g_dbus_proxy_call_sync(proxy,
1520                         "Get",
1521                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1522                                 "Address"),
1523                         G_DBUS_CALL_FLAGS_NONE,
1524                         -1,
1525                         NULL,
1526                         &error);
1527
1528         if (!result) {
1529                 ERR("Failed to get local address");
1530                 if (error != NULL) {
1531                         ERR("Failed to get local address (Error: %s)", error->message);
1532                         g_clear_error(&error);
1533                 }
1534                 return BT_STATUS_FAIL;
1535         }
1536
1537         g_variant_get(result, "(v)", &temp);
1538         address = g_variant_dup_string(temp, NULL);
1539
1540         if (address)
1541                 DBG("Address:%s", address);
1542         else
1543                 return BT_STATUS_FAIL;
1544
1545         g_variant_unref(result);
1546         g_variant_unref(temp);
1547
1548         /*
1549          * As we need to provide async callback to user from HAL, simply schedule a
1550          * callback method which will carry actual result
1551          */
1552         g_idle_add(__bt_adapter_local_address_cb, (gpointer) address);
1553
1554         return BT_STATUS_SUCCESS;
1555 }
1556
1557 /* Get Local services API and callback */
1558 static gboolean __bt_adapter_service_uuids_cb(gpointer user_data)
1559 {
1560         GVariant *result = user_data;
1561         GVariant *temp;
1562         GVariantIter *iter = NULL;
1563         gchar *uuid_str;
1564
1565         /* Buffer and propety count management */
1566         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1567         struct hal_ev_adapter_props_changed *ev = (void*) buf;
1568         size_t size = 0;
1569
1570         /* UUID collection */
1571         uint8_t uuids[HAL_UUID_LEN * MAX_UUID_COUNT];
1572         int uuid_count = 0;
1573
1574         memset(buf, 0, sizeof(buf));
1575         size = sizeof(*ev);
1576         ev->num_props = 0;
1577         ev->status = BT_STATUS_SUCCESS;
1578
1579         g_variant_get(result, "(v)", &temp);
1580         g_variant_get(temp, "as", &iter);
1581         if (iter == NULL) {
1582                 ERR("Failed to get UUIDs");
1583                 goto fail;
1584         }
1585
1586         while (g_variant_iter_loop(iter, "s", &uuid_str)) {
1587                 uint8_t uuid[HAL_UUID_LEN];
1588
1589                 DBG("UUID string [%s]\n", uuid_str);
1590                 _bt_hal_convert_uuid_string_to_type(uuid, uuid_str);
1591                 memcpy(uuids + uuid_count * HAL_UUID_LEN, uuid, HAL_UUID_LEN);
1592                 uuid_count++;
1593         }
1594
1595         size += __bt_insert_hal_properties(buf + size,
1596                         HAL_PROP_ADAPTER_UUIDS,
1597                         (HAL_UUID_LEN * uuid_count),
1598                         uuids);
1599         ev->num_props++;
1600
1601         if (!event_cb)
1602                 event_cb = _bt_get_adapter_event_cb();
1603         if (!event_cb) {
1604                 ERR("event_cb is NULL");
1605                 goto done;
1606         }
1607
1608         if (size > 2) {
1609                 DBG("Send Adapter properties changed event to HAL user,"
1610                                 " Num Prop [%d] total size [%zd]", ev->num_props, size);
1611                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1612         }
1613 done:
1614         g_variant_iter_free(iter);
1615         g_variant_unref(result);
1616         g_variant_unref(temp);
1617         return FALSE;
1618 fail:
1619         if (!event_cb)
1620                 event_cb = _bt_get_adapter_event_cb();
1621         if (event_cb) {
1622                 ev->status = BT_STATUS_FAIL;
1623                 ev->num_props = 0;
1624                 DBG("Send Adapter properties changed event to HAL user,"
1625                                 " Num Prop [%d] total size [%zd]", ev->num_props, size);
1626                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1627         }
1628
1629         g_variant_unref(result);
1630         return FALSE;
1631 }
1632
1633 int _bt_hal_dbus_get_adapter_supported_uuids(void)
1634 {
1635         GDBusProxy *proxy;
1636         GError *error = NULL;
1637         GVariant *result;
1638
1639         proxy = _bt_hal_get_adapter_properties_proxy();
1640         if (!proxy) {
1641                 DBG("Adapter Properties proxy get failed!!!");
1642                 return BT_STATUS_FAIL;
1643         }
1644
1645         result = g_dbus_proxy_call_sync(proxy,
1646                         "Get",
1647                         g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1648                                 "UUIDs"),
1649                         G_DBUS_CALL_FLAGS_NONE,
1650                         -1,
1651                         NULL,
1652                         &error);
1653
1654         if (!result) {
1655                 if (error != NULL) {
1656                         ERR("Failed to get UUIDs (Error: %s)", error->message);
1657                         g_clear_error(&error);
1658                 } else
1659                         ERR("Failed to get UUIDs");
1660                 return BT_STATUS_FAIL;
1661         }
1662
1663
1664         DBG("Got All Adaptr service UUID's from Bluez Stack!!, time to start parsing");
1665
1666         /*
1667          * As we need to provide async callback to user from HAL, simply schedule a
1668          * callback method which will carry actual result
1669          */
1670         g_idle_add(__bt_adapter_service_uuids_cb, (gpointer)result);
1671
1672         return BT_STATUS_SUCCESS;
1673 }
1674
1675 static gboolean __is_device_paired(GVariantIter *item_iter)
1676 {
1677         gboolean paired = FALSE;
1678         GVariant *value;
1679         gchar *key;
1680
1681         while (g_variant_iter_loop(item_iter, "{sv}", &key, &value)) {
1682                 if (NULL == key || g_strcmp0(key, "Paired"))
1683                         continue;
1684
1685                 paired = g_variant_get_boolean(value);
1686                 g_variant_unref(value);
1687                 g_free(key);
1688                 break;
1689         }
1690
1691         return paired;
1692 }
1693
1694 static gboolean __bt_adapter_bonded_devices_cb(gpointer user_data)
1695 {
1696         /* Buffer and propety count management */
1697         uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1698         uint8_t addresses[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1699         struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1700         size_t size = 0;
1701         size_t count = 0;
1702
1703         GVariant *result = user_data;
1704         GVariantIter *iter;
1705         GVariantIter *interface_iter;
1706         GVariantIter *svc_iter;
1707         char *object_path = NULL;
1708         char *interface_str = NULL;
1709
1710         char device_address[BT_HAL_ADDRESS_STRING_SIZE];
1711         uint8_t bdaddr[BT_HAL_ADDRESS_LENGTH_MAX];
1712
1713         memset(buf, 0, sizeof(buf));
1714         size = sizeof(*ev);
1715         ev->num_props = 0;
1716         ev->status = BT_STATUS_SUCCESS;
1717
1718         INFO("Size [%zd]", size);
1719
1720         /* signature of GetManagedObjects:  a{oa{sa{sv}}} */
1721         g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
1722
1723         /* Parse the signature: {oa{sa{sv}}} */
1724         while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path, &interface_iter)) {
1725                 if (object_path == NULL)
1726                         continue;
1727
1728                 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
1729                                         &interface_str, &svc_iter)) {
1730                         if (g_strcmp0(interface_str, "org.bluez.Device1") == 0) {
1731                                 DBG("Found a device: %s", object_path);
1732                                 if (__is_device_paired(svc_iter)) {
1733                                         _bt_hal_convert_device_path_to_address(object_path, device_address);
1734                                         DBG("Paired Device Address: [%s]", device_address);
1735
1736                                         _bt_hal_convert_addr_string_to_type(bdaddr, device_address);
1737                                         memcpy((addresses + (count * BT_HAL_ADDRESS_LENGTH_MAX)),
1738                                                         bdaddr, BT_HAL_ADDRESS_LENGTH_MAX);
1739                                         count++;
1740                                 }
1741                                 g_variant_iter_free(svc_iter);
1742                                 g_free(interface_str);
1743                                 interface_str = NULL;
1744                                 break;
1745                         }
1746                 }
1747         }
1748
1749         g_variant_iter_free(iter);
1750         g_variant_unref(result);
1751
1752         size += __bt_insert_hal_properties((buf + size),
1753                         HAL_PROP_ADAPTER_BONDED_DEVICES,
1754                         (count * BT_HAL_ADDRESS_LENGTH_MAX), addresses);
1755         ev->num_props++;
1756
1757         if (!event_cb)
1758                 event_cb = _bt_get_adapter_event_cb();
1759         if (!event_cb) {
1760                 ERR("event_cb is NULL");
1761                 goto done;
1762         }
1763
1764         if (size > 2) {
1765                 DBG("Send Adapter properties changed event to HAL user,"
1766                         " Num Prop [%d] total size [%zd]", ev->num_props, size);
1767                 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1768         }
1769 done:
1770         return FALSE;
1771 }
1772
1773 int _bt_hal_dbus_get_bonded_devices(void)
1774 {
1775         GDBusProxy *manager_proxy;
1776         GVariant *result = NULL;
1777
1778         manager_proxy = _bt_hal_get_manager_proxy();
1779         if (manager_proxy == NULL)
1780                 return  BT_STATUS_FAIL;
1781
1782         result = g_dbus_proxy_call_sync(manager_proxy, "GetManagedObjects",
1783                         NULL,
1784                         G_DBUS_CALL_FLAGS_NONE,
1785                         -1,
1786                         NULL,
1787                         NULL);
1788         if (!result) {
1789                 ERR("Can't get managed objects");
1790                 return BT_STATUS_FAIL;
1791         }
1792
1793         /*
1794          * As we need to provide async callback to user from HAL, simply schedule a
1795          * callback method which will carry actual result
1796          */
1797         g_idle_add(__bt_adapter_bonded_devices_cb, (gpointer) result);
1798
1799         return BT_STATUS_SUCCESS;
1800 }
1801
1802 int _bt_hal_dbus_get_adapter_property(bt_property_type_t property_type)
1803 {
1804         DBG("property_type: %d", property_type);
1805
1806         switch (property_type) {
1807         case BT_PROPERTY_BDADDR:
1808                 return _bt_hal_dbus_get_local_address();
1809         case BT_PROPERTY_BDNAME:
1810                 return _bt_hal_dbus_get_local_name();
1811         case BT_PROPERTY_VERSION:
1812                 return _bt_hal_dbus_get_local_version();
1813         case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
1814                 return _bt_hal_dbus_get_discovery_timeout();
1815         case BT_PROPERTY_ADAPTER_SCAN_MODE:
1816                 return _bt_hal_dbus_get_scan_mode();
1817         case BT_PROPERTY_CLASS_OF_DEVICE:
1818                 return BT_STATUS_UNSUPPORTED;
1819         case BT_PROPERTY_UUIDS:
1820                 return _bt_hal_dbus_get_adapter_supported_uuids();
1821         case BT_PROPERTY_ADAPTER_BONDED_DEVICES:
1822                 return _bt_hal_dbus_get_bonded_devices();
1823         default:
1824                 return BT_STATUS_UNSUPPORTED;
1825         }
1826 }
1827
1828 static int __bt_hal_dbus_set_local_name(void *data)
1829 {
1830         GDBusProxy *proxy;
1831         const char *name = data;
1832         GVariant *result;
1833         GError *error = NULL;
1834
1835         DBG("Local Name: [%s]", name);
1836         proxy = _bt_hal_get_adapter_properties_proxy();
1837         if (!proxy) {
1838                 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1839                 return BT_STATUS_FAIL;
1840         }
1841
1842         result = g_dbus_proxy_call_sync(proxy,
1843                         "Set",
1844                         g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1845                                 "Alias", g_variant_new("s", name)),
1846                         G_DBUS_CALL_FLAGS_NONE,
1847                         -1,
1848                         NULL,
1849                         &error);
1850         if (!result) {
1851                 if (error != NULL) {
1852                         ERR("Failed to set local name (Error: %s)", error->message);
1853                         g_clear_error(&error);
1854                 } else
1855                         ERR("Failed to set local name");
1856                 return BT_STATUS_FAIL;
1857         }
1858         g_variant_unref(result);
1859
1860         return BT_STATUS_SUCCESS;
1861 }
1862
1863 static int __bt_hal_dbus_set_scan_mode(void *data)
1864 {
1865         GDBusProxy *proxy;
1866         int *mode = data;
1867         GVariant *result;
1868         GError *error = NULL;
1869         gboolean pg_scan;
1870         gboolean inq_scan;
1871
1872         DBG("Scan mode: [%d]", *mode);
1873         proxy = _bt_hal_get_adapter_properties_proxy();
1874         if (!proxy) {
1875                 DBG("Adapter Properties proxy get failed!!!");
1876                 return BT_STATUS_FAIL;
1877         }
1878
1879         switch (*mode) {
1880         case BT_SCAN_MODE_NONE:
1881                 pg_scan = FALSE;
1882                 inq_scan = FALSE;
1883                 break;
1884         case BT_SCAN_MODE_CONNECTABLE:
1885                 pg_scan = TRUE;
1886                 inq_scan = FALSE;
1887                 break;
1888         case BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
1889                 pg_scan = TRUE;
1890                 inq_scan = TRUE;
1891                 break;
1892         default:
1893                 ERR("Invalid scan mode");
1894                 return BT_STATUS_FAIL;
1895         }
1896
1897         result = g_dbus_proxy_call_sync(proxy,
1898                         "Set",
1899                         g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1900                                 "Connectable", g_variant_new("b", pg_scan)),
1901                         G_DBUS_CALL_FLAGS_NONE,
1902                         -1,
1903                         NULL,
1904                         &error);
1905         if (!result) {
1906                 if (error != NULL) {
1907                         ERR("Failed to set connectable property (Error: %s)", error->message);
1908                         g_clear_error(&error);
1909                 } else
1910                         ERR("Failed to set connectable property");
1911                 return BT_STATUS_FAIL;
1912         }
1913         g_variant_unref(result);
1914
1915         result = g_dbus_proxy_call_sync(proxy,
1916                         "Set",
1917                         g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE, "Discoverable",
1918                                 g_variant_new("b", inq_scan)),
1919                         G_DBUS_CALL_FLAGS_NONE,
1920                         -1,
1921                         NULL,
1922                         &error);
1923         if (!result) {
1924                 if (error != NULL) {
1925                         ERR("Failed to set Discoverable property (Error: %s)", error->message);
1926                         g_clear_error(&error);
1927                 } else
1928                         ERR("Failed to set Discoverable property");
1929                 return BT_STATUS_FAIL;
1930         }
1931         g_variant_unref(result);
1932
1933         return BT_STATUS_SUCCESS;
1934 }
1935
1936 static int __bt_hal_dbus_set_discovery_timeout(void *data)
1937 {
1938         GDBusProxy *proxy;
1939         unsigned int *timeout = data;
1940         GVariant *result;
1941         GError *error = NULL;
1942
1943         DBG("Discovery Timeout: [%d]", *timeout);
1944         proxy = _bt_hal_get_adapter_properties_proxy();
1945         if (!proxy) {
1946                 DBG("Adapter Properties proxy get failed!!!");
1947                 return BT_STATUS_FAIL;
1948         }
1949
1950         result = g_dbus_proxy_call_sync(proxy,
1951                         "Set",
1952                         g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1953                                 "DiscoverableTimeout", g_variant_new("u", *timeout)),
1954                         G_DBUS_CALL_FLAGS_NONE,
1955                         -1,
1956                         NULL,
1957                         &error);
1958         if (!result) {
1959                 if (error != NULL) {
1960                         ERR("Failed to set DiscoverableTimeout property (Error: %s)", error->message);
1961                         g_clear_error(&error);
1962                 } else
1963                         ERR("Failed to set DiscoverableTimeout property");
1964                 return BT_STATUS_FAIL;
1965         }
1966         g_variant_unref(result);
1967
1968         return BT_STATUS_SUCCESS;
1969 }
1970
1971 /* Set Adapter Properties */
1972 int _bt_hal_dbus_set_adapter_property(const bt_property_t *property)
1973 {
1974         int result;
1975
1976         if (property == NULL || property->val == NULL) {
1977                 ERR("Invalid parameters received");
1978                 return BT_STATUS_FAIL;
1979         }
1980
1981         switch (property->type) {
1982         case BT_PROPERTY_BDNAME:
1983                 result =  __bt_hal_dbus_set_local_name(property->val);
1984                 break;
1985         case BT_PROPERTY_ADAPTER_SCAN_MODE:
1986                 result =  __bt_hal_dbus_set_scan_mode(property->val);
1987                 break;
1988         case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
1989                 result =  __bt_hal_dbus_set_discovery_timeout(property->val);
1990                 break;
1991         default:
1992                 result = BT_STATUS_UNSUPPORTED;
1993         }
1994
1995         return result;
1996 }