[pulseaudio-discuss] [PATCH 37/56] bluetooth: Parse BlueZ 5 device properties
Tanu Kaskinen
tanu.kaskinen at linux.intel.com
Mon Jul 22 03:33:03 PDT 2013
On Fri, 2013-07-12 at 15:06 -0300, jprvita at gmail.com wrote:
> +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 = pa_bluetooth_dbus_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);
> + } 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);
Please use proper sentences in the log. Or is this a temporary log
message that you just forgot to remove from the final patch?
> + 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 = (int) value;
Is the device allowed to change its class at runtime? If not, then there
should be a check for is_property_change like with Address.
> +
> + 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")) {
> + while (dbus_message_iter_get_arg_type(&ai) != DBUS_TYPE_INVALID) {
> + pa_bluetooth_uuid *node;
> + const char *value;
> +
> + dbus_message_iter_get_basic(&ai, &value);
> +
> + if (pa_bluetooth_uuid_has(d->uuids, value)) {
> + dbus_message_iter_next(&ai);
> + continue;
> + }
> +
> + node = pa_bluetooth_uuid_new(value);
> + PA_LLIST_PREPEND(pa_bluetooth_uuid, d->uuids, node);
> +
> + pa_log_debug("%s: %s", key, value);
> + dbus_message_iter_next(&ai);
This code only adds UUIDs to pa_bluetooth_device, never removes them. Is
this intentional? If so, I think a comment explaining the rationale
would be good.
There aren't any hooks that would be fired when the properties (Alias,
Class, UUIDs) change. Perhaps you implement them in some later patches?
> + }
> + }
> +
> + 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)
> + ret = -1;
> +
> + dbus_message_iter_next(&element_i);
> + }
> +
> + if (!d->address || !d->alias/* || d->paired < 0 || d->trusted < 0*/) {
If you don't plan to support the paired and trusted properties (which
would be a good plan IMO), please remove the commented out code.
> + 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 void register_endpoint_reply(DBusPendingCall *pending, void *userdata) {
> DBusMessage *r;
> pa_dbus_pending *p;
> @@ -423,6 +595,8 @@ static void parse_interfaces_and_properties(pa_bluetooth_discovery *y, DBusMessa
> register_endpoint(y, path, A2DP_SOURCE_ENDPOINT, A2DP_SOURCE_UUID);
> register_endpoint(y, path, A2DP_SINK_ENDPOINT, A2DP_SINK_UUID);
> } else if (pa_streq(interface, BLUEZ_DEVICE_INTERFACE)) {
> + pa_bluetooth_device *d;
> +
> if (pa_bluetooth_discovery_get_device_by_path(y, path)) {
> pa_log_error("Found duplicated D-Bus path for device %s", path);
> return;
> @@ -430,8 +604,8 @@ static void parse_interfaces_and_properties(pa_bluetooth_discovery *y, DBusMessa
>
> pa_log_debug("Device %s found", path);
>
> - pa_bluetooth_discovery_create_device(y, path);
> - /* TODO: parse device properties */
> + d = pa_bluetooth_discovery_create_device(y, path);
> + parse_device_properties(d, &iface_i, false);
If parsing the device properties fails, we shouldn't create the device.
> } 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 68c2dc0..b1a112f 100644
> --- a/src/modules/bluetooth/bluez5-util.h
> +++ b/src/modules/bluetooth/bluez5-util.h
> @@ -27,6 +27,7 @@
> #define A2DP_SOURCE_UUID "0000110a-0000-1000-8000-00805f9b34fb"
> #define A2DP_SINK_UUID "0000110b-0000-1000-8000-00805f9b34fb"
>
> +typedef struct pa_bluetooth_uuid pa_bluetooth_uuid;
I don't see the point of a separate struct. The purpose seems to be only
to make it possible to save the UUIDs in a linked list, but using a
hashmap (as a set, i.e. the key and value are the same) would be much
simpler.
--
Tanu
More information about the pulseaudio-discuss
mailing list