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