Subject: [PATCH RFC 0/4] Reference implementation for DBUS.Properties

Reference implementation for org.freedesktop.DBus.Properties.* in
manager, device, adapter and thermometer using de Marchi's getter/setter
implementation.

Notes:
* Current GetProperties/SetPropety implementations flagged as deprecated
* Current implementation for the "Icon" property in device.c has a potential
assignment to an uninitialized value (when both read_remote_class and
read_remote_appearance return error). In the new implementation, this case
is handled as a non existent property.
* The new implementation separates the exists() logic from the actual
read/write and since the "Icon" and "Class" properties in device.c are read
from a file, the new implementation reads the file twice. If it's better
(and safe) to move the properties to some allocated structure, I can change
the code.
* In functions that return arrays (get_property_uuids, get_property_services,
etc) I keep the extra array allocation from the current code, but if it's not
desired, I can remove it.


Henrique Dante de Almeida (4):
manager: implement support for DBus.Properties.Get
thermometer: implement support for DBus.Properties.Get and
DBus.Properties.Set
adapter: implement DBus.Properties
device: implement DBus.Properties

src/adapter.c | 280 +++++++++++++++++++++++++++++++++
src/device.c | 384 ++++++++++++++++++++++++++++++++++++++++++++-
src/manager.c | 31 ++++-
thermometer/thermometer.c | 86 ++++++++++-
4 files changed, 772 insertions(+), 9 deletions(-)

--
1.7.5.4



Subject: [PATCH RFC 4/4] device: implement DBus.Properties

---
src/device.c | 384 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 380 insertions(+), 4 deletions(-)

diff --git a/src/device.c b/src/device.c
index 567ece1..a2d91cd 100644
--- a/src/device.c
+++ b/src/device.c
@@ -314,6 +314,314 @@ gboolean device_is_trusted(struct btd_device *device)
return device->trusted;
}

