Merge BlueZ upstream master branch
Merged several post-5.28-release fixes from BlueZ upstream .
BUG=none
TEST=emerge bluez
diff --git a/Makefile.plugins b/Makefile.plugins
index 52b51c5..a5d62d0 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -1,4 +1,7 @@
+builtin_modules += chromium
+builtin_sources += plugins/chromium.c
+
builtin_modules += hostname
builtin_sources += plugins/hostname.c
diff --git a/Makefile.tools b/Makefile.tools
index e42e42d..16cc571 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -121,7 +121,8 @@
bin_PROGRAMS += tools/hciattach tools/hciconfig tools/hcitool tools/hcidump \
tools/rfcomm tools/rctest tools/l2test tools/l2ping \
tools/sdptool tools/ciptool tools/bccmd \
- tools/bluemoon tools/hex2hcd tools/mpris-proxy
+ tools/bluemoon tools/hex2hcd tools/mpris-proxy \
+ tools/btmgmt tools/btgatt-client tools/btgatt-server
tools_hciattach_SOURCES = tools/hciattach.c tools/hciattach.h \
tools/hciattach_st.c \
@@ -190,6 +191,17 @@
tools_hex2hcd_SOURCES = tools/hex2hcd.c
+tools_btmgmt_SOURCES = tools/btmgmt.c src/uuid-helper.c
+tools_btmgmt_LDADD = lib/libbluetooth-internal.la src/libshared-mainloop.la
+
+tools_btgatt_client_SOURCES = tools/btgatt-client.c src/uuid-helper.c
+tools_btgatt_client_LDADD = src/libshared-mainloop.la \
+ lib/libbluetooth-internal.la
+
+tools_btgatt_server_SOURCES = tools/btgatt-server.c src/uuid-helper.c
+tools_btgatt_server_LDADD = src/libshared-mainloop.la \
+ lib/libbluetooth-internal.la
+
tools_mpris_proxy_SOURCES = tools/mpris-proxy.c
tools_mpris_proxy_LDADD = gdbus/libgdbus-internal.la @GLIB_LIBS@ @DBUS_LIBS@
@@ -220,11 +232,10 @@
noinst_PROGRAMS += tools/bdaddr tools/avinfo tools/avtest \
tools/scotest tools/amptest tools/hwdb \
tools/hcieventmask tools/hcisecfilter \
- tools/btmgmt tools/btinfo tools/btattach \
+ tools/btinfo tools/btattach \
tools/btsnoop tools/btproxy \
tools/btiotest tools/mcaptest tools/cltest \
- tools/oobtest tools/seq2bseq tools/ibeacon \
- tools/btgatt-client tools/btgatt-server
+ tools/oobtest tools/seq2bseq tools/ibeacon
tools_bdaddr_SOURCES = tools/bdaddr.c src/oui.h src/oui.c
tools_bdaddr_LDADD = lib/libbluetooth-internal.la @UDEV_LIBS@
@@ -241,9 +252,6 @@
tools_hcieventmask_LDADD = lib/libbluetooth-internal.la
-tools_btmgmt_SOURCES = tools/btmgmt.c src/uuid-helper.c
-tools_btmgmt_LDADD = lib/libbluetooth-internal.la src/libshared-mainloop.la
-
tools_btinfo_SOURCES = tools/btinfo.c monitor/bt.h
tools_btinfo_LDADD = src/libshared-mainloop.la
@@ -276,14 +284,6 @@
tools_ibeacon_SOURCES = tools/ibeacon.c monitor/bt.h
tools_ibeacon_LDADD = src/libshared-mainloop.la
-tools_btgatt_client_SOURCES = tools/btgatt-client.c src/uuid-helper.c
-tools_btgatt_client_LDADD = src/libshared-mainloop.la \
- lib/libbluetooth-internal.la
-
-tools_btgatt_server_SOURCES = tools/btgatt-server.c src/uuid-helper.c
-tools_btgatt_server_LDADD = src/libshared-mainloop.la \
- lib/libbluetooth-internal.la
-
EXTRA_DIST += tools/bdaddr.1
endif
diff --git a/README.chromium b/README.chromium
new file mode 100644
index 0000000..c931b6b
--- /dev/null
+++ b/README.chromium
@@ -0,0 +1,14 @@
+Homepage: http://www.bluez.org
+Upstream Repo: http://git.kernel.org/cgit/bluetooth/bluez.git
+License: GPLv2
+License File: COPYING
+
+Description:
+
+User-space daemon for the official Linux Bluetooth stack. It provides high-level
+APIs for core Bluetooth functionality as well as several profiles used by OS
+features, such as audio and input.
+
+This repository mirrors the master branch of the upstream project while
+containing Chromium OS only additions that won't be upstream, as well as fixes
+that were sent upstream but were first merged locally.
diff --git a/acinclude.m4 b/acinclude.m4
index bc39c6d..04b7670 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -11,21 +11,18 @@
])
AC_DEFUN([COMPILER_FLAGS], [
- with_cflags=""
- if (test "$USE_MAINTAINER_MODE" = "yes"); then
- with_cflags="$with_cflags -Wall -Werror -Wextra"
- with_cflags="$with_cflags -Wno-unused-parameter"
- with_cflags="$with_cflags -Wno-missing-field-initializers"
- with_cflags="$with_cflags -Wdeclaration-after-statement"
- with_cflags="$with_cflags -Wmissing-declarations"
- with_cflags="$with_cflags -Wredundant-decls"
- with_cflags="$with_cflags -Wcast-align"
- with_cflags="$with_cflags -Wswitch-enum"
- with_cflags="$with_cflags -Wformat -Wformat-security"
- with_cflags="$with_cflags -DG_DISABLE_DEPRECATED"
- with_cflags="$with_cflags -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_28"
- with_cflags="$with_cflags -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_28"
- fi
+ with_cflags="-Wall -Werror -Wextra"
+ with_cflags="$with_cflags -Wno-unused-parameter"
+ with_cflags="$with_cflags -Wno-missing-field-initializers"
+ with_cflags="$with_cflags -Wdeclaration-after-statement"
+ with_cflags="$with_cflags -Wmissing-declarations"
+ with_cflags="$with_cflags -Wredundant-decls"
+ with_cflags="$with_cflags -Wcast-align"
+ with_cflags="$with_cflags -Wswitch-enum"
+ with_cflags="$with_cflags -Wformat -Wformat-security"
+ with_cflags="$with_cflags -DG_DISABLE_DEPRECATED"
+ with_cflags="$with_cflags -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_28"
+ with_cflags="$with_cflags -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_28"
AC_SUBST([WARNING_CFLAGS], $with_cflags)
])
diff --git a/lib/sdp.h b/lib/sdp.h
index cc10e9f..69a2122 100644
--- a/lib/sdp.h
+++ b/lib/sdp.h
@@ -34,7 +34,7 @@
#include <stdint.h>
#include <bluetooth/bluetooth.h>
-#define SDP_UNIX_PATH "/var/run/sdp"
+#define SDP_UNIX_PATH "/var/run/bluetooth/sdp"
#define SDP_RESPONSE_TIMEOUT 20
#define SDP_REQ_BUFFER_SIZE 2048
#define SDP_RSP_BUFFER_SIZE 65535
diff --git a/plugins/chromium.c b/plugins/chromium.c
new file mode 100644
index 0000000..3d362652
--- /dev/null
+++ b/plugins/chromium.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <gdbus/gdbus.h>
+
+#include <bluetooth/bluetooth.h>
+
+#include "lib/mgmt.h"
+#include "src/adapter.h"
+#include "src/dbus-common.h"
+#include "src/device.h"
+#include "src/error.h"
+#include "src/log.h"
+#include "src/plugin.h"
+#include "src/shared/mgmt.h"
+
+#define DBUS_PATH "/org/bluez"
+#define DBUS_PLUGIN_INTERFACE "org.chromium.Bluetooth"
+#define DBUS_PLUGIN_DEVICE_INTERFACE "org.chromium.BluetoothDevice"
+
+#define DBUS_BLUEZ_SERVICE "org.bluez"
+#define DBUS_OBJECT_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager"
+
+#define DBUS_BLUEZ_DEVICE_INTERFACE "org.bluez.Device1"
+
+static struct mgmt *mgmt_if = NULL;
+
+static bool supports_le_services = false;
+static bool supports_conn_info = false;
+
+static int interfaces_added_watch_id = 0;
+static int interfaces_removed_watch_id = 0;
+
+static gboolean chromium_property_get_supports_le_services(
+ const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ dbus_bool_t value = supports_le_services;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &value);
+
+ return TRUE;
+}
+
+static gboolean chromium_property_get_supports_conn_info(
+ const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ dbus_bool_t value = supports_conn_info;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &value);
+
+ return TRUE;
+}
+
+/* Helper functions and struct to find a device and the adapter it belongs to
+ * for a given DBus object path.
+ */
+struct find_device_context {
+ const char *device_path;
+ struct btd_adapter *adapter;
+ struct btd_device *device;
+};
+
+static void find_by_path_device_cb(struct btd_device *device, void *data) {
+ struct find_device_context *context = data;
+
+ if (strcmp(context->device_path, device_get_path(device)) == 0)
+ context->device = device;
+}
+
+static void find_by_path_adapter_cb(struct btd_adapter *adapter,
+ gpointer user_data) {
+ struct find_device_context *context = user_data;
+
+ context->adapter = adapter;
+ btd_adapter_for_each_device(adapter, find_by_path_device_cb, context);
+}
+
+static gboolean find_device_by_path(const char *device_path,
+ struct btd_adapter **out_adapter,
+ struct btd_device **out_device) {
+ struct find_device_context context;
+
+ context.device_path = device_path;
+ context.device = NULL;
+
+ adapter_foreach(find_by_path_adapter_cb, &context);
+ if (context.adapter == NULL || context.device == NULL)
+ return FALSE;
+
+ *out_adapter = context.adapter;
+ *out_device = context.device;
+ return TRUE;
+}
+
+static void get_conn_info_complete(uint8_t status, uint16_t length,
+ const void *param, void *user_data) {
+ DBusMessage *msg = user_data;
+ DBusMessage *reply;
+ const struct mgmt_rp_get_conn_info *rp;
+ int16_t rssi, tx_power, max_tx_power;
+
+ if (status == 0) {
+ DBusMessageIter iter;
+
+ reply = dbus_message_new_method_return(msg);
+ if (reply == NULL) {
+ dbus_message_unref(msg);
+ error("Failed to create dbus reply message.");
+ return;
+ }
+
+ rp = param;
+ rssi = rp->rssi;
+ tx_power = rp->tx_power;
+ max_tx_power = rp->max_tx_power;
+
+ dbus_message_iter_init_append(reply, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT16, &rssi);
+ dbus_message_iter_append_basic(
+ &iter, DBUS_TYPE_INT16, &tx_power);
+ dbus_message_iter_append_basic(
+ &iter, DBUS_TYPE_INT16, &max_tx_power);
+ } else {
+ reply = btd_error_failed(msg, mgmt_errstr(status));
+ if (!reply) {
+ dbus_message_unref(msg);
+ error("Failed to create dbus error reply message.");
+ return;
+ }
+ }
+
+ if (!g_dbus_send_message(btd_get_dbus_connection(), reply))
+ error("DBus send failed.");
+ dbus_message_unref(msg);
+}
+
+static DBusMessage *get_conn_info(DBusConnection *conn, DBusMessage *msg,
+ void *user_data)
+{
+ const char *device_path = dbus_message_get_path(msg);
+ struct btd_adapter *adapter = NULL;
+ struct btd_device *device = NULL;
+ struct mgmt_cp_get_conn_info cp;
+
+ if (!mgmt_if)
+ return btd_error_not_ready(msg);
+
+ if (!supports_conn_info)
+ return btd_error_not_supported(msg);
+
+ if (!find_device_by_path(device_path, &adapter, &device))
+ return btd_error_does_not_exist(msg);
+
+ if (!btd_device_is_connected(device))
+ return btd_error_not_connected(msg);
+
+ memset(&cp, 0, sizeof(cp));
+ cp.addr.type = btd_device_get_bdaddr_type(device);
+ cp.addr.bdaddr = *device_get_address(device);
+
+ dbus_message_ref(msg);
+ if (mgmt_send(mgmt_if, MGMT_OP_GET_CONN_INFO,
+ btd_adapter_get_index(adapter), sizeof(cp), &cp,
+ get_conn_info_complete, msg, NULL) == 0)
+ return btd_error_failed(msg,
+ "Failed to send get_conn_info mgmt command");
+ return NULL;
+}
+
+static const GDBusMethodTable device_methods[] = {
+ /* GetConnInfo is a simple DBus wrapper over the get_conn_info mgmt API.
+ */
+ { GDBUS_ASYNC_METHOD("GetConnInfo", NULL, GDBUS_ARGS({"TXPower", "y"},
+ {"MaximumTXPower", "y"}, {"RSSI", "y"}),
+ get_conn_info) },
+ { }
+};
+
+static bool is_interface_entry_bluez_device(DBusMessageIter *array_iter) {
+ int arg_type;
+ DBusMessageIter dict_iter;
+ char *interface = NULL;
+
+ arg_type = dbus_message_iter_get_arg_type(array_iter);
+ if (arg_type == 'e') {
+ dbus_message_iter_recurse(array_iter, &dict_iter);
+ arg_type = dbus_message_iter_get_arg_type(&dict_iter);
+ if (arg_type == 's')
+ dbus_message_iter_get_basic(&dict_iter, &interface);
+ else
+ error("Expected string in InterfaceAdded signal.");
+
+ } else if (arg_type == 's') {
+ dbus_message_iter_get_basic(array_iter, &interface);
+ } else {
+ error("Expected string in InterfaceRemoved signal.");
+ }
+
+ return interface &&
+ strcmp(interface, DBUS_BLUEZ_DEVICE_INTERFACE) == 0;
+}
+
+/* Given an InterfaceAdded or InterfaceRemoved ObjectManager signal, return
+ * the object path if it contains the BlueZ device interface; otherwise, return
+ * null.
+ *
+ * The documentation for these ObjectManager signals can be found at
+ * http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager
+ */
+static const char *get_device_path_from_interface_msg(DBusMessage *msg) {
+ int arg_type;
+ char *object_path = NULL;
+ DBusMessageIter args_iter, array_iter;
+
+ dbus_message_iter_init(msg, &args_iter);
+ arg_type = dbus_message_iter_get_arg_type(&args_iter);
+ if (arg_type != 'o') {
+ error("Expected object path in ObjectManager signal.");
+ return NULL;
+ }
+
+ dbus_message_iter_get_basic(&args_iter, &object_path);
+ dbus_message_iter_next(&args_iter);
+ if (!object_path)
+ return NULL;
+
+ arg_type = dbus_message_iter_get_arg_type(&args_iter);
+ if (arg_type != 'a') {
+ error("Expected array in ObjectManager signal.");
+ return NULL;
+ }
+
+ dbus_message_iter_recurse(&args_iter, &array_iter);
+ while (dbus_message_iter_has_next(&array_iter)) {
+ if (is_interface_entry_bluez_device(&array_iter))
+ return object_path;
+ dbus_message_iter_next(&array_iter);
+ }
+
+ return NULL;
+}
+
+static gboolean interfaces_added(DBusConnection *conn, DBusMessage *msg,
+ void *user_data)
+{
+ const char *device_path = get_device_path_from_interface_msg(msg);
+
+ if (!device_path)
+ return TRUE;
+
+ g_dbus_register_interface(btd_get_dbus_connection(),
+ device_path, DBUS_PLUGIN_DEVICE_INTERFACE,
+ device_methods, NULL, NULL, NULL, NULL);
+
+ return TRUE;
+}
+
+static gboolean interfaces_removed(DBusConnection *conn, DBusMessage *msg,
+ void *user_data)
+{
+ const char *device_path = get_device_path_from_interface_msg(msg);
+
+ if (!device_path)
+ return TRUE;
+
+ g_dbus_unregister_interface(btd_get_dbus_connection(),
+ device_path, DBUS_PLUGIN_DEVICE_INTERFACE);
+
+ return TRUE;
+}
+
+static void remove_dbus_watches() {
+ if (interfaces_added_watch_id)
+ g_dbus_remove_watch(btd_get_dbus_connection(),
+ interfaces_added_watch_id);
+
+ if (interfaces_removed_watch_id)
+ g_dbus_remove_watch(btd_get_dbus_connection(),
+ interfaces_removed_watch_id);
+}
+
+static const GDBusPropertyTable chromium_properties[] = {
+ { "SupportsLEServices", "b",
+ chromium_property_get_supports_le_services },
+ { "SupportsConnInfo", "b",
+ chromium_property_get_supports_conn_info },
+ { }
+};
+
+static void read_version_complete(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ const struct mgmt_rp_read_version *rp = param;
+ uint8_t mgmt_version, mgmt_revision;
+
+ if (status != MGMT_STATUS_SUCCESS) {
+ error("Failed to read version information: %s (0x%02x)",
+ mgmt_errstr(status), status);
+ return;
+ }
+
+ if (length < sizeof(*rp)) {
+ error("Wrong size of read version response");
+ return;
+ }
+
+ mgmt_version = rp->version;
+ mgmt_revision = btohs(rp->revision);
+
+ supports_le_services = (mgmt_version > 1 ||
+ (mgmt_version == 1 && mgmt_revision >= 4));
+ supports_conn_info = (mgmt_revision > 1 ||
+ (mgmt_version == 1 && mgmt_revision >= 5));
+
+ g_dbus_emit_property_changed(btd_get_dbus_connection(),
+ DBUS_PATH, DBUS_PLUGIN_INTERFACE, "SupportsLEServices");
+ g_dbus_emit_property_changed(btd_get_dbus_connection(),
+ DBUS_PATH, DBUS_PLUGIN_INTERFACE, "SupportsConnInfo");
+}
+
+static int chromium_init(void)
+{
+ DBG("");
+
+ mgmt_if = mgmt_new_default();
+ if (!mgmt_if)
+ error("Failed to access management interface");
+ else if (!mgmt_send(mgmt_if, MGMT_OP_READ_VERSION,
+ MGMT_INDEX_NONE, 0, NULL,
+ read_version_complete, NULL, NULL))
+ error("Failed to read management version information");
+
+ g_dbus_register_interface(btd_get_dbus_connection(),
+ DBUS_PATH, DBUS_PLUGIN_INTERFACE,
+ NULL, NULL, chromium_properties, NULL, NULL);
+
+ /* Listen for new device objects being added so we can add the plugin
+ * interface to them.
+ */
+ interfaces_added_watch_id = g_dbus_add_signal_watch(
+ btd_get_dbus_connection(), DBUS_BLUEZ_SERVICE,
+ "/", DBUS_OBJECT_MANAGER_INTERFACE, "InterfacesAdded",
+ interfaces_added, NULL, NULL);
+ if (!interfaces_added_watch_id) {
+ error("Failed to add watch for InterfacesAdded signal");
+ return 0;
+ }
+
+ interfaces_removed_watch_id = g_dbus_add_signal_watch(
+ btd_get_dbus_connection(), DBUS_BLUEZ_SERVICE,
+ "/", DBUS_OBJECT_MANAGER_INTERFACE, "InterfacesRemoved",
+ interfaces_removed, NULL, NULL);
+ if (!interfaces_removed_watch_id) {
+ error("Failed to add watch for InterfaceRemoved signal");
+ remove_dbus_watches();
+ }
+
+ return 0;
+}
+
+static void chromium_exit(void)
+{
+ DBG("");
+
+ mgmt_unref(mgmt_if);
+ mgmt_if = NULL;
+
+ remove_dbus_watches();
+}
+
+BLUETOOTH_PLUGIN_DEFINE(chromium, VERSION, BLUETOOTH_PLUGIN_PRIORITY_HIGH,
+ chromium_init, chromium_exit)
diff --git a/plugins/sixaxis.c b/plugins/sixaxis.c
index ac53ba9..0a4e3d8 100644
--- a/plugins/sixaxis.c
+++ b/plugins/sixaxis.c
@@ -289,7 +289,7 @@
device = btd_adapter_get_device(adapter, &device_bdaddr, BDADDR_BREDR);
- if (g_slist_find_custom(btd_device_get_uuids(device), HID_UUID,
+ if (g_slist_find_custom(btd_device_get_sdp_uuids(device), HID_UUID,
(GCompareFunc)strcasecmp)) {
DBG("device %s already known, skipping", device_addr);
return true;
diff --git a/src/adapter.c b/src/adapter.c
index 1839286..42077b7 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -170,6 +170,7 @@
char *short_name; /* controller short name */
uint32_t supported_settings; /* controller supported settings */
uint32_t current_settings; /* current controller settings */
+ bool desired_powered; /* powered status desired by clients */
char *path; /* adapter object path */
uint8_t major_class; /* configured major class */
@@ -422,6 +423,10 @@
g_key_file_set_string(key_file, "General", "Alias",
adapter->stored_alias);
+ /* Always store the powered status */
+ g_key_file_set_boolean(key_file, "General", "Powered",
+ adapter->desired_powered);
+
ba2str(&adapter->bdaddr, address);
snprintf(filename, PATH_MAX, STORAGEDIR "/%s/settings", address);
@@ -455,6 +460,14 @@
g_dbus_emit_property_changed(dbus_conn, adapter->path,
ADAPTER_INTERFACE, "Powered");
+ /*
+ * Don't store the adapter information during daemon shutdown.
+ * It will store the adapter as powered off as part of the
+ * shutdown.
+ */
+ if (!powering_down)
+ store_adapter_info(adapter);
+
if (adapter->current_settings & MGMT_SETTING_POWERED) {
adapter_start(adapter);
} else {
@@ -2056,6 +2069,7 @@
GDBusPendingPropertySet id, void *user_data)
{
struct btd_adapter *adapter = user_data;
+ dbus_bool_t enabled;
if (powering_down) {
g_dbus_pending_property_error(id, ERROR_INTERFACE ".Failed",
@@ -2063,6 +2077,9 @@
return;
}
+ dbus_message_iter_get_basic(iter, &enabled);
+ adapter->desired_powered = enabled;
+
property_set_mode(adapter, MGMT_SETTING_POWERED, iter, id);
}
@@ -2912,9 +2929,13 @@
/* TODO: register services from pre-loaded list of primaries */
- list = btd_device_get_uuids(device);
+ list = btd_device_get_sdp_uuids(device);
if (list)
- device_probe_profiles(device, list);
+ device_probe_profiles(device, list, false);
+
+ list = btd_device_get_gatt_uuids(device);
+ if (list)
+ device_probe_profiles(device, list, true);
device_exist:
if (key_info) {
@@ -4343,6 +4364,8 @@
mode = get_mode(str);
g_key_file_set_boolean(key_file, "General", "Discoverable",
mode == MODE_DISCOVERABLE);
+ g_key_file_set_boolean(key_file, "General", "Powered",
+ mode == MODE_DISCOVERABLE || mode == MODE_CONNECTABLE);
}
if (read_local_name(&adapter->bdaddr, str) == 0)
@@ -4425,6 +4448,7 @@
char address[18];
struct stat st;
GError *gerr = NULL;
+ gboolean powered;
ba2str(&adapter->bdaddr, address);
@@ -4475,6 +4499,18 @@
gerr = NULL;
}
+ /* Get power status */
+ powered = g_key_file_get_boolean(key_file, "General", "Powered", &gerr);
+ if (gerr) {
+ powered = false;
+ g_error_free(gerr);
+ gerr = NULL;
+ }
+
+ /* Update the power status for this adapter */
+ adapter->desired_powered = powered;
+ set_mode(adapter, MGMT_OP_SET_POWERED, powered ? 0x01 : 0x00);
+
g_key_file_free(key_file);
}
diff --git a/src/bluetooth.conf b/src/bluetooth.conf
index ad8891a..074bcd6 100644
--- a/src/bluetooth.conf
+++ b/src/bluetooth.conf
@@ -8,6 +8,10 @@
<!-- ../system.conf have denied everything, so we just punch some holes -->
<policy user="root">
+ <allow send_destination="org.bluez"/>
+ </policy>
+
+ <policy user="bluetooth">
<allow own="org.bluez"/>
<allow send_destination="org.bluez"/>
<allow send_interface="org.bluez.Agent1"/>
@@ -21,13 +25,11 @@
<allow send_interface="org.freedesktop.DBus.ObjectManager"/>
</policy>
- <policy at_console="true">
+ <policy user="chronos">
<allow send_destination="org.bluez"/>
</policy>
- <!-- allow users of lp group (printing subsystem) to
- communicate with bluetoothd -->
- <policy group="lp">
+ <policy user="cras">
<allow send_destination="org.bluez"/>
</policy>
diff --git a/src/device.c b/src/device.c
index a28d6fb..05a4bd9 100644
--- a/src/device.c
+++ b/src/device.c
@@ -169,6 +169,7 @@
bool bonded;
bool connected;
bool svc_resolved;
+ GSList *uuids;
};
struct btd_device {
@@ -193,7 +194,7 @@
uint16_t appearance;
char *modalias;
struct btd_adapter *adapter;
- GSList *uuids;
+ GSList *legacy_uuids;
GSList *primaries; /* List of primary services */
GSList *services; /* List of btd_service */
GSList *pending; /* Pending services */
@@ -335,6 +336,28 @@
list, len);
}
+static char **store_service_uuids(GKeyFile *key_file, gchar *key, GSList *uuids)
+{
+ GSList *l;
+ char **array;
+ int i;
+
+ if (!uuids) {
+ g_key_file_remove_key(key_file, "General", key, NULL);
+ return NULL;
+ }
+
+ array = g_new0(char *, g_slist_length(uuids) + 1);
+
+ for (i = 0, l = uuids; l; l = g_slist_next(l), i++)
+ array[i] = l->data;
+
+ g_key_file_set_string_list(key_file, "General", key,
+ (const char **)array, i);
+
+ return array;
+}
+
static gboolean store_device_info_cb(gpointer user_data)
{
struct btd_device *device = user_data;
@@ -344,7 +367,7 @@
char device_addr[18];
char *str;
char class[9];
- char **uuids = NULL;
+ char **sdp_uuids, **gatt_uuids;
gsize length = 0;
device->store_id = 0;
@@ -387,18 +410,17 @@
g_key_file_set_boolean(key_file, "General", "Blocked",
device->blocked);
- if (device->uuids) {
- GSList *l;
- int i;
-
- uuids = g_new0(char *, g_slist_length(device->uuids) + 1);
- for (i = 0, l = device->uuids; l; l = g_slist_next(l), i++)
- uuids[i] = l->data;
- g_key_file_set_string_list(key_file, "General", "Services",
- (const char **)uuids, i);
- } else {
+ /*
+ * Remove the legacy-format "Services" entry if we have new data to
+ * populate for either GATT or SDP after a connection.
+ */
+ if (device->bredr_state.uuids || device->le_state.uuids)
g_key_file_remove_key(key_file, "General", "Services", NULL);
- }
+
+ sdp_uuids = store_service_uuids(key_file, "SDPServices",
+ device->bredr_state.uuids);
+ gatt_uuids = store_service_uuids(key_file, "GATTServices",
+ device->le_state.uuids);
if (device->vendor_src) {
g_key_file_set_integer(key_file, "DeviceID", "Source",
@@ -420,7 +442,8 @@
g_free(str);
g_key_file_free(key_file);
- g_free(uuids);
+ g_free(sdp_uuids);
+ g_free(gatt_uuids);
return FALSE;
}
@@ -585,7 +608,9 @@
btd_gatt_client_destroy(device->client_dbus);
device->client_dbus = NULL;
- g_slist_free_full(device->uuids, g_free);
+ g_slist_free_full(device->bredr_state.uuids, g_free);
+ g_slist_free_full(device->le_state.uuids, g_free);
+ g_slist_free_full(device->legacy_uuids, g_free);
g_slist_free_full(device->primaries, g_free);
g_slist_free_full(device->attios, g_free);
g_slist_free_full(device->attios_offline, g_free);
@@ -994,26 +1019,48 @@
return TRUE;
}
+static void insert_uuid(gpointer data, gpointer user_data)
+{
+ char *uuid = data;
+ GSList **uuids = user_data;
+
+ if (g_slist_find_custom(*uuids, uuid, bt_uuid_strcmp))
+ return;
+
+ *uuids = g_slist_insert_sorted(*uuids, uuid, bt_uuid_strcmp);
+}
+
static gboolean dev_property_get_uuids(const GDBusPropertyTable *property,
DBusMessageIter *iter, void *data)
{
struct btd_device *dev = data;
DBusMessageIter entry;
- GSList *l;
+ GSList *uuids, *l;
+ bool needs_free = false;
dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
DBUS_TYPE_STRING_AS_STRING, &entry);
- if (dev->bredr_state.svc_resolved || dev->le_state.svc_resolved)
- l = dev->uuids;
- else if (dev->eir_uuids)
- l = dev->eir_uuids;
- else
- l = dev->uuids;
+ if (!dev->bredr_state.svc_resolved && !dev->le_state.svc_resolved
+ && dev->eir_uuids)
+ uuids = dev->eir_uuids;
+ else if (!dev->bredr_state.uuids && !dev->le_state.uuids)
+ uuids = dev->legacy_uuids;
+ else {
+ uuids = NULL;
+ g_slist_foreach(dev->bredr_state.uuids, insert_uuid, &uuids);
+ g_slist_foreach(dev->le_state.uuids, insert_uuid, &uuids);
- for (; l != NULL; l = l->next)
+ if (uuids)
+ needs_free = true;
+ }
+
+ for (l = uuids; l; l = g_slist_next(l))
dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
- &l->data);
+ &l->data);
+
+ if (needs_free)
+ g_slist_free(l);
dbus_message_iter_close_container(iter, &entry);
@@ -1141,7 +1188,8 @@
if (!silent) {
g_dbus_emit_property_changed(dbus_conn, device->path,
DEVICE_INTERFACE, "Blocked");
- device_probe_profiles(device, device->uuids);
+ device_probe_profiles(device, device->bredr_state.uuids, false);
+ device_probe_profiles(device, device->le_state.uuids, true);
}
return 0;
@@ -2276,6 +2324,66 @@
return str;
}
+static bool device_add_uuid(GSList **uuids, const char *uuid)
+{
+ if (g_slist_find_custom(*uuids, uuid, bt_uuid_strcmp))
+ return false;
+
+ *uuids = g_slist_insert_sorted(*uuids, g_strdup(uuid), bt_uuid_strcmp);
+
+ return true;
+}
+
+static bool device_add_uuids(struct btd_device *device, GSList **uuids,
+ GSList *new_uuids)
+{
+ GSList *l;
+ bool changed = false;
+
+ for (l = new_uuids; l; l = g_slist_next(l)) {
+ if (device_add_uuid(uuids, l->data))
+ changed = true;
+ }
+
+ if (changed)
+ g_dbus_emit_property_changed(dbus_conn, device->path,
+ DEVICE_INTERFACE, "UUIDs");
+
+ return changed;
+}
+
+static bool device_add_sdp_uuid(struct btd_device *device, const char *uuid)
+{
+ return device_add_uuid(&device->bredr_state.uuids, uuid);
+}
+
+static bool device_add_sdp_uuids(struct btd_device *device, GSList *uuids)
+{
+ return device_add_uuids(device, &device->bredr_state.uuids, uuids);
+}
+
+static bool device_add_gatt_uuid(struct btd_device *device, const char *uuid)
+{
+ return device_add_uuid(&device->le_state.uuids, uuid);
+}
+
+static bool device_add_gatt_uuids(struct btd_device *device, GSList *uuids)
+{
+ return device_add_uuids(device, &device->le_state.uuids, uuids);
+}
+
+static void device_remove_gatt_uuid(struct btd_device *device, const char *uuid)
+{
+ GSList *l;
+
+ l = g_slist_find_custom(device->le_state.uuids, uuid, bt_uuid_strcmp);
+ if (!l)
+ return;
+
+ g_free(l->data);
+ device->le_state.uuids = g_slist_delete_link(device->le_state.uuids, l);
+}
+
static void load_info(struct btd_device *device, const char *local,
const char *peer, GKeyFile *key_file)
{
@@ -2365,30 +2473,58 @@
if (blocked)
device_block(device, FALSE);
- /* Load device profile list */
+ /*
+ * Load legacy, mixed profile list, to display UUIDs before a
+ * connection. We immediately load the values and then clear the stored
+ * value.
+ */
uuids = g_key_file_get_string_list(key_file, "General", "Services",
- NULL, NULL);
+ NULL, NULL);
if (uuids) {
char **uuid;
- for (uuid = uuids; *uuid; uuid++) {
- GSList *match;
+ for (uuid = uuids; *uuid; uuid++)
+ device->legacy_uuids = g_slist_append(
+ device->legacy_uuids,
+ g_strdup(*uuid));
- match = g_slist_find_custom(device->uuids, *uuid,
- bt_uuid_strcmp);
- if (match)
- continue;
+ g_strfreev(uuids);
+ }
- device->uuids = g_slist_insert_sorted(device->uuids,
- g_strdup(*uuid),
- bt_uuid_strcmp);
- }
+ /* Load classic device profile list */
+ uuids = g_key_file_get_string_list(key_file, "General", "SDPServices",
+ NULL, NULL);
+ if (uuids) {
+ char **uuid;
+
+ for (uuid = uuids; *uuid; uuid++)
+ device_add_sdp_uuid(device, *uuid);
+
g_strfreev(uuids);
/* Discovered services restored from storage */
device->bredr_state.svc_resolved = true;
}
+ /* Load GATT-based device profile list */
+ uuids = g_key_file_get_string_list(key_file, "General", "GATTServices",
+ NULL, NULL);
+ if (uuids) {
+ char **uuid;
+
+ for (uuid = uuids; *uuid; uuid++)
+ device_add_gatt_uuid(device, *uuid);
+
+ g_strfreev(uuids);
+
+ /*
+ * TODO: The GATT-based service UUIDs have been restored from
+ * storage but we don't have a populated gatt-db yet. Here we
+ * should mark le_state.svc_resolved as true, if we're bonded
+ * and we have a populated gatt_db.
+ */
+ }
+
/* Load device id */
source = g_key_file_get_integer(key_file, "DeviceID", "Source", NULL);
if (source) {
@@ -2522,32 +2658,11 @@
*new_services = g_slist_append(*new_services, prim);
}
-static void device_add_uuids(struct btd_device *device, GSList *uuids)
-{
- GSList *l;
- bool changed = false;
-
- for (l = uuids; l != NULL; l = g_slist_next(l)) {
- GSList *match = g_slist_find_custom(device->uuids, l->data,
- bt_uuid_strcmp);
- if (match)
- continue;
-
- changed = true;
- device->uuids = g_slist_insert_sorted(device->uuids,
- g_strdup(l->data),
- bt_uuid_strcmp);
- }
-
- if (changed)
- g_dbus_emit_property_changed(dbus_conn, device->path,
- DEVICE_INTERFACE, "UUIDs");
-}
-
struct gatt_probe_data {
struct btd_device *dev;
bool all_services;
- GSList *uuids;
+ GSList *new_uuids;
+ GSList *old_uuids;
struct gatt_db_attribute *cur_attr;
char cur_uuid[MAX_LEN_UUID_STR];
};
@@ -2597,20 +2712,31 @@
{
struct gatt_probe_data *data = user_data;
bt_uuid_t uuid;
- GSList *l = NULL;
+ gpointer dup_uuid;
gatt_db_attribute_get_service_uuid(attr, &uuid);
bt_uuid_to_string(&uuid, data->cur_uuid, sizeof(data->cur_uuid));
data->cur_attr = attr;
- /*
- * If we're probing for all services, store the UUID since device->uuids
- * was cleared.
- */
- if (data->all_services)
- data->uuids = g_slist_append(data->uuids,
+ if (data->all_services) {
+ GSList *l;
+
+ /*
+ * Check if the service is already in the old UUIDs list. If so,
+ * remove it.
+ */
+ l = g_slist_find_custom(data->old_uuids, data->cur_uuid,
+ bt_uuid_strcmp);
+ if (l) {
+ g_free(l->data);
+ data->old_uuids = g_slist_delete_link(data->old_uuids,
+ l);
+ } else {
+ data->new_uuids = g_slist_append(data->new_uuids,
g_strdup(data->cur_uuid));
+ }
+ }
/* Don't probe the profiles if a matching service already exists. */
if (find_service_with_uuid(data->dev->services, data->cur_uuid)) {
@@ -2624,8 +2750,14 @@
if (data->all_services)
return;
- l = g_slist_append(l, g_strdup(data->cur_uuid));
- device_add_uuids(data->dev, l);
+ dup_uuid = g_strdup(data->cur_uuid);
+ if (!device_add_gatt_uuid(data->dev, dup_uuid)) {
+ g_free(dup_uuid);
+ return;
+ }
+
+ g_dbus_emit_property_changed(dbus_conn, data->dev->path,
+ DEVICE_INTERFACE, "UUIDs");
}
static void device_probe_gatt_profile(struct btd_device *device,
@@ -2638,13 +2770,33 @@
data.dev = device;
dev_probe_gatt_profile(attr, &data);
- g_slist_free_full(data.uuids, g_free);
+}
+
+static void remove_invalid_services(struct gatt_probe_data *data)
+{
+ struct btd_device *dev = data->dev;
+ struct btd_service *service;
+ GSList *l, *svc;
+
+ for (l = data->old_uuids; l; l = g_slist_next(l)) {
+ device_remove_gatt_uuid(dev, l->data);
+
+ svc = find_service_with_uuid(dev->services, l->data);
+ if (!svc)
+ continue;
+
+ service = svc->data;
+ dev->services = g_slist_delete_link(dev->services, svc);
+ dev->pending = g_slist_remove(dev->pending, service);
+ service_remove(service);
+ }
}
static void device_probe_gatt_profiles(struct btd_device *device)
{
struct gatt_probe_data data;
char addr[18];
+ GSList *l;
ba2str(&device->bdaddr, addr);
@@ -2658,11 +2810,24 @@
data.dev = device;
data.all_services = true;
+ /* Copy current list of GATT UUIDs */
+ for (l = device->le_state.uuids; l; l = g_slist_next(l))
+ data.old_uuids = g_slist_append(data.old_uuids,
+ g_strdup(l->data));
+
gatt_db_foreach_service(device->db, NULL, dev_probe_gatt_profile,
&data);
- device_add_uuids(device, data.uuids);
- g_slist_free_full(data.uuids, g_free);
+ /* Whatever remains in data.old_uuids is stale and should be removed */
+ remove_invalid_services(&data);
+
+ /* Update the list with new UUIDs */
+ if (!device_add_gatt_uuids(device, data.new_uuids) && data.old_uuids)
+ g_dbus_emit_property_changed(dbus_conn, device->path,
+ DEVICE_INTERFACE, "UUIDs");
+
+ g_slist_free_full(data.new_uuids, g_free);
+ g_slist_free_full(data.old_uuids, g_free);
}
static void device_accept_gatt_profiles(struct btd_device *device)
@@ -2751,21 +2916,14 @@
return !(prim->range.start == start && prim->range.end == end);
}
-static gint prim_uuid_cmp(gconstpointer a, gconstpointer b)
-{
- const struct gatt_primary *prim = a;
- const char *uuid = b;
-
- return bt_uuid_strcmp(prim->uuid, uuid);
-}
-
static void gatt_service_removed(struct gatt_db_attribute *attr,
void *user_data)
{
struct btd_device *device = user_data;
GSList *l;
- struct gatt_primary *prim;
uint16_t start, end;
+ bt_uuid_t uuid;
+ char uuid_str[MAX_LEN_UUID_STR];
/*
* NOTE: shared/gatt-client clears the database in case of failure. This
@@ -2783,26 +2941,26 @@
* In this case the gatt-client will not be ready.
*/
- gatt_db_attribute_get_service_handles(attr, &start, &end);
+ gatt_db_attribute_get_service_data(attr, &start, &end, NULL, &uuid);
DBG("start: 0x%04x, end: 0x%04x", start, end);
/* Remove the corresponding gatt_primary */
l = g_slist_find_custom(device->primaries, attr, prim_attr_cmp);
- if (!l)
- return;
+ if (l) {
+ g_free(l->data);
+ device->primaries = g_slist_delete_link(device->primaries, l);
+ }
- prim = l->data;
- device->primaries = g_slist_delete_link(device->primaries, l);
+ bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
/*
* Remove the corresponding UUIDs entry and profile, only if this is
* the last service with this UUID.
*/
- l = g_slist_find_custom(device->uuids, prim->uuid, bt_uuid_strcmp);
-
- if (l && !g_slist_find_custom(device->primaries, prim->uuid,
- prim_uuid_cmp)) {
+ l = g_slist_find_custom(device->le_state.uuids, uuid_str,
+ bt_uuid_strcmp);
+ if (l && !gatt_db_get_service_with_uuid(device->db, &uuid)) {
/*
* If this happend since the db was cleared for a non-bonded
* device, then don't remove the btd_service just yet. We do
@@ -2815,13 +2973,12 @@
device_remove_gatt_profile(device, attr);
g_free(l->data);
- device->uuids = g_slist_delete_link(device->uuids, l);
+ device->le_state.uuids = g_slist_delete_link(
+ device->le_state.uuids, l);
g_dbus_emit_property_changed(dbus_conn, device->path,
DEVICE_INTERFACE, "UUIDs");
}
- g_free(prim);
-
store_device_info(device);
btd_gatt_client_service_removed(device->client_dbus, attr);
@@ -3076,8 +3233,13 @@
dev->trusted = dup->trusted;
dev->blocked = dup->blocked;
- for (l = dup->uuids; l; l = g_slist_next(l))
- dev->uuids = g_slist_append(dev->uuids, g_strdup(l->data));
+ for (l = dup->bredr_state.uuids; l; l = g_slist_next(l))
+ dev->bredr_state.uuids = g_slist_append(dev->bredr_state.uuids,
+ g_strdup(l->data));
+
+ for (l = dup->le_state.uuids; l; l = g_slist_next(l))
+ dev->le_state.uuids = g_slist_append(dev->le_state.uuids,
+ g_strdup(l->data));
if (dev->name[0] == '\0')
strcpy(dev->name, dup->name);
@@ -3328,9 +3490,14 @@
return FALSE;
}
-GSList *btd_device_get_uuids(struct btd_device *device)
+GSList *btd_device_get_sdp_uuids(struct btd_device *device)
{
- return device->uuids;
+ return device->bredr_state.uuids;
+}
+
+GSList *btd_device_get_gatt_uuids(struct btd_device *device)
+{
+ return device->le_state.uuids;
}
struct probe_data {
@@ -3368,7 +3535,8 @@
if (profile->device_probe == NULL)
return;
- if (!device_match_profile(device, profile, device->uuids))
+ if (!device_match_profile(device, profile, device->bredr_state.uuids) &&
+ !device_match_profile(device, profile, device->le_state.uuids))
return;
service = service_create(device, profile);
@@ -3406,7 +3574,8 @@
service_remove(service);
}
-void device_probe_profiles(struct btd_device *device, GSList *uuids)
+void device_probe_profiles(struct btd_device *device, GSList *uuids,
+ bool gatt)
{
struct probe_data d = { device, uuids };
char addr[18];
@@ -3423,7 +3592,10 @@
btd_profile_foreach(dev_probe, &d);
add_uuids:
- device_add_uuids(device, uuids);
+ if (gatt)
+ device_add_gatt_uuids(device, uuids);
+ else
+ device_add_sdp_uuids(device, uuids);
}
static void store_sdp_record(GKeyFile *key_file, sdp_record_t *rec)
@@ -3519,7 +3691,8 @@
req->records = sdp_list_append(req->records, sdp_copy_record(rec));
/* Check if UUID is duplicated */
- l = g_slist_find_custom(req->device->uuids, uuid, bt_uuid_strcmp);
+ l = g_slist_find_custom(req->device->bredr_state.uuids, uuid,
+ bt_uuid_strcmp);
if (l == NULL) {
l = g_slist_find_custom(req->profiles_added, uuid,
bt_uuid_strcmp);
@@ -3750,7 +3923,7 @@
* the full list of services and populate a client-role gatt_db over
* BR/EDR.
*/
- device_probe_profiles(device, req->profiles_added);
+ device_probe_profiles(device, req->profiles_added, false);
/* Propagate services changes */
g_dbus_emit_property_changed(dbus_conn, req->device->path,
@@ -4437,8 +4610,8 @@
else
delta = rssi - device->rssi;
- /* only report changes of 8 dBm or more */
- if (delta < 8)
+ /* only report changes of 2 dBm or more */
+ if (delta < 2)
return;
DBG("rssi %d delta %d", rssi, delta);
@@ -5094,13 +5267,14 @@
GSList *uuid_list;
char *new_uuid;
- if (g_slist_find_custom(device->uuids, uuid, bt_uuid_strcmp))
+ if (g_slist_find_custom(device->bredr_state.uuids, uuid,
+ bt_uuid_strcmp))
return;
new_uuid = g_strdup(uuid);
uuid_list = g_slist_append(NULL, new_uuid);
- device_probe_profiles(device, uuid_list);
+ device_probe_profiles(device, uuid_list, false);
g_free(new_uuid);
g_slist_free(uuid_list);
diff --git a/src/device.h b/src/device.h
index a7fefee..f250bfa 100644
--- a/src/device.h
+++ b/src/device.h
@@ -60,8 +60,10 @@
};
int device_addr_type_cmp(gconstpointer a, gconstpointer b);
-GSList *btd_device_get_uuids(struct btd_device *device);
-void device_probe_profiles(struct btd_device *device, GSList *profiles);
+GSList *btd_device_get_sdp_uuids(struct btd_device *device);
+GSList *btd_device_get_gatt_uuids(struct btd_device *device);
+void device_probe_profiles(struct btd_device *device, GSList *profiles,
+ bool gatt);
const sdp_record_t *btd_device_get_record(struct btd_device *device,
const char *uuid);
struct gatt_primary *btd_device_get_primary(struct btd_device *device,
diff --git a/src/gatt-client.c b/src/gatt-client.c
index 9811bd8..373f27a 100644
--- a/src/gatt-client.c
+++ b/src/gatt-client.c
@@ -564,21 +564,16 @@
}
static const GDBusPropertyTable descriptor_properties[] = {
- { "UUID", "s", descriptor_get_uuid, NULL, NULL,
- G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
- { "Characteristic", "o", descriptor_get_characteristic, NULL, NULL,
- G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
- { "Value", "ay", descriptor_get_value, NULL, descriptor_value_exists,
- G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+ { "UUID", "s", descriptor_get_uuid, NULL, NULL },
+ { "Characteristic", "o", descriptor_get_characteristic, NULL, NULL },
+ { "Value", "ay", descriptor_get_value, NULL, descriptor_value_exists },
{ }
};
static const GDBusMethodTable descriptor_methods[] = {
- { GDBUS_EXPERIMENTAL_ASYNC_METHOD("ReadValue", NULL,
- GDBUS_ARGS({ "value", "ay" }),
+ { GDBUS_ASYNC_METHOD("ReadValue", NULL, GDBUS_ARGS({ "value", "ay" }),
descriptor_read_value) },
- { GDBUS_EXPERIMENTAL_ASYNC_METHOD("WriteValue",
- GDBUS_ARGS({ "value", "ay" }),
+ { GDBUS_ASYNC_METHOD("WriteValue", GDBUS_ARGS({ "value", "ay" }),
NULL,
descriptor_write_value) },
{ }
@@ -1246,33 +1241,25 @@
}
static const GDBusPropertyTable characteristic_properties[] = {
- { "UUID", "s", characteristic_get_uuid, NULL, NULL,
- G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
- { "Service", "o", characteristic_get_service, NULL, NULL,
- G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+ { "UUID", "s", characteristic_get_uuid, NULL, NULL },
+ { "Service", "o", characteristic_get_service, NULL, NULL },
{ "Value", "ay", characteristic_get_value, NULL,
- characteristic_value_exists,
- G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
- { "Notifying", "b", characteristic_get_notifying, NULL, NULL,
- G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
- { "Flags", "as", characteristic_get_flags, NULL, NULL,
- G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
- { "Descriptors", "ao", characteristic_get_descriptors, NULL, NULL,
- G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+ characteristic_value_exists },
+ { "Notifying", "b", characteristic_get_notifying, NULL, NULL },
+ { "Flags", "as", characteristic_get_flags, NULL, NULL },
+ { "Descriptors", "ao", characteristic_get_descriptors, NULL, NULL },
{ }
};
static const GDBusMethodTable characteristic_methods[] = {
- { GDBUS_EXPERIMENTAL_ASYNC_METHOD("ReadValue", NULL,
- GDBUS_ARGS({ "value", "ay" }),
+ { GDBUS_ASYNC_METHOD("ReadValue", NULL, GDBUS_ARGS({ "value", "ay" }),
characteristic_read_value) },
- { GDBUS_EXPERIMENTAL_ASYNC_METHOD("WriteValue",
- GDBUS_ARGS({ "value", "ay" }),
+ { GDBUS_ASYNC_METHOD("WriteValue", GDBUS_ARGS({ "value", "ay" }),
NULL,
characteristic_write_value) },
- { GDBUS_EXPERIMENTAL_ASYNC_METHOD("StartNotify", NULL, NULL,
+ { GDBUS_ASYNC_METHOD("StartNotify", NULL, NULL,
characteristic_start_notify) },
- { GDBUS_EXPERIMENTAL_METHOD("StopNotify", NULL, NULL,
+ { GDBUS_METHOD("StopNotify", NULL, NULL,
characteristic_stop_notify) },
{ }
};
@@ -1425,14 +1412,10 @@
}
static const GDBusPropertyTable service_properties[] = {
- { "UUID", "s", service_get_uuid, NULL, NULL,
- G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
- { "Device", "o", service_get_device, NULL, NULL,
- G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
- { "Primary", "b", service_get_primary, NULL, NULL,
- G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
- { "Characteristics", "ao", service_get_characteristics, NULL, NULL,
- G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+ { "UUID", "s", service_get_uuid, NULL, NULL },
+ { "Device", "o", service_get_device, NULL, NULL },
+ { "Primary", "b", service_get_primary, NULL, NULL },
+ { "Characteristics", "ao", service_get_characteristics, NULL, NULL },
{ }
};