A hashmap is more convenient than a linked list for storing the UUIDs, so change the BlueZ 4 code accordingly. Rename the BlueZ 4 UUID constants to match the BlueZ 5 naming. The only changes to the BlueZ 5 code are the addition of one comment and making another comment a bit clearer. --- src/modules/bluetooth/bluez4-util.c | 70 ++++++++-------------------- src/modules/bluetooth/bluez4-util.h | 28 +++-------- src/modules/bluetooth/bluez5-util.c | 4 +- src/modules/bluetooth/bluez5-util.h | 2 +- src/modules/bluetooth/module-bluez4-device.c | 15 +++--- 5 files changed, 38 insertions(+), 81 deletions(-) diff --git a/src/modules/bluetooth/bluez4-util.c b/src/modules/bluetooth/bluez4-util.c index 97b5ab0..a30e438 100644 --- a/src/modules/bluetooth/bluez4-util.c +++ b/src/modules/bluetooth/bluez4-util.c @@ -146,23 +146,6 @@ static pa_bluez4_transport_state_t audio_state_to_transport_state(pa_bluez4_audi pa_assert_not_reached(); } -static pa_bluez4_uuid *uuid_new(const char *uuid) { - pa_bluez4_uuid *u; - - u = pa_xnew(pa_bluez4_uuid, 1); - u->uuid = pa_xstrdup(uuid); - PA_LLIST_INIT(pa_bluez4_uuid, u); - - return u; -} - -static void uuid_free(pa_bluez4_uuid *u) { - pa_assert(u); - - pa_xfree(u->uuid); - pa_xfree(u); -} - static pa_bluez4_device* device_new(pa_bluez4_discovery *discovery, const char *path) { pa_bluez4_device *d; unsigned i; @@ -181,7 +164,7 @@ static pa_bluez4_device* device_new(pa_bluez4_discovery *discovery, const char * d->path = pa_xstrdup(path); d->paired = -1; d->alias = NULL; - PA_LLIST_HEAD_INIT(pa_bluez4_uuid, d->uuids); + d->uuids = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, pa_xfree); d->address = NULL; d->class = -1; d->trusted = -1; @@ -204,7 +187,6 @@ static void transport_free(pa_bluez4_transport *t) { } static void device_free(pa_bluez4_device *d) { - pa_bluez4_uuid *u; pa_bluez4_transport *t; unsigned i; @@ -221,10 +203,8 @@ static void device_free(pa_bluez4_device *d) { transport_free(t); } - while ((u = d->uuids)) { - PA_LLIST_REMOVE(pa_bluez4_uuid, d->uuids, u); - uuid_free(u); - } + if (d->uuids) + pa_hashmap_free(d->uuids); pa_xfree(d->name); pa_xfree(d->path); @@ -416,7 +396,6 @@ static int parse_device_property(pa_bluez4_device *d, DBusMessageIter *i, bool i } case DBUS_TYPE_ARRAY: { - DBusMessageIter ai; dbus_message_iter_recurse(&variant_i, &ai); @@ -424,42 +403,46 @@ static int parse_device_property(pa_bluez4_device *d, DBusMessageIter *i, bool i DBusMessage *m; bool has_audio = false; + /* bluetoothd never removes UUIDs from a device object so we + * don't need to check for disappeared UUIDs here. */ while (dbus_message_iter_get_arg_type(&ai) != DBUS_TYPE_INVALID) { - pa_bluez4_uuid *node; const char *value; + char *uuid; struct pa_bluez4_hook_uuid_data uuiddata; dbus_message_iter_get_basic(&ai, &value); - if (pa_bluez4_uuid_has(d->uuids, value)) { + if (pa_hashmap_get(d->uuids, value)) { dbus_message_iter_next(&ai); continue; } - node = uuid_new(value); - PA_LLIST_PREPEND(pa_bluez4_uuid, d->uuids, node); + uuid = pa_xstrdup(value); + pa_hashmap_put(d->uuids, uuid, uuid); + + pa_log_debug("%s: %s", key, value); uuiddata.device = d; uuiddata.uuid = value; pa_hook_fire(&d->discovery->hooks[PA_BLUEZ4_HOOK_DEVICE_UUID_ADDED], &uuiddata); /* Vudentz said the interfaces are here when the UUIDs are announced */ - if (strcasecmp(HSP_AG_UUID, value) == 0 || strcasecmp(HFP_AG_UUID, value) == 0) { + if (pa_streq(PA_BLUEZ4_UUID_HSP_AG, value) || pa_streq(PA_BLUEZ4_UUID_HFP_AG, value)) { pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->path, "org.bluez.HandsfreeGateway", "GetProperties")); send_and_add_to_pending(d->discovery, m, get_properties_reply, d); has_audio = true; - } else if (strcasecmp(HSP_HS_UUID, value) == 0 || strcasecmp(HFP_HS_UUID, value) == 0) { + } else if (pa_streq(PA_BLUEZ4_UUID_HSP_HS, value) || pa_streq(PA_BLUEZ4_UUID_HFP_HF, value)) { pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->path, "org.bluez.Headset", "GetProperties")); send_and_add_to_pending(d->discovery, m, get_properties_reply, d); has_audio = true; - } else if (strcasecmp(A2DP_SINK_UUID, value) == 0) { + } else if (pa_streq(PA_BLUEZ4_UUID_A2DP_SINK, value)) { pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->path, "org.bluez.AudioSink", "GetProperties")); send_and_add_to_pending(d->discovery, m, get_properties_reply, d); has_audio = true; - } else if (strcasecmp(A2DP_SOURCE_UUID, value) == 0) { + } else if (pa_streq(PA_BLUEZ4_UUID_A2DP_SOURCE, value)) { pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->path, "org.bluez.AudioSource", "GetProperties")); send_and_add_to_pending(d->discovery, m, get_properties_reply, d); @@ -829,7 +812,7 @@ static void register_endpoint(pa_bluez4_discovery *y, const char *path, const ch pa_dbus_append_basic_variant_dict_entry(&d, "Codec", DBUS_TYPE_BYTE, &codec); - if (pa_streq(uuid, HFP_AG_UUID) || pa_streq(uuid, HFP_HS_UUID)) { + if (pa_streq(uuid, PA_BLUEZ4_UUID_HFP_AG) || pa_streq(uuid, PA_BLUEZ4_UUID_HFP_HF)) { uint8_t capability = 0; pa_dbus_append_basic_array_variant_dict_entry(&d, "Capabilities", DBUS_TYPE_BYTE, &capability, 1); } else { @@ -860,10 +843,10 @@ static void found_adapter(pa_bluez4_discovery *y, const char *path) { pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.Adapter", "GetProperties")); send_and_add_to_pending(y, m, get_properties_reply, NULL); - register_endpoint(y, path, ENDPOINT_PATH_HFP_AG, HFP_AG_UUID); - register_endpoint(y, path, ENDPOINT_PATH_HFP_HS, HFP_HS_UUID); - register_endpoint(y, path, ENDPOINT_PATH_A2DP_SOURCE, A2DP_SOURCE_UUID); - register_endpoint(y, path, ENDPOINT_PATH_A2DP_SINK, A2DP_SINK_UUID); + register_endpoint(y, path, ENDPOINT_PATH_HFP_AG, PA_BLUEZ4_UUID_HFP_AG); + register_endpoint(y, path, ENDPOINT_PATH_HFP_HS, PA_BLUEZ4_UUID_HFP_HF); + register_endpoint(y, path, ENDPOINT_PATH_A2DP_SOURCE, PA_BLUEZ4_UUID_A2DP_SOURCE); + register_endpoint(y, path, ENDPOINT_PATH_A2DP_SINK, PA_BLUEZ4_UUID_A2DP_SINK); } static void list_adapters(pa_bluez4_discovery *y) { @@ -1888,16 +1871,3 @@ char *pa_bluez4_cleanup_name(const char *name) { return t; } - -bool pa_bluez4_uuid_has(pa_bluez4_uuid *uuids, const char *uuid) { - pa_assert(uuid); - - while (uuids) { - if (strcasecmp(uuids->uuid, uuid) == 0) - return true; - - uuids = uuids->next; - } - - return false; -} diff --git a/src/modules/bluetooth/bluez4-util.h b/src/modules/bluetooth/bluez4-util.h index 7c76aac..abbbfab 100644 --- a/src/modules/bluetooth/bluez4-util.h +++ b/src/modules/bluetooth/bluez4-util.h @@ -27,34 +27,21 @@ #define PA_BLUEZ4_ERROR_NOT_SUPPORTED "org.bluez.Error.NotSupported" -/* UUID copied from bluez/audio/device.h */ -#define GENERIC_AUDIO_UUID "00001203-0000-1000-8000-00805f9b34fb" - -#define HSP_HS_UUID "00001108-0000-1000-8000-00805f9b34fb" -#define HSP_AG_UUID "00001112-0000-1000-8000-00805f9b34fb" - -#define HFP_HS_UUID "0000111e-0000-1000-8000-00805f9b34fb" -#define HFP_AG_UUID "0000111f-0000-1000-8000-00805f9b34fb" - -#define ADVANCED_AUDIO_UUID "0000110d-0000-1000-8000-00805f9b34fb" - -#define A2DP_SOURCE_UUID "0000110a-0000-1000-8000-00805f9b34fb" -#define A2DP_SINK_UUID "0000110b-0000-1000-8000-00805f9b34fb" +#define PA_BLUEZ4_UUID_A2DP_SOURCE "0000110a-0000-1000-8000-00805f9b34fb" +#define PA_BLUEZ4_UUID_A2DP_SINK "0000110b-0000-1000-8000-00805f9b34fb" +#define PA_BLUEZ4_UUID_HSP_HS "00001108-0000-1000-8000-00805f9b34fb" +#define PA_BLUEZ4_UUID_HSP_AG "00001112-0000-1000-8000-00805f9b34fb" +#define PA_BLUEZ4_UUID_HFP_HF "0000111e-0000-1000-8000-00805f9b34fb" +#define PA_BLUEZ4_UUID_HFP_AG "0000111f-0000-1000-8000-00805f9b34fb" #define HSP_MAX_GAIN 15 -typedef struct pa_bluez4_uuid pa_bluez4_uuid; typedef struct pa_bluez4_device pa_bluez4_device; typedef struct pa_bluez4_discovery pa_bluez4_discovery; typedef struct pa_bluez4_transport pa_bluez4_transport; struct userdata; -struct pa_bluez4_uuid { - char *uuid; - PA_LLIST_FIELDS(pa_bluez4_uuid); -}; - typedef enum pa_bluez4_profile { PA_BLUEZ4_PROFILE_A2DP, PA_BLUEZ4_PROFILE_A2DP_SOURCE, @@ -123,9 +110,9 @@ struct pa_bluez4_device { pa_bluez4_transport *transports[PA_BLUEZ4_PROFILE_COUNT]; int paired; char *alias; - PA_LLIST_HEAD(pa_bluez4_uuid, uuids); char *address; int class; + pa_hashmap *uuids; /* char* -> char* (hashmap-as-a-set) */ int trusted; /* Audio state */ @@ -170,7 +157,6 @@ const char *pa_bluez4_form_factor_to_string(pa_bluez4_form_factor_t ff); char *pa_bluez4_cleanup_name(const char *name); -bool pa_bluez4_uuid_has(pa_bluez4_uuid *uuids, const char *uuid); const char *pa_bluez4_profile_to_string(pa_bluez4_profile_t profile); #endif diff --git a/src/modules/bluetooth/bluez5-util.c b/src/modules/bluetooth/bluez5-util.c index b2abce3..305dfc8 100644 --- a/src/modules/bluetooth/bluez5-util.c +++ b/src/modules/bluetooth/bluez5-util.c @@ -734,8 +734,8 @@ static void parse_device_property(pa_bluetooth_device *d, DBusMessageIter *i) { 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. */ + /* bluetoothd never removes UUIDs from a device object so we + * don't need to check for disappeared UUIDs here. */ while (dbus_message_iter_get_arg_type(&ai) != DBUS_TYPE_INVALID) { const char *value; char *uuid; diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h index 2aa6ea6..7f124e2 100644 --- a/src/modules/bluetooth/bluez5-util.h +++ b/src/modules/bluetooth/bluez5-util.h @@ -102,7 +102,7 @@ struct pa_bluetooth_device { char *alias; char *address; uint32_t class_of_device; - pa_hashmap *uuids; + pa_hashmap *uuids; /* char* -> char* (hashmap-as-a-set) */ pa_bluetooth_transport *transports[PA_BLUETOOTH_PROFILE_COUNT]; diff --git a/src/modules/bluetooth/module-bluez4-device.c b/src/modules/bluetooth/module-bluez4-device.c index 13fb7ab..bae4e45 100644 --- a/src/modules/bluetooth/module-bluez4-device.c +++ b/src/modules/bluetooth/module-bluez4-device.c @@ -2172,7 +2172,7 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid pa_assert_se(input_port = pa_hashmap_get(ports, u->input_port_name)); pa_assert_se(output_port = pa_hashmap_get(ports, u->output_port_name)); - if (pa_streq(uuid, A2DP_SINK_UUID)) { + if (pa_streq(uuid, PA_BLUEZ4_UUID_A2DP_SINK)) { p = pa_card_profile_new("a2dp", _("High Fidelity Playback (A2DP)"), sizeof(pa_bluez4_profile_t)); p->priority = 10; p->n_sinks = 1; @@ -2183,7 +2183,7 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid d = PA_CARD_PROFILE_DATA(p); *d = PA_BLUEZ4_PROFILE_A2DP; - } else if (pa_streq(uuid, A2DP_SOURCE_UUID)) { + } else if (pa_streq(uuid, PA_BLUEZ4_UUID_A2DP_SOURCE)) { p = pa_card_profile_new("a2dp_source", _("High Fidelity Capture (A2DP)"), sizeof(pa_bluez4_profile_t)); p->priority = 10; p->n_sinks = 0; @@ -2194,7 +2194,7 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid d = PA_CARD_PROFILE_DATA(p); *d = PA_BLUEZ4_PROFILE_A2DP_SOURCE; - } else if (pa_streq(uuid, HSP_HS_UUID) || pa_streq(uuid, HFP_HS_UUID)) { + } else if (pa_streq(uuid, PA_BLUEZ4_UUID_HSP_HS) || pa_streq(uuid, PA_BLUEZ4_UUID_HFP_HF)) { p = pa_card_profile_new("hsp", _("Telephony Duplex (HSP/HFP)"), sizeof(pa_bluez4_profile_t)); p->priority = 20; p->n_sinks = 1; @@ -2206,7 +2206,7 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid d = PA_CARD_PROFILE_DATA(p); *d = PA_BLUEZ4_PROFILE_HSP; - } else if (pa_streq(uuid, HFP_AG_UUID)) { + } else if (pa_streq(uuid, PA_BLUEZ4_UUID_HFP_AG)) { p = pa_card_profile_new("hfgw", _("Handsfree Gateway"), sizeof(pa_bluez4_profile_t)); p->priority = 20; p->n_sinks = 1; @@ -2240,7 +2240,8 @@ static int add_card(struct userdata *u) { char *n; const char *profile_str; const pa_bluez4_device *device; - const pa_bluez4_uuid *uuid; + const char *uuid; + void *state; pa_assert(u); pa_assert(u->device); @@ -2276,8 +2277,8 @@ static int add_card(struct userdata *u) { create_card_ports(u, data.ports); - PA_LLIST_FOREACH(uuid, device->uuids) { - p = create_card_profile(u, uuid->uuid, data.ports); + PA_HASHMAP_FOREACH(uuid, device->uuids, state) { + p = create_card_profile(u, uuid, data.ports); if (!p) continue; -- 2.8.1