+static gboolean get_property_address(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *device = data;
+ char dstaddr[18];
+
+ ba2str(&device->bdaddr, dstaddr);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &dstaddr);
+
+ return TRUE;
+}
+
+static gboolean get_property_name(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *device = data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &device->name);
+ return TRUE;
+}
+
+static gboolean get_property_alias(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *device = data;
+ const char *ptr = device->name;
+ char dstaddr[18];
+
+ ba2str(&device->bdaddr, dstaddr);
+
+ if (device->alias != NULL)
+ ptr = device->alias;
+ else if (strlen(ptr) == 0) {
+ g_strdelimit(dstaddr, ":", '-');
+ ptr = dstaddr;
+ }
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &ptr);
+ return TRUE;
+}
+
+static gboolean get_property_class(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *device = data;
+ struct btd_adapter *adapter = device->adapter;
+ uint32_t class;
+ bdaddr_t src;
+
+ adapter_get_address(adapter, &src);
+
+ if (read_remote_class(&src, &device->bdaddr, &class) == 0) {
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &class);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean get_property_icon(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *device = data;
+ struct btd_adapter *adapter = device->adapter;
+ uint32_t class;
+ uint16_t app;
+ const char *icon;
+ bdaddr_t src;
+
+ adapter_get_address(adapter, &src);
+
+ if (read_remote_class(&src, &device->bdaddr, &class) == 0) {
+ icon = class_to_icon(class);
+ } else if (read_remote_appearance(&src, &device->bdaddr, &app) == 0) {
+ icon = gap_appearance_to_icon(app);
+ }
+ else {
+ return FALSE;
+ }
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &icon);
+ return TRUE;
+}
+
+static gboolean get_property_vendor(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *device = data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &device->vendor);
+ return TRUE;
+}
+
+static gboolean get_property_vendor_source(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *device = data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
+ &device->vendor_src);
+ return TRUE;
+}
+
+static gboolean get_property_product(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *device = data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
+ &device->product);
+ return TRUE;
+}
+
+static gboolean get_property_version(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *device = data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
+ &device->version);
+ return TRUE;
+}
+
+static gboolean get_property_paired(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *device = data;
+ dbus_bool_t boolean;
+
+ boolean = device_is_paired(device);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &boolean);
+ return TRUE;
+}
+
+static gboolean get_property_trusted(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *device = data;
+ dbus_bool_t boolean;
+
+ boolean = device_is_trusted(device);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &boolean);
+ return TRUE;
+}
+
+static gboolean get_property_blocked(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *device = data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN,
+ &device->blocked);
+ return TRUE;
+}
+
+static gboolean get_property_connected(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *device = data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN,
+ &device->connected);
+ return TRUE;
+}
+
+static gboolean get_property_uuids(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *variant, void *data)
+{
+ struct btd_device *device = data;
+ char **str;
+ GSList *l;
+ DBusMessageIter iter;
+ int i;
+
+ dbus_message_iter_open_container(variant, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING, &iter);
+ str = g_new0(char *, g_slist_length(device->uuids) + 1);
+
+ for (i = 0, l = device->uuids; l; l = l->next, i++) {
+ str[i] = l->data;
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
+ &(str[i]));
+ }
+
+ dbus_message_iter_close_container(variant, &iter);
+ g_free(str);
+
+ return TRUE;
+}
+
+static gboolean get_property_services(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *variant, void *data)
+{
+ struct btd_device *device = data;
+ char **str;
+ GSList *l;
+ DBusMessageIter iter;
+ int i;
+
+ dbus_message_iter_open_container(variant, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
+ str = g_new0(char *, g_slist_length(device->services) + 1);
+
+ for (i = 0, l = device->services; l; l = l->next, i++) {
+ str[i] = l->data;
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
+ &str[i]);
+ }
+
+ dbus_message_iter_close_container(variant, &iter);
+ g_free(str);
+
+ return TRUE;
+}
+
+static gboolean get_property_adapter(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *device = data;
+ struct btd_adapter *adapter = device->adapter;
+ const char *ptr;
+
+ ptr = adapter_get_path(adapter);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &ptr);
+ return TRUE;
+}
+
+gboolean property_class_exists(const GDBusPropertyTable *property, void *data)
+{
+ struct btd_device *device = data;
+ struct btd_adapter *adapter = device->adapter;
+ uint32_t class;
+ bdaddr_t src;
+
+ adapter_get_address(adapter, &src);
+
+ if (read_remote_class(&src, &device->bdaddr, &class) == 0) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gboolean property_icon_exists(const GDBusPropertyTable *property, void *data)
+{
+ struct btd_device *device = data;
+ struct btd_adapter *adapter = device->adapter;
+ uint32_t class;
+ uint16_t app;
+ bdaddr_t src;
+
+ adapter_get_address(adapter, &src);
+
+ if (read_remote_class(&src, &device->bdaddr, &class) == 0) {
+ return TRUE;
+ } else if (read_remote_appearance(&src, &device->bdaddr, &app) == 0) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gboolean property_vendor_exists(const GDBusPropertyTable *property, void *data)
+{
+ struct btd_device *device = data;
+
+ return (device->vendor != 0);
+}
+
+gboolean property_vendor_source_exists(const GDBusPropertyTable *property,
+ void *data)
+{
+ struct btd_device *device = data;
+
+ return (device->vendor_src != 0);
+}
+
+gboolean property_product_exists(const GDBusPropertyTable *property, void *data)
+{
+ struct btd_device *device = data;
+
+ return (device->product != 0);
+}
+
+gboolean property_version_exists(const GDBusPropertyTable *property, void *data)
+{
+ struct btd_device *device = data;
+
+ return (device->version != 0);
+}
+
static DBusMessage *get_properties(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
@@ -613,6 +921,48 @@ static DBusMessage *set_blocked(DBusConnection *conn, DBusMessage *msg,
}
}

+DBusMessage *set_property_alias(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ const char *alias;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
+ return btd_error_invalid_args(message);
+
+ dbus_message_iter_get_basic(iter, &alias);
+
+ return set_alias(connection, message, alias, data);
+}
+
+DBusMessage *set_property_trusted(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ dbus_bool_t value;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BOOLEAN)
+ return btd_error_invalid_args(message);
+
+ dbus_message_iter_get_basic(iter, &value);
+
+ return set_trust(connection, message, value, data);
+}
+
+DBusMessage *set_property_blocked(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ dbus_bool_t value;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BOOLEAN)
+ return btd_error_invalid_args(message);
+
+ dbus_message_iter_get_basic(iter, &value);
+
+ return set_blocked(connection, message, value, data);
+}
+
static DBusMessage *set_property(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -631,6 +981,7 @@ static DBusMessage *set_property(DBusConnection *conn,

if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
return btd_error_invalid_args(msg);
+
dbus_message_iter_recurse(&iter, &sub);

if (g_str_equal("Trusted", property)) {
@@ -878,8 +1229,10 @@ static DBusMessage *disconnect(DBusConnection *conn, DBusMessage *msg,
}

static const GDBusMethodTable device_methods[] = {
- { "GetProperties", "", "a{sv}[properties]", get_properties },
- { "SetProperty", "s[name]v[value]", "", set_property },
+ { "GetProperties", "", "a{sv}[properties]", get_properties,
+ G_DBUS_METHOD_FLAG_DEPRECATED },
+ { "SetProperty", "s[name]v[value]", "", set_property,
+ G_DBUS_METHOD_FLAG_DEPRECATED },
{ "DiscoverServices", "s[pattern]", "a{us}[services]", discover_services,
G_DBUS_METHOD_FLAG_ASYNC},
{ "CancelDiscovery", "", "", cancel_discover },
@@ -894,6 +1247,29 @@ static const GDBusSignalTable device_signals[] = {
{ }
};

+static const GDBusPropertyTable device_properties[] = {
+ { "Address", "s", 0, get_property_address },
+ { "Name", "s", 0, get_property_name },
+ { "Alias", "s", 0, get_property_alias, set_property_alias },
+ { "Class", "u", 0, get_property_class, NULL, property_class_exists },
+ { "Icon", "s", 0, get_property_icon, NULL, property_icon_exists },
+ { "Vendor", "q", 0, get_property_vendor, NULL, property_vendor_exists },
+ { "VendorSource", "q", 0, get_property_vendor_source, NULL,
+ property_vendor_source_exists },
+ { "Product", "q", 0, get_property_product, NULL,
+ property_product_exists },
+ { "Version", "q", 0, get_property_version, NULL,
+ property_version_exists },
+ { "Paired", "b", 0, get_property_paired },
+ { "Trusted", "b", 0, get_property_trusted, set_property_trusted },
+ { "Blocked", "b", 0, get_property_blocked, set_property_blocked },
+ { "Connected", "b", 0, get_property_connected },
+ { "UUIDs", "as", 0, get_property_uuids },
+ { "Services", "ao", 0, get_property_services },
+ { "Adapter", "o", 0, get_property_adapter },
+ { }
+};
+
gboolean device_is_connected(struct btd_device *device)
{
return device->connected;
@@ -1057,8 +1433,8 @@ struct btd_device *device_create(DBusConnection *conn,
DBG("Creating device %s", device->path);

if (g_dbus_register_interface(conn, device->path, DEVICE_INTERFACE,
- device_methods, device_signals, NULL,
- device, device_free) == FALSE) {
+ device_methods, device_signals, device_properties,
+ device, device_free) == FALSE) {
device_free(device);
return NULL;
}
--
1.7.5.4


Subject: [PATCH RFC 3/4] adapter: implement DBus.Properties

---
src/adapter.c | 280 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 280 insertions(+), 0 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 772c926..4c9b639 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1071,6 +1071,179 @@ static DBusMessage *adapter_stop_discovery(DBusConnection *conn,
return dbus_message_new_method_return(msg);
}

+static gboolean get_property_address(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_adapter *adapter = data;
+ char srcaddr[18];
+
+ ba2str(&adapter->bdaddr, srcaddr);
+
+ if (check_address(srcaddr) < 0)
+ return FALSE;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &srcaddr);
+
+ return TRUE;
+}
+
+static gboolean get_property_name(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_adapter *adapter = data;
+ const char *name;
+
+ name = adapter->name ? : "";
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &name);
+
+ return TRUE;
+}
+
+static gboolean get_property_class(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_adapter *adapter = data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32,
+ &adapter->dev_class);
+
+ return TRUE;
+}
+
+static gboolean get_property_powered(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_adapter *adapter = data;
+ gboolean value;
+
+ value = (adapter->up && !adapter->off_requested) ? TRUE : FALSE;
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &value);
+
+ return TRUE;
+}
+
+static gboolean get_property_discoverable(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_adapter *adapter = data;
+ gboolean value;
+
+ value = adapter->scan_mode & SCAN_INQUIRY ? TRUE : FALSE;
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &value);
+
+ return TRUE;
+}
+
+static gboolean get_property_pairable(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_adapter *adapter = data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN,
+ &adapter->pairable);
+
+ return TRUE;
+}
+
+static gboolean get_property_discoverable_timeout(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_adapter *adapter = data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32,
+ &adapter->discov_timeout);
+
+ return TRUE;
+}
+
+static gboolean get_property_pairable_timeout(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_adapter *adapter = data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32,
+ &adapter->pairable_timeout);
+
+ return TRUE;
+}
+
+static gboolean get_property_discovering(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_adapter *adapter = data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN,
+ &adapter->discovering);
+
+ return TRUE;
+}
+
+static gboolean get_property_devices(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *variant, void *data)
+{
+ DBusMessageIter iter;
+ struct btd_adapter *adapter = data;
+ GSList *l;
+
+ dbus_message_iter_open_container(variant, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
+
+ for (l = adapter->devices; l; l = l->next) {
+ struct btd_device *dev = l->data;
+ const char *device_path = device_get_path(dev);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+ &device_path);
+ }
+
+ dbus_message_iter_close_container(variant, &iter);
+
+ return TRUE;
+}
+
+static gboolean get_property_uuids(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *variant, void *data)
+{
+ DBusMessageIter iter;
+ struct btd_adapter *adapter = data;
+ sdp_list_t *list;
+ char **uuids;
+ int i;
+
+ dbus_message_iter_open_container(variant, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING, &iter);
+
+ uuids = g_new0(char *, sdp_list_len(adapter->services) + 1);
+
+ for (i = 0, list = adapter->services; list; list = list->next) {
+ sdp_record_t *rec = list->data;
+ char *uuid = bt_uuid2string(&rec->svclass);
+
+ if (uuid) {
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
+ &uuid);
+ uuids[i++] = uuid;
+ }
+
+ }
+
+ g_strfreev(uuids);
+ dbus_message_iter_close_container(variant, &iter);
+
+ return TRUE;
+}
+
static DBusMessage *get_properties(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -1171,6 +1344,95 @@ static DBusMessage *get_properties(DBusConnection *conn,
return reply;
}

+static DBusMessage *set_property_name(DBusConnection *connection,
+ DBusMessage *message,
+ const GDBusPropertyTable *property,
+ DBusMessageIter *value, void *data)
+{
+ const char *name;
+
+ if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_STRING)
+ return btd_error_invalid_args(message);
+ dbus_message_iter_get_basic(value, &name);
+
+ return set_name(connection, message, name, data);
+}
+
+static DBusMessage *set_property_powered(DBusConnection *connection,
+ DBusMessage *message,
+ const GDBusPropertyTable *property,
+ DBusMessageIter *value, void *data)
+{
+ gboolean powered;
+
+ if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_BOOLEAN)
+ return btd_error_invalid_args(message);
+
+ dbus_message_iter_get_basic(value, &powered);
+
+ return set_powered(connection, message, powered, data);
+}
+
+static DBusMessage *set_property_discoverable(DBusConnection *connection,
+ DBusMessage *message,
+ const GDBusPropertyTable *property,
+ DBusMessageIter *value, void *data)
+{
+ gboolean discoverable;
+
+ if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_BOOLEAN)
+ return btd_error_invalid_args(message);
+
+ dbus_message_iter_get_basic(value, &discoverable);
+
+ return set_discoverable(connection, message, discoverable, data);
+}
+
+static DBusMessage *set_property_discoverable_timeout(DBusConnection *connection,
+ DBusMessage *message,
+ const GDBusPropertyTable *property,
+ DBusMessageIter *value, void *data)
+{
+ uint32_t timeout;
+
+ if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_UINT32)
+ return btd_error_invalid_args(message);
+
+ dbus_message_iter_get_basic(value, &timeout);
+
+ return set_discoverable_timeout(connection, message, timeout, data);
+}
+
+static DBusMessage *set_property_pairable(DBusConnection *connection,
+ DBusMessage *message,
+ const GDBusPropertyTable *property,
+ DBusMessageIter *value, void *data)
+{
+ gboolean pairable;
+
+ if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_BOOLEAN)
+ return btd_error_invalid_args(message);
+
+ dbus_message_iter_get_basic(value, &pairable);
+
+ return set_pairable(connection, message, pairable, data);
+}
+
+static DBusMessage *set_property_pairable_timeout(DBusConnection *connection,
+ DBusMessage *message,
+ const GDBusPropertyTable *property,
+ DBusMessageIter *value, void *data)
+{
+ uint32_t timeout;
+
+ if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_UINT32)
+ return btd_error_invalid_args(message);
+
+ dbus_message_iter_get_basic(value, &timeout);
+
+ return set_pairable_timeout(connection, message, timeout, data);
+}
+
static DBusMessage *set_property(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -1694,6 +1956,24 @@ static const GDBusSignalTable adapter_signals[] = {
{ }
};

+static const GDBusPropertyTable adapter_properties[] = {
+ { "Address", "s", 0, get_property_address },
+ { "Name", "s", 0, get_property_name, set_property_name },
+ { "Class", "u", 0, get_property_class },
+ { "Powered", "b", 0, get_property_powered, set_property_powered },
+ { "Discoverable", "b", 0, get_property_discoverable,
+ set_property_discoverable },
+ { "Pairable", "b", 0, get_property_pairable, set_property_pairable },
+ { "DiscoverableTimeout", "u", 0, get_property_discoverable_timeout,
+ set_property_discoverable_timeout },
+ { "PairableTimeout", "u", 0, get_property_pairable_timeout,
+ set_property_pairable_timeout },
+ { "Discovering", "b", 0, get_property_discovering },
+ { "Devices", "ao", 0, get_property_devices },
+ { "UUIDs", "s", 0, get_property_uuids },
+ { }
+};
+
static void create_stored_device_from_profiles(char *key, char *value,
void *user_data)
{
--
1.7.5.4


Subject: [PATCH RFC 2/4] thermometer: implement support for DBus.Properties.Get and DBus.Properties.Set

---
thermometer/thermometer.c | 86 +++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 83 insertions(+), 3 deletions(-)

diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 487c1fc..2c70721 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -556,6 +556,57 @@ static void configure_thermometer_cb(GSList *characteristics, guint8 status,
}
}

+static gboolean get_property_intermediate(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *variant, void *data)
+{
+ struct thermometer *t = data;
+ dbus_message_iter_append_basic(variant, DBUS_TYPE_BOOLEAN,
+ &t->intermediate);
+ return TRUE;
+}
+
+gboolean property_interval_exists(const GDBusPropertyTable *property,
+ void *data)
+{
+ struct thermometer *t = data;
+
+ return (t->has_interval);
+}
+
+static gboolean get_property_interval(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *variant, void *data)
+{
+ struct thermometer *t = data;
+
+ dbus_message_iter_append_basic(variant, DBUS_TYPE_UINT16, &t->interval);
+
+ return TRUE;
+}
+
+static gboolean get_property_maximum(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *variant, void *data)
+{
+ struct thermometer *t = data;
+
+ dbus_message_iter_append_basic(variant, DBUS_TYPE_UINT16, &t->max);
+
+ return TRUE;
+}
+
+static gboolean get_property_minimum(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *variant, void *data)
+{
+ struct thermometer *t = data;
+
+ dbus_message_iter_append_basic(variant, DBUS_TYPE_UINT16, &t->min);
+
+ return TRUE;
+}
+
static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg,
void *data)
{
@@ -640,6 +691,21 @@ static DBusMessage *write_attr_interval(struct thermometer *t, DBusMessage *msg,
return dbus_message_new_method_return(msg);
}

+DBusMessage *set_property_interval(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct thermometer *t = data;
+ uint16_t value;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT16)
+ return btd_error_invalid_args(message);
+
+ dbus_message_iter_get_basic(iter, &value);
+
+ return write_attr_interval(t, message, value);
+}
+
static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
void *data)
{
@@ -960,9 +1026,11 @@ static DBusMessage *disable_intermediate(DBusConnection *conn, DBusMessage *msg,
}

static const GDBusMethodTable thermometer_methods[] = {
- { "GetProperties", "", "a{sv}[properties]", get_properties },
+ { "GetProperties", "", "a{sv}[properties]", get_properties,
+ G_DBUS_METHOD_FLAG_DEPRECATED},
{ "SetProperty", "s[name]v[value]", "", set_property,
- G_DBUS_METHOD_FLAG_ASYNC },
+ G_DBUS_METHOD_FLAG_ASYNC |
+ G_DBUS_METHOD_FLAG_DEPRECATED},
{ "RegisterWatcher", "o[agent]", "", register_watcher },
{ "UnregisterWatcher", "o[agent]", "", unregister_watcher },
{ "EnableIntermediateMeasurement", "o[agent]", "", enable_intermediate },
@@ -975,6 +1043,17 @@ static const GDBusSignalTable thermometer_signals[] = {
{ }
};

+static const GDBusPropertyTable thermometer_properties[] = {
+ { "Intermediate", "b", 0, get_property_intermediate },
+ { "Interval", "q", 0, get_property_interval, set_property_interval,
+ property_interval_exists },
+ { "Maximum", "q", 0, get_property_maximum, NULL,
+ property_interval_exists },
+ { "Minimum", "q", 0, get_property_minimum, NULL,
+ property_interval_exists },
+ { }
+};
+
static void update_watcher(gpointer data, gpointer user_data)
{
struct watcher *w = data;
@@ -1228,7 +1307,8 @@ int thermometer_register(DBusConnection *connection, struct btd_device *device,

if (!g_dbus_register_interface(t->conn, path, THERMOMETER_INTERFACE,
thermometer_methods, thermometer_signals,
- NULL, t, destroy_thermometer)) {
+ thermometer_properties, t,
+ destroy_thermometer)) {
error("D-Bus failed to register %s interface",
THERMOMETER_INTERFACE);
destroy_thermometer(t);
--
1.7.5.4


Subject: [PATCH RFC 1/4] manager: implement support for DBus.Properties.Get

---
src/manager.c | 31 +++++++++++++++++++++++++++++--
1 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/src/manager.c b/src/manager.c
index f43861d..b159f62 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -160,6 +160,27 @@ static DBusMessage *list_adapters(DBusConnection *conn,
return reply;
}

+static gboolean get_property_adapters(DBusConnection *connection,
+ DBusMessage *message, const GDBusPropertyTable *property,
+ DBusMessageIter *variant, void *data)
+{
+ DBusMessageIter iter;
+ GSList *list;
+
+ dbus_message_iter_open_container(variant, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
+
+ for (list = adapters; list; list = list->next) {
+ struct btd_adapter *adapter = list->data;
+ const char *adapter_path = adapter_get_path(adapter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+ &adapter_path);
+ }
+
+ dbus_message_iter_close_container(variant, &iter);
+ return TRUE;
+}
+
static DBusMessage *get_properties(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -197,7 +218,8 @@ static DBusMessage *get_properties(DBusConnection *conn,
}

static const GDBusMethodTable manager_methods[] = {
- { "GetProperties", "", "a{sv}[properties]",get_properties },
+ { "GetProperties", "", "a{sv}[properties]", get_properties,
+ G_DBUS_METHOD_FLAG_DEPRECATED},
{ "DefaultAdapter", "", "o[adapter]", default_adapter },
{ "FindAdapter", "s[pattern]", "o[adapter]", find_adapter },
{ "ListAdapters", "", "ao[adapters]", list_adapters,
@@ -213,6 +235,11 @@ static const GDBusSignalTable manager_signals[] = {
{ }
};

+static const GDBusPropertyTable manager_properties[] = {
+ { "Adapters", "ao", 0, get_property_adapters, NULL, NULL },
+ { }
+};
+
dbus_bool_t manager_init(DBusConnection *conn, const char *path)
{
connection = conn;
@@ -221,7 +248,7 @@ dbus_bool_t manager_init(DBusConnection *conn, const char *path)

return g_dbus_register_interface(conn, "/", MANAGER_INTERFACE,
manager_methods, manager_signals,
- NULL, NULL, NULL);
+ manager_properties, NULL, NULL);
}

static void manager_update_adapters(void)
--
1.7.5.4