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);
525 } else if (!g_strcmp0(key, "Alias")) {
526 name = (gchar *) g_variant_get_string(value, NULL);
527 DBG("Alias [%s]", name);
528 size += __bt_insert_hal_properties(buf + size,
529 HAL_PROP_ADAPTER_NAME, strlen(name) + 1, name);
531 } else if (!g_strcmp0(key, "Class")) {
532 cod = g_variant_get_uint32(value);
533 DBG("Class [%d]", cod);
534 size += __bt_insert_hal_properties(buf + size,
535 HAL_PROP_ADAPTER_CLASS, sizeof(unsigned int), &cod);
537 } else if (!g_strcmp0(key, "Discoverable")) {
538 discoverable = g_variant_get_boolean(value);
539 DBG("Discoverable [%d]", discoverable);
541 scan_mode = BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
542 scan_mode_property_update = TRUE;
543 } else if (!g_strcmp0(key, "DiscoverableTimeout")) {
544 disc_timeout = g_variant_get_uint32(value);
545 DBG("Discoverable Timeout [%d]", disc_timeout);
546 size += __bt_insert_hal_properties(buf + size,
547 HAL_PROP_ADAPTER_DISC_TIMEOUT, sizeof(unsigned int), &disc_timeout);
549 } else if (!g_strcmp0(key, "Connectable")) {
550 connectable = g_variant_get_boolean(value);
551 DBG("Connectable [%d]", connectable);
552 if (scan_mode == BT_SCAN_MODE_NONE)
553 scan_mode = BT_SCAN_MODE_CONNECTABLE;
554 scan_mode_property_update = TRUE;
555 } else if (!g_strcmp0(key, "Version")) {
556 version = (gchar *) g_variant_get_string(value, NULL);
557 DBG("Version [%s]", version);
558 size += __bt_insert_hal_properties(buf + size,
559 HAL_PROP_ADAPTER_VERSION, strlen(version) + 1, version);
561 } else if (!g_strcmp0(key, "Name")) {
562 name = (gchar *) g_variant_get_string(value, NULL);
563 DBG("Name [%s]", name);
564 size += __bt_insert_hal_properties(buf + size,
565 HAL_PROP_ADAPTER_NAME, strlen(name) + 1, name);
567 } else if (!g_strcmp0(key, "Powered")) {
568 powered = g_variant_get_boolean(value);
569 DBG("Powered = [%d]", powered);
570 } else if (!g_strcmp0(key, "Pairable")) {
571 pairable = (g_variant_get_boolean(value) ? 1 : 0);
572 DBG("Pairable [%d]", pairable);
573 size += __bt_insert_hal_properties(buf + size,
574 HAL_PROP_ADAPTER_PAIRABLE, sizeof(uint8_t), &pairable);
576 } else if (!g_strcmp0(key, "PairableTimeout")) {
577 pairable_timeout = g_variant_get_uint32(value);
578 DBG("Pairable Timeout = [%d]", pairable_timeout);
579 size += __bt_insert_hal_properties(buf + size,
580 HAL_PROP_ADAPTER_PAIRABLE_TIMEOUT, sizeof(unsigned int), &pairable_timeout);
582 } else if (!g_strcmp0(key, "UUIDs")) {
587 size1 = g_variant_get_size(value);
588 int num_props_tmp = ev->num_props;
590 uuid_value = (char **)g_variant_get_strv(value, &size1);
591 for (i = 0; uuid_value[i] != NULL; i++)
593 /* UUID collection */
594 uint8_t uuids[HAL_UUID_LEN * uuid_count];
595 for (i = 0; uuid_value[i] != NULL; i++) {
596 char *uuid_str = NULL;
597 uint8_t uuid[HAL_UUID_LEN];
598 uuid_str = g_strdup(uuid_value[i]);
599 DBG("UUID string [%s]\n", uuid_str);
600 _bt_hal_convert_uuid_string_to_type(uuid, uuid_str);
601 memcpy(uuids + i * HAL_UUID_LEN, uuid, HAL_UUID_LEN);
604 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_UUIDS,
605 (HAL_UUID_LEN * uuid_count),
607 ev->num_props = num_props_tmp + 1;
610 } else if (!g_strcmp0(key, "Discovering")) {
611 is_discovering = g_variant_get_boolean(value);
612 DBG("Discovering = [%d]", is_discovering);
613 } else if (!g_strcmp0(key, "LEDiscovering")) {
614 is_le_discovering = g_variant_get_boolean(value);
615 DBG("LE Discovering = [%d]", is_le_discovering);
616 } else if (!g_strcmp0(key, "Modalias")) {
617 char *modalias = NULL;
618 g_variant_get(value, "s", &modalias);
619 DBG("Adapter ModAlias [%s]", modalias);
620 size += __bt_insert_hal_properties(buf + size,
621 HAL_PROP_ADAPTER_MODALIAS, strlen(modalias) + 1, modalias);
624 } else if (!g_strcmp0(key, "SupportedLEFeatures")) {
625 DBG("LE Supported features");
628 GVariantIter *iter = NULL;
629 bt_local_le_features_t le_features;
630 gboolean le_features_present = FALSE;
632 memset(&le_features, 0x00, sizeof(le_features));
634 g_variant_get(value, "as", &iter);
636 while (g_variant_iter_loop(iter, "s", &name)) {
637 DBG("name = %s", name);
638 g_variant_iter_loop(iter, "s", &val);
639 DBG("Value = %s", val);
640 _bt_hal_update_le_feature_support(name, val, &le_features);
641 le_features_present = TRUE;
643 g_variant_iter_free(iter);
645 if (le_features_present) {
646 size += __bt_insert_hal_properties(buf + size,
647 HAL_PROP_ADAPTER_LOCAL_LE_FEAT, sizeof(le_features), &le_features);
650 DBG("le supported features values are NOT provided by Stack");
653 } else if (!g_strcmp0(key, "IpspInitStateChanged")) {
654 ipsp_initialized = (g_variant_get_boolean(value) ? 1 : 0);
655 DBG("IPSP Initialized = %d", ipsp_initialized);
656 size += __bt_insert_hal_properties(buf + size,
657 HAL_PROP_ADAPTER_IPSP_INITIALIZED, sizeof(uint8_t), &ipsp_initialized);
660 ERR("Unhandled Property:[%s]", key);
664 if (scan_mode_property_update) {
665 size += __bt_insert_hal_properties(buf + size,
666 HAL_PROP_ADAPTER_SCAN_MODE, sizeof(int), &scan_mode);
671 event_cb = _bt_get_adapter_event_cb();
673 ERR("event_cb is NULL");
678 DBG("Send Adapter properties changed event to HAL user,"
679 " Num Prop [%d] total size [%d]", ev->num_props, size);
680 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
683 g_variant_unref(result);
687 static int __bt_hal_dbus_get_all_adapter_properties(void)
691 GError *error = NULL;
695 proxy = _bt_hal_get_adapter_properties_proxy();
697 DBG("Adapter Properties proxy get failed!!!");
698 return BT_STATUS_FAIL;
701 result = g_dbus_proxy_call_sync(proxy,
703 g_variant_new("(s)", BT_HAL_ADAPTER_INTERFACE),
704 G_DBUS_CALL_FLAGS_NONE,
711 ERR("Failed to get all adapter properties (Error: %s)", error->message);
712 g_clear_error(&error);
714 ERR("Failed to get all adapter properties");
715 return BT_STATUS_FAIL;
718 DBG("Got All properties from Bluez Stack!!, time to start parsing");
720 * As we need to provide async callback to user from HAL, simply schedule a
721 * callback method which will carry actual result
723 g_idle_add(__bt_adapter_all_properties_cb, (gpointer)result);
726 return BT_STATUS_SUCCESS;
729 int _bt_hal_dbus_get_adapter_properties(void)
733 return __bt_hal_dbus_get_all_adapter_properties();
736 int _bt_hal_get_adapter_powered_state(uint8_t *state)
738 char *adapter_path = NULL;
739 gboolean powered = FALSE;
740 int ret = BT_STATUS_FAIL;
742 /* Check Valid Adapter Path, followed by Adapter Powered state.
743 If any of these fails, adapter will be considered Disabled */
744 adapter_path = _bt_hal_get_adapter_path();
746 if (adapter_path == NULL) {
747 INFO("Adapter is not powered");
748 g_free(adapter_path);
753 /* Check Adapter Powered Status */
754 ret = _bt_hal_is_adapter_powered(&powered);
755 if (BT_STATUS_FAIL == ret) {
756 INFO("Adapter is not powered");
757 g_free(adapter_path);
770 /* Get Discoverable timeout API and callback */
771 static gboolean __bt_adapter_discovery_timeout_cb(gpointer user_data)
773 /* Buffer and propety count management */
774 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
775 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
777 unsigned int *timeout = user_data;
779 memset(buf, 0, sizeof(buf));
782 ev->status = BT_STATUS_SUCCESS;
784 DBG("Discovery timeout in callback: [%d]", *timeout);
786 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_DISC_TIMEOUT,
787 sizeof(unsigned int), timeout);
790 DBG("Timeout value [%d] property Num [%d]", *timeout, ev->num_props);
793 event_cb = _bt_get_adapter_event_cb();
795 ERR("event_cb is NULL");
800 DBG("Send Adapter Properties changed event to HAL user,"
801 " Num Prop [%d] total size [%d]", ev->num_props, size);
802 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
809 int _bt_hal_dbus_get_discovery_timeout(void)
814 GError *error = NULL;
815 unsigned int *timeout;
818 proxy = _bt_hal_get_adapter_properties_proxy();
820 DBG("Adapter Properties proxy get failed!!!");
821 return BT_STATUS_FAIL;
824 result = g_dbus_proxy_call_sync(proxy,
826 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
827 "DiscoverableTimeout"),
828 G_DBUS_CALL_FLAGS_NONE,
835 ERR("Failed to get local version (Error: %s)", error->message);
836 g_clear_error(&error);
838 ERR("Failed to get local version");
839 return BT_STATUS_FAIL;
842 timeout = g_malloc0(sizeof(int));
844 ERR("Memory allocation failed");
845 g_variant_unref(result);
846 return BT_STATUS_FAIL;
849 g_variant_get(result, "(v)", &temp);
850 *timeout = g_variant_get_uint32(temp);
851 DBG("Timeout value: [%d]", *timeout);
853 g_variant_unref(result);
854 g_variant_unref(temp);
857 * As we need to provide async callback to user from HAL, simply schedule a
858 * callback method which will carry actual result
860 g_idle_add(__bt_adapter_discovery_timeout_cb, (gpointer) timeout);
863 return BT_STATUS_SUCCESS;
866 /* Get Discoverable Mode API and callback */
867 static gboolean __bt_adapter_scan_mode_cb(gpointer user_data)
869 /* Buffer and propety count management */
870 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
871 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
873 int *mode = user_data;
875 memset(buf, 0, sizeof(buf));
878 ev->status = BT_STATUS_SUCCESS;
880 DBG("Scan mode callback: [%d]", *mode);
882 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_SCAN_MODE,
886 DBG("Scan mode [%d] property Num [%d]", *mode, ev->num_props);
889 event_cb = _bt_get_adapter_event_cb();
891 ERR("event_cb is NULL");
896 DBG("Send Adapter Properties changed event to HAL user,"
897 " Num Prop [%d] total size [%d]", ev->num_props, size);
898 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
905 int _bt_hal_dbus_get_scan_mode(void)
908 gboolean discoverable;
909 gboolean connectable;
912 GError *error = NULL;
917 proxy = _bt_hal_get_adapter_properties_proxy();
919 DBG("Adapter Properties proxy get failed!!!");
920 return BT_STATUS_FAIL;
923 result = g_dbus_proxy_call_sync(proxy,
925 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
927 G_DBUS_CALL_FLAGS_NONE,
934 ERR("Failed to get discoverable mode (Error: %s)", error->message);
935 g_clear_error(&error);
937 ERR("Failed to get discoverable mode");
938 return BT_STATUS_FAIL;
941 g_variant_get(result, "(v)", &temp);
942 discoverable = g_variant_get_boolean(temp);
943 DBG("discoverable:%d", discoverable);
945 g_variant_unref(result);
946 g_variant_unref(temp);
949 result = g_dbus_proxy_call_sync(proxy,
951 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
953 G_DBUS_CALL_FLAGS_NONE,
959 ERR("Failed to get connectable mode (Error: %s)", error->message);
960 g_clear_error(&error);
962 ERR("Failed to get connectable mode");
963 return BT_STATUS_FAIL;
966 g_variant_get(result, "(v)", &temp);
967 connectable = g_variant_get_boolean(temp);
968 DBG("connectable:%d", connectable);
970 g_variant_unref(result);
971 g_variant_unref(temp);
974 scan_mode = g_malloc0(sizeof(int));
976 ERR("Memory allocation failed");
977 return BT_STATUS_FAIL;
981 *scan_mode = BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
982 else if (connectable)
983 *scan_mode = BT_SCAN_MODE_CONNECTABLE;
985 *scan_mode = BT_SCAN_MODE_NONE;
988 * As we need to provide async callback to user from HAL, simply schedule a
989 * callback method which will carry actual result
991 g_idle_add(__bt_adapter_scan_mode_cb, (gpointer) scan_mode);
994 return BT_STATUS_SUCCESS;
997 /* Get Local Version API and callback */
998 static gboolean __bt_adapter_local_version_cb(gpointer user_data)
1000 /* Buffer and propety count management */
1001 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1002 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1004 char *version = NULL;
1006 memset(buf, 0, sizeof(buf));
1009 ev->status = BT_STATUS_SUCCESS;
1011 version = (char*) user_data;
1012 DBG("Local Version in callback: [%s]", version);
1014 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_VERSION,
1015 (strlen(version) + 1), version);
1018 DBG("Device version [%s] property Num [%d]", version, ev->num_props);
1021 event_cb = _bt_get_adapter_event_cb();
1023 ERR("event_cb is NULL");
1028 DBG("Send Adapter Properties changed event to HAL user,"
1029 " Num Prop [%d] total size [%d]", ev->num_props, size);
1030 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1037 int _bt_hal_dbus_get_local_version(void)
1040 const char *version = NULL;
1043 GError *error = NULL;
1046 proxy = _bt_hal_get_adapter_properties_proxy();
1048 DBG("Adapter Properties proxy get failed!!!");
1049 return BT_STATUS_FAIL;
1052 result = g_dbus_proxy_call_sync(proxy,
1054 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1056 G_DBUS_CALL_FLAGS_NONE,
1062 if (error != NULL) {
1063 ERR("Failed to get local version (Error: %s)", error->message);
1064 g_clear_error(&error);
1066 ERR("Failed to get local version");
1067 return BT_STATUS_FAIL;
1070 g_variant_get(result, "(v)", &temp);
1071 version = g_variant_dup_string(temp, NULL);
1072 DBG("Local Version: [%s]", version);
1074 g_variant_unref(result);
1075 g_variant_unref(temp);
1078 * As we need to provide async callback to user from HAL, simply schedule a
1079 * callback method which will carry actual result
1081 g_idle_add(__bt_adapter_local_version_cb, (gpointer) version);
1084 return BT_STATUS_SUCCESS;
1087 /* Get Local Name API and callback */
1088 static gboolean __bt_adapter_local_name_cb(gpointer user_data)
1090 /* Buffer and propety count management */
1091 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1092 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1096 memset(buf, 0, sizeof(buf));
1099 ev->status = BT_STATUS_SUCCESS;
1101 name = (char*) user_data;
1102 DBG("Local Name in callback: [%s]", name);
1104 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_NAME,
1105 strlen(name) + 1, name);
1108 DBG("Device name [%s] property Num [%d]", name, ev->num_props);
1111 event_cb = _bt_get_adapter_event_cb();
1113 ERR("event_cb is NULL");
1118 DBG("Send Adapter Properties changed event to HAL user,"
1119 " Num Prop [%d] total size [%d]", ev->num_props, size);
1120 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1127 int _bt_hal_dbus_get_local_name(void)
1130 const char *name = NULL;
1133 GError *error = NULL;
1136 proxy = _bt_hal_get_adapter_properties_proxy();
1138 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1139 return BT_STATUS_FAIL;
1142 result = g_dbus_proxy_call_sync(proxy,
1144 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1146 G_DBUS_CALL_FLAGS_NONE,
1152 if (error != NULL) {
1153 ERR("Failed to get local name (Error: %s)", error->message);
1154 g_clear_error(&error);
1156 ERR("Failed to get local name");
1157 return BT_STATUS_FAIL;
1160 g_variant_get(result, "(v)", &temp);
1161 name = g_variant_dup_string(temp, NULL);
1162 DBG("Local Name: [%s]", name);
1164 g_variant_unref(result);
1165 g_variant_unref(temp);
1168 * As we need to provide async callback to user from HAL, simply schedule a
1169 * callback method which will carry actual result
1171 g_idle_add(__bt_adapter_local_name_cb, (gpointer) name);
1174 return BT_STATUS_SUCCESS;
1177 /* Get Local Address API and callback */
1178 static gboolean __bt_adapter_local_address_cb(gpointer user_data)
1180 /* Buffer and propety count management */
1181 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1182 struct hal_ev_adapter_props_changed *ev = (void*) buf;
1184 char * address = NULL;
1186 memset(buf, 0, sizeof(buf));
1189 ev->status = BT_STATUS_SUCCESS;
1191 address = (char*) user_data;
1194 _bt_hal_convert_addr_string_to_type(bdaddr, address);
1196 size += __bt_insert_hal_properties(buf + size, HAL_PROP_DEVICE_ADDR,
1197 sizeof(bdaddr), bdaddr);
1200 DBG("Device address [%s] property Num [%d]", address, ev->num_props);
1202 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_ADDR,
1203 sizeof(bdaddr), bdaddr);
1206 event_cb = _bt_get_adapter_event_cb();
1208 ERR("event_cb is NULL");
1213 DBG("Send Device found event to HAL user,"
1214 " Num Prop [%d] total size [%d]", ev->num_props, size);
1215 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1222 int _bt_hal_dbus_get_local_address(void)
1225 GError *error = NULL;
1226 const char *address;
1232 proxy = _bt_hal_get_adapter_properties_proxy();
1234 DBG("_bt_hal_dbus_get_local_address: Adapter Properties proxy get failed!!!");
1235 return BT_STATUS_FAIL;
1238 result = g_dbus_proxy_call_sync(proxy,
1240 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1242 G_DBUS_CALL_FLAGS_NONE,
1248 ERR("Failed to get local address");
1249 if (error != NULL) {
1250 ERR("Failed to get local address (Error: %s)", error->message);
1251 g_clear_error(&error);
1253 return BT_STATUS_FAIL;
1256 g_variant_get(result, "(v)", &temp);
1257 address = g_variant_dup_string(temp, NULL);
1260 DBG("Address:%s", address);
1262 return BT_STATUS_FAIL;
1264 g_variant_unref(result);
1265 g_variant_unref(temp);
1268 * As we need to provide async callback to user from HAL, simply schedule a
1269 * callback method which will carry actual result
1271 g_idle_add(__bt_adapter_local_address_cb, (gpointer) address);
1274 return BT_STATUS_SUCCESS;
1277 /* Get Local services API and callback */
1278 static gboolean __bt_adapter_service_uuids_cb(gpointer user_data)
1280 GVariant *result = user_data;
1282 GVariantIter *iter = NULL;
1285 /* Buffer and propety count management */
1286 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1287 struct hal_ev_adapter_props_changed *ev = (void*) buf;
1290 /* UUID collection */
1291 uint8_t uuids[HAL_UUID_LEN * MAX_UUID_COUNT];
1294 memset(buf, 0, sizeof(buf));
1297 ev->status = BT_STATUS_SUCCESS;
1299 g_variant_get(result, "(v)", &temp);
1300 g_variant_get(temp, "as", &iter);
1302 ERR("Failed to get UUIDs");
1306 while (g_variant_iter_loop(iter, "s", &uuid_str)) {
1307 uint8_t uuid[HAL_UUID_LEN];
1309 DBG("UUID string [%s]\n", uuid_str);
1310 _bt_hal_convert_uuid_string_to_type(uuid, uuid_str);
1311 memcpy(uuids + uuid_count * HAL_UUID_LEN, uuid, HAL_UUID_LEN);
1315 size += __bt_insert_hal_properties(buf + size,
1316 HAL_PROP_ADAPTER_UUIDS,
1317 (HAL_UUID_LEN * uuid_count),
1322 event_cb = _bt_get_adapter_event_cb();
1324 ERR("event_cb is NULL");
1329 DBG("Send Adapter properties changed event to HAL user,"
1330 " Num Prop [%d] total size [%d]", ev->num_props, size);
1331 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1334 g_variant_iter_free(iter);
1335 g_variant_unref(result);
1336 g_variant_unref(temp);
1340 event_cb = _bt_get_adapter_event_cb();
1342 ev->status = BT_STATUS_FAIL;
1344 DBG("Send Adapter properties changed event to HAL user,"
1345 " Num Prop [%d] total size [%d]", ev->num_props, size);
1346 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1349 g_variant_unref(result);
1353 int _bt_hal_dbus_get_adapter_supported_uuids(void)
1356 GError *error = NULL;
1361 proxy = _bt_hal_get_adapter_properties_proxy();
1364 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1365 return BT_STATUS_FAIL;
1368 result = g_dbus_proxy_call_sync(proxy,
1370 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1372 G_DBUS_CALL_FLAGS_NONE,
1378 if (error != NULL) {
1379 ERR("Failed to get UUIDs (Error: %s)", error->message);
1380 g_clear_error(&error);
1382 ERR("Failed to get UUIDs");
1383 return BT_STATUS_FAIL;
1387 DBG("Got All Adaptr service UUID's from Bluez Stack!!, time to start parsing");
1390 * As we need to provide async callback to user from HAL, simply schedule a
1391 * callback method which will carry actual result
1393 g_idle_add(__bt_adapter_service_uuids_cb, (gpointer)result);
1396 return BT_STATUS_SUCCESS;
1399 static gboolean __is_device_paired(GVariantIter *item_iter)
1401 gboolean paired = FALSE;
1405 while (g_variant_iter_loop(item_iter, "{sv}", &key, &value)) {
1406 if (NULL == key || g_strcmp0(key, "Paired"))
1409 paired = g_variant_get_boolean(value);
1410 g_variant_unref(value);
1418 static gboolean __bt_adapter_bonded_devices_cb(gpointer user_data)
1420 /* Buffer and propety count management */
1421 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1422 uint8_t addresses[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1423 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1427 GVariant *result = user_data;
1429 GVariantIter *interface_iter;
1430 GVariantIter *svc_iter;
1431 char *object_path = NULL;
1432 char *interface_str = NULL;
1434 char device_address[BT_HAL_ADDRESS_STRING_SIZE];
1435 uint8_t bdaddr[BT_HAL_ADDRESS_LENGTH_MAX];
1437 memset(buf, 0, sizeof(buf));
1440 ev->status = BT_STATUS_SUCCESS;
1442 INFO("Size [%d]", size);
1444 /* signature of GetManagedObjects: a{oa{sa{sv}}} */
1445 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
1447 /* Parse the signature: {oa{sa{sv}}} */
1448 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path, &interface_iter)) {
1449 if (object_path == NULL)
1452 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
1453 &interface_str, &svc_iter)) {
1454 if (g_strcmp0(interface_str, "org.bluez.Device1") == 0) {
1455 DBG("Found a device: %s", object_path);
1456 if (__is_device_paired(svc_iter)) {
1457 _bt_hal_convert_device_path_to_address(object_path, device_address);
1458 DBG("Paired Device Address: [%s]", device_address);
1460 _bt_hal_convert_addr_string_to_type(bdaddr, device_address);
1461 memcpy((addresses + (count * BT_HAL_ADDRESS_LENGTH_MAX)),
1462 bdaddr, BT_HAL_ADDRESS_LENGTH_MAX);
1465 g_variant_iter_free(svc_iter);
1466 g_free(interface_str);
1467 interface_str = NULL;
1473 g_variant_iter_free(iter);
1474 g_variant_unref(result);
1476 size += __bt_insert_hal_properties((buf + size),
1477 HAL_PROP_ADAPTER_BONDED_DEVICES,
1478 (count * BT_HAL_ADDRESS_LENGTH_MAX), addresses);
1482 event_cb = _bt_get_adapter_event_cb();
1484 ERR("event_cb is NULL");
1489 DBG("Send Adapter properties changed event to HAL user,"
1490 " Num Prop [%d] total size [%d]", ev->num_props, size);
1491 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1497 int _bt_hal_dbus_get_bonded_devices(void)
1499 GDBusProxy *manager_proxy;
1500 GVariant *result = NULL;
1504 manager_proxy = _bt_hal_get_manager_proxy();
1505 if (manager_proxy == NULL)
1506 return BT_STATUS_FAIL;
1508 result = g_dbus_proxy_call_sync(manager_proxy, "GetManagedObjects",
1510 G_DBUS_CALL_FLAGS_NONE,
1515 ERR("Can't get managed objects");
1516 return BT_STATUS_FAIL;
1520 * As we need to provide async callback to user from HAL, simply schedule a
1521 * callback method which will carry actual result
1523 g_idle_add(__bt_adapter_bonded_devices_cb, (gpointer) result);
1526 return BT_STATUS_SUCCESS;
1529 int _bt_hal_dbus_get_adapter_property(bt_property_type_t property_type)
1533 INFO("property_type: %d", property_type);
1535 switch (property_type) {
1536 case BT_PROPERTY_BDADDR:
1537 return _bt_hal_dbus_get_local_address();
1538 case BT_PROPERTY_BDNAME:
1539 return _bt_hal_dbus_get_local_name();
1540 case BT_PROPERTY_VERSION:
1541 return _bt_hal_dbus_get_local_version();
1542 case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
1543 return _bt_hal_dbus_get_discovery_timeout();
1544 case BT_PROPERTY_ADAPTER_SCAN_MODE:
1545 return _bt_hal_dbus_get_scan_mode();
1546 case BT_PROPERTY_CLASS_OF_DEVICE:
1547 return BT_STATUS_UNSUPPORTED;
1548 case BT_PROPERTY_UUIDS:
1549 return _bt_hal_dbus_get_adapter_supported_uuids();
1550 case BT_PROPERTY_ADAPTER_BONDED_DEVICES:
1551 return _bt_hal_dbus_get_bonded_devices();
1553 return BT_STATUS_UNSUPPORTED;
1559 static int __bt_hal_dbus_set_local_name(void *data)
1562 const char *name = data;
1564 GError *error = NULL;
1567 DBG("Local Name: [%s]", name);
1568 proxy = _bt_hal_get_adapter_properties_proxy();
1570 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1571 return BT_STATUS_FAIL;
1574 result = g_dbus_proxy_call_sync(proxy,
1576 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1577 "Alias", g_variant_new("s", name)),
1578 G_DBUS_CALL_FLAGS_NONE,
1583 if (error != NULL) {
1584 ERR("Failed to set local name (Error: %s)", error->message);
1585 g_clear_error(&error);
1587 ERR("Failed to set local name");
1588 return BT_STATUS_FAIL;
1590 g_variant_unref(result);
1593 return BT_STATUS_SUCCESS;
1596 static int __bt_hal_dbus_set_scan_mode(void *data)
1601 GError *error = NULL;
1606 DBG("Scan mode: [%d]", *mode);
1607 proxy = _bt_hal_get_adapter_properties_proxy();
1609 DBG("Adapter Properties proxy get failed!!!");
1610 return BT_STATUS_FAIL;
1614 case BT_SCAN_MODE_NONE:
1618 case BT_SCAN_MODE_CONNECTABLE:
1622 case BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
1627 ERR("Invalid scan mode");
1628 return BT_STATUS_FAIL;
1631 result = g_dbus_proxy_call_sync(proxy,
1633 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1634 "Connectable", g_variant_new("b", pg_scan)),
1635 G_DBUS_CALL_FLAGS_NONE,
1640 if (error != NULL) {
1641 ERR("Failed to set connectable property (Error: %s)", error->message);
1642 g_clear_error(&error);
1644 ERR("Failed to set connectable property");
1645 return BT_STATUS_FAIL;
1647 g_variant_unref(result);
1649 result = g_dbus_proxy_call_sync(proxy,
1651 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE, "Discoverable",
1652 g_variant_new("b", inq_scan)),
1653 G_DBUS_CALL_FLAGS_NONE,
1658 if (error != NULL) {
1659 ERR("Failed to set Discoverable property (Error: %s)", error->message);
1660 g_clear_error(&error);
1662 ERR("Failed to set Discoverable property");
1663 return BT_STATUS_FAIL;
1665 g_variant_unref(result);
1668 return BT_STATUS_SUCCESS;
1671 static int __bt_hal_dbus_set_discovery_timeout(void *data)
1674 unsigned int *timeout = data;
1676 GError *error = NULL;
1681 DBG("Discovery Timeout: [%d]", *timeout);
1682 proxy = _bt_hal_get_adapter_properties_proxy();
1684 DBG("Adapter Properties proxy get failed!!!");
1685 return BT_STATUS_FAIL;
1688 result = g_dbus_proxy_call_sync(proxy,
1690 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1691 "DiscoverableTimeout", g_variant_new("u", *timeout)),
1692 G_DBUS_CALL_FLAGS_NONE,
1697 if (error != NULL) {
1698 ERR("Failed to set DiscoverableTimeout property (Error: %s)", error->message);
1699 g_clear_error(&error);
1701 ERR("Failed to set DiscoverableTimeout property");
1702 return BT_STATUS_FAIL;
1704 g_variant_unref(result);
1707 return BT_STATUS_SUCCESS;
1710 /* Set Adapter Properties */
1711 int _bt_hal_dbus_set_adapter_property(const bt_property_t *property)
1717 if (property == NULL || property->val == NULL) {
1718 ERR("Invalid parameters received");
1719 return BT_STATUS_FAIL;
1722 switch (property->type) {
1723 case BT_PROPERTY_BDNAME:
1724 result = __bt_hal_dbus_set_local_name(property->val);
1726 case BT_PROPERTY_ADAPTER_SCAN_MODE:
1727 result = __bt_hal_dbus_set_scan_mode(property->val);
1729 case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
1730 result = __bt_hal_dbus_set_discovery_timeout(property->val);
1733 result = BT_STATUS_UNSUPPORTED;
1736 DBG("Result= [%d]", result);