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 static gboolean __bt_hal_send_adapter_event(gpointer user_data)
106 struct hal_ev_adapter_state_changed ev;
107 gboolean *enable = (gboolean *)user_data;
110 ev.state = HAL_POWER_ON;
112 ev.state = HAL_POWER_OFF;
115 event_cb = _bt_get_adapter_event_cb();
118 event_cb(HAL_EV_ADAPTER_STATE_CHANGED, &ev, sizeof(ev));
124 static gboolean __bt_hal_send_le_event(gpointer user_data)
126 struct hal_ev_le_state_changed ev;
127 gboolean *enable = (gboolean *)user_data;
130 ev.state = HAL_POWER_ON;
132 ev.state = HAL_POWER_OFF;
135 event_cb = _bt_get_adapter_event_cb();
138 event_cb(HAL_EV_LE_STATE_CHANGED, &ev, sizeof(ev));
145 int _bt_hal_dbus_enable_adapter(void)
148 GError *error = NULL;
149 GVariant *result = NULL;
150 unsigned char powered = 0;
154 int le_value = VCONFKEY_BT_LE_STATUS_OFF;
155 if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &le_value))
156 ERR("fail to get vconf key!");
158 if (_bt_hal_get_adapter_powered_state(&powered) == BT_STATUS_FAIL)
159 ERR("_bt_hal_get_adapter_powered_state failed");
161 /*if LE is enabled and bluez is UP , send event from here and return.*/
162 if ((le_value == VCONFKEY_BT_LE_STATUS_ON) && (powered == 1)) {
163 gboolean *user_data = g_new0(int, 1);
165 g_idle_add(__bt_hal_send_adapter_event, (gpointer)user_data);
166 return BT_STATUS_SUCCESS;
168 proxy = __bt_get_core_proxy();
171 DBG("_bt_hal_dbus_enable_adapter: Core proxy get failed!!!");
172 return BT_STATUS_FAIL;
175 _bt_hal_set_adapter_request_state(TRUE);
176 _bt_hal_set_le_request_state(TRUE);
177 result = g_dbus_proxy_call_sync(proxy, "EnableAdapter",
179 G_DBUS_CALL_FLAGS_NONE, BT_ENABLE_TIMEOUT,
182 DBG("EnableAdapter failed: %s", error->message);
183 g_clear_error(&error);
185 _bt_hal_set_adapter_request_state(FALSE);
186 _bt_hal_set_le_request_state(FALSE);
187 result = g_dbus_proxy_call_sync(proxy,
190 G_DBUS_CALL_FLAGS_NONE,
196 DBG("Bt core call failed(Error: %s)", error->message);
197 g_clear_error(&error);
199 g_variant_unref(result);
201 /* TODO: Terminate bluetooth service or not, need to check */
202 /*g_idle_add((GSourceFunc)_bt_terminate_service, NULL);*/
203 return BT_STATUS_FAIL;
207 g_variant_unref(result);
208 return BT_STATUS_SUCCESS;
211 int _bt_hal_dbus_disable_adapter(void)
214 GError *error = NULL;
215 GVariant *result = NULL;
218 proxy = __bt_get_core_proxy();
221 DBG("_bt_hal_dbus_enable_adapter: Core proxy get failed!!!");
222 return BT_STATUS_FAIL;
225 result = g_dbus_proxy_call_sync(proxy, "DisableAdapter",
227 G_DBUS_CALL_FLAGS_NONE, -1,
230 DBG("DisableAdapter failed: %s", error->message);
231 g_clear_error(&error);
233 g_variant_unref(result);
235 /* TODO: Terminate bluetooth service or not, need to check */
236 /*g_idle_add((GSourceFunc)_bt_terminate_service, NULL);*/
237 return BT_STATUS_FAIL;
241 g_variant_unref(result);
242 return BT_STATUS_SUCCESS;
246 int _bt_hal_dbus_enable_le(void)
249 GError *error = NULL;
250 GVariant *result = NULL;
251 int adapter_value = VCONFKEY_BT_STATUS_OFF;
252 unsigned char powered = 0;
256 if (vconf_get_int(VCONFKEY_BT_STATUS, &adapter_value) != 0)
257 ERR("fail to get vconf key!");
259 if (_bt_hal_get_adapter_powered_state(&powered) == BT_STATUS_FAIL)
260 ERR("_bt_hal_get_adapter_powered_state failed");
262 if ((adapter_value == VCONFKEY_BT_STATUS_ON) && (powered == 1)) {
263 gboolean *user_data = g_new0(int, 1);
265 g_idle_add(__bt_hal_send_le_event, (gpointer)user_data);
266 return BT_STATUS_SUCCESS;
269 proxy = __bt_get_core_proxy();
272 DBG("_bt_hal_dbus_enable_le: Core proxy get failed!!!");
273 return BT_STATUS_FAIL;
275 _bt_hal_set_le_request_state(TRUE);
277 result = g_dbus_proxy_call_sync(proxy, "EnableAdapterLe",
279 G_DBUS_CALL_FLAGS_NONE, BT_ENABLE_TIMEOUT,
282 DBG("EnableAdapter failed: %s", error->message);
283 g_clear_error(&error);
285 result = g_dbus_proxy_call_sync(proxy,
288 G_DBUS_CALL_FLAGS_NONE,
293 _bt_hal_set_le_request_state(FALSE);
295 DBG("Bt core call failed(Error: %s)", error->message);
296 g_clear_error(&error);
298 g_variant_unref(result);
300 return BT_STATUS_FAIL;
304 g_variant_unref(result);
305 return BT_STATUS_SUCCESS;
308 int _bt_hal_dbus_disable_le(void)
311 GError *error = NULL;
312 GVariant *result = NULL;
313 int adapter_value = VCONFKEY_BT_STATUS_OFF;
316 if (vconf_get_int(VCONFKEY_BT_STATUS, &adapter_value) != 0)
317 ERR("fail to get vconf key!");
319 if (adapter_value == VCONFKEY_BT_STATUS_ON) {
320 gboolean *user_data = g_new0(int, 1);
322 g_idle_add(__bt_hal_send_le_event, (gpointer)user_data);
323 return BT_STATUS_SUCCESS;
326 proxy = __bt_get_core_proxy();
329 DBG("_bt_hal_dbus_disable_le: Core proxy get failed!!!");
330 return BT_STATUS_FAIL;
333 result = g_dbus_proxy_call_sync(proxy, "DisableAdapterLe",
335 G_DBUS_CALL_FLAGS_NONE, -1,
338 DBG("DisableAdapter failed: %s", error->message);
339 g_clear_error(&error);
341 g_variant_unref(result);
342 return BT_STATUS_FAIL;
348 g_variant_unref(result);
349 return BT_STATUS_SUCCESS;
354 int _bt_hal_dbus_reset_adapter(void)
358 GError *error = NULL;
361 proxy = __bt_get_core_proxy();
363 return BT_STATUS_FAIL;
365 result = g_dbus_proxy_call_sync(proxy,
368 G_DBUS_CALL_FLAGS_NONE,
375 ERR("Failed to ResetAdapter (Error: %s)", error->message);
376 g_clear_error(&error);
378 ERR("Failed to ResetAdapter");
379 return BT_STATUS_FAIL;
382 g_variant_unref(result);
383 return BT_STATUS_SUCCESS;
387 int _bt_hal_dbus_start_discovery(gboolean is_custom,
388 bt_disc_role_type_t role)
391 GError *error = NULL;
393 const gchar *disc_type;
394 DBG("Discovery Type: Is Custom : [%s]", is_custom ? "TRUE" : "FALSE");
396 proxy = _bt_hal_get_adapter_proxy();
398 DBG("Adapter proxy get failed!!!");
399 return BT_STATUS_FAIL;
403 if (role == BT_DISC_ROLE_BREDR)
405 else if (role == BT_DISC_ROLE_LE)
407 else if (role == BT_DISC_ROLE_DUAL)
408 disc_type = "LE_BREDR";
410 return BT_STATUS_PARM_INVALID;
412 result = g_dbus_proxy_call_sync(proxy,
413 "StartCustomDiscovery",
414 g_variant_new("s", disc_type),
415 G_DBUS_CALL_FLAGS_NONE,
420 result = g_dbus_proxy_call_sync(proxy,
423 G_DBUS_CALL_FLAGS_NONE,
430 ERR("StartDiscovery failed (Error: %s)", error->message);
431 g_clear_error(&error);
433 ERR("StartDiscovery failed");
434 return BT_STATUS_FAIL;
437 /* discovery status will be change in event */
439 g_variant_unref(result);
440 return BT_STATUS_SUCCESS;
443 int _bt_hal_dbus_stop_discovery(void)
446 GError *error = NULL;
450 proxy = _bt_hal_get_adapter_proxy();
452 DBG("_bt_hal_dbus_stop_discovery: Adapter proxy get failed!!!");
453 return BT_STATUS_FAIL;
456 result = g_dbus_proxy_call_sync(proxy,
459 G_DBUS_CALL_FLAGS_NONE,
466 ERR("StopDiscovery failed (Error: %s)", error->message);
467 g_clear_error(&error);
469 ERR("StopDiscovery failed");
470 return BT_STATUS_FAIL;
473 /* discovery status will be change in event */
475 g_variant_unref(result);
476 return BT_STATUS_SUCCESS;
479 static gboolean __bt_adapter_all_properties_cb(gpointer user_data)
481 GVariant *result = user_data;
482 GVariantIter *property_iter;
486 /* Buffer and propety count management */
487 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
488 struct hal_ev_adapter_props_changed *ev = (void*) buf;
490 gchar *address = NULL;
492 unsigned int cod = 0;
493 gboolean discoverable;
494 gboolean connectable;
495 unsigned int scan_mode = BT_SCAN_MODE_NONE;
496 unsigned int disc_timeout;
498 gboolean is_discovering;
499 gboolean is_le_discovering;
500 uint8_t ipsp_initialized;
503 unsigned int pairable_timeout;
504 gboolean scan_mode_property_update = FALSE;
508 memset(buf, 0, sizeof(buf));
511 ev->status = BT_STATUS_SUCCESS;
513 DBG("@@Start parsing properties");
514 g_variant_get(result, "(a{sv})", &property_iter);
515 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
516 if (!g_strcmp0(key, "Address")) {
519 address = (gchar *) g_variant_get_string(value, NULL);
520 DBG("Address [%s]", address);
521 _bt_hal_convert_addr_string_to_type(bdaddr, address);
522 size += __bt_insert_hal_properties(buf + size,
523 HAL_PROP_ADAPTER_ADDR, sizeof(bdaddr), bdaddr);
526 } else if (!g_strcmp0(key, "Alias")) {
527 name = (gchar *) g_variant_get_string(value, NULL);
528 DBG("Alias [%s]", name);
529 size += __bt_insert_hal_properties(buf + size,
530 HAL_PROP_ADAPTER_NAME, strlen(name) + 1, name);
533 } else if (!g_strcmp0(key, "Class")) {
534 cod = g_variant_get_uint32(value);
535 DBG("Class [%d]", cod);
536 size += __bt_insert_hal_properties(buf + size,
537 HAL_PROP_ADAPTER_CLASS, sizeof(unsigned int), &cod);
539 } else if (!g_strcmp0(key, "Discoverable")) {
540 discoverable = g_variant_get_boolean(value);
541 DBG("Discoverable [%d]", discoverable);
543 scan_mode = BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
544 scan_mode_property_update = TRUE;
545 } else if (!g_strcmp0(key, "DiscoverableTimeout")) {
546 disc_timeout = g_variant_get_uint32(value);
547 DBG("Discoverable Timeout [%d]", disc_timeout);
548 size += __bt_insert_hal_properties(buf + size,
549 HAL_PROP_ADAPTER_DISC_TIMEOUT, sizeof(unsigned int), &disc_timeout);
551 } else if (!g_strcmp0(key, "Connectable")) {
552 connectable = g_variant_get_boolean(value);
553 DBG("Connectable [%d]", connectable);
554 if (scan_mode == BT_SCAN_MODE_NONE)
555 scan_mode = BT_SCAN_MODE_CONNECTABLE;
556 scan_mode_property_update = TRUE;
557 } else if (!g_strcmp0(key, "Version")) {
558 version = (gchar *) g_variant_get_string(value, NULL);
559 DBG("Version [%s]", version);
560 size += __bt_insert_hal_properties(buf + size,
561 HAL_PROP_ADAPTER_VERSION, strlen(version) + 1, version);
563 } else if (!g_strcmp0(key, "Name")) {
564 name = (gchar *) g_variant_get_string(value, NULL);
565 DBG("Name [%s]", name);
566 size += __bt_insert_hal_properties(buf + size,
567 HAL_PROP_ADAPTER_NAME, strlen(name) + 1, name);
570 } else if (!g_strcmp0(key, "Powered")) {
571 powered = g_variant_get_boolean(value);
572 DBG("Powered = [%d]", powered);
573 } else if (!g_strcmp0(key, "Pairable")) {
574 pairable = (g_variant_get_boolean(value) ? 1 : 0);
575 DBG("Pairable [%d]", pairable);
576 size += __bt_insert_hal_properties(buf + size,
577 HAL_PROP_ADAPTER_PAIRABLE, sizeof(uint8_t), &pairable);
579 } else if (!g_strcmp0(key, "PairableTimeout")) {
580 pairable_timeout = g_variant_get_uint32(value);
581 DBG("Pairable Timeout = [%d]", pairable_timeout);
582 size += __bt_insert_hal_properties(buf + size,
583 HAL_PROP_ADAPTER_PAIRABLE_TIMEOUT, sizeof(unsigned int), &pairable_timeout);
585 } else if (!g_strcmp0(key, "UUIDs")) {
590 size1 = g_variant_get_size(value);
591 int num_props_tmp = ev->num_props;
593 uuid_value = (char **)g_variant_get_strv(value, &size1);
594 for (i = 0; uuid_value[i] != NULL; i++)
596 /* UUID collection */
597 uint8_t uuids[HAL_UUID_LEN * uuid_count];
598 for (i = 0; uuid_value[i] != NULL; i++) {
599 char *uuid_str = NULL;
600 uint8_t uuid[HAL_UUID_LEN];
601 uuid_str = g_strdup(uuid_value[i]);
602 DBG("UUID string [%s]\n", uuid_str);
603 _bt_hal_convert_uuid_string_to_type(uuid, uuid_str);
604 memcpy(uuids + i * HAL_UUID_LEN, uuid, HAL_UUID_LEN);
607 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_UUIDS,
608 (HAL_UUID_LEN * uuid_count),
610 ev->num_props = num_props_tmp + 1;
613 } else if (!g_strcmp0(key, "Discovering")) {
614 is_discovering = g_variant_get_boolean(value);
615 DBG("Discovering = [%d]", is_discovering);
616 } else if (!g_strcmp0(key, "LEDiscovering")) {
617 is_le_discovering = g_variant_get_boolean(value);
618 DBG("LE Discovering = [%d]", is_le_discovering);
619 } else if (!g_strcmp0(key, "Modalias")) {
620 char *modalias = NULL;
621 g_variant_get(value, "s", &modalias);
622 DBG("Adapter ModAlias [%s]", modalias);
623 size += __bt_insert_hal_properties(buf + size,
624 HAL_PROP_ADAPTER_MODALIAS, strlen(modalias) + 1, modalias);
627 } else if (!g_strcmp0(key, "SupportedLEFeatures")) {
628 DBG("LE Supported features");
631 GVariantIter *iter = NULL;
632 bt_local_le_features_t le_features;
633 gboolean le_features_present = FALSE;
635 memset(&le_features, 0x00, sizeof(le_features));
637 g_variant_get(value, "as", &iter);
639 while (g_variant_iter_loop(iter, "s", &name)) {
640 DBG("name = %s", name);
641 g_variant_iter_loop(iter, "s", &val);
642 DBG("Value = %s", val);
643 _bt_hal_update_le_feature_support(name, val, &le_features);
644 le_features_present = TRUE;
646 g_variant_iter_free(iter);
648 if (le_features_present) {
649 size += __bt_insert_hal_properties(buf + size,
650 HAL_PROP_ADAPTER_LOCAL_LE_FEAT, sizeof(le_features), &le_features);
653 DBG("le supported features values are NOT provided by Stack");
656 } else if (!g_strcmp0(key, "IpspInitStateChanged")) {
657 ipsp_initialized = (g_variant_get_boolean(value) ? 1 : 0);
658 DBG("IPSP Initialized = %d", ipsp_initialized);
659 size += __bt_insert_hal_properties(buf + size,
660 HAL_PROP_ADAPTER_IPSP_INITIALIZED, sizeof(uint8_t), &ipsp_initialized);
663 ERR("Unhandled Property:[%s]", key);
667 if (scan_mode_property_update) {
668 size += __bt_insert_hal_properties(buf + size,
669 HAL_PROP_ADAPTER_SCAN_MODE, sizeof(int), &scan_mode);
674 event_cb = _bt_get_adapter_event_cb();
676 ERR("event_cb is NULL");
681 DBG("Send Adapter properties changed event to HAL user,"
682 " Num Prop [%d] total size [%d]", ev->num_props, size);
683 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
686 g_variant_unref(result);
690 static int __bt_hal_dbus_get_all_adapter_properties(void)
694 GError *error = NULL;
698 proxy = _bt_hal_get_adapter_properties_proxy();
700 DBG("Adapter Properties proxy get failed!!!");
701 return BT_STATUS_FAIL;
704 result = g_dbus_proxy_call_sync(proxy,
706 g_variant_new("(s)", BT_HAL_ADAPTER_INTERFACE),
707 G_DBUS_CALL_FLAGS_NONE,
714 ERR("Failed to get all adapter properties (Error: %s)", error->message);
715 g_clear_error(&error);
717 ERR("Failed to get all adapter properties");
718 return BT_STATUS_FAIL;
721 DBG("Got All properties from Bluez Stack!!, time to start parsing");
723 * As we need to provide async callback to user from HAL, simply schedule a
724 * callback method which will carry actual result
726 g_idle_add(__bt_adapter_all_properties_cb, (gpointer)result);
729 return BT_STATUS_SUCCESS;
732 int _bt_hal_dbus_get_adapter_properties(void)
736 return __bt_hal_dbus_get_all_adapter_properties();
739 int _bt_hal_get_adapter_powered_state(uint8_t *state)
741 char *adapter_path = NULL;
742 gboolean powered = FALSE;
743 int ret = BT_STATUS_FAIL;
745 /* Check Valid Adapter Path, followed by Adapter Powered state.
746 If any of these fails, adapter will be considered Disabled */
747 adapter_path = _bt_hal_get_adapter_path();
749 if (adapter_path == NULL) {
750 INFO("Adapter is not powered");
751 g_free(adapter_path);
756 /* Check Adapter Powered Status */
757 ret = _bt_hal_is_adapter_powered(&powered);
758 if (BT_STATUS_FAIL == ret) {
759 INFO("Adapter is not powered");
760 g_free(adapter_path);
773 /* Get Discoverable timeout API and callback */
774 static gboolean __bt_adapter_discovery_timeout_cb(gpointer user_data)
776 /* Buffer and propety count management */
777 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
778 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
780 unsigned int *timeout = user_data;
782 memset(buf, 0, sizeof(buf));
785 ev->status = BT_STATUS_SUCCESS;
787 DBG("Discovery timeout in callback: [%d]", *timeout);
789 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_DISC_TIMEOUT,
790 sizeof(unsigned int), timeout);
793 DBG("Timeout value [%d] property Num [%d]", *timeout, ev->num_props);
796 event_cb = _bt_get_adapter_event_cb();
798 ERR("event_cb is NULL");
803 DBG("Send Adapter Properties changed event to HAL user,"
804 " Num Prop [%d] total size [%d]", ev->num_props, size);
805 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
812 int _bt_hal_dbus_get_discovery_timeout(void)
817 GError *error = NULL;
818 unsigned int *timeout;
821 proxy = _bt_hal_get_adapter_properties_proxy();
823 DBG("Adapter Properties proxy get failed!!!");
824 return BT_STATUS_FAIL;
827 result = g_dbus_proxy_call_sync(proxy,
829 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
830 "DiscoverableTimeout"),
831 G_DBUS_CALL_FLAGS_NONE,
838 ERR("Failed to get local version (Error: %s)", error->message);
839 g_clear_error(&error);
841 ERR("Failed to get local version");
842 return BT_STATUS_FAIL;
845 timeout = g_malloc0(sizeof(int));
847 ERR("Memory allocation failed");
848 g_variant_unref(result);
849 return BT_STATUS_FAIL;
852 g_variant_get(result, "(v)", &temp);
853 *timeout = g_variant_get_uint32(temp);
854 DBG("Timeout value: [%d]", *timeout);
856 g_variant_unref(result);
857 g_variant_unref(temp);
860 * As we need to provide async callback to user from HAL, simply schedule a
861 * callback method which will carry actual result
863 g_idle_add(__bt_adapter_discovery_timeout_cb, (gpointer) timeout);
866 return BT_STATUS_SUCCESS;
869 /* Get Discoverable Mode API and callback */
870 static gboolean __bt_adapter_scan_mode_cb(gpointer user_data)
872 /* Buffer and propety count management */
873 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
874 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
876 int *mode = user_data;
878 memset(buf, 0, sizeof(buf));
881 ev->status = BT_STATUS_SUCCESS;
883 DBG("Scan mode callback: [%d]", *mode);
885 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_SCAN_MODE,
889 DBG("Scan mode [%d] property Num [%d]", *mode, ev->num_props);
892 event_cb = _bt_get_adapter_event_cb();
894 ERR("event_cb is NULL");
899 DBG("Send Adapter Properties changed event to HAL user,"
900 " Num Prop [%d] total size [%d]", ev->num_props, size);
901 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
908 int _bt_hal_dbus_get_scan_mode(void)
911 gboolean discoverable;
912 gboolean connectable;
915 GError *error = NULL;
920 proxy = _bt_hal_get_adapter_properties_proxy();
922 DBG("Adapter Properties proxy get failed!!!");
923 return BT_STATUS_FAIL;
926 result = g_dbus_proxy_call_sync(proxy,
928 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
930 G_DBUS_CALL_FLAGS_NONE,
937 ERR("Failed to get discoverable mode (Error: %s)", error->message);
938 g_clear_error(&error);
940 ERR("Failed to get discoverable mode");
941 return BT_STATUS_FAIL;
944 g_variant_get(result, "(v)", &temp);
945 discoverable = g_variant_get_boolean(temp);
946 DBG("discoverable:%d", discoverable);
948 g_variant_unref(result);
949 g_variant_unref(temp);
952 result = g_dbus_proxy_call_sync(proxy,
954 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
956 G_DBUS_CALL_FLAGS_NONE,
962 ERR("Failed to get connectable mode (Error: %s)", error->message);
963 g_clear_error(&error);
965 ERR("Failed to get connectable mode");
966 return BT_STATUS_FAIL;
969 g_variant_get(result, "(v)", &temp);
970 connectable = g_variant_get_boolean(temp);
971 DBG("connectable:%d", connectable);
973 g_variant_unref(result);
974 g_variant_unref(temp);
977 scan_mode = g_malloc0(sizeof(int));
979 ERR("Memory allocation failed");
980 return BT_STATUS_FAIL;
984 *scan_mode = BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
985 else if (connectable)
986 *scan_mode = BT_SCAN_MODE_CONNECTABLE;
988 *scan_mode = BT_SCAN_MODE_NONE;
991 * As we need to provide async callback to user from HAL, simply schedule a
992 * callback method which will carry actual result
994 g_idle_add(__bt_adapter_scan_mode_cb, (gpointer) scan_mode);
997 return BT_STATUS_SUCCESS;
1000 /* Get Local Version API and callback */
1001 static gboolean __bt_adapter_local_version_cb(gpointer user_data)
1003 /* Buffer and propety count management */
1004 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1005 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1007 char *version = NULL;
1009 memset(buf, 0, sizeof(buf));
1012 ev->status = BT_STATUS_SUCCESS;
1014 version = (char*) user_data;
1015 DBG("Local Version in callback: [%s]", version);
1017 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_VERSION,
1018 (strlen(version) + 1), version);
1021 DBG("Device version [%s] property Num [%d]", version, ev->num_props);
1024 event_cb = _bt_get_adapter_event_cb();
1026 ERR("event_cb is NULL");
1031 DBG("Send Adapter Properties changed event to HAL user,"
1032 " Num Prop [%d] total size [%d]", ev->num_props, size);
1033 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1040 int _bt_hal_dbus_get_local_version(void)
1043 const char *version = NULL;
1046 GError *error = NULL;
1049 proxy = _bt_hal_get_adapter_properties_proxy();
1051 DBG("Adapter Properties proxy get failed!!!");
1052 return BT_STATUS_FAIL;
1055 result = g_dbus_proxy_call_sync(proxy,
1057 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1059 G_DBUS_CALL_FLAGS_NONE,
1065 if (error != NULL) {
1066 ERR("Failed to get local version (Error: %s)", error->message);
1067 g_clear_error(&error);
1069 ERR("Failed to get local version");
1070 return BT_STATUS_FAIL;
1073 g_variant_get(result, "(v)", &temp);
1074 version = g_variant_dup_string(temp, NULL);
1075 DBG("Local Version: [%s]", version);
1077 g_variant_unref(result);
1078 g_variant_unref(temp);
1081 * As we need to provide async callback to user from HAL, simply schedule a
1082 * callback method which will carry actual result
1084 g_idle_add(__bt_adapter_local_version_cb, (gpointer) version);
1087 return BT_STATUS_SUCCESS;
1090 /* Get Local Name API and callback */
1091 static gboolean __bt_adapter_local_name_cb(gpointer user_data)
1093 /* Buffer and propety count management */
1094 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1095 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1099 memset(buf, 0, sizeof(buf));
1102 ev->status = BT_STATUS_SUCCESS;
1104 name = (char*) user_data;
1105 DBG("Local Name in callback: [%s]", name);
1107 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_NAME,
1108 strlen(name) + 1, name);
1111 DBG("Device name [%s] property Num [%d]", name, ev->num_props);
1114 event_cb = _bt_get_adapter_event_cb();
1116 ERR("event_cb is NULL");
1121 DBG("Send Adapter Properties changed event to HAL user,"
1122 " Num Prop [%d] total size [%d]", ev->num_props, size);
1123 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1130 int _bt_hal_dbus_get_local_name(void)
1133 const char *name = NULL;
1136 GError *error = NULL;
1139 proxy = _bt_hal_get_adapter_properties_proxy();
1141 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1142 return BT_STATUS_FAIL;
1145 result = g_dbus_proxy_call_sync(proxy,
1147 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1149 G_DBUS_CALL_FLAGS_NONE,
1155 if (error != NULL) {
1156 ERR("Failed to get local name (Error: %s)", error->message);
1157 g_clear_error(&error);
1159 ERR("Failed to get local name");
1160 return BT_STATUS_FAIL;
1163 g_variant_get(result, "(v)", &temp);
1164 name = g_variant_dup_string(temp, NULL);
1165 DBG("Local Name: [%s]", name);
1167 g_variant_unref(result);
1168 g_variant_unref(temp);
1171 * As we need to provide async callback to user from HAL, simply schedule a
1172 * callback method which will carry actual result
1174 g_idle_add(__bt_adapter_local_name_cb, (gpointer) name);
1177 return BT_STATUS_SUCCESS;
1180 /* Get Local Address API and callback */
1181 static gboolean __bt_adapter_local_address_cb(gpointer user_data)
1183 /* Buffer and propety count management */
1184 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1185 struct hal_ev_adapter_props_changed *ev = (void*) buf;
1187 char * address = NULL;
1189 memset(buf, 0, sizeof(buf));
1192 ev->status = BT_STATUS_SUCCESS;
1194 address = (char*) user_data;
1197 _bt_hal_convert_addr_string_to_type(bdaddr, address);
1199 size += __bt_insert_hal_properties(buf + size, HAL_PROP_DEVICE_ADDR,
1200 sizeof(bdaddr), bdaddr);
1203 DBG("Device address [%s] property Num [%d]", address, ev->num_props);
1205 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_ADDR,
1206 sizeof(bdaddr), bdaddr);
1209 event_cb = _bt_get_adapter_event_cb();
1211 ERR("event_cb is NULL");
1216 DBG("Send Device found event to HAL user,"
1217 " Num Prop [%d] total size [%d]", ev->num_props, size);
1218 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1225 int _bt_hal_dbus_get_local_address(void)
1228 GError *error = NULL;
1229 const char *address;
1235 proxy = _bt_hal_get_adapter_properties_proxy();
1237 DBG("_bt_hal_dbus_get_local_address: Adapter Properties proxy get failed!!!");
1238 return BT_STATUS_FAIL;
1241 result = g_dbus_proxy_call_sync(proxy,
1243 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1245 G_DBUS_CALL_FLAGS_NONE,
1251 ERR("Failed to get local address");
1252 if (error != NULL) {
1253 ERR("Failed to get local address (Error: %s)", error->message);
1254 g_clear_error(&error);
1256 return BT_STATUS_FAIL;
1259 g_variant_get(result, "(v)", &temp);
1260 address = g_variant_dup_string(temp, NULL);
1263 DBG("Address:%s", address);
1265 return BT_STATUS_FAIL;
1267 g_variant_unref(result);
1268 g_variant_unref(temp);
1271 * As we need to provide async callback to user from HAL, simply schedule a
1272 * callback method which will carry actual result
1274 g_idle_add(__bt_adapter_local_address_cb, (gpointer) address);
1277 return BT_STATUS_SUCCESS;
1280 /* Get Local services API and callback */
1281 static gboolean __bt_adapter_service_uuids_cb(gpointer user_data)
1283 GVariant *result = user_data;
1285 GVariantIter *iter = NULL;
1288 /* Buffer and propety count management */
1289 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1290 struct hal_ev_adapter_props_changed *ev = (void*) buf;
1293 /* UUID collection */
1294 uint8_t uuids[HAL_UUID_LEN * MAX_UUID_COUNT];
1297 memset(buf, 0, sizeof(buf));
1300 ev->status = BT_STATUS_SUCCESS;
1302 g_variant_get(result, "(v)", &temp);
1303 g_variant_get(temp, "as", &iter);
1305 ERR("Failed to get UUIDs");
1309 while (g_variant_iter_loop(iter, "s", &uuid_str)) {
1310 uint8_t uuid[HAL_UUID_LEN];
1312 DBG("UUID string [%s]\n", uuid_str);
1313 _bt_hal_convert_uuid_string_to_type(uuid, uuid_str);
1314 memcpy(uuids + uuid_count * HAL_UUID_LEN, uuid, HAL_UUID_LEN);
1318 size += __bt_insert_hal_properties(buf + size,
1319 HAL_PROP_ADAPTER_UUIDS,
1320 (HAL_UUID_LEN * uuid_count),
1325 event_cb = _bt_get_adapter_event_cb();
1327 ERR("event_cb is NULL");
1332 DBG("Send Adapter properties changed event to HAL user,"
1333 " Num Prop [%d] total size [%d]", ev->num_props, size);
1334 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1337 g_variant_iter_free(iter);
1338 g_variant_unref(result);
1339 g_variant_unref(temp);
1343 event_cb = _bt_get_adapter_event_cb();
1345 ev->status = BT_STATUS_FAIL;
1347 DBG("Send Adapter properties changed event to HAL user,"
1348 " Num Prop [%d] total size [%d]", ev->num_props, size);
1349 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1352 g_variant_unref(result);
1356 int _bt_hal_dbus_get_adapter_supported_uuids(void)
1359 GError *error = NULL;
1364 proxy = _bt_hal_get_adapter_properties_proxy();
1367 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1368 return BT_STATUS_FAIL;
1371 result = g_dbus_proxy_call_sync(proxy,
1373 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1375 G_DBUS_CALL_FLAGS_NONE,
1381 if (error != NULL) {
1382 ERR("Failed to get UUIDs (Error: %s)", error->message);
1383 g_clear_error(&error);
1385 ERR("Failed to get UUIDs");
1386 return BT_STATUS_FAIL;
1390 DBG("Got All Adaptr service UUID's from Bluez Stack!!, time to start parsing");
1393 * As we need to provide async callback to user from HAL, simply schedule a
1394 * callback method which will carry actual result
1396 g_idle_add(__bt_adapter_service_uuids_cb, (gpointer)result);
1399 return BT_STATUS_SUCCESS;
1402 static gboolean __is_device_paired(GVariantIter *item_iter)
1404 gboolean paired = FALSE;
1408 while (g_variant_iter_loop(item_iter, "{sv}", &key, &value)) {
1409 if (NULL == key || g_strcmp0(key, "Paired"))
1412 paired = g_variant_get_boolean(value);
1413 g_variant_unref(value);
1421 static gboolean __bt_adapter_bonded_devices_cb(gpointer user_data)
1423 /* Buffer and propety count management */
1424 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1425 uint8_t addresses[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1426 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1430 GVariant *result = user_data;
1432 GVariantIter *interface_iter;
1433 GVariantIter *svc_iter;
1434 char *object_path = NULL;
1435 char *interface_str = NULL;
1437 char device_address[BT_HAL_ADDRESS_STRING_SIZE];
1438 uint8_t bdaddr[BT_HAL_ADDRESS_LENGTH_MAX];
1440 memset(buf, 0, sizeof(buf));
1443 ev->status = BT_STATUS_SUCCESS;
1445 INFO("Size [%d]", size);
1447 /* signature of GetManagedObjects: a{oa{sa{sv}}} */
1448 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
1450 /* Parse the signature: {oa{sa{sv}}} */
1451 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path, &interface_iter)) {
1452 if (object_path == NULL)
1455 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
1456 &interface_str, &svc_iter)) {
1457 if (g_strcmp0(interface_str, "org.bluez.Device1") == 0) {
1458 DBG("Found a device: %s", object_path);
1459 if (__is_device_paired(svc_iter)) {
1460 _bt_hal_convert_device_path_to_address(object_path, device_address);
1461 DBG("Paired Device Address: [%s]", device_address);
1463 _bt_hal_convert_addr_string_to_type(bdaddr, device_address);
1464 memcpy((addresses + (count * BT_HAL_ADDRESS_LENGTH_MAX)),
1465 bdaddr, BT_HAL_ADDRESS_LENGTH_MAX);
1468 g_variant_iter_free(svc_iter);
1469 g_free(interface_str);
1470 interface_str = NULL;
1476 g_variant_iter_free(iter);
1477 g_variant_unref(result);
1479 size += __bt_insert_hal_properties((buf + size),
1480 HAL_PROP_ADAPTER_BONDED_DEVICES,
1481 (count * BT_HAL_ADDRESS_LENGTH_MAX), addresses);
1485 event_cb = _bt_get_adapter_event_cb();
1487 ERR("event_cb is NULL");
1492 DBG("Send Adapter properties changed event to HAL user,"
1493 " Num Prop [%d] total size [%d]", ev->num_props, size);
1494 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1500 int _bt_hal_dbus_get_bonded_devices(void)
1502 GDBusProxy *manager_proxy;
1503 GVariant *result = NULL;
1507 manager_proxy = _bt_hal_get_manager_proxy();
1508 if (manager_proxy == NULL)
1509 return BT_STATUS_FAIL;
1511 result = g_dbus_proxy_call_sync(manager_proxy, "GetManagedObjects",
1513 G_DBUS_CALL_FLAGS_NONE,
1518 ERR("Can't get managed objects");
1519 return BT_STATUS_FAIL;
1523 * As we need to provide async callback to user from HAL, simply schedule a
1524 * callback method which will carry actual result
1526 g_idle_add(__bt_adapter_bonded_devices_cb, (gpointer) result);
1529 return BT_STATUS_SUCCESS;
1532 int _bt_hal_dbus_get_adapter_property(bt_property_type_t property_type)
1536 INFO("property_type: %d", property_type);
1538 switch (property_type) {
1539 case BT_PROPERTY_BDADDR:
1540 return _bt_hal_dbus_get_local_address();
1541 case BT_PROPERTY_BDNAME:
1542 return _bt_hal_dbus_get_local_name();
1543 case BT_PROPERTY_VERSION:
1544 return _bt_hal_dbus_get_local_version();
1545 case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
1546 return _bt_hal_dbus_get_discovery_timeout();
1547 case BT_PROPERTY_ADAPTER_SCAN_MODE:
1548 return _bt_hal_dbus_get_scan_mode();
1549 case BT_PROPERTY_CLASS_OF_DEVICE:
1550 return BT_STATUS_UNSUPPORTED;
1551 case BT_PROPERTY_UUIDS:
1552 return _bt_hal_dbus_get_adapter_supported_uuids();
1553 case BT_PROPERTY_ADAPTER_BONDED_DEVICES:
1554 return _bt_hal_dbus_get_bonded_devices();
1556 return BT_STATUS_UNSUPPORTED;
1562 static int __bt_hal_dbus_set_local_name(void *data)
1565 const char *name = data;
1567 GError *error = NULL;
1570 DBG("Local Name: [%s]", name);
1571 proxy = _bt_hal_get_adapter_properties_proxy();
1573 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1574 return BT_STATUS_FAIL;
1577 result = g_dbus_proxy_call_sync(proxy,
1579 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1580 "Alias", g_variant_new("s", name)),
1581 G_DBUS_CALL_FLAGS_NONE,
1586 if (error != NULL) {
1587 ERR("Failed to set local name (Error: %s)", error->message);
1588 g_clear_error(&error);
1590 ERR("Failed to set local name");
1591 return BT_STATUS_FAIL;
1593 g_variant_unref(result);
1596 return BT_STATUS_SUCCESS;
1599 static int __bt_hal_dbus_set_scan_mode(void *data)
1604 GError *error = NULL;
1609 DBG("Scan mode: [%d]", *mode);
1610 proxy = _bt_hal_get_adapter_properties_proxy();
1612 DBG("Adapter Properties proxy get failed!!!");
1613 return BT_STATUS_FAIL;
1617 case BT_SCAN_MODE_NONE:
1621 case BT_SCAN_MODE_CONNECTABLE:
1625 case BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
1630 ERR("Invalid scan mode");
1631 return BT_STATUS_FAIL;
1634 result = g_dbus_proxy_call_sync(proxy,
1636 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1637 "Connectable", g_variant_new("b", pg_scan)),
1638 G_DBUS_CALL_FLAGS_NONE,
1643 if (error != NULL) {
1644 ERR("Failed to set connectable property (Error: %s)", error->message);
1645 g_clear_error(&error);
1647 ERR("Failed to set connectable property");
1648 return BT_STATUS_FAIL;
1650 g_variant_unref(result);
1652 result = g_dbus_proxy_call_sync(proxy,
1654 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE, "Discoverable",
1655 g_variant_new("b", inq_scan)),
1656 G_DBUS_CALL_FLAGS_NONE,
1661 if (error != NULL) {
1662 ERR("Failed to set Discoverable property (Error: %s)", error->message);
1663 g_clear_error(&error);
1665 ERR("Failed to set Discoverable property");
1666 return BT_STATUS_FAIL;
1668 g_variant_unref(result);
1671 return BT_STATUS_SUCCESS;
1674 static int __bt_hal_dbus_set_discovery_timeout(void *data)
1677 unsigned int *timeout = data;
1679 GError *error = NULL;
1684 DBG("Discovery Timeout: [%d]", *timeout);
1685 proxy = _bt_hal_get_adapter_properties_proxy();
1687 DBG("Adapter Properties proxy get failed!!!");
1688 return BT_STATUS_FAIL;
1691 result = g_dbus_proxy_call_sync(proxy,
1693 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1694 "DiscoverableTimeout", g_variant_new("u", *timeout)),
1695 G_DBUS_CALL_FLAGS_NONE,
1700 if (error != NULL) {
1701 ERR("Failed to set DiscoverableTimeout property (Error: %s)", error->message);
1702 g_clear_error(&error);
1704 ERR("Failed to set DiscoverableTimeout property");
1705 return BT_STATUS_FAIL;
1707 g_variant_unref(result);
1710 return BT_STATUS_SUCCESS;
1713 /* Set Adapter Properties */
1714 int _bt_hal_dbus_set_adapter_property(const bt_property_t *property)
1720 if (property == NULL || property->val == NULL) {
1721 ERR("Invalid parameters received");
1722 return BT_STATUS_FAIL;
1725 switch (property->type) {
1726 case BT_PROPERTY_BDNAME:
1727 result = __bt_hal_dbus_set_local_name(property->val);
1729 case BT_PROPERTY_ADAPTER_SCAN_MODE:
1730 result = __bt_hal_dbus_set_scan_mode(property->val);
1732 case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
1733 result = __bt_hal_dbus_set_discovery_timeout(property->val);
1736 result = BT_STATUS_UNSUPPORTED;
1739 DBG("Result= [%d]", result);