[pulseaudio-discuss] [RFCv3 18/43] bluetooth: Parse BlueZ 5 device properties
jprvita at gmail.com
jprvita at gmail.com
Fri Sep 13 16:34:25 PDT 2013
From: João Paulo Rechi Vita <jprvita at openbossa.org>
This code is based on previous work by Mikel Astiz.
---
src/modules/bluetooth/bluez5-util.c | 153 ++++++++++++++++++++++++++++++++++--
src/modules/bluetooth/bluez5-util.h | 1 +
2 files changed, 146 insertions(+), 8 deletions(-)
diff --git a/src/modules/bluetooth/bluez5-util.c b/src/modules/bluetooth/bluez5-util.c
index 7fc7d50..485471f 100644
--- a/src/modules/bluetooth/bluez5-util.c
+++ b/src/modules/bluetooth/bluez5-util.c
@@ -297,6 +297,7 @@ static pa_bluetooth_device* device_create(pa_bluetooth_discovery *y, const char
d = pa_xnew0(pa_bluetooth_device, 1);
d->discovery = y;
d->path = pa_xstrdup(path);
+ d->uuids = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
pa_hashmap_put(y->devices, d->path, d);
@@ -348,6 +349,9 @@ static void device_free(pa_bluetooth_device *d) {
pa_bluetooth_transport_free(t);
}
+ if (d->uuids)
+ pa_hashmap_free(d->uuids, NULL);
+
d->discovery = NULL;
d->adapter = NULL;
pa_xfree(d->path);
@@ -408,6 +412,145 @@ static void adapter_remove_all(pa_bluetooth_discovery *y) {
}
}
+static int parse_device_property(pa_bluetooth_device *d, DBusMessageIter *i, bool is_property_change) {
+ const char *key;
+ DBusMessageIter variant_i;
+
+ pa_assert(d);
+
+ key = check_variant_property(i);
+ if (key == NULL) {
+ pa_log_error("Received invalid property for device %s", d->path);
+ return -1;
+ }
+
+ dbus_message_iter_recurse(i, &variant_i);
+
+ switch (dbus_message_iter_get_arg_type(&variant_i)) {
+
+ case DBUS_TYPE_STRING: {
+ const char *value;
+ dbus_message_iter_get_basic(&variant_i, &value);
+
+ if (pa_streq(key, "Alias")) {
+ pa_xfree(d->alias);
+ d->alias = pa_xstrdup(value);
+ pa_log_debug("%s: %s", key, value);
+ } else if (pa_streq(key, "Address")) {
+ if (is_property_change) {
+ pa_log_error("Device property 'Address' expected to be constant but changed for %s", d->path);
+ return -1;
+ }
+
+ if (d->address) {
+ pa_log_error("Device %s: Received a duplicate 'Address' property.", d->path);
+ return -1;
+ }
+
+ d->address = pa_xstrdup(value);
+ pa_log_debug("%s: %s", key, value);
+ }
+
+ break;
+ }
+
+ case DBUS_TYPE_OBJECT_PATH: {
+ const char *value;
+ dbus_message_iter_get_basic(&variant_i, &value);
+
+ if (pa_streq(key, "Adapter")) {
+
+ if (is_property_change) {
+ pa_log_error("Device property 'Adapter' expected to be constant but changed for %s", d->path);
+ return -1;
+ }
+
+ if (d->adapter) {
+ pa_log_error("Device %s: Received a duplicate 'Adapter' property.", d->path);
+ return -1;
+ }
+
+ d->adapter = pa_hashmap_get(d->discovery->adapters, value);
+ pa_log_debug("%s: %s", key, value);
+ }
+
+ break;
+ }
+
+ case DBUS_TYPE_UINT32: {
+ uint32_t value;
+ dbus_message_iter_get_basic(&variant_i, &value);
+
+ if (pa_streq(key, "Class")) {
+ d->class_of_device = value;
+ pa_log_debug("%s: %d", key, value);
+ }
+
+ break;
+ }
+
+ case DBUS_TYPE_ARRAY: {
+ DBusMessageIter ai;
+ dbus_message_iter_recurse(&variant_i, &ai);
+
+ if (dbus_message_iter_get_arg_type(&ai) == DBUS_TYPE_STRING && pa_streq(key, "UUIDs")) {
+ /* bluetoothd never removes UUIDs from a device object so there
+ * is no need to handle it here. */
+ while (dbus_message_iter_get_arg_type(&ai) != DBUS_TYPE_INVALID) {
+ const char *value;
+ char *uuid;
+
+ dbus_message_iter_get_basic(&ai, &value);
+
+ if (pa_hashmap_get(d->uuids, value)) {
+ dbus_message_iter_next(&ai);
+ continue;
+ }
+
+ uuid = pa_xstrdup(value);
+ pa_hashmap_put(d->uuids, uuid, uuid);
+
+ pa_log_debug("%s: %s", key, value);
+ dbus_message_iter_next(&ai);
+ }
+ }
+
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int parse_device_properties(pa_bluetooth_device *d, DBusMessageIter *i, bool is_property_change) {
+ DBusMessageIter element_i;
+ int ret = 0;
+
+ dbus_message_iter_recurse(i, &element_i);
+
+ while (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter dict_i;
+
+ dbus_message_iter_recurse(&element_i, &dict_i);
+
+ if (parse_device_property(d, &dict_i, is_property_change) < 0) {
+ d->device_info_valid = -1;
+ ret = -1;
+ }
+
+ dbus_message_iter_next(&element_i);
+ }
+
+ if (!d->address || !d->adapter || !d->alias) {
+ pa_log_error("Non-optional information missing for device %s", d->path);
+ d->device_info_valid = -1;
+ return -1;
+ }
+
+ d->device_info_valid = 1;
+ return ret;
+}
+
static int parse_adapter_properties(pa_bluetooth_adapter *a, DBusMessageIter *i, bool is_property_change) {
DBusMessageIter element_i;
@@ -561,22 +704,16 @@ static void parse_interfaces_and_properties(pa_bluetooth_discovery *y, DBusMessa
pa_bluetooth_device *d;
if ((d = pa_hashmap_get(y->devices, path))) {
- if (d->device_info_valid == 1) {
+ if (d->device_info_valid != 0) {
pa_log_error("Found duplicated D-Bus path for device %s", path);
return;
}
-
- if (d->device_info_valid == -1) {
- pa_log_notice("Device %s was known before but had invalid information, reseting", path);
- d->device_info_valid = 0;
- }
-
} else
d = device_create(y, path);
pa_log_debug("Device %s found", d->path);
- /* TODO: parse device properties */
+ parse_device_properties(d, &iface_i, false);
} else
pa_log_debug("Unknown interface %s found, skipping", interface);
diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h
index 4e0b567..41673e3 100644
--- a/src/modules/bluetooth/bluez5-util.h
+++ b/src/modules/bluetooth/bluez5-util.h
@@ -83,6 +83,7 @@ struct pa_bluetooth_device {
char *alias;
char *address;
uint32_t class_of_device;
+ pa_hashmap *uuids;
pa_bluetooth_transport *transports[PA_BLUETOOTH_PROFILE_COUNT];
};
--
1.8.3.1
More information about the pulseaudio-discuss
mailing list