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"
36 #include "bt-hal-adapter-le.h"
38 #include <bt-hal-adapter-dbus-handler.h>
39 #include <bt-hal-dbus-common-utils.h>
41 #define BT_ENABLE_TIMEOUT 20000 /* 20 seconds */
42 #define BT_CORE_NAME "org.projectx.bt_core"
43 #define BT_CORE_PATH "/org/projectx/bt_core"
44 #define BT_CORE_INTERFACE "org.projectx.btcore"
46 static GDBusProxy *core_proxy = NULL;
47 static GDBusConnection *system_conn = NULL;
48 static handle_stack_msg event_cb = NULL;
50 handle_stack_msg _bt_get_adapter_event_cb(void)
58 GDBusConnection *__bt_hal_get_system_gconn(void)
61 if (system_conn == NULL)
62 system_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
68 GDBusProxy *_bt_init_core_proxy(void)
70 GDBusConnection *conn;
73 conn = __bt_hal_get_system_gconn();
77 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
93 static GDBusProxy *__bt_get_core_proxy(void)
95 return (core_proxy) ? core_proxy : _bt_init_core_proxy();
98 /* To send stack event to hal-bluetooth handler */
99 void _bt_hal_dbus_store_stack_msg_cb(handle_stack_msg cb)
104 int _bt_hal_enable_core(void)
109 GError *error = NULL;
111 proxy = __bt_get_core_proxy();
113 return BT_HAL_ERROR_INTERNAL;
115 /* Clean up the process */
116 result = g_dbus_proxy_call_sync(proxy,
119 G_DBUS_CALL_FLAGS_NONE,
126 ERR("Bt core call failed(Error: %s)", error->message);
127 g_clear_error(&error);
129 ERR("Bt core call failed");
130 return BT_HAL_ERROR_INTERNAL;
133 g_variant_unref(result);
134 return BT_HAL_ERROR_NONE;
137 static gboolean __bt_hal_send_adapter_event(gpointer user_data)
139 struct hal_ev_adapter_state_changed ev;
140 gboolean *enable = (gboolean *)user_data;
143 ev.state = HAL_POWER_ON;
145 ev.state = HAL_POWER_OFF;
148 event_cb = _bt_get_adapter_event_cb();
151 event_cb(HAL_EV_ADAPTER_STATE_CHANGED, &ev, sizeof(ev));
157 static gboolean __bt_hal_send_le_event(gpointer user_data)
159 struct hal_ev_le_state_changed ev;
160 gboolean *enable = (gboolean *)user_data;
163 ev.state = HAL_POWER_ON;
165 ev.state = HAL_POWER_OFF;
168 event_cb = _bt_get_adapter_event_cb();
171 event_cb(HAL_EV_LE_STATE_CHANGED, &ev, sizeof(ev));
178 int _bt_hal_dbus_enable_adapter(void)
181 GError *error = NULL;
182 GVariant *result = NULL;
183 unsigned char powered = 0;
187 int le_value = VCONFKEY_BT_LE_STATUS_OFF;
188 if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &le_value))
189 ERR("fail to get vconf key!");
191 if (_bt_hal_get_adapter_powered_state(&powered) == BT_STATUS_FAIL)
192 ERR("_bt_hal_get_adapter_powered_state failed");
194 /*if LE is enabled and bluez is UP , send event from here and return.*/
195 if ((le_value == VCONFKEY_BT_LE_STATUS_ON) && (powered == 1)) {
196 gboolean *user_data = g_new0(int, 1);
198 g_idle_add(__bt_hal_send_adapter_event, (gpointer)user_data);
199 return BT_STATUS_SUCCESS;
201 proxy = __bt_get_core_proxy();
204 DBG("_bt_hal_dbus_enable_adapter: Core proxy get failed!!!");
205 return BT_STATUS_FAIL;
208 _bt_hal_set_adapter_request_state(TRUE);
209 _bt_hal_set_le_request_state(TRUE);
210 result = g_dbus_proxy_call_sync(proxy, "EnableAdapter",
212 G_DBUS_CALL_FLAGS_NONE, BT_ENABLE_TIMEOUT,
215 DBG("EnableAdapter failed: %s", error->message);
216 g_clear_error(&error);
218 _bt_hal_set_adapter_request_state(FALSE);
219 _bt_hal_set_le_request_state(FALSE);
220 result = g_dbus_proxy_call_sync(proxy,
223 G_DBUS_CALL_FLAGS_NONE,
229 DBG("Bt core call failed(Error: %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;
244 int _bt_hal_dbus_disable_adapter(void)
247 GError *error = NULL;
248 GVariant *result = NULL;
251 proxy = __bt_get_core_proxy();
254 DBG("_bt_hal_dbus_enable_adapter: Core proxy get failed!!!");
255 return BT_STATUS_FAIL;
258 result = g_dbus_proxy_call_sync(proxy, "DisableAdapter",
260 G_DBUS_CALL_FLAGS_NONE, -1,
263 DBG("DisableAdapter failed: %s", error->message);
264 g_clear_error(&error);
266 g_variant_unref(result);
268 /* TODO: Terminate bluetooth service or not, need to check */
269 /*g_idle_add((GSourceFunc)_bt_terminate_service, NULL);*/
270 return BT_STATUS_FAIL;
274 g_variant_unref(result);
275 return BT_STATUS_SUCCESS;
278 int _bt_hal_dbus_recover_adapter(void)
281 GVariant *result = NULL;
282 GError *error = NULL;
285 proxy = __bt_get_core_proxy();
288 DBG("_bt_hal_dbus_recover_adapter: Core proxy get failed!!!");
289 return BT_STATUS_FAIL;
292 result = g_dbus_proxy_call_sync(proxy, "RecoverAdapter",
294 G_DBUS_CALL_FLAGS_NONE, -1,
297 DBG("RecoverAdapter failed: %s", error->message);
298 g_clear_error(&error);
300 return BT_STATUS_FAIL;
304 g_variant_unref(result);
305 return BT_STATUS_SUCCESS;
309 int _bt_hal_dbus_enable_le(void)
312 GError *error = NULL;
313 GVariant *result = NULL;
314 int adapter_value = VCONFKEY_BT_STATUS_OFF;
315 unsigned char powered = 0;
319 if (vconf_get_int(VCONFKEY_BT_STATUS, &adapter_value) != 0)
320 ERR("fail to get vconf key!");
322 if (_bt_hal_get_adapter_powered_state(&powered) == BT_STATUS_FAIL)
323 ERR("_bt_hal_get_adapter_powered_state failed");
325 if ((adapter_value == VCONFKEY_BT_STATUS_ON) && (powered == 1)) {
326 gboolean *user_data = g_new0(int, 1);
328 g_idle_add(__bt_hal_send_le_event, (gpointer)user_data);
329 return BT_STATUS_SUCCESS;
332 proxy = __bt_get_core_proxy();
335 DBG("_bt_hal_dbus_enable_le: Core proxy get failed!!!");
336 return BT_STATUS_FAIL;
338 _bt_hal_set_le_request_state(TRUE);
340 result = g_dbus_proxy_call_sync(proxy, "EnableAdapterLe",
342 G_DBUS_CALL_FLAGS_NONE, BT_ENABLE_TIMEOUT,
345 DBG("EnableAdapterLe failed: %s", error->message);
346 g_clear_error(&error);
348 result = g_dbus_proxy_call_sync(proxy,
351 G_DBUS_CALL_FLAGS_NONE,
356 _bt_hal_set_le_request_state(FALSE);
358 DBG("Bt core call failed(Error: %s)", error->message);
359 g_clear_error(&error);
361 g_variant_unref(result);
363 return BT_STATUS_FAIL;
367 g_variant_unref(result);
368 return BT_STATUS_SUCCESS;
371 int _bt_hal_dbus_disable_le(void)
374 GError *error = NULL;
375 GVariant *result = NULL;
376 int adapter_value = VCONFKEY_BT_STATUS_OFF;
379 if (vconf_get_int(VCONFKEY_BT_STATUS, &adapter_value) != 0)
380 ERR("fail to get vconf key!");
382 if (adapter_value == VCONFKEY_BT_STATUS_ON) {
383 gboolean *user_data = g_new0(int, 1);
385 g_idle_add(__bt_hal_send_le_event, (gpointer)user_data);
386 return BT_STATUS_SUCCESS;
389 proxy = __bt_get_core_proxy();
392 DBG("_bt_hal_dbus_disable_le: Core proxy get failed!!!");
393 return BT_STATUS_FAIL;
396 result = g_dbus_proxy_call_sync(proxy, "DisableAdapterLe",
398 G_DBUS_CALL_FLAGS_NONE, -1,
401 DBG("DisableAdapter failed: %s", error->message);
402 g_clear_error(&error);
404 g_variant_unref(result);
405 return BT_STATUS_FAIL;
411 g_variant_unref(result);
412 return BT_STATUS_SUCCESS;
417 int _bt_hal_dbus_reset_adapter(void)
421 GError *error = NULL;
424 proxy = __bt_get_core_proxy();
426 return BT_STATUS_FAIL;
428 result = g_dbus_proxy_call_sync(proxy,
431 G_DBUS_CALL_FLAGS_NONE,
438 ERR("Failed to ResetAdapter (Error: %s)", error->message);
439 g_clear_error(&error);
441 ERR("Failed to ResetAdapter");
442 return BT_STATUS_FAIL;
445 g_variant_unref(result);
446 return BT_STATUS_SUCCESS;
450 int _bt_hal_dbus_start_discovery(gboolean is_custom,
451 bt_disc_role_type_t role)
454 GError *error = NULL;
456 const gchar *disc_type;
457 DBG("Discovery Type: Is Custom : [%s]", is_custom ? "TRUE" : "FALSE");
459 proxy = _bt_hal_get_adapter_proxy();
461 DBG("Adapter proxy get failed!!!");
462 return BT_STATUS_FAIL;
466 if (role == BT_DISC_ROLE_BREDR)
468 else if (role == BT_DISC_ROLE_LE)
470 else if (role == BT_DISC_ROLE_DUAL)
471 disc_type = "LE_BREDR";
473 return BT_STATUS_PARM_INVALID;
475 result = g_dbus_proxy_call_sync(proxy,
476 "StartCustomDiscovery",
477 g_variant_new("s", disc_type),
478 G_DBUS_CALL_FLAGS_NONE,
483 result = g_dbus_proxy_call_sync(proxy,
486 G_DBUS_CALL_FLAGS_NONE,
493 ERR("StartDiscovery failed (Error: %s)", error->message);
494 g_clear_error(&error);
496 ERR("StartDiscovery failed");
497 return BT_STATUS_FAIL;
500 /* discovery status will be change in event */
502 g_variant_unref(result);
503 return BT_STATUS_SUCCESS;
506 int _bt_hal_dbus_stop_discovery(void)
509 GError *error = NULL;
513 proxy = _bt_hal_get_adapter_proxy();
515 DBG("_bt_hal_dbus_stop_discovery: Adapter proxy get failed!!!");
516 return BT_STATUS_FAIL;
519 result = g_dbus_proxy_call_sync(proxy,
522 G_DBUS_CALL_FLAGS_NONE,
529 ERR("StopDiscovery failed (Error: %s)", error->message);
530 g_clear_error(&error);
532 ERR("StopDiscovery failed");
533 return BT_STATUS_FAIL;
536 /* discovery status will be change in event */
538 g_variant_unref(result);
539 return BT_STATUS_SUCCESS;
542 static gboolean __bt_adapter_all_properties_cb(gpointer user_data)
544 GVariant *result = user_data;
545 GVariantIter *property_iter;
549 /* Buffer and propety count management */
550 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
551 struct hal_ev_adapter_props_changed *ev = (void*) buf;
553 gchar *address = NULL;
555 unsigned int cod = 0;
556 gboolean discoverable;
557 gboolean connectable;
558 unsigned int scan_mode = BT_SCAN_MODE_NONE;
559 unsigned int disc_timeout;
561 gboolean is_discovering;
562 gboolean is_le_discovering;
563 uint8_t ipsp_initialized;
566 unsigned int pairable_timeout;
567 gboolean scan_mode_property_update = FALSE;
571 memset(buf, 0, sizeof(buf));
574 ev->status = BT_STATUS_SUCCESS;
576 DBG("@@Start parsing properties");
577 g_variant_get(result, "(a{sv})", &property_iter);
578 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
579 if (!g_strcmp0(key, "Address")) {
582 address = (gchar *) g_variant_get_string(value, NULL);
583 DBG("Address [%s]", address);
584 _bt_hal_convert_addr_string_to_type(bdaddr, address);
585 size += __bt_insert_hal_properties(buf + size,
586 HAL_PROP_ADAPTER_ADDR, sizeof(bdaddr), bdaddr);
588 } else if (!g_strcmp0(key, "Alias")) {
589 name = (gchar *) g_variant_get_string(value, NULL);
590 DBG("Alias [%s]", name);
591 size += __bt_insert_hal_properties(buf + size,
592 HAL_PROP_ADAPTER_NAME, strlen(name) + 1, name);
594 } else if (!g_strcmp0(key, "Class")) {
595 cod = g_variant_get_uint32(value);
596 DBG("Class [%d]", cod);
597 size += __bt_insert_hal_properties(buf + size,
598 HAL_PROP_ADAPTER_CLASS, sizeof(unsigned int), &cod);
600 } else if (!g_strcmp0(key, "Discoverable")) {
601 discoverable = g_variant_get_boolean(value);
602 DBG("Discoverable [%d]", discoverable);
604 scan_mode = BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
605 scan_mode_property_update = TRUE;
606 } else if (!g_strcmp0(key, "DiscoverableTimeout")) {
607 disc_timeout = g_variant_get_uint32(value);
608 DBG("Discoverable Timeout [%d]", disc_timeout);
609 size += __bt_insert_hal_properties(buf + size,
610 HAL_PROP_ADAPTER_DISC_TIMEOUT, sizeof(unsigned int), &disc_timeout);
612 } else if (!g_strcmp0(key, "Connectable")) {
613 connectable = g_variant_get_boolean(value);
614 DBG("Connectable [%d]", connectable);
615 if (scan_mode == BT_SCAN_MODE_NONE)
616 scan_mode = BT_SCAN_MODE_CONNECTABLE;
617 scan_mode_property_update = TRUE;
618 } else if (!g_strcmp0(key, "Version")) {
619 version = (gchar *) g_variant_get_string(value, NULL);
620 DBG("Version [%s]", version);
621 size += __bt_insert_hal_properties(buf + size,
622 HAL_PROP_ADAPTER_VERSION, strlen(version) + 1, version);
624 } else if (!g_strcmp0(key, "Name")) {
625 name = (gchar *) g_variant_get_string(value, NULL);
626 DBG("Name [%s]", name);
627 size += __bt_insert_hal_properties(buf + size,
628 HAL_PROP_ADAPTER_NAME, strlen(name) + 1, name);
630 } else if (!g_strcmp0(key, "Powered")) {
631 powered = g_variant_get_boolean(value);
632 DBG("Powered = [%d]", powered);
633 } else if (!g_strcmp0(key, "Pairable")) {
634 pairable = (g_variant_get_boolean(value) ? 1 : 0);
635 DBG("Pairable [%d]", pairable);
636 size += __bt_insert_hal_properties(buf + size,
637 HAL_PROP_ADAPTER_PAIRABLE, sizeof(uint8_t), &pairable);
639 } else if (!g_strcmp0(key, "PairableTimeout")) {
640 pairable_timeout = g_variant_get_uint32(value);
641 DBG("Pairable Timeout = [%d]", pairable_timeout);
642 size += __bt_insert_hal_properties(buf + size,
643 HAL_PROP_ADAPTER_PAIRABLE_TIMEOUT, sizeof(unsigned int), &pairable_timeout);
645 } else if (!g_strcmp0(key, "UUIDs")) {
650 size1 = g_variant_get_size(value);
651 int num_props_tmp = ev->num_props;
653 uuid_value = (char **)g_variant_get_strv(value, &size1);
654 for (i = 0; uuid_value[i] != NULL; i++)
656 /* UUID collection */
657 uint8_t uuids[HAL_UUID_LEN * uuid_count];
658 for (i = 0; uuid_value[i] != NULL; i++) {
659 char *uuid_str = NULL;
660 uint8_t uuid[HAL_UUID_LEN];
661 uuid_str = g_strdup(uuid_value[i]);
662 DBG("UUID string [%s]\n", uuid_str);
663 _bt_hal_convert_uuid_string_to_type(uuid, uuid_str);
664 memcpy(uuids + i * HAL_UUID_LEN, uuid, HAL_UUID_LEN);
667 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_UUIDS,
668 (HAL_UUID_LEN * uuid_count),
670 ev->num_props = num_props_tmp + 1;
673 } else if (!g_strcmp0(key, "Discovering")) {
674 is_discovering = g_variant_get_boolean(value);
675 DBG("Discovering = [%d]", is_discovering);
676 } else if (!g_strcmp0(key, "LEDiscovering")) {
677 is_le_discovering = g_variant_get_boolean(value);
678 DBG("LE Discovering = [%d]", is_le_discovering);
679 } else if (!g_strcmp0(key, "Modalias")) {
680 char *modalias = NULL;
681 g_variant_get(value, "s", &modalias);
682 DBG("Adapter ModAlias [%s]", modalias);
683 size += __bt_insert_hal_properties(buf + size,
684 HAL_PROP_ADAPTER_MODALIAS, strlen(modalias) + 1, modalias);
687 } else if (!g_strcmp0(key, "SupportedLEFeatures")) {
688 DBG("LE Supported features");
691 GVariantIter *iter = NULL;
692 bt_local_le_features_t le_features;
693 gboolean le_features_present = FALSE;
695 memset(&le_features, 0x00, sizeof(le_features));
697 g_variant_get(value, "as", &iter);
699 while (g_variant_iter_loop(iter, "s", &name)) {
700 DBG("name = %s", name);
701 g_variant_iter_loop(iter, "s", &val);
702 DBG("Value = %s", val);
703 _bt_hal_update_le_feature_support(name, val, &le_features);
704 le_features_present = TRUE;
706 g_variant_iter_free(iter);
708 if (le_features_present) {
709 size += __bt_insert_hal_properties(buf + size,
710 HAL_PROP_ADAPTER_LOCAL_LE_FEAT, sizeof(le_features), &le_features);
713 DBG("le supported features values are NOT provided by Stack");
716 } else if (!g_strcmp0(key, "IpspInitStateChanged")) {
717 ipsp_initialized = (g_variant_get_boolean(value) ? 1 : 0);
718 DBG("IPSP Initialized = %d", ipsp_initialized);
719 size += __bt_insert_hal_properties(buf + size,
720 HAL_PROP_ADAPTER_IPSP_INITIALIZED, sizeof(uint8_t), &ipsp_initialized);
723 ERR("Unhandled Property:[%s]", key);
727 if (scan_mode_property_update) {
728 size += __bt_insert_hal_properties(buf + size,
729 HAL_PROP_ADAPTER_SCAN_MODE, sizeof(int), &scan_mode);
734 event_cb = _bt_get_adapter_event_cb();
736 ERR("event_cb is NULL");
741 DBG("Send Adapter properties changed event to HAL user,"
742 " Num Prop [%d] total size [%zd]", ev->num_props, size);
743 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
746 g_variant_unref(result);
750 static int __bt_hal_dbus_get_all_adapter_properties(void)
754 GError *error = NULL;
758 proxy = _bt_hal_get_adapter_properties_proxy();
760 DBG("Adapter Properties proxy get failed!!!");
761 return BT_STATUS_FAIL;
764 result = g_dbus_proxy_call_sync(proxy,
766 g_variant_new("(s)", BT_HAL_ADAPTER_INTERFACE),
767 G_DBUS_CALL_FLAGS_NONE,
774 ERR("Failed to get all adapter properties (Error: %s)", error->message);
775 g_clear_error(&error);
777 ERR("Failed to get all adapter properties");
778 return BT_STATUS_FAIL;
781 DBG("Got All properties from Bluez Stack!!, time to start parsing");
783 * As we need to provide async callback to user from HAL, simply schedule a
784 * callback method which will carry actual result
786 g_idle_add(__bt_adapter_all_properties_cb, (gpointer)result);
789 return BT_STATUS_SUCCESS;
792 int _bt_hal_dbus_get_adapter_properties(void)
796 return __bt_hal_dbus_get_all_adapter_properties();
799 int _bt_hal_get_adapter_powered_state(uint8_t *state)
801 char *adapter_path = NULL;
802 gboolean powered = FALSE;
803 int ret = BT_STATUS_FAIL;
805 /* Check Valid Adapter Path, followed by Adapter Powered state.
806 If any of these fails, adapter will be considered Disabled */
807 adapter_path = _bt_hal_get_adapter_path();
809 if (adapter_path == NULL) {
810 INFO("Adapter is not powered");
811 g_free(adapter_path);
816 /* Check Adapter Powered Status */
817 ret = _bt_hal_is_adapter_powered(&powered);
818 if (BT_STATUS_FAIL == ret) {
819 INFO("Adapter is not powered");
820 g_free(adapter_path);
833 /* Get Discoverable timeout API and callback */
834 static gboolean __bt_adapter_discovery_timeout_cb(gpointer user_data)
836 /* Buffer and propety count management */
837 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
838 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
840 unsigned int *timeout = user_data;
842 memset(buf, 0, sizeof(buf));
845 ev->status = BT_STATUS_SUCCESS;
847 DBG("Discovery timeout in callback: [%d]", *timeout);
849 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_DISC_TIMEOUT,
850 sizeof(unsigned int), timeout);
853 DBG("Timeout value [%d] property Num [%d]", *timeout, ev->num_props);
856 event_cb = _bt_get_adapter_event_cb();
858 ERR("event_cb is NULL");
863 DBG("Send Adapter Properties changed event to HAL user,"
864 " Num Prop [%d] total size [%zd]", ev->num_props, size);
865 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
872 int _bt_hal_dbus_get_discovery_timeout(void)
877 GError *error = NULL;
878 unsigned int *timeout;
881 proxy = _bt_hal_get_adapter_properties_proxy();
883 DBG("Adapter Properties proxy get failed!!!");
884 return BT_STATUS_FAIL;
887 result = g_dbus_proxy_call_sync(proxy,
889 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
890 "DiscoverableTimeout"),
891 G_DBUS_CALL_FLAGS_NONE,
898 ERR("Failed to get local version (Error: %s)", error->message);
899 g_clear_error(&error);
901 ERR("Failed to get local version");
902 return BT_STATUS_FAIL;
905 timeout = g_malloc0(sizeof(int));
907 ERR("Memory allocation failed");
908 g_variant_unref(result);
909 return BT_STATUS_FAIL;
912 g_variant_get(result, "(v)", &temp);
913 *timeout = g_variant_get_uint32(temp);
914 DBG("Timeout value: [%d]", *timeout);
916 g_variant_unref(result);
917 g_variant_unref(temp);
920 * As we need to provide async callback to user from HAL, simply schedule a
921 * callback method which will carry actual result
923 g_idle_add(__bt_adapter_discovery_timeout_cb, (gpointer) timeout);
926 return BT_STATUS_SUCCESS;
929 int _bt_hal_dbus_get_adapter_class(unsigned int *adapter_class)
934 GError *error = NULL;
937 proxy = _bt_hal_get_adapter_properties_proxy();
939 DBG("Adapter Properties proxy get failed!!!");
940 return BT_STATUS_FAIL;
943 result = g_dbus_proxy_call_sync(proxy,
945 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
947 G_DBUS_CALL_FLAGS_NONE,
954 ERR("Failed to get class (Error: %s)", error->message);
955 g_clear_error(&error);
957 ERR("Failed to get class");
958 return BT_STATUS_FAIL;
962 g_variant_get(result, "(v)", &temp);
963 *adapter_class = g_variant_get_uint32(temp);
964 DBG("Class value: [0x%06x]", *adapter_class);
966 g_variant_unref(result);
967 g_variant_unref(temp);
970 return BT_STATUS_SUCCESS;
973 /* Get Discoverable Mode API and callback */
974 static gboolean __bt_adapter_scan_mode_cb(gpointer user_data)
976 /* Buffer and propety count management */
977 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
978 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
980 int *mode = user_data;
982 memset(buf, 0, sizeof(buf));
985 ev->status = BT_STATUS_SUCCESS;
987 DBG("Scan mode callback: [%d]", *mode);
989 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_SCAN_MODE,
993 DBG("Scan mode [%d] property Num [%d]", *mode, ev->num_props);
996 event_cb = _bt_get_adapter_event_cb();
998 ERR("event_cb is NULL");
1003 DBG("Send Adapter Properties changed event to HAL user,"
1004 " Num Prop [%d] total size [%zd]", ev->num_props, size);
1005 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1012 int _bt_hal_dbus_get_scan_mode(void)
1015 gboolean discoverable;
1016 gboolean connectable;
1019 GError *error = NULL;
1024 proxy = _bt_hal_get_adapter_properties_proxy();
1026 DBG("Adapter Properties proxy get failed!!!");
1027 return BT_STATUS_FAIL;
1030 result = g_dbus_proxy_call_sync(proxy,
1032 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1034 G_DBUS_CALL_FLAGS_NONE,
1040 if (error != NULL) {
1041 ERR("Failed to get discoverable mode (Error: %s)", error->message);
1042 g_clear_error(&error);
1044 ERR("Failed to get discoverable mode");
1045 return BT_STATUS_FAIL;
1048 g_variant_get(result, "(v)", &temp);
1049 discoverable = g_variant_get_boolean(temp);
1050 DBG("discoverable:%d", discoverable);
1052 g_variant_unref(result);
1053 g_variant_unref(temp);
1055 if (!discoverable) {
1056 result = g_dbus_proxy_call_sync(proxy,
1058 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1060 G_DBUS_CALL_FLAGS_NONE,
1065 if (error != NULL) {
1066 ERR("Failed to get connectable mode (Error: %s)", error->message);
1067 g_clear_error(&error);
1069 ERR("Failed to get connectable mode");
1070 return BT_STATUS_FAIL;
1073 g_variant_get(result, "(v)", &temp);
1074 connectable = g_variant_get_boolean(temp);
1075 DBG("connectable:%d", connectable);
1077 g_variant_unref(result);
1078 g_variant_unref(temp);
1081 scan_mode = g_malloc0(sizeof(int));
1083 ERR("Memory allocation failed");
1084 return BT_STATUS_FAIL;
1088 *scan_mode = BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
1089 else if (connectable)
1090 *scan_mode = BT_SCAN_MODE_CONNECTABLE;
1092 *scan_mode = BT_SCAN_MODE_NONE;
1095 * As we need to provide async callback to user from HAL, simply schedule a
1096 * callback method which will carry actual result
1098 g_idle_add(__bt_adapter_scan_mode_cb, (gpointer) scan_mode);
1101 return BT_STATUS_SUCCESS;
1104 /* Get Local Version API and callback */
1105 static gboolean __bt_adapter_local_version_cb(gpointer user_data)
1107 /* Buffer and propety count management */
1108 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1109 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1111 char *version = NULL;
1113 memset(buf, 0, sizeof(buf));
1116 ev->status = BT_STATUS_SUCCESS;
1118 version = (char*) user_data;
1119 DBG("Local Version in callback: [%s]", version);
1121 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_VERSION,
1122 (strlen(version) + 1), version);
1125 DBG("Device version [%s] property Num [%d]", version, ev->num_props);
1128 event_cb = _bt_get_adapter_event_cb();
1130 ERR("event_cb is NULL");
1135 DBG("Send Adapter Properties changed event to HAL user,"
1136 " Num Prop [%d] total size [%zd]", ev->num_props, size);
1137 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1144 int _bt_hal_dbus_get_local_version(void)
1147 const char *version = NULL;
1150 GError *error = NULL;
1153 proxy = _bt_hal_get_adapter_properties_proxy();
1155 DBG("Adapter Properties proxy get failed!!!");
1156 return BT_STATUS_FAIL;
1159 result = g_dbus_proxy_call_sync(proxy,
1161 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1163 G_DBUS_CALL_FLAGS_NONE,
1169 if (error != NULL) {
1170 ERR("Failed to get local version (Error: %s)", error->message);
1171 g_clear_error(&error);
1173 ERR("Failed to get local version");
1174 return BT_STATUS_FAIL;
1177 g_variant_get(result, "(v)", &temp);
1178 version = g_variant_dup_string(temp, NULL);
1179 DBG("Local Version: [%s]", version);
1181 g_variant_unref(result);
1182 g_variant_unref(temp);
1185 * As we need to provide async callback to user from HAL, simply schedule a
1186 * callback method which will carry actual result
1188 g_idle_add(__bt_adapter_local_version_cb, (gpointer) version);
1191 return BT_STATUS_SUCCESS;
1194 /* Get Local Name API and callback */
1195 static gboolean __bt_adapter_local_name_cb(gpointer user_data)
1197 /* Buffer and propety count management */
1198 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1199 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1203 memset(buf, 0, sizeof(buf));
1206 ev->status = BT_STATUS_SUCCESS;
1208 name = (char*) user_data;
1209 DBG("Local Name in callback: [%s]", name);
1211 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_NAME,
1212 strlen(name) + 1, name);
1215 DBG("Device name [%s] property Num [%d]", name, ev->num_props);
1218 event_cb = _bt_get_adapter_event_cb();
1220 ERR("event_cb is NULL");
1225 DBG("Send Adapter Properties changed event to HAL user,"
1226 " Num Prop [%d] total size [%zd]", ev->num_props, size);
1227 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1234 int _bt_hal_dbus_get_local_name(void)
1237 const char *name = NULL;
1240 GError *error = NULL;
1243 proxy = _bt_hal_get_adapter_properties_proxy();
1245 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1246 return BT_STATUS_FAIL;
1249 result = g_dbus_proxy_call_sync(proxy,
1251 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1253 G_DBUS_CALL_FLAGS_NONE,
1259 if (error != NULL) {
1260 ERR("Failed to get local name (Error: %s)", error->message);
1261 g_clear_error(&error);
1263 ERR("Failed to get local name");
1264 return BT_STATUS_FAIL;
1267 g_variant_get(result, "(v)", &temp);
1268 name = g_variant_dup_string(temp, NULL);
1269 DBG("Local Name: [%s]", name);
1271 g_variant_unref(result);
1272 g_variant_unref(temp);
1275 * As we need to provide async callback to user from HAL, simply schedule a
1276 * callback method which will carry actual result
1278 g_idle_add(__bt_adapter_local_name_cb, (gpointer) name);
1281 return BT_STATUS_SUCCESS;
1284 /* Get Local Address API and callback */
1285 static gboolean __bt_adapter_local_address_cb(gpointer user_data)
1287 /* Buffer and propety count management */
1288 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1289 struct hal_ev_adapter_props_changed *ev = (void*) buf;
1291 char * address = NULL;
1293 memset(buf, 0, sizeof(buf));
1296 ev->status = BT_STATUS_SUCCESS;
1298 address = (char*) user_data;
1301 _bt_hal_convert_addr_string_to_type(bdaddr, address);
1303 size += __bt_insert_hal_properties(buf + size, HAL_PROP_DEVICE_ADDR,
1304 sizeof(bdaddr), bdaddr);
1307 DBG("Device address [%s] property Num [%d]", address, ev->num_props);
1309 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_ADDR,
1310 sizeof(bdaddr), bdaddr);
1313 event_cb = _bt_get_adapter_event_cb();
1315 ERR("event_cb is NULL");
1320 DBG("Send Device found event to HAL user,"
1321 " Num Prop [%d] total size [%zd]", ev->num_props, size);
1322 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1329 int _bt_hal_dbus_get_local_address(void)
1332 GError *error = NULL;
1333 const char *address;
1339 proxy = _bt_hal_get_adapter_properties_proxy();
1341 DBG("_bt_hal_dbus_get_local_address: Adapter Properties proxy get failed!!!");
1342 return BT_STATUS_FAIL;
1345 result = g_dbus_proxy_call_sync(proxy,
1347 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1349 G_DBUS_CALL_FLAGS_NONE,
1355 ERR("Failed to get local address");
1356 if (error != NULL) {
1357 ERR("Failed to get local address (Error: %s)", error->message);
1358 g_clear_error(&error);
1360 return BT_STATUS_FAIL;
1363 g_variant_get(result, "(v)", &temp);
1364 address = g_variant_dup_string(temp, NULL);
1367 DBG("Address:%s", address);
1369 return BT_STATUS_FAIL;
1371 g_variant_unref(result);
1372 g_variant_unref(temp);
1375 * As we need to provide async callback to user from HAL, simply schedule a
1376 * callback method which will carry actual result
1378 g_idle_add(__bt_adapter_local_address_cb, (gpointer) address);
1381 return BT_STATUS_SUCCESS;
1384 /* Get Local services API and callback */
1385 static gboolean __bt_adapter_service_uuids_cb(gpointer user_data)
1387 GVariant *result = user_data;
1389 GVariantIter *iter = NULL;
1392 /* Buffer and propety count management */
1393 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1394 struct hal_ev_adapter_props_changed *ev = (void*) buf;
1397 /* UUID collection */
1398 uint8_t uuids[HAL_UUID_LEN * MAX_UUID_COUNT];
1401 memset(buf, 0, sizeof(buf));
1404 ev->status = BT_STATUS_SUCCESS;
1406 g_variant_get(result, "(v)", &temp);
1407 g_variant_get(temp, "as", &iter);
1409 ERR("Failed to get UUIDs");
1413 while (g_variant_iter_loop(iter, "s", &uuid_str)) {
1414 uint8_t uuid[HAL_UUID_LEN];
1416 DBG("UUID string [%s]\n", uuid_str);
1417 _bt_hal_convert_uuid_string_to_type(uuid, uuid_str);
1418 memcpy(uuids + uuid_count * HAL_UUID_LEN, uuid, HAL_UUID_LEN);
1422 size += __bt_insert_hal_properties(buf + size,
1423 HAL_PROP_ADAPTER_UUIDS,
1424 (HAL_UUID_LEN * uuid_count),
1429 event_cb = _bt_get_adapter_event_cb();
1431 ERR("event_cb is NULL");
1436 DBG("Send Adapter properties changed event to HAL user,"
1437 " Num Prop [%d] total size [%zd]", ev->num_props, size);
1438 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1441 g_variant_iter_free(iter);
1442 g_variant_unref(result);
1443 g_variant_unref(temp);
1447 event_cb = _bt_get_adapter_event_cb();
1449 ev->status = BT_STATUS_FAIL;
1451 DBG("Send Adapter properties changed event to HAL user,"
1452 " Num Prop [%d] total size [%zd]", ev->num_props, size);
1453 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1456 g_variant_unref(result);
1460 int _bt_hal_dbus_get_adapter_supported_uuids(void)
1463 GError *error = NULL;
1468 proxy = _bt_hal_get_adapter_properties_proxy();
1471 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1472 return BT_STATUS_FAIL;
1475 result = g_dbus_proxy_call_sync(proxy,
1477 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1479 G_DBUS_CALL_FLAGS_NONE,
1485 if (error != NULL) {
1486 ERR("Failed to get UUIDs (Error: %s)", error->message);
1487 g_clear_error(&error);
1489 ERR("Failed to get UUIDs");
1490 return BT_STATUS_FAIL;
1494 DBG("Got All Adaptr service UUID's from Bluez Stack!!, time to start parsing");
1497 * As we need to provide async callback to user from HAL, simply schedule a
1498 * callback method which will carry actual result
1500 g_idle_add(__bt_adapter_service_uuids_cb, (gpointer)result);
1503 return BT_STATUS_SUCCESS;
1506 static gboolean __is_device_paired(GVariantIter *item_iter)
1508 gboolean paired = FALSE;
1512 while (g_variant_iter_loop(item_iter, "{sv}", &key, &value)) {
1513 if (NULL == key || g_strcmp0(key, "Paired"))
1516 paired = g_variant_get_boolean(value);
1517 g_variant_unref(value);
1525 static gboolean __bt_adapter_bonded_devices_cb(gpointer user_data)
1527 /* Buffer and propety count management */
1528 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1529 uint8_t addresses[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1530 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1534 GVariant *result = user_data;
1536 GVariantIter *interface_iter;
1537 GVariantIter *svc_iter;
1538 char *object_path = NULL;
1539 char *interface_str = NULL;
1541 char device_address[BT_HAL_ADDRESS_STRING_SIZE];
1542 uint8_t bdaddr[BT_HAL_ADDRESS_LENGTH_MAX];
1544 memset(buf, 0, sizeof(buf));
1547 ev->status = BT_STATUS_SUCCESS;
1549 INFO("Size [%zd]", size);
1551 /* signature of GetManagedObjects: a{oa{sa{sv}}} */
1552 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
1554 /* Parse the signature: {oa{sa{sv}}} */
1555 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path, &interface_iter)) {
1556 if (object_path == NULL)
1559 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
1560 &interface_str, &svc_iter)) {
1561 if (g_strcmp0(interface_str, "org.bluez.Device1") == 0) {
1562 DBG("Found a device: %s", object_path);
1563 if (__is_device_paired(svc_iter)) {
1564 _bt_hal_convert_device_path_to_address(object_path, device_address);
1565 DBG("Paired Device Address: [%s]", device_address);
1567 _bt_hal_convert_addr_string_to_type(bdaddr, device_address);
1568 memcpy((addresses + (count * BT_HAL_ADDRESS_LENGTH_MAX)),
1569 bdaddr, BT_HAL_ADDRESS_LENGTH_MAX);
1572 g_variant_iter_free(svc_iter);
1573 g_free(interface_str);
1574 interface_str = NULL;
1580 g_variant_iter_free(iter);
1581 g_variant_unref(result);
1583 size += __bt_insert_hal_properties((buf + size),
1584 HAL_PROP_ADAPTER_BONDED_DEVICES,
1585 (count * BT_HAL_ADDRESS_LENGTH_MAX), addresses);
1589 event_cb = _bt_get_adapter_event_cb();
1591 ERR("event_cb is NULL");
1596 DBG("Send Adapter properties changed event to HAL user,"
1597 " Num Prop [%d] total size [%zd]", ev->num_props, size);
1598 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1604 int _bt_hal_dbus_get_bonded_devices(void)
1606 GDBusProxy *manager_proxy;
1607 GVariant *result = NULL;
1611 manager_proxy = _bt_hal_get_manager_proxy();
1612 if (manager_proxy == NULL)
1613 return BT_STATUS_FAIL;
1615 result = g_dbus_proxy_call_sync(manager_proxy, "GetManagedObjects",
1617 G_DBUS_CALL_FLAGS_NONE,
1622 ERR("Can't get managed objects");
1623 return BT_STATUS_FAIL;
1627 * As we need to provide async callback to user from HAL, simply schedule a
1628 * callback method which will carry actual result
1630 g_idle_add(__bt_adapter_bonded_devices_cb, (gpointer) result);
1633 return BT_STATUS_SUCCESS;
1636 int _bt_hal_dbus_get_adapter_property(bt_property_type_t property_type)
1640 INFO("property_type: %d", property_type);
1642 switch (property_type) {
1643 case BT_PROPERTY_BDADDR:
1644 return _bt_hal_dbus_get_local_address();
1645 case BT_PROPERTY_BDNAME:
1646 return _bt_hal_dbus_get_local_name();
1647 case BT_PROPERTY_VERSION:
1648 return _bt_hal_dbus_get_local_version();
1649 case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
1650 return _bt_hal_dbus_get_discovery_timeout();
1651 case BT_PROPERTY_ADAPTER_SCAN_MODE:
1652 return _bt_hal_dbus_get_scan_mode();
1653 case BT_PROPERTY_CLASS_OF_DEVICE:
1654 return BT_STATUS_UNSUPPORTED;
1655 case BT_PROPERTY_UUIDS:
1656 return _bt_hal_dbus_get_adapter_supported_uuids();
1657 case BT_PROPERTY_ADAPTER_BONDED_DEVICES:
1658 return _bt_hal_dbus_get_bonded_devices();
1660 return BT_STATUS_UNSUPPORTED;
1666 static int __bt_hal_dbus_set_local_name(void *data)
1669 const char *name = data;
1671 GError *error = NULL;
1674 DBG("Local Name: [%s]", name);
1675 proxy = _bt_hal_get_adapter_properties_proxy();
1677 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1678 return BT_STATUS_FAIL;
1681 result = g_dbus_proxy_call_sync(proxy,
1683 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1684 "Alias", g_variant_new("s", name)),
1685 G_DBUS_CALL_FLAGS_NONE,
1690 if (error != NULL) {
1691 ERR("Failed to set local name (Error: %s)", error->message);
1692 g_clear_error(&error);
1694 ERR("Failed to set local name");
1695 return BT_STATUS_FAIL;
1697 g_variant_unref(result);
1700 return BT_STATUS_SUCCESS;
1703 static int __bt_hal_dbus_set_scan_mode(void *data)
1708 GError *error = NULL;
1713 DBG("Scan mode: [%d]", *mode);
1714 proxy = _bt_hal_get_adapter_properties_proxy();
1716 DBG("Adapter Properties proxy get failed!!!");
1717 return BT_STATUS_FAIL;
1721 case BT_SCAN_MODE_NONE:
1725 case BT_SCAN_MODE_CONNECTABLE:
1729 case BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
1734 ERR("Invalid scan mode");
1735 return BT_STATUS_FAIL;
1738 result = g_dbus_proxy_call_sync(proxy,
1740 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1741 "Connectable", g_variant_new("b", pg_scan)),
1742 G_DBUS_CALL_FLAGS_NONE,
1747 if (error != NULL) {
1748 ERR("Failed to set connectable property (Error: %s)", error->message);
1749 g_clear_error(&error);
1751 ERR("Failed to set connectable property");
1752 return BT_STATUS_FAIL;
1754 g_variant_unref(result);
1756 result = g_dbus_proxy_call_sync(proxy,
1758 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE, "Discoverable",
1759 g_variant_new("b", inq_scan)),
1760 G_DBUS_CALL_FLAGS_NONE,
1765 if (error != NULL) {
1766 ERR("Failed to set Discoverable property (Error: %s)", error->message);
1767 g_clear_error(&error);
1769 ERR("Failed to set Discoverable property");
1770 return BT_STATUS_FAIL;
1772 g_variant_unref(result);
1775 return BT_STATUS_SUCCESS;
1778 static int __bt_hal_dbus_set_discovery_timeout(void *data)
1781 unsigned int *timeout = data;
1783 GError *error = NULL;
1788 DBG("Discovery Timeout: [%d]", *timeout);
1789 proxy = _bt_hal_get_adapter_properties_proxy();
1791 DBG("Adapter Properties proxy get failed!!!");
1792 return BT_STATUS_FAIL;
1795 result = g_dbus_proxy_call_sync(proxy,
1797 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1798 "DiscoverableTimeout", g_variant_new("u", *timeout)),
1799 G_DBUS_CALL_FLAGS_NONE,
1804 if (error != NULL) {
1805 ERR("Failed to set DiscoverableTimeout property (Error: %s)", error->message);
1806 g_clear_error(&error);
1808 ERR("Failed to set DiscoverableTimeout property");
1809 return BT_STATUS_FAIL;
1811 g_variant_unref(result);
1814 return BT_STATUS_SUCCESS;
1817 /* Set Adapter Properties */
1818 int _bt_hal_dbus_set_adapter_property(const bt_property_t *property)
1824 if (property == NULL || property->val == NULL) {
1825 ERR("Invalid parameters received");
1826 return BT_STATUS_FAIL;
1829 switch (property->type) {
1830 case BT_PROPERTY_BDNAME:
1831 result = __bt_hal_dbus_set_local_name(property->val);
1833 case BT_PROPERTY_ADAPTER_SCAN_MODE:
1834 result = __bt_hal_dbus_set_scan_mode(property->val);
1836 case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
1837 result = __bt_hal_dbus_set_discovery_timeout(property->val);
1840 result = BT_STATUS_UNSUPPORTED;
1843 DBG("Result= [%d]", result);