4 * Copyright (c) 2015 -2016 Samsung Electronics Co., Ltd All Rights Reserved.
6 * Contact: Anupam Roy <anupam.r@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
33 #include "bt-hal-log.h"
34 #include "bt-hal-msg.h"
35 #include "bt-hal-utils.h"
37 #include <bt-hal-adapter-dbus-handler.h>
38 #include <bt-hal-dbus-common-utils.h>
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"
45 static GDBusProxy *core_proxy = NULL;
46 static GDBusConnection *system_conn = NULL;
47 static handle_stack_msg event_cb = NULL;
49 handle_stack_msg _bt_get_adapter_event_cb(void)
57 GDBusConnection *__bt_hal_get_system_gconn(void)
60 if (system_conn == NULL)
61 system_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
67 GDBusProxy *_bt_init_core_proxy(void)
69 GDBusConnection *conn;
72 conn = __bt_hal_get_system_gconn();
76 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
92 static GDBusProxy *__bt_get_core_proxy(void)
94 return (core_proxy) ? core_proxy : _bt_init_core_proxy();
97 /* To send stack event to hal-bluetooth handler */
98 void _bt_hal_dbus_store_stack_msg_cb(handle_stack_msg cb)
103 static gboolean __bt_hal_send_adapter_event(gpointer user_data)
105 struct hal_ev_adapter_state_changed ev;
106 gboolean *enable = (gboolean *)user_data;
109 ev.state = HAL_POWER_ON;
111 ev.state = HAL_POWER_OFF;
114 event_cb = _bt_get_adapter_event_cb();
117 event_cb(HAL_EV_ADAPTER_STATE_CHANGED, &ev, sizeof(ev));
123 static gboolean __bt_hal_send_le_event(gpointer user_data)
125 struct hal_ev_le_state_changed ev;
126 gboolean *enable = (gboolean *)user_data;
129 ev.state = HAL_POWER_ON;
131 ev.state = HAL_POWER_OFF;
134 event_cb = _bt_get_adapter_event_cb();
137 event_cb(HAL_EV_LE_STATE_CHANGED, &ev, sizeof(ev));
144 int _bt_hal_dbus_enable_adapter(void)
147 GError *error = NULL;
148 GVariant *result = NULL;
149 unsigned char powered = 0;
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!");
157 if (_bt_hal_get_adapter_powered_state(&powered) == BT_STATUS_FAIL)
158 ERR("_bt_hal_get_adapter_powered_state failed");
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);
164 g_idle_add(__bt_hal_send_adapter_event, (gpointer)user_data);
165 return BT_STATUS_SUCCESS;
167 proxy = __bt_get_core_proxy();
170 DBG("_bt_hal_dbus_enable_adapter: Core proxy get failed!!!");
171 return BT_STATUS_FAIL;
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",
178 G_DBUS_CALL_FLAGS_NONE, BT_ENABLE_TIMEOUT,
181 DBG("EnableAdapter failed: %s", error->message);
182 g_clear_error(&error);
184 _bt_hal_set_adapter_request_state(FALSE);
185 _bt_hal_set_le_request_state(FALSE);
186 result = g_dbus_proxy_call_sync(proxy,
189 G_DBUS_CALL_FLAGS_NONE,
195 DBG("Bt core call failed(Error: %s)", error->message);
196 g_clear_error(&error);
198 g_variant_unref(result);
200 /* TODO: Terminate bluetooth service or not, need to check */
201 /*g_idle_add((GSourceFunc)_bt_terminate_service, NULL);*/
202 return BT_STATUS_FAIL;
206 g_variant_unref(result);
207 return BT_STATUS_SUCCESS;
210 int _bt_hal_dbus_disable_adapter(void)
213 GError *error = NULL;
214 GVariant *result = NULL;
217 proxy = __bt_get_core_proxy();
220 DBG("_bt_hal_dbus_enable_adapter: Core proxy get failed!!!");
221 return BT_STATUS_FAIL;
224 result = g_dbus_proxy_call_sync(proxy, "DisableAdapter",
226 G_DBUS_CALL_FLAGS_NONE, -1,
229 DBG("DisableAdapter failed: %s", error->message);
230 g_clear_error(&error);
232 g_variant_unref(result);
234 /* TODO: Terminate bluetooth service or not, need to check */
235 /*g_idle_add((GSourceFunc)_bt_terminate_service, NULL);*/
236 return BT_STATUS_FAIL;
240 g_variant_unref(result);
241 return BT_STATUS_SUCCESS;
245 int _bt_hal_dbus_enable_le(void)
248 GError *error = NULL;
249 GVariant *result = NULL;
250 int adapter_value = VCONFKEY_BT_STATUS_OFF;
251 unsigned char powered = 0;
255 if (vconf_get_int(VCONFKEY_BT_STATUS, &adapter_value) != 0)
256 ERR("fail to get vconf key!");
258 if (_bt_hal_get_adapter_powered_state(&powered) == BT_STATUS_FAIL)
259 ERR("_bt_hal_get_adapter_powered_state failed");
261 if ((adapter_value == VCONFKEY_BT_STATUS_ON) && (powered == 1)) {
262 gboolean *user_data = g_new0(int, 1);
264 g_idle_add(__bt_hal_send_le_event, (gpointer)user_data);
265 return BT_STATUS_SUCCESS;
268 proxy = __bt_get_core_proxy();
271 DBG("_bt_hal_dbus_enable_le: Core proxy get failed!!!");
272 return BT_STATUS_FAIL;
274 _bt_hal_set_le_request_state(TRUE);
276 result = g_dbus_proxy_call_sync(proxy, "EnableAdapterLe",
278 G_DBUS_CALL_FLAGS_NONE, BT_ENABLE_TIMEOUT,
281 DBG("EnableAdapter failed: %s", error->message);
282 g_clear_error(&error);
284 result = g_dbus_proxy_call_sync(proxy,
287 G_DBUS_CALL_FLAGS_NONE,
292 _bt_hal_set_le_request_state(FALSE);
294 DBG("Bt core call failed(Error: %s)", error->message);
295 g_clear_error(&error);
297 g_variant_unref(result);
299 return BT_STATUS_FAIL;
303 g_variant_unref(result);
304 return BT_STATUS_SUCCESS;
307 int _bt_hal_dbus_disable_le(void)
310 GError *error = NULL;
311 GVariant *result = NULL;
312 int adapter_value = VCONFKEY_BT_STATUS_OFF;
315 if (vconf_get_int(VCONFKEY_BT_STATUS, &adapter_value) != 0)
316 ERR("fail to get vconf key!");
318 if (adapter_value == VCONFKEY_BT_STATUS_ON) {
319 gboolean *user_data = g_new0(int, 1);
321 g_idle_add(__bt_hal_send_le_event, (gpointer)user_data);
322 return BT_STATUS_SUCCESS;
325 proxy = __bt_get_core_proxy();
328 DBG("_bt_hal_dbus_disable_le: Core proxy get failed!!!");
329 return BT_STATUS_FAIL;
332 result = g_dbus_proxy_call_sync(proxy, "DisableAdapterLe",
334 G_DBUS_CALL_FLAGS_NONE, -1,
337 DBG("DisableAdapter failed: %s", error->message);
338 g_clear_error(&error);
340 g_variant_unref(result);
341 return BT_STATUS_FAIL;
347 g_variant_unref(result);
348 return BT_STATUS_SUCCESS;
353 int _bt_hal_dbus_reset_adapter(void)
357 GError *error = NULL;
360 proxy = __bt_get_core_proxy();
362 return BT_STATUS_FAIL;
364 result = g_dbus_proxy_call_sync(proxy,
367 G_DBUS_CALL_FLAGS_NONE,
374 ERR("Failed to ResetAdapter (Error: %s)", error->message);
375 g_clear_error(&error);
377 ERR("Failed to ResetAdapter");
378 return BT_STATUS_FAIL;
381 g_variant_unref(result);
382 return BT_STATUS_SUCCESS;
386 int _bt_hal_dbus_start_discovery(gboolean is_custom,
387 bt_disc_role_type_t role)
390 GError *error = NULL;
392 const gchar *disc_type;
393 DBG("Discovery Type: Is Custom : [%s]", is_custom ? "TRUE" : "FALSE");
395 proxy = _bt_hal_get_adapter_proxy();
397 DBG("Adapter proxy get failed!!!");
398 return BT_STATUS_FAIL;
402 if (role == BT_DISC_ROLE_BREDR)
404 else if (role == BT_DISC_ROLE_LE)
406 else if (role == BT_DISC_ROLE_DUAL)
407 disc_type = "LE_BREDR";
409 return BT_STATUS_PARM_INVALID;
411 result = g_dbus_proxy_call_sync(proxy,
412 "StartCustomDiscovery",
413 g_variant_new("s", disc_type),
414 G_DBUS_CALL_FLAGS_NONE,
419 result = g_dbus_proxy_call_sync(proxy,
422 G_DBUS_CALL_FLAGS_NONE,
429 ERR("StartDiscovery failed (Error: %s)", error->message);
430 g_clear_error(&error);
432 ERR("StartDiscovery failed");
433 return BT_STATUS_FAIL;
436 /* discovery status will be change in event */
438 g_variant_unref(result);
439 return BT_STATUS_SUCCESS;
442 int _bt_hal_dbus_stop_discovery(void)
445 GError *error = NULL;
449 proxy = _bt_hal_get_adapter_proxy();
451 DBG("_bt_hal_dbus_stop_discovery: Adapter proxy get failed!!!");
452 return BT_STATUS_FAIL;
455 result = g_dbus_proxy_call_sync(proxy,
458 G_DBUS_CALL_FLAGS_NONE,
465 ERR("StopDiscovery failed (Error: %s)", error->message);
466 g_clear_error(&error);
468 ERR("StopDiscovery failed");
469 return BT_STATUS_FAIL;
472 /* discovery status will be change in event */
474 g_variant_unref(result);
475 return BT_STATUS_SUCCESS;
478 static void ___bt_fill_le_supported_features(const char *item,
479 const char *value, uint8_t *le_features)
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);
490 DBG("No registered item");
493 * TODO: Need to check these usages for Bluez Case. In Bluedroid case,
494 * these are used, so just setting all to 0
496 le_features[3] = 0; /* Adapter MAX IRK List Size */
498 le_features[5] = 0; /* Adapter Scan result storage size */
501 le_features[7] = 0; /* Adapter Activity energy info supported */
506 static gboolean __bt_adapter_all_properties_cb(gpointer user_data)
508 GVariant *result = user_data;
509 GVariantIter *property_iter;
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;
517 gchar *address = 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;
525 gboolean is_discovering;
526 gboolean is_le_discovering;
527 uint8_t ipsp_initialized;
530 unsigned int pairable_timeout;
531 gboolean scan_mode_property_update = FALSE;
535 memset(buf, 0, sizeof(buf));
538 ev->status = BT_STATUS_SUCCESS;
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")) {
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);
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);
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);
566 } else if (!g_strcmp0(key, "Discoverable")) {
567 discoverable = g_variant_get_boolean(value);
568 DBG("Discoverable [%d]", 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);
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);
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);
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);
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);
612 } else if (!g_strcmp0(key, "UUIDs")) {
617 size1 = g_variant_get_size(value);
618 int num_props_tmp = ev->num_props;
620 uuid_value = (char **)g_variant_get_strv(value, &size1);
621 for (i = 0; uuid_value[i] != NULL; i++)
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);
634 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_UUIDS,
635 (HAL_UUID_LEN * uuid_count),
637 ev->num_props = num_props_tmp + 1;
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);
654 } else if (!g_strcmp0(key, "SupportedLEFeatures")) {
655 DBG("LE Supported features");
658 GVariantIter *iter = NULL;
659 uint8_t le_features[8];
660 gboolean le_features_present = FALSE;
662 g_variant_get(value, "as", &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;
671 g_variant_iter_free(iter);
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);
678 DBG("le supported features values are NOT provided by Stack");
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);
688 ERR("Unhandled Property:[%s]", key);
692 if (scan_mode_property_update) {
693 size += __bt_insert_hal_properties(buf + size,
694 HAL_PROP_ADAPTER_SCAN_MODE, sizeof(int), &scan_mode);
699 event_cb = _bt_get_adapter_event_cb();
701 ERR("event_cb is NULL");
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);
711 g_variant_unref(result);
715 static int __bt_hal_dbus_get_all_adapter_properties(void)
719 GError *error = NULL;
723 proxy = _bt_hal_get_adapter_properties_proxy();
725 DBG("Adapter Properties proxy get failed!!!");
726 return BT_STATUS_FAIL;
729 result = g_dbus_proxy_call_sync(proxy,
731 g_variant_new("(s)", BT_HAL_ADAPTER_INTERFACE),
732 G_DBUS_CALL_FLAGS_NONE,
739 ERR("Failed to get all adapter properties (Error: %s)", error->message);
740 g_clear_error(&error);
742 ERR("Failed to get all adapter properties");
743 return BT_STATUS_FAIL;
746 DBG("Got All properties from Bluez Stack!!, time to start parsing");
748 * As we need to provide async callback to user from HAL, simply schedule a
749 * callback method which will carry actual result
751 g_idle_add(__bt_adapter_all_properties_cb, (gpointer)result);
754 return BT_STATUS_SUCCESS;
757 int _bt_hal_dbus_get_adapter_properties(void)
761 return __bt_hal_dbus_get_all_adapter_properties();
764 int _bt_hal_get_adapter_powered_state(uint8_t *state)
766 char *adapter_path = NULL;
767 gboolean powered = FALSE;
768 int ret = BT_STATUS_FAIL;
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();
774 if (adapter_path == NULL) {
775 INFO("Adapter is not powered");
776 g_free(adapter_path);
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);
798 /* Get Discoverable timeout API and callback */
799 static gboolean __bt_adapter_discovery_timeout_cb(gpointer user_data)
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;;
805 unsigned int *timeout = user_data;
807 memset(buf, 0, sizeof(buf));
810 ev->status = BT_STATUS_SUCCESS;
812 DBG("Discovery timeout in callback: [%d]", *timeout);
814 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_DISC_TIMEOUT,
815 sizeof(unsigned int), timeout);
818 DBG("Timeout value [%d] property Num [%d]", *timeout, ev->num_props);
821 event_cb = _bt_get_adapter_event_cb();
823 ERR("event_cb is NULL");
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);
837 int _bt_hal_dbus_get_discovery_timeout(void)
842 GError *error = NULL;
843 unsigned int *timeout;
846 proxy = _bt_hal_get_adapter_properties_proxy();
848 DBG("Adapter Properties proxy get failed!!!");
849 return BT_STATUS_FAIL;
852 result = g_dbus_proxy_call_sync(proxy,
854 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
855 "DiscoverableTimeout"),
856 G_DBUS_CALL_FLAGS_NONE,
863 ERR("Failed to get local version (Error: %s)", error->message);
864 g_clear_error(&error);
866 ERR("Failed to get local version");
867 return BT_STATUS_FAIL;
870 timeout = g_malloc0(sizeof(int));
872 ERR("Memory allocation failed");
873 g_variant_unref(result);
874 return BT_STATUS_FAIL;
877 g_variant_get(result, "(v)", &temp);
878 *timeout = g_variant_get_uint32(temp);
879 DBG("Timeout value: [%d]", *timeout);
881 g_variant_unref(result);
882 g_variant_unref(temp);
885 * As we need to provide async callback to user from HAL, simply schedule a
886 * callback method which will carry actual result
888 g_idle_add(__bt_adapter_discovery_timeout_cb, (gpointer) timeout);
891 return BT_STATUS_SUCCESS;
894 /* Get Discoverable Mode API and callback */
895 static gboolean __bt_adapter_scan_mode_cb(gpointer user_data)
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;;
901 int *mode = user_data;
903 memset(buf, 0, sizeof(buf));
906 ev->status = BT_STATUS_SUCCESS;
908 DBG("Scan mode callback: [%d]", *mode);
910 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_SCAN_MODE,
914 DBG("Scan mode [%d] property Num [%d]", *mode, ev->num_props);
917 event_cb = _bt_get_adapter_event_cb();
919 ERR("event_cb is NULL");
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);
933 int _bt_hal_dbus_get_scan_mode(void)
936 gboolean discoverable;
937 gboolean connectable;
940 GError *error = NULL;
945 proxy = _bt_hal_get_adapter_properties_proxy();
947 DBG("Adapter Properties proxy get failed!!!");
948 return BT_STATUS_FAIL;
951 result = g_dbus_proxy_call_sync(proxy,
953 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
955 G_DBUS_CALL_FLAGS_NONE,
962 ERR("Failed to get discoverable mode (Error: %s)", error->message);
963 g_clear_error(&error);
965 ERR("Failed to get discoverable mode");
966 return BT_STATUS_FAIL;
969 g_variant_get(result, "(v)", &temp);
970 discoverable = g_variant_get_boolean(temp);
971 DBG("discoverable:%d", discoverable);
973 g_variant_unref(result);
974 g_variant_unref(temp);
977 result = g_dbus_proxy_call_sync(proxy,
979 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
981 G_DBUS_CALL_FLAGS_NONE,
987 ERR("Failed to get connectable mode (Error: %s)", error->message);
988 g_clear_error(&error);
990 ERR("Failed to get connectable mode");
991 return BT_STATUS_FAIL;
994 g_variant_get(result, "(v)", &temp);
995 connectable = g_variant_get_boolean(temp);
996 DBG("connectable:%d", connectable);
998 g_variant_unref(result);
999 g_variant_unref(temp);
1002 scan_mode = g_malloc0(sizeof(int));
1004 ERR("Memory allocation failed");
1005 return BT_STATUS_FAIL;
1009 *scan_mode = BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
1010 else if (connectable)
1011 *scan_mode = BT_SCAN_MODE_CONNECTABLE;
1013 *scan_mode = BT_SCAN_MODE_NONE;
1016 * As we need to provide async callback to user from HAL, simply schedule a
1017 * callback method which will carry actual result
1019 g_idle_add(__bt_adapter_scan_mode_cb, (gpointer) scan_mode);
1022 return BT_STATUS_SUCCESS;
1025 /* Get Local Version API and callback */
1026 static gboolean __bt_adapter_local_version_cb(gpointer user_data)
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;;
1032 char *version = NULL;
1034 memset(buf, 0, sizeof(buf));
1037 ev->status = BT_STATUS_SUCCESS;
1039 version = (char*) user_data;
1040 DBG("Local Version in callback: [%s]", version);
1042 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_VERSION,
1043 (strlen(version) + 1), version);
1046 DBG("Device version [%s] property Num [%d]", version, ev->num_props);
1049 event_cb = _bt_get_adapter_event_cb();
1051 ERR("event_cb is NULL");
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);
1065 int _bt_hal_dbus_get_local_version(void)
1068 const char *version = NULL;
1071 GError *error = NULL;
1074 proxy = _bt_hal_get_adapter_properties_proxy();
1076 DBG("Adapter Properties proxy get failed!!!");
1077 return BT_STATUS_FAIL;
1080 result = g_dbus_proxy_call_sync(proxy,
1082 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1084 G_DBUS_CALL_FLAGS_NONE,
1090 if (error != NULL) {
1091 ERR("Failed to get local version (Error: %s)", error->message);
1092 g_clear_error(&error);
1094 ERR("Failed to get local version");
1095 return BT_STATUS_FAIL;
1098 g_variant_get(result, "(v)", &temp);
1099 version = g_variant_dup_string(temp, NULL);
1100 DBG("Local Version: [%s]", version);
1102 g_variant_unref(result);
1103 g_variant_unref(temp);
1106 * As we need to provide async callback to user from HAL, simply schedule a
1107 * callback method which will carry actual result
1109 g_idle_add(__bt_adapter_local_version_cb, (gpointer) version);
1112 return BT_STATUS_SUCCESS;
1115 /* Get Local Name API and callback */
1116 static gboolean __bt_adapter_local_name_cb(gpointer user_data)
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;;
1124 memset(buf, 0, sizeof(buf));
1127 ev->status = BT_STATUS_SUCCESS;
1129 name = (char*) user_data;
1130 DBG("Local Name in callback: [%s]", name);
1132 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_NAME,
1133 strlen(name) + 1, name);
1136 DBG("Device name [%s] property Num [%d]", name, ev->num_props);
1139 event_cb = _bt_get_adapter_event_cb();
1141 ERR("event_cb is NULL");
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);
1155 int _bt_hal_dbus_get_local_name(void)
1158 const char *name = NULL;
1161 GError *error = NULL;
1164 proxy = _bt_hal_get_adapter_properties_proxy();
1166 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1167 return BT_STATUS_FAIL;
1170 result = g_dbus_proxy_call_sync(proxy,
1172 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1174 G_DBUS_CALL_FLAGS_NONE,
1180 if (error != NULL) {
1181 ERR("Failed to get local name (Error: %s)", error->message);
1182 g_clear_error(&error);
1184 ERR("Failed to get local name");
1185 return BT_STATUS_FAIL;
1188 g_variant_get(result, "(v)", &temp);
1189 name = g_variant_dup_string(temp, NULL);
1190 DBG("Local Name: [%s]", name);
1192 g_variant_unref(result);
1193 g_variant_unref(temp);
1196 * As we need to provide async callback to user from HAL, simply schedule a
1197 * callback method which will carry actual result
1199 g_idle_add(__bt_adapter_local_name_cb, (gpointer) name);
1202 return BT_STATUS_SUCCESS;
1205 /* Get Local Address API and callback */
1206 static gboolean __bt_adapter_local_address_cb(gpointer user_data)
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;
1212 char * address = NULL;
1214 memset(buf, 0, sizeof(buf));
1217 ev->status = BT_STATUS_SUCCESS;
1219 address = (char*) user_data;
1222 _bt_hal_convert_addr_string_to_type(bdaddr, address);
1224 size += __bt_insert_hal_properties(buf + size, HAL_PROP_DEVICE_ADDR,
1225 sizeof(bdaddr), bdaddr);
1228 DBG("Device address [%s] property Num [%d]", address, ev->num_props);
1230 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_ADDR,
1231 sizeof(bdaddr), bdaddr);
1234 event_cb = _bt_get_adapter_event_cb();
1236 ERR("event_cb is NULL");
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);
1250 int _bt_hal_dbus_get_local_address(void)
1253 GError *error = NULL;
1254 const char *address;
1260 proxy = _bt_hal_get_adapter_properties_proxy();
1262 DBG("_bt_hal_dbus_get_local_address: Adapter Properties proxy get failed!!!");
1263 return BT_STATUS_FAIL;
1266 result = g_dbus_proxy_call_sync(proxy,
1268 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1270 G_DBUS_CALL_FLAGS_NONE,
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);
1281 return BT_STATUS_FAIL;
1284 g_variant_get(result, "(v)", &temp);
1285 address = g_variant_dup_string(temp, NULL);
1288 DBG("Address:%s", address);
1290 return BT_STATUS_FAIL;
1292 g_variant_unref(result);
1293 g_variant_unref(temp);
1296 * As we need to provide async callback to user from HAL, simply schedule a
1297 * callback method which will carry actual result
1299 g_idle_add(__bt_adapter_local_address_cb, (gpointer) address);
1302 return BT_STATUS_SUCCESS;
1305 /* Get Local services API and callback */
1306 static gboolean __bt_adapter_service_uuids_cb(gpointer user_data)
1308 GVariant *result = user_data;
1310 GVariantIter *iter = NULL;
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;
1318 /* UUID collection */
1319 uint8_t uuids[HAL_UUID_LEN * MAX_UUID_COUNT];
1322 memset(buf, 0, sizeof(buf));
1325 ev->status = BT_STATUS_SUCCESS;
1327 g_variant_get(result, "(v)", &temp);
1328 g_variant_get(temp, "as", &iter);
1330 ERR("Failed to get UUIDs");
1334 while (g_variant_iter_loop(iter, "s", &uuid_str)) {
1335 uint8_t uuid[HAL_UUID_LEN];
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);
1343 size += __bt_insert_hal_properties(buf + size,
1344 HAL_PROP_ADAPTER_UUIDS,
1345 (HAL_UUID_LEN * uuid_count),
1350 event_cb = _bt_get_adapter_event_cb();
1352 ERR("event_cb is NULL");
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);
1362 g_variant_iter_free(iter);
1363 g_variant_unref(result);
1364 g_variant_unref(temp);
1368 event_cb = _bt_get_adapter_event_cb();
1370 ev->status = BT_STATUS_FAIL;
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);
1377 g_variant_unref(result);
1381 int _bt_hal_dbus_get_adapter_supported_uuids(void)
1384 GError *error = NULL;
1389 proxy = _bt_hal_get_adapter_properties_proxy();
1392 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1393 return BT_STATUS_FAIL;
1396 result = g_dbus_proxy_call_sync(proxy,
1398 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1400 G_DBUS_CALL_FLAGS_NONE,
1406 if (error != NULL) {
1407 ERR("Failed to get UUIDs (Error: %s)", error->message);
1408 g_clear_error(&error);
1410 ERR("Failed to get UUIDs");
1411 return BT_STATUS_FAIL;
1415 DBG("Got All Adaptr service UUID's from Bluez Stack!!, time to start parsing");
1418 * As we need to provide async callback to user from HAL, simply schedule a
1419 * callback method which will carry actual result
1421 g_idle_add(__bt_adapter_service_uuids_cb, (gpointer)result);
1424 return BT_STATUS_SUCCESS;
1427 static gboolean __is_device_paired(GVariantIter *item_iter)
1429 gboolean paired = FALSE;
1433 while (g_variant_iter_loop(item_iter, "{sv}", &key, &value)) {
1434 if (NULL == key || g_strcmp0(key, "Paired"))
1437 paired = g_variant_get_boolean(value);
1438 g_variant_unref(value);
1446 static gboolean __bt_adapter_bonded_devices_cb(gpointer user_data)
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;;
1455 GVariant *result = user_data;
1457 GVariantIter *interface_iter;
1458 GVariantIter *svc_iter;
1459 char *object_path = NULL;
1460 char *interface_str = NULL;
1462 char device_address[BT_HAL_ADDRESS_STRING_SIZE];
1463 uint8_t bdaddr[BT_HAL_ADDRESS_LENGTH_MAX];
1465 memset(buf, 0, sizeof(buf));
1468 ev->status = BT_STATUS_SUCCESS;
1470 INFO("Size [%d]", size);
1472 /* signature of GetManagedObjects: a{oa{sa{sv}}} */
1473 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
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)
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);
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);
1493 g_variant_iter_free(svc_iter);
1494 g_free(interface_str);
1495 interface_str = NULL;
1501 g_variant_iter_free(iter);
1502 g_variant_unref(result);
1504 size += __bt_insert_hal_properties((buf + size),
1505 HAL_PROP_ADAPTER_BONDED_DEVICES,
1506 (count * BT_HAL_ADDRESS_LENGTH_MAX), addresses);
1510 event_cb = _bt_get_adapter_event_cb();
1512 ERR("event_cb is NULL");
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);
1525 int _bt_hal_dbus_get_bonded_devices(void)
1527 GDBusProxy *manager_proxy;
1528 GVariant *result = NULL;
1532 manager_proxy = _bt_hal_get_manager_proxy();
1533 if (manager_proxy == NULL)
1534 return BT_STATUS_FAIL;
1536 result = g_dbus_proxy_call_sync(manager_proxy, "GetManagedObjects",
1538 G_DBUS_CALL_FLAGS_NONE,
1543 ERR("Can't get managed objects");
1544 return BT_STATUS_FAIL;
1548 * As we need to provide async callback to user from HAL, simply schedule a
1549 * callback method which will carry actual result
1551 g_idle_add(__bt_adapter_bonded_devices_cb, (gpointer) result);
1554 return BT_STATUS_SUCCESS;
1557 int _bt_hal_dbus_get_adapter_property(bt_property_type_t property_type)
1561 INFO("property_type: %d", property_type);
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();
1581 return BT_STATUS_UNSUPPORTED;
1587 static int __bt_hal_dbus_set_local_name(void *data)
1590 const char *name = data;
1592 GError *error = NULL;
1595 DBG("Local Name: [%s]", name);
1596 proxy = _bt_hal_get_adapter_properties_proxy();
1598 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1599 return BT_STATUS_FAIL;
1602 result = g_dbus_proxy_call_sync(proxy,
1604 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1605 "Alias", g_variant_new("s", name)),
1606 G_DBUS_CALL_FLAGS_NONE,
1611 if (error != NULL) {
1612 ERR("Failed to set local name (Error: %s)", error->message);
1613 g_clear_error(&error);
1615 ERR("Failed to set local name");
1616 return BT_STATUS_FAIL;
1618 g_variant_unref(result);
1621 return BT_STATUS_SUCCESS;
1624 static int __bt_hal_dbus_set_scan_mode(void *data)
1629 GError *error = NULL;
1634 DBG("Scan mode: [%d]", *mode);
1635 proxy = _bt_hal_get_adapter_properties_proxy();
1637 DBG("Adapter Properties proxy get failed!!!");
1638 return BT_STATUS_FAIL;
1642 case BT_SCAN_MODE_NONE:
1646 case BT_SCAN_MODE_CONNECTABLE:
1650 case BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
1655 ERR("Invalid scan mode");
1656 return BT_STATUS_FAIL;
1659 result = g_dbus_proxy_call_sync(proxy,
1661 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1662 "Connectable", g_variant_new("b", pg_scan)),
1663 G_DBUS_CALL_FLAGS_NONE,
1668 if (error != NULL) {
1669 ERR("Failed to set connectable property (Error: %s)", error->message);
1670 g_clear_error(&error);
1672 ERR("Failed to set connectable property");
1673 return BT_STATUS_FAIL;
1675 g_variant_unref(result);
1677 result = g_dbus_proxy_call_sync(proxy,
1679 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE, "Discoverable",
1680 g_variant_new("b", inq_scan)),
1681 G_DBUS_CALL_FLAGS_NONE,
1686 if (error != NULL) {
1687 ERR("Failed to set Discoverable property (Error: %s)", error->message);
1688 g_clear_error(&error);
1690 ERR("Failed to set Discoverable property");
1691 return BT_STATUS_FAIL;
1693 g_variant_unref(result);
1696 return BT_STATUS_SUCCESS;
1699 static int __bt_hal_dbus_set_discovery_timeout(void *data)
1702 unsigned int *timeout = data;
1704 GError *error = NULL;
1709 DBG("Discovery Timeout: [%d]", *timeout);
1710 proxy = _bt_hal_get_adapter_properties_proxy();
1712 DBG("Adapter Properties proxy get failed!!!");
1713 return BT_STATUS_FAIL;
1716 result = g_dbus_proxy_call_sync(proxy,
1718 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1719 "DiscoverableTimeout", g_variant_new("u", *timeout)),
1720 G_DBUS_CALL_FLAGS_NONE,
1725 if (error != NULL) {
1726 ERR("Failed to set DiscoverableTimeout property (Error: %s)", error->message);
1727 g_clear_error(&error);
1729 ERR("Failed to set DiscoverableTimeout property");
1730 return BT_STATUS_FAIL;
1732 g_variant_unref(result);
1735 return BT_STATUS_SUCCESS;
1738 /* Set Adapter Properties */
1739 int _bt_hal_dbus_set_adapter_property(const bt_property_t *property)
1745 if (property == NULL || property->val == NULL) {
1746 ERR("Invalid parameters received");
1747 return BT_STATUS_FAIL;
1750 switch (property->type) {
1751 case BT_PROPERTY_BDNAME:
1752 result = __bt_hal_dbus_set_local_name(property->val);
1754 case BT_PROPERTY_ADAPTER_SCAN_MODE:
1755 result = __bt_hal_dbus_set_scan_mode(property->val);
1757 case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
1758 result = __bt_hal_dbus_set_discovery_timeout(property->val);
1761 result = BT_STATUS_UNSUPPORTED;
1764 DBG("Result= [%d]", result);