4 * Copyright (c) 2015 -2016 Samsung Electronics Co., Ltd All Rights Reserved.
6 * Contact: Anupam Roy <anupam.r@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
33 #include "bt-hal-log.h"
34 #include "bt-hal-msg.h"
35 #include "bt-hal-utils.h"
37 #include <bt-hal-adapter-dbus-handler.h>
38 #include <bt-hal-dbus-common-utils.h>
40 #define BT_ENABLE_TIMEOUT 20000 /* 20 seconds */
41 #define BT_CORE_NAME "org.projectx.bt_core"
42 #define BT_CORE_PATH "/org/projectx/bt_core"
43 #define BT_CORE_INTERFACE "org.projectx.btcore"
45 static GDBusProxy *core_proxy = NULL;
46 static GDBusConnection *system_conn = NULL;
47 static handle_stack_msg event_cb = NULL;
49 handle_stack_msg _bt_get_adapter_event_cb(void)
57 GDBusConnection *__bt_hal_get_system_gconn(void)
60 if (system_conn == NULL)
61 system_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
67 GDBusProxy *_bt_init_core_proxy(void)
69 GDBusConnection *conn;
72 conn = __bt_hal_get_system_gconn();
76 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
92 static GDBusProxy *__bt_get_core_proxy(void)
94 return (core_proxy) ? core_proxy : _bt_init_core_proxy();
97 /* To send stack event to hal-bluetooth handler */
98 void _bt_hal_dbus_store_stack_msg_cb(handle_stack_msg cb)
103 static gboolean __bt_hal_send_adapter_event(gpointer user_data)
105 struct hal_ev_adapter_state_changed ev;
106 gboolean *enable = (gboolean *)user_data;
109 ev.state = HAL_POWER_ON;
111 ev.state = HAL_POWER_OFF;
114 event_cb = _bt_get_adapter_event_cb();
117 event_cb(HAL_EV_ADAPTER_STATE_CHANGED, &ev, sizeof(ev));
123 static gboolean __bt_hal_send_le_event(gpointer user_data)
125 struct hal_ev_le_state_changed ev;
126 gboolean *enable = (gboolean *)user_data;
129 ev.state = HAL_POWER_ON;
131 ev.state = HAL_POWER_OFF;
134 event_cb = _bt_get_adapter_event_cb();
137 event_cb(HAL_EV_LE_STATE_CHANGED, &ev, sizeof(ev));
144 int _bt_hal_dbus_enable_adapter(void)
147 GError *error = NULL;
148 GVariant *result = NULL;
149 unsigned char powered = 0;
153 int le_value = VCONFKEY_BT_LE_STATUS_OFF;
154 if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &le_value)) {
155 ERR("fail to get vconf key!");
158 if(_bt_hal_get_adapter_powered_state(&powered) == BT_STATUS_FAIL) {
159 ERR("_bt_hal_get_adapter_powered_state failed");
162 /*if LE is enabled and bluez is UP , send event from here and return.*/
163 if((le_value == VCONFKEY_BT_LE_STATUS_ON)&&(powered == 1)) {
164 gboolean *user_data = g_new0(int, 1);
166 g_idle_add(__bt_hal_send_adapter_event, (gpointer)user_data);
167 return BT_STATUS_SUCCESS;
169 proxy = __bt_get_core_proxy();
172 DBG("_bt_hal_dbus_enable_adapter: Core proxy get failed!!!");
173 return BT_STATUS_FAIL;
176 _bt_hal_set_adapter_request_state(TRUE);
177 _bt_hal_set_le_request_state(TRUE);
178 result = g_dbus_proxy_call_sync(proxy, "EnableAdapter",
180 G_DBUS_CALL_FLAGS_NONE, BT_ENABLE_TIMEOUT,
183 DBG("EnableAdapter failed: %s", error->message);
184 g_clear_error(&error);
186 _bt_hal_set_adapter_request_state(FALSE);
187 _bt_hal_set_le_request_state(FALSE);
188 result = g_dbus_proxy_call_sync(proxy,
191 G_DBUS_CALL_FLAGS_NONE,
197 DBG("Bt core call failed(Error: %s)", error->message);
198 g_clear_error(&error);
200 g_variant_unref(result);
202 /* TODO: Terminate bluetooth service or not, need to check */
203 /*g_idle_add((GSourceFunc)_bt_terminate_service, NULL);*/
204 return BT_STATUS_FAIL;
208 g_variant_unref(result);
209 return BT_STATUS_SUCCESS;
212 int _bt_hal_dbus_disable_adapter(void)
215 GError *error = NULL;
216 GVariant *result = NULL;
219 proxy = __bt_get_core_proxy();
222 DBG("_bt_hal_dbus_enable_adapter: Core proxy get failed!!!");
223 return BT_STATUS_FAIL;
226 result = g_dbus_proxy_call_sync(proxy, "DisableAdapter",
228 G_DBUS_CALL_FLAGS_NONE, -1,
231 DBG("DisableAdapter failed: %s", error->message);
232 g_clear_error(&error);
234 g_variant_unref(result);
236 /* TODO: Terminate bluetooth service or not, need to check */
237 /*g_idle_add((GSourceFunc)_bt_terminate_service, NULL);*/
238 return BT_STATUS_FAIL;
242 g_variant_unref(result);
243 return BT_STATUS_SUCCESS;
247 int _bt_hal_dbus_enable_le(void)
250 GError *error = NULL;
251 GVariant *result = NULL;
252 int adapter_value = VCONFKEY_BT_STATUS_OFF;
253 unsigned char powered = 0;
257 if (vconf_get_int(VCONFKEY_BT_STATUS, &adapter_value) != 0) {
258 ERR("fail to get vconf key!");
261 if(_bt_hal_get_adapter_powered_state(&powered) == BT_STATUS_FAIL) {
262 ERR("_bt_hal_get_adapter_powered_state failed");
265 if((adapter_value == VCONFKEY_BT_STATUS_ON) && (powered == 1)) {
266 gboolean *user_data = g_new0(int, 1);
268 g_idle_add(__bt_hal_send_le_event, (gpointer)user_data);
269 return BT_STATUS_SUCCESS;
272 proxy = __bt_get_core_proxy();
275 DBG("_bt_hal_dbus_enable_le: Core proxy get failed!!!");
276 return BT_STATUS_FAIL;
278 _bt_hal_set_le_request_state(TRUE);
280 result = g_dbus_proxy_call_sync(proxy, "EnableAdapterLe",
282 G_DBUS_CALL_FLAGS_NONE, BT_ENABLE_TIMEOUT,
285 DBG("EnableAdapter failed: %s", error->message);
286 g_clear_error(&error);
288 result = g_dbus_proxy_call_sync(proxy,
291 G_DBUS_CALL_FLAGS_NONE,
296 _bt_hal_set_le_request_state(FALSE);
298 DBG("Bt core call failed(Error: %s)", error->message);
299 g_clear_error(&error);
301 g_variant_unref(result);
303 return BT_STATUS_FAIL;
307 g_variant_unref(result);
308 return BT_STATUS_SUCCESS;
311 int _bt_hal_dbus_disable_le(void)
314 GError *error = NULL;
315 GVariant *result = NULL;
316 int adapter_value = VCONFKEY_BT_STATUS_OFF;
319 if (vconf_get_int(VCONFKEY_BT_STATUS, &adapter_value) != 0) {
320 ERR("fail to get vconf key!");
323 if(adapter_value == VCONFKEY_BT_STATUS_ON) {
324 gboolean *user_data = g_new0(int, 1);
326 g_idle_add(__bt_hal_send_le_event, (gpointer)user_data);
327 return BT_STATUS_SUCCESS;
330 proxy = __bt_get_core_proxy();
333 DBG("_bt_hal_dbus_disable_le: Core proxy get failed!!!");
334 return BT_STATUS_FAIL;
337 result = g_dbus_proxy_call_sync(proxy, "DisableAdapterLe",
339 G_DBUS_CALL_FLAGS_NONE, -1,
342 DBG("DisableAdapter failed: %s", error->message);
343 g_clear_error(&error);
345 g_variant_unref(result);
346 return BT_STATUS_FAIL;
352 g_variant_unref(result);
353 return BT_STATUS_SUCCESS;
358 int _bt_hal_dbus_reset_adapter(void)
362 GError *error = NULL;
365 proxy = __bt_get_core_proxy();
367 return BT_STATUS_FAIL;
369 result = g_dbus_proxy_call_sync(proxy,
372 G_DBUS_CALL_FLAGS_NONE,
379 ERR("Failed to ResetAdapter (Error: %s)", error->message);
380 g_clear_error(&error);
382 ERR("Failed to ResetAdapter");
383 return BT_STATUS_FAIL;
386 g_variant_unref(result);
387 return BT_STATUS_SUCCESS;
391 int _bt_hal_dbus_start_discovery(gboolean is_custom,
392 bt_disc_role_type_t role)
395 GError *error = NULL;
397 const gchar *disc_type;
398 DBG("Discovery Type: Is Custom : [%s]", is_custom ? "TRUE" : "FALSE");
400 proxy = _bt_hal_get_adapter_proxy();
402 DBG("Adapter proxy get failed!!!");
403 return BT_STATUS_FAIL;
407 if (role == BT_DISC_ROLE_BREDR)
409 else if (role == BT_DISC_ROLE_LE)
411 else if (role == BT_DISC_ROLE_DUAL)
412 disc_type = "LE_BREDR";
414 return BT_STATUS_PARM_INVALID;
416 result = g_dbus_proxy_call_sync(proxy,
417 "StartCustomDiscovery",
418 g_variant_new("s", disc_type),
419 G_DBUS_CALL_FLAGS_NONE,
424 result = g_dbus_proxy_call_sync(proxy,
427 G_DBUS_CALL_FLAGS_NONE,
434 ERR("StartDiscovery failed (Error: %s)", error->message);
435 g_clear_error(&error);
437 ERR("StartDiscovery failed");
438 return BT_STATUS_FAIL;
441 /* discovery status will be change in event */
443 g_variant_unref(result);
444 return BT_STATUS_SUCCESS;
447 int _bt_hal_dbus_stop_discovery(void)
450 GError *error = NULL;
454 proxy = _bt_hal_get_adapter_proxy();
456 DBG("_bt_hal_dbus_stop_discovery: Adapter proxy get failed!!!");
457 return BT_STATUS_FAIL;
460 result = g_dbus_proxy_call_sync(proxy,
463 G_DBUS_CALL_FLAGS_NONE,
470 ERR("StopDiscovery failed (Error: %s)", error->message);
471 g_clear_error(&error);
473 ERR("StopDiscovery failed");
474 return BT_STATUS_FAIL;
477 /* discovery status will be change in event */
479 g_variant_unref(result);
480 return BT_STATUS_SUCCESS;
483 static void ___bt_fill_le_supported_features(const char *item,
484 const char *value, uint8_t *le_features)
488 if (g_strcmp0(item, "adv_inst_max") == 0) {
489 le_features[1] = atoi(value);
490 } else if (g_strcmp0(item, "rpa_offloading") == 0) {
491 le_features[2] = atoi(value);
492 } else if (g_strcmp0(item, "max_filter") == 0) {
493 le_features[4] = atoi(value);
495 DBG("No registered item");
499 * TODO: Need to check these usages for Bluez Case. In Bluedroid case,
500 * these are used, so just setting all to 0
502 le_features[3] = 0; /* Adapter MAX IRK List Size */
504 le_features[5] = 0; /* Adapter Scan result storage size */
507 le_features[7] = 0; /* Adapter Activity energy info supported */
512 static gboolean __bt_adapter_all_properties_cb(gpointer user_data)
514 GVariant *result = user_data;
515 GVariantIter *property_iter;
519 /* Buffer and propety count management */
520 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
521 struct hal_ev_adapter_props_changed *ev = (void*) buf;
523 gchar *address = NULL;
525 unsigned int cod = 0;
526 gboolean discoverable;
527 gboolean connectable;
528 unsigned int scan_mode = BT_SCAN_MODE_NONE;
529 unsigned int disc_timeout;
531 gboolean is_discovering;
532 gboolean is_le_discovering;
533 uint8_t ipsp_initialized;
536 unsigned int pairable_timeout;
537 gboolean scan_mode_property_update = FALSE;
541 memset(buf, 0, sizeof(buf));
544 ev->status = BT_STATUS_SUCCESS;
546 DBG("@@Start parsing properties");
547 g_variant_get(result, "(a{sv})", &property_iter);
548 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
549 if(!g_strcmp0(key, "Address")) {
552 address = (gchar *) g_variant_get_string(value, NULL);
553 DBG("Address [%s]", address);
554 _bt_hal_convert_addr_string_to_type(bdaddr, address);
555 size += __bt_insert_hal_properties(buf + size,
556 HAL_PROP_ADAPTER_ADDR, sizeof(bdaddr), bdaddr);
559 } else if (!g_strcmp0(key, "Alias")) {
560 name = (gchar *) g_variant_get_string(value, NULL);
561 DBG("Alias [%s]", name);
562 size += __bt_insert_hal_properties(buf + size,
563 HAL_PROP_ADAPTER_NAME, strlen(name) + 1, name);
566 } else if (!g_strcmp0(key, "Class")) {
567 cod = g_variant_get_uint32(value);
568 DBG("Class [%d]", cod);
569 size += __bt_insert_hal_properties(buf + size,
570 HAL_PROP_ADAPTER_CLASS, sizeof(unsigned int), &cod);
572 } else if (!g_strcmp0(key, "Discoverable")) {
573 discoverable = g_variant_get_boolean(value);
574 DBG("Discoverable [%d]", discoverable);
576 scan_mode = BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
577 scan_mode_property_update = TRUE;
578 } else if (!g_strcmp0(key, "DiscoverableTimeout")) {
579 disc_timeout = g_variant_get_uint32(value);
580 DBG("Discoverable Timeout [%d]", disc_timeout);
581 size += __bt_insert_hal_properties(buf + size,
582 HAL_PROP_ADAPTER_DISC_TIMEOUT, sizeof(unsigned int), &disc_timeout);
584 } else if (!g_strcmp0(key, "Connectable")) {
585 connectable = g_variant_get_boolean(value);
586 DBG("Connectable [%d]", connectable);
587 if (scan_mode == BT_SCAN_MODE_NONE)
588 scan_mode = BT_SCAN_MODE_CONNECTABLE;
589 scan_mode_property_update = TRUE;
590 } else if (!g_strcmp0(key, "Version")) {
591 version = (gchar *) g_variant_get_string(value, NULL);
592 DBG("Version [%s]", version);
593 size += __bt_insert_hal_properties(buf + size,
594 HAL_PROP_ADAPTER_VERSION, strlen(version) + 1, version);
596 } else if (!g_strcmp0(key, "Name")) {
597 name = (gchar *) g_variant_get_string(value, NULL);
598 DBG("Name [%s]", name);
599 size += __bt_insert_hal_properties(buf + size,
600 HAL_PROP_ADAPTER_NAME, strlen(name) + 1, name);
603 } else if (!g_strcmp0(key, "Powered")) {
604 powered = g_variant_get_boolean(value);
605 DBG("Powered = [%d]", powered);
606 } else if (!g_strcmp0(key, "Pairable")) {
607 pairable = (g_variant_get_boolean(value) ? 1 : 0);
608 DBG("Pairable [%d]", pairable);
609 size += __bt_insert_hal_properties(buf + size,
610 HAL_PROP_ADAPTER_PAIRABLE, sizeof(uint8_t), &pairable);
612 } else if (!g_strcmp0(key, "PairableTimeout")) {
613 pairable_timeout = g_variant_get_uint32(value);
614 DBG("Pairable Timeout = [%d]", pairable_timeout);
615 size += __bt_insert_hal_properties(buf + size,
616 HAL_PROP_ADAPTER_PAIRABLE_TIMEOUT, sizeof(unsigned int), &pairable_timeout);
618 } else if (!g_strcmp0(key, "UUIDs")) {
623 size1 = g_variant_get_size(value);
624 int num_props_tmp = ev->num_props;
626 uuid_value = (char **)g_variant_get_strv(value, &size1);
627 for (i = 0; uuid_value[i] != NULL; i++)
629 /* UUID collection */
630 uint8_t uuids[HAL_UUID_LEN * uuid_count];
631 for (i = 0; uuid_value[i] != NULL; i++) {
632 char *uuid_str = NULL;
633 uint8_t uuid[HAL_UUID_LEN];
634 uuid_str = g_strdup(uuid_value[i]);
635 DBG("UUID string [%s]\n", uuid_str);
636 _bt_hal_convert_uuid_string_to_type(uuid, uuid_str);
637 memcpy(uuids + i * HAL_UUID_LEN, uuid, HAL_UUID_LEN);
639 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_UUIDS,
640 (HAL_UUID_LEN * uuid_count),
642 ev->num_props = num_props_tmp + 1;
645 } else if (!g_strcmp0(key, "Discovering")) {
646 is_discovering = g_variant_get_boolean(value);
647 DBG("Discovering = [%d]", is_discovering);
648 } else if (!g_strcmp0(key, "LEDiscovering")) {
649 is_le_discovering = g_variant_get_boolean(value);
650 DBG("LE Discovering = [%d]", is_le_discovering);
651 } else if (!g_strcmp0(key, "Modalias")) {
652 char *modalias = NULL;
653 g_variant_get(value, "s", &modalias);
654 DBG("Adapter ModAlias [%s]", modalias);
655 size += __bt_insert_hal_properties(buf + size,
656 HAL_PROP_ADAPTER_MODALIAS, strlen(modalias) + 1, modalias);
659 } else if (!g_strcmp0(key, "SupportedLEFeatures")) {
660 DBG("LE Supported features");
663 GVariantIter *iter = NULL;
664 uint8_t le_features[8];
665 gboolean le_features_present = FALSE;
667 g_variant_get(value, "as", &iter);
669 while (g_variant_iter_loop(iter, "s", &name)) {
670 DBG("name = %s", name);
671 g_variant_iter_loop(iter, "s", &val);
672 DBG("Value = %s", val);
673 ___bt_fill_le_supported_features(name, val, le_features);
674 le_features_present = TRUE;
676 g_variant_iter_free(iter);
678 if (le_features_present) {
679 size += __bt_insert_hal_properties(buf + size,
680 HAL_PROP_ADAPTER_LOCAL_LE_FEAT, sizeof(le_features), le_features);
683 DBG("le supported features values are NOT provided by Stack");
686 } else if (!g_strcmp0(key, "IpspInitStateChanged")) {
687 ipsp_initialized = (g_variant_get_boolean(value) ? 1 : 0);
688 DBG("IPSP Initialized = %d", ipsp_initialized);
689 size += __bt_insert_hal_properties(buf + size,
690 HAL_PROP_ADAPTER_IPSP_INITIALIZED, sizeof(uint8_t), &ipsp_initialized);
693 ERR("Unhandled Property:[%s]", key);
697 if (scan_mode_property_update) {
698 size += __bt_insert_hal_properties(buf + size,
699 HAL_PROP_ADAPTER_SCAN_MODE, sizeof(int), &scan_mode);
704 event_cb = _bt_get_adapter_event_cb();
706 ERR("event_cb is NULL");
711 DBG("Send Adapter properties changed event to HAL user,"
712 " Num Prop [%d] total size [%d]", ev->num_props, size);
713 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
716 g_variant_unref(result);
720 static int __bt_hal_dbus_get_all_adapter_properties(void)
724 GError *error = NULL;
728 proxy = _bt_hal_get_adapter_properties_proxy();
730 DBG("Adapter Properties proxy get failed!!!");
731 return BT_STATUS_FAIL;
734 result = g_dbus_proxy_call_sync(proxy,
736 g_variant_new("(s)", BT_HAL_ADAPTER_INTERFACE),
737 G_DBUS_CALL_FLAGS_NONE,
744 ERR("Failed to get all adapter properties (Error: %s)", error->message);
745 g_clear_error(&error);
747 ERR("Failed to get all adapter properties");
748 return BT_STATUS_FAIL;
751 DBG("Got All properties from Bluez Stack!!, time to start parsing");
753 * As we need to provide async callback to user from HAL, simply schedule a
754 * callback method which will carry actual result
756 g_idle_add(__bt_adapter_all_properties_cb, (gpointer)result);
759 return BT_STATUS_SUCCESS;
762 int _bt_hal_dbus_get_adapter_properties(void)
766 return __bt_hal_dbus_get_all_adapter_properties();
769 int _bt_hal_get_adapter_powered_state(uint8_t *state)
771 char *adapter_path = NULL;
772 gboolean powered = FALSE;
773 int ret = BT_STATUS_FAIL;
775 /* Check Valid Adapter Path, followed by Adapter Powered state.
776 If any of these fails, adapter will be considered Disabled */
777 adapter_path = _bt_hal_get_adapter_path();
779 if (adapter_path == NULL) {
780 INFO("Adapter is not powered");
781 g_free(adapter_path);
786 /* Check Adapter Powered Status */
787 ret = _bt_hal_is_adapter_powered(&powered);
788 if (BT_STATUS_FAIL == ret) {
789 INFO("Adapter is not powered");
802 /* Get Discoverable timeout API and callback */
803 static gboolean __bt_adapter_discovery_timeout_cb(gpointer user_data)
805 /* Buffer and propety count management */
806 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
807 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
809 unsigned int *timeout = user_data;
811 memset(buf, 0, sizeof(buf));
814 ev->status = BT_STATUS_SUCCESS;
816 DBG("Discovery timeout in callback: [%d]", *timeout);
818 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_DISC_TIMEOUT,
819 sizeof(unsigned int), timeout);
822 DBG("Timeout value [%d] property Num [%d]", *timeout, ev->num_props);
825 event_cb = _bt_get_adapter_event_cb();
827 ERR("event_cb is NULL");
832 DBG("Send Adapter Properties changed event to HAL user,"
833 " Num Prop [%d] total size [%d]",ev->num_props, size);
834 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
841 int _bt_hal_dbus_get_discovery_timeout(void)
846 GError *error = NULL;
847 unsigned int *timeout;
850 proxy = _bt_hal_get_adapter_properties_proxy();
852 DBG("Adapter Properties proxy get failed!!!");
853 return BT_STATUS_FAIL;
856 result = g_dbus_proxy_call_sync(proxy,
858 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
859 "DiscoverableTimeout"),
860 G_DBUS_CALL_FLAGS_NONE,
867 ERR("Failed to get local version (Error: %s)", error->message);
868 g_clear_error(&error);
870 ERR("Failed to get local version");
871 return BT_STATUS_FAIL;
874 timeout = g_malloc0(sizeof(int));
876 ERR("Memory allocation failed");
877 g_variant_unref(result);
878 return BT_STATUS_FAIL;
881 g_variant_get(result, "(v)", &temp);
882 *timeout = g_variant_get_uint32(temp);
883 DBG("Timeout value: [%d]", *timeout);
885 g_variant_unref(result);
886 g_variant_unref(temp);
889 * As we need to provide async callback to user from HAL, simply schedule a
890 * callback method which will carry actual result
892 g_idle_add(__bt_adapter_discovery_timeout_cb, (gpointer) timeout);
895 return BT_STATUS_SUCCESS;
898 /* Get Discoverable Mode API and callback */
899 static gboolean __bt_adapter_scan_mode_cb(gpointer user_data)
901 /* Buffer and propety count management */
902 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
903 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
905 int *mode = user_data;
907 memset(buf, 0, sizeof(buf));
910 ev->status = BT_STATUS_SUCCESS;
912 DBG("Scan mode callback: [%d]", *mode);
914 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_SCAN_MODE,
918 DBG("Scan mode [%d] property Num [%d]", *mode, ev->num_props);
921 event_cb = _bt_get_adapter_event_cb();
923 ERR("event_cb is NULL");
928 DBG("Send Adapter Properties changed event to HAL user,"
929 " Num Prop [%d] total size [%d]",ev->num_props, size);
930 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
937 int _bt_hal_dbus_get_scan_mode(void)
940 gboolean discoverable;
941 gboolean connectable;
944 GError *error = NULL;
949 proxy = _bt_hal_get_adapter_properties_proxy();
951 DBG("Adapter Properties proxy get failed!!!");
952 return BT_STATUS_FAIL;
955 result = g_dbus_proxy_call_sync(proxy,
957 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
959 G_DBUS_CALL_FLAGS_NONE,
966 ERR("Failed to get discoverable mode (Error: %s)", error->message);
967 g_clear_error(&error);
969 ERR("Failed to get discoverable mode");
970 return BT_STATUS_FAIL;
973 g_variant_get(result, "(v)", &temp);
974 discoverable = g_variant_get_boolean(temp);
975 DBG("discoverable:%d", discoverable);
977 g_variant_unref(result);
978 g_variant_unref(temp);
981 result = g_dbus_proxy_call_sync(proxy,
983 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
985 G_DBUS_CALL_FLAGS_NONE,
991 ERR("Failed to get connectable mode (Error: %s)", error->message);
992 g_clear_error(&error);
994 ERR("Failed to get connectable mode");
995 return BT_STATUS_FAIL;
998 g_variant_get(result, "(v)", &temp);
999 connectable = g_variant_get_boolean(temp);
1000 DBG("connectable:%d", connectable);
1002 g_variant_unref(result);
1003 g_variant_unref(temp);
1006 scan_mode = g_malloc0(sizeof(int));
1008 ERR("Memory allocation failed");
1009 return BT_STATUS_FAIL;
1013 *scan_mode = BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
1014 else if (connectable)
1015 *scan_mode = BT_SCAN_MODE_CONNECTABLE;
1017 *scan_mode = BT_SCAN_MODE_NONE;
1020 * As we need to provide async callback to user from HAL, simply schedule a
1021 * callback method which will carry actual result
1023 g_idle_add(__bt_adapter_scan_mode_cb, (gpointer) scan_mode);
1026 return BT_STATUS_SUCCESS;
1029 /* Get Local Version API and callback */
1030 static gboolean __bt_adapter_local_version_cb(gpointer user_data)
1032 /* Buffer and propety count management */
1033 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1034 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1036 char *version = NULL;
1038 memset(buf, 0, sizeof(buf));
1041 ev->status = BT_STATUS_SUCCESS;
1043 version = (char*) user_data;
1044 DBG("Local Version in callback: [%s]", version);
1046 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_VERSION,
1047 (strlen(version) + 1), version);
1050 DBG("Device version [%s] property Num [%d]", version, ev->num_props);
1053 event_cb = _bt_get_adapter_event_cb();
1055 ERR("event_cb is NULL");
1060 DBG("Send Adapter Properties changed event to HAL user,"
1061 " Num Prop [%d] total size [%d]",ev->num_props, size);
1062 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1069 int _bt_hal_dbus_get_local_version(void)
1072 const char *version = NULL;
1075 GError *error = NULL;
1078 proxy = _bt_hal_get_adapter_properties_proxy();
1080 DBG("Adapter Properties proxy get failed!!!");
1081 return BT_STATUS_FAIL;
1084 result = g_dbus_proxy_call_sync(proxy,
1086 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1088 G_DBUS_CALL_FLAGS_NONE,
1094 if (error != NULL) {
1095 ERR("Failed to get local version (Error: %s)", error->message);
1096 g_clear_error(&error);
1098 ERR("Failed to get local version");
1099 return BT_STATUS_FAIL;
1102 g_variant_get(result, "(v)", &temp);
1103 version = g_variant_dup_string(temp, NULL);
1104 DBG("Local Version: [%s]", version);
1106 g_variant_unref(result);
1107 g_variant_unref(temp);
1110 * As we need to provide async callback to user from HAL, simply schedule a
1111 * callback method which will carry actual result
1113 g_idle_add(__bt_adapter_local_version_cb, (gpointer) version);
1116 return BT_STATUS_SUCCESS;
1119 /* Get Local Name API and callback */
1120 static gboolean __bt_adapter_local_name_cb(gpointer user_data)
1122 /* Buffer and propety count management */
1123 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1124 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1128 memset(buf, 0, sizeof(buf));
1131 ev->status = BT_STATUS_SUCCESS;
1133 name = (char*) user_data;
1134 DBG("Local Name in callback: [%s]", name);
1136 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_NAME,
1137 strlen(name) + 1, name);
1140 DBG("Device name [%s] property Num [%d]",name, ev->num_props);
1143 event_cb = _bt_get_adapter_event_cb();
1145 ERR("event_cb is NULL");
1150 DBG("Send Adapter Properties changed event to HAL user,"
1151 " Num Prop [%d] total size [%d]",ev->num_props, size);
1152 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1159 int _bt_hal_dbus_get_local_name(void)
1162 const char *name = NULL;
1165 GError *error = NULL;
1168 proxy = _bt_hal_get_adapter_properties_proxy();
1170 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1171 return BT_STATUS_FAIL;
1174 result = g_dbus_proxy_call_sync(proxy,
1176 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1178 G_DBUS_CALL_FLAGS_NONE,
1184 if (error != NULL) {
1185 ERR("Failed to get local name (Error: %s)", error->message);
1186 g_clear_error(&error);
1188 ERR("Failed to get local name");
1189 return BT_STATUS_FAIL;
1192 g_variant_get(result, "(v)", &temp);
1193 name = g_variant_dup_string(temp, NULL);
1194 DBG("Local Name: [%s]", name);
1196 g_variant_unref(result);
1197 g_variant_unref(temp);
1200 * As we need to provide async callback to user from HAL, simply schedule a
1201 * callback method which will carry actual result
1203 g_idle_add(__bt_adapter_local_name_cb, (gpointer) name);
1206 return BT_STATUS_SUCCESS;
1209 /* Get Local Address API and callback */
1210 static gboolean __bt_adapter_local_address_cb(gpointer user_data)
1212 /* Buffer and propety count management */
1213 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1214 struct hal_ev_adapter_props_changed *ev = (void*) buf;
1216 char * address = NULL;
1218 memset(buf, 0, sizeof(buf));
1221 ev->status = BT_STATUS_SUCCESS;
1223 address = (char*) user_data;
1226 _bt_hal_convert_addr_string_to_type(bdaddr, address);
1228 size += __bt_insert_hal_properties(buf + size, HAL_PROP_DEVICE_ADDR,
1229 sizeof(bdaddr), bdaddr);
1232 DBG("Device address [%s] property Num [%d]",address, ev->num_props);
1234 size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_ADDR,
1235 sizeof(bdaddr), bdaddr);
1238 event_cb = _bt_get_adapter_event_cb();
1240 ERR("event_cb is NULL");
1245 DBG("Send Device found event to HAL user,"
1246 " Num Prop [%d] total size [%d]",ev->num_props, size);
1247 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1254 int _bt_hal_dbus_get_local_address(void)
1257 GError *error = NULL;
1258 const char *address;
1264 proxy = _bt_hal_get_adapter_properties_proxy();
1266 DBG("_bt_hal_dbus_get_local_address: Adapter Properties proxy get failed!!!");
1267 return BT_STATUS_FAIL;
1270 result = g_dbus_proxy_call_sync(proxy,
1272 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1274 G_DBUS_CALL_FLAGS_NONE,
1280 ERR("Failed to get local address");
1281 if (error != NULL) {
1282 ERR("Failed to get local address (Error: %s)", error->message);
1283 g_clear_error(&error);
1285 return BT_STATUS_FAIL;
1288 g_variant_get(result, "(v)", &temp);
1289 address = g_variant_dup_string(temp, NULL);
1292 DBG("Address:%s", address);
1294 return BT_STATUS_FAIL;
1297 g_variant_unref(result);
1298 g_variant_unref(temp);
1301 * As we need to provide async callback to user from HAL, simply schedule a
1302 * callback method which will carry actual result
1304 g_idle_add(__bt_adapter_local_address_cb, (gpointer) address);
1307 return BT_STATUS_SUCCESS;
1310 /* Get Local services API and callback */
1311 static gboolean __bt_adapter_service_uuids_cb(gpointer user_data)
1313 GVariant *result = user_data;
1315 GVariantIter *iter = NULL;
1318 /* Buffer and propety count management */
1319 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1320 struct hal_ev_adapter_props_changed *ev = (void*) buf;
1323 /* UUID collection */
1324 uint8_t uuids[HAL_UUID_LEN * MAX_UUID_COUNT];
1327 memset(buf, 0, sizeof(buf));
1330 ev->status = BT_STATUS_SUCCESS;
1332 g_variant_get(result, "(v)", &temp);
1333 g_variant_get(temp, "as", &iter);
1335 ERR("Failed to get UUIDs");
1339 while (g_variant_iter_loop(iter, "s", &uuid_str)) {
1340 uint8_t uuid[HAL_UUID_LEN];
1342 DBG("UUID string [%s]\n", uuid_str);
1343 _bt_hal_convert_uuid_string_to_type(uuid, uuid_str);
1344 memcpy(uuids + uuid_count * HAL_UUID_LEN, uuid, HAL_UUID_LEN);
1348 size += __bt_insert_hal_properties(buf + size,
1349 HAL_PROP_ADAPTER_UUIDS,
1350 (HAL_UUID_LEN * uuid_count),
1355 event_cb = _bt_get_adapter_event_cb();
1357 ERR("event_cb is NULL");
1362 DBG("Send Adapter properties changed event to HAL user,"
1363 " Num Prop [%d] total size [%d]", ev->num_props, size);
1364 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1367 g_variant_iter_free(iter);
1368 g_variant_unref(result);
1369 g_variant_unref(temp);
1373 event_cb = _bt_get_adapter_event_cb();
1375 ev->status = BT_STATUS_FAIL;
1377 DBG("Send Adapter properties changed event to HAL user,"
1378 " Num Prop [%d] total size [%d]", ev->num_props, size);
1379 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1382 g_variant_unref(result);
1386 int _bt_hal_dbus_get_adapter_supported_uuids(void)
1389 GError *error = NULL;
1394 proxy = _bt_hal_get_adapter_properties_proxy();
1397 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1398 return BT_STATUS_FAIL;
1401 result = g_dbus_proxy_call_sync(proxy,
1403 g_variant_new("(ss)", BT_HAL_ADAPTER_INTERFACE,
1405 G_DBUS_CALL_FLAGS_NONE,
1411 if (error != NULL) {
1412 ERR("Failed to get UUIDs (Error: %s)", error->message);
1413 g_clear_error(&error);
1415 ERR("Failed to get UUIDs");
1416 return BT_STATUS_FAIL;
1420 DBG("Got All Adaptr service UUID's from Bluez Stack!!, time to start parsing");
1423 * As we need to provide async callback to user from HAL, simply schedule a
1424 * callback method which will carry actual result
1426 g_idle_add(__bt_adapter_service_uuids_cb, (gpointer)result);
1429 return BT_STATUS_SUCCESS;
1432 static gboolean __is_device_paired(GVariantIter *item_iter)
1434 gboolean paired = FALSE;
1438 while (g_variant_iter_loop(item_iter, "{sv}", &key, &value)) {
1439 if (NULL == key || g_strcmp0(key,"Paired"))
1442 paired = g_variant_get_boolean(value);
1443 g_variant_unref(value);
1451 static gboolean __bt_adapter_bonded_devices_cb(gpointer user_data)
1453 /* Buffer and propety count management */
1454 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1455 uint8_t addresses[BT_HAL_MAX_PROPERTY_BUF_SIZE];
1456 struct hal_ev_adapter_props_changed *ev = (void*) buf;;
1460 GVariant *result = user_data;
1462 GVariantIter *interface_iter;
1463 GVariantIter *svc_iter;
1464 char *object_path = NULL;
1465 char *interface_str = NULL;
1467 char device_address[BT_HAL_ADDRESS_STRING_SIZE];
1468 uint8_t bdaddr[BT_HAL_ADDRESS_LENGTH_MAX];
1470 memset(buf, 0, sizeof(buf));
1473 ev->status = BT_STATUS_SUCCESS;
1475 INFO("Size [%d]", size);
1477 /* signature of GetManagedObjects: a{oa{sa{sv}}} */
1478 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
1480 /* Parse the signature: {oa{sa{sv}}} */
1481 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path, &interface_iter)) {
1482 if(object_path == NULL)
1485 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
1486 &interface_str, &svc_iter)) {
1487 if (g_strcmp0(interface_str, "org.bluez.Device1") == 0) {
1488 DBG("Found a device: %s", object_path);
1489 if (__is_device_paired(svc_iter)) {
1490 _bt_hal_convert_device_path_to_address(object_path, device_address);
1491 DBG("Paired Device Address: [%s]", device_address);
1493 _bt_hal_convert_addr_string_to_type(bdaddr, device_address);
1494 memcpy((addresses + (count * BT_HAL_ADDRESS_LENGTH_MAX)),
1495 bdaddr, BT_HAL_ADDRESS_LENGTH_MAX);
1498 g_variant_iter_free(svc_iter);
1499 g_free(interface_str);
1500 interface_str = NULL;
1506 g_variant_iter_free(iter);
1507 g_variant_unref(result);
1509 size += __bt_insert_hal_properties((buf + size),
1510 HAL_PROP_ADAPTER_BONDED_DEVICES,
1511 (count * BT_HAL_ADDRESS_LENGTH_MAX), addresses);
1515 event_cb = _bt_get_adapter_event_cb();
1517 ERR("event_cb is NULL");
1522 DBG("Send Adapter properties changed event to HAL user,"
1523 " Num Prop [%d] total size [%d]",ev->num_props, size);
1524 event_cb(HAL_EV_ADAPTER_PROPS_CHANGED, (void*) buf, size);
1530 int _bt_hal_dbus_get_bonded_devices(void)
1532 GDBusProxy *manager_proxy;
1533 GVariant *result = NULL;
1537 manager_proxy = _bt_hal_get_manager_proxy();
1538 if (manager_proxy == NULL)
1539 return BT_STATUS_FAIL;
1541 result = g_dbus_proxy_call_sync(manager_proxy, "GetManagedObjects",
1543 G_DBUS_CALL_FLAGS_NONE,
1548 ERR("Can't get managed objects");
1549 return BT_STATUS_FAIL;
1553 * As we need to provide async callback to user from HAL, simply schedule a
1554 * callback method which will carry actual result
1556 g_idle_add(__bt_adapter_bonded_devices_cb, (gpointer) result);
1559 return BT_STATUS_SUCCESS;
1562 int _bt_hal_dbus_get_adapter_property(bt_property_type_t property_type)
1566 INFO("property_type: %d", property_type);
1568 switch (property_type) {
1569 case BT_PROPERTY_BDADDR:
1570 return _bt_hal_dbus_get_local_address();
1571 case BT_PROPERTY_BDNAME:
1572 return _bt_hal_dbus_get_local_name();
1573 case BT_PROPERTY_VERSION:
1574 return _bt_hal_dbus_get_local_version();
1575 case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
1576 return _bt_hal_dbus_get_discovery_timeout();
1577 case BT_PROPERTY_ADAPTER_SCAN_MODE:
1578 return _bt_hal_dbus_get_scan_mode();
1579 case BT_PROPERTY_CLASS_OF_DEVICE:
1580 return BT_STATUS_UNSUPPORTED;
1581 case BT_PROPERTY_UUIDS:
1582 return _bt_hal_dbus_get_adapter_supported_uuids();
1583 case BT_PROPERTY_ADAPTER_BONDED_DEVICES:
1584 return _bt_hal_dbus_get_bonded_devices();
1586 return BT_STATUS_UNSUPPORTED;
1592 static int __bt_hal_dbus_set_local_name(void *data)
1595 const char *name = data;
1597 GError *error = NULL;
1600 DBG("Local Name: [%s]", name);
1601 proxy = _bt_hal_get_adapter_properties_proxy();
1603 DBG("_bt_hal_dbus_get_local_name: Adapter Properties proxy get failed!!!");
1604 return BT_STATUS_FAIL;
1607 result = g_dbus_proxy_call_sync(proxy,
1609 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1610 "Alias", g_variant_new("s", name)),
1611 G_DBUS_CALL_FLAGS_NONE,
1616 if (error != NULL) {
1617 ERR("Failed to set local name (Error: %s)", error->message);
1618 g_clear_error(&error);
1620 ERR("Failed to set local name");
1621 return BT_STATUS_FAIL;
1623 g_variant_unref(result);
1626 return BT_STATUS_SUCCESS;
1629 static int __bt_hal_dbus_set_scan_mode(void *data)
1634 GError *error = NULL;
1639 DBG("Scan mode: [%d]", *mode);
1640 proxy = _bt_hal_get_adapter_properties_proxy();
1642 DBG("Adapter Properties proxy get failed!!!");
1643 return BT_STATUS_FAIL;
1647 case BT_SCAN_MODE_NONE:
1651 case BT_SCAN_MODE_CONNECTABLE:
1655 case BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
1660 ERR("Invalid scan mode");
1661 return BT_STATUS_FAIL;
1664 result = g_dbus_proxy_call_sync(proxy,
1666 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1667 "Connectable", g_variant_new("b", pg_scan)),
1668 G_DBUS_CALL_FLAGS_NONE,
1673 if (error != NULL) {
1674 ERR("Failed to set connectable property (Error: %s)", error->message);
1675 g_clear_error(&error);
1677 ERR("Failed to set connectable property");
1678 return BT_STATUS_FAIL;
1680 g_variant_unref(result);
1682 result = g_dbus_proxy_call_sync(proxy,
1684 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE, "Discoverable",
1685 g_variant_new("b", inq_scan)),
1686 G_DBUS_CALL_FLAGS_NONE,
1691 if (error != NULL) {
1692 ERR("Failed to set Discoverable property (Error: %s)", error->message);
1693 g_clear_error(&error);
1695 ERR("Failed to set Discoverable property");
1696 return BT_STATUS_FAIL;
1698 g_variant_unref(result);
1701 return BT_STATUS_SUCCESS;
1704 static int __bt_hal_dbus_set_discovery_timeout(void *data)
1707 unsigned int *timeout = data;
1709 GError *error = NULL;
1714 DBG("Discovery Timeout: [%d]", *timeout);
1715 proxy = _bt_hal_get_adapter_properties_proxy();
1717 DBG("Adapter Properties proxy get failed!!!");
1718 return BT_STATUS_FAIL;
1721 result = g_dbus_proxy_call_sync(proxy,
1723 g_variant_new("(ssv)", BT_HAL_ADAPTER_INTERFACE,
1724 "DiscoverableTimeout", g_variant_new("u", *timeout)),
1725 G_DBUS_CALL_FLAGS_NONE,
1730 if (error != NULL) {
1731 ERR("Failed to set DiscoverableTimeout property (Error: %s)", error->message);
1732 g_clear_error(&error);
1734 ERR("Failed to set DiscoverableTimeout property");
1735 return BT_STATUS_FAIL;
1737 g_variant_unref(result);
1740 return BT_STATUS_SUCCESS;
1743 /* Set Adapter Properties */
1744 int _bt_hal_dbus_set_adapter_property(const bt_property_t *property)
1750 if (property == NULL || property->val == NULL) {
1751 ERR("Invalid parameters received");
1752 return BT_STATUS_FAIL;
1755 switch (property->type) {
1756 case BT_PROPERTY_BDNAME:
1757 result = __bt_hal_dbus_set_local_name(property->val);
1759 case BT_PROPERTY_ADAPTER_SCAN_MODE:
1760 result = __bt_hal_dbus_set_scan_mode(property->val);
1762 case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
1763 result = __bt_hal_dbus_set_discovery_timeout(property->val);
1766 result = BT_STATUS_UNSUPPORTED;
1769 DBG("Result= [%d]", result);