[pulseaudio-discuss] [PATCH 37/56] bluetooth: Parse BlueZ 5 device properties

João Paulo Rechi Vita jprvita at gmail.com
Fri Jul 26 06:45:11 PDT 2013


On Thu, Jul 25, 2013 at 1:44 AM, João Paulo Rechi Vita
<jprvita at gmail.com> wrote:
> On Mon, Jul 22, 2013 at 7:33 AM, Tanu Kaskinen
> <tanu.kaskinen at linux.intel.com> wrote:
>> 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?
>>
>
> This is usually received when the device is created, together with a
> lot of other properties, so I think is better to minimize verbosity
> here. What I'll change to improve this scenario is add a log in the
> beginning of the function with the device path.
>

Actually there is already a message right before parsing properties
that says that a new device have been found, so I'll keep the original
version. The log will look like this:

D: [memcheck-amd64-] bluez5-util.c: Device
/org/bluez/hci0/dev_00_0D_3C_B1_B5_5C found
D: [memcheck-amd64-] bluez5-util.c: Address: 00:0D:3C:B1:B5:5C
D: [memcheck-amd64-] bluez5-util.c: Name: Nokia BH-503
D: [memcheck-amd64-] bluez5-util.c: Alias: Nokia BH-503
D: [memcheck-amd64-] bluez5-util.c: Class: 2360324
D: [memcheck-amd64-] bluez5-util.c: Icon: audio-card
D: [memcheck-amd64-] bluez5-util.c: UUIDs: 00001108-0000-1000-8000-00805f9b34fb
D: [memcheck-amd64-] bluez5-util.c: UUIDs: 0000110b-0000-1000-8000-00805f9b34fb
D: [memcheck-amd64-] bluez5-util.c: UUIDs: 0000110c-0000-1000-8000-00805f9b34fb
D: [memcheck-amd64-] bluez5-util.c: UUIDs: 0000110d-0000-1000-8000-00805f9b34fb
D: [memcheck-amd64-] bluez5-util.c: UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
D: [memcheck-amd64-] bluez5-util.c: UUIDs: 0000111e-0000-1000-8000-00805f9b34fb
D: [memcheck-amd64-] bluez5-util.c: Adapter: /org/bluez/hci0

>>> +            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.
>>
>
> I'm not sure, and BlueZ' documentation does't mention anything about
> that. Maybe Luiz have more information about that.
>
>>> +
>>> +            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?
>>
>
> This is used to create card profiles on load of module-bluez5-device.
> It is possible (although not likely) that a device change the
> implemented UUIDs during the connection lifetime. Alias can change,
> but I think this should be handled in a separate patch (I've not
> written that yet).
>
>>> +                }
>>> +            }
>>> +
>>> +            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.
>>
>
> Yes, I've forgot to remove that. There is no use for the Paired and
> Trusted properties in PulseAudio.
>
>>> +        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.
>>
>
> parse_device_properties() will fail even if the parsing of an optional
> property fails, but the device is still fully usable, so we should
> still create the device in this case. To differentiate between these
> two situations there is the device_info_valid field. Maybe we can
> review the necessity of the device_info_valid field, but since this
> affects the modules working logic and may introduce bugs I would
> prefer to change that in a latter moment to minimize the impact.
>
>>>          } 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.
>>
>
> AFAIK that's the only purpose, so I think it makes sense to change to
> a hashmap as you suggested.
>
> --
> João Paulo Rechi Vita
> http://about.me/jprvita



-- 
João Paulo Rechi Vita
http://about.me/jprvita


More information about the pulseaudio-discuss mailing list