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