diff options
author | Bastien Nocera <hadess@hadess.net> | 2023-06-30 10:17:33 +0200 |
---|---|---|
committer | Bastien Nocera <hadess@hadess.net> | 2023-07-03 15:54:51 +0200 |
commit | ac68136b41a4d3e67b8776e7dfdb675e77e70bf6 (patch) | |
tree | f5884f69f4a9062cfd21d026ce776c9a9c046362 | |
parent | ab116cda4a6e698a4f4b6128851452df38e42f2a (diff) |
linux: Fix headsets type detection when hotplugged
When a UpDevice is finally created, it's possible that we've seen "add"
events as well as "change" events for siblings. But as the "change"
events don't create new unknown siblings to store, we have GUdevDevices
from the original "add" event in that store.
As the GUdevDevice documentation mentions:
"By design, GUdevDevice will not react to changes for a device – it
only contains a snapshot of information when the GUdevDevice object
was created. To work with changes, you typically connect to the
“uevent” signal on a GUdevClient and get a new GUdevDevice
whenever an event happens."
To avoid having to try and update the siblings store, fetch an updated
GUdevDevice for the sibling we want to tell the core about, with the
properties all updated.
This fixes headsets plugged in after the daemon start being detected as
keyboards when the sound card device is tagged with the form factor
in a change event before the battery is exported.
Closes: https://gitlab.freedesktop.org/upower/upower/-/issues/239
-rw-r--r-- | src/linux/up-enumerator-udev.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/src/linux/up-enumerator-udev.c b/src/linux/up-enumerator-udev.c index 97abaef..ef578e3 100644 --- a/src/linux/up-enumerator-udev.c +++ b/src/linux/up-enumerator-udev.c @@ -161,6 +161,18 @@ device_new (UpEnumeratorUdev *self, GUdevDevice *native) } } +/* As GUdevDevice are static and do not update when the sysfs device + * changes, this helps get a GUdevDevice with updated properties */ +static GUdevDevice * +get_latest_udev_device (UpEnumeratorUdev *self, + GObject *obj) +{ + const char *sysfs_path; + + sysfs_path = g_udev_device_get_sysfs_path (G_UDEV_DEVICE (obj)); + return g_udev_client_query_by_sysfs_path (self->udev, sysfs_path); +} + static void uevent_signal_handler_cb (UpEnumeratorUdev *self, const gchar *action, @@ -222,8 +234,11 @@ uevent_signal_handler_cb (UpEnumeratorUdev *self, for (i = 0; i < devices->len; i++) { GObject *sibling = g_ptr_array_index (devices, i); - if (up_dev) - up_device_sibling_discovered (up_dev, sibling); + if (up_dev) { + g_autoptr(GUdevDevice) d = get_latest_udev_device (self, sibling); + if (d) + up_device_sibling_discovered (up_dev, G_OBJECT (d)); + } if (UP_IS_DEVICE (sibling)) up_device_sibling_discovered (UP_DEVICE (sibling), obj); } |