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