linux: up-enumerator-udev: Process add, change, and remove udev events for keyboard backlight device

Add, update, and remove the keyboard backlight LED device when receiving
add, change, and remove udev events.
This commit is contained in:
Kate Hsuan 2025-03-11 17:18:50 +08:00
parent e01aa7c903
commit fd6eebb397

View file

@ -31,6 +31,7 @@
#include "up-device-supply-battery.h" #include "up-device-supply-battery.h"
#include "up-device-hid.h" #include "up-device-hid.h"
#include "up-device-wup.h" #include "up-device-wup.h"
#include "up-kbd-backlight-led.h"
#ifdef HAVE_IDEVICE #ifdef HAVE_IDEVICE
#include "up-device-idevice.h" #include "up-device-idevice.h"
#endif /* HAVE_IDEVICE */ #endif /* HAVE_IDEVICE */
@ -216,13 +217,102 @@ emit_changes_for_siblings (UpEnumeratorUdev *self,
} }
} }
static void
power_supply_add_helper (UpEnumeratorUdev *self,
const gchar *action,
GUdevDevice *device,
GUdevClient *client,
GObject *obj,
const gchar *device_key)
{
g_autoptr(UpDevice) up_dev = NULL;
g_autofree char *parent_id = NULL;
up_dev = device_new (self, device);
/* We work with `obj` further down, which is the UpDevice
* if we have it, or the GUdevDevice if not. */
if (up_dev)
obj = G_OBJECT (up_dev);
else
obj = G_OBJECT (device);
g_hash_table_insert (self->known, (char*) device_key, g_object_ref (obj));
/* Fire relevant sibling events and insert into lookup table */
parent_id = device_parent_id (device);
g_debug ("device %s has parent id: %s", device_key, parent_id);
if (parent_id) {
GPtrArray *devices = NULL;
char *parent_id_key = NULL;
int i;
g_hash_table_lookup_extended (self->siblings, parent_id,
(gpointer*)&parent_id_key, (gpointer*)&devices);
if (!devices)
devices = g_ptr_array_new_with_free_func (g_object_unref);
for (i = 0; i < devices->len; i++) {
GObject *sibling = g_ptr_array_index (devices, i);
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);
}
g_ptr_array_add (devices, g_object_ref (obj));
if (!parent_id_key) {
parent_id_key = g_strdup (parent_id);
g_hash_table_insert (self->siblings, parent_id_key, devices);
}
/* Just a reference to the hash table key */
g_object_set_data (obj, "udev-parent-id", parent_id_key);
}
if (up_dev)
g_signal_emit_by_name (self, "device-added", up_dev);
}
static void
kbd_backlight_add_helper (UpEnumeratorUdev *self,
const gchar *action,
GUdevDevice *device,
GUdevClient *client,
GObject *obj,
const char *device_key)
{
UpDaemon *daemon;
g_autoptr(UpDeviceKbdBacklight) up_kbd = NULL;
g_autofree char *parent_id = NULL;
daemon = up_enumerator_get_daemon (UP_ENUMERATOR (self));
up_kbd = g_initable_new (UP_TYPE_KBD_BACKLIGHT_LED, NULL, NULL,
"daemon", daemon,
"native", device,
NULL);
if (up_kbd)
obj = G_OBJECT (up_kbd);
else
obj = G_OBJECT (device);
g_hash_table_insert (self->known, (char*) device_key, g_object_ref (obj));
if (up_kbd)
g_signal_emit_by_name (self, "device-added", G_OBJECT (up_kbd));
}
static void static void
uevent_signal_handler_cb (UpEnumeratorUdev *self, uevent_signal_handler_cb (UpEnumeratorUdev *self,
const gchar *action, const gchar *action,
GUdevDevice *device, GUdevDevice *device,
GUdevClient *client) GUdevClient *client)
{ {
const char *device_key = g_udev_device_get_sysfs_path (device); const char *device_key = g_udev_device_get_sysfs_path (device);
gboolean is_kbd_backlight = FALSE;
g_debug ("Received uevent %s on device %s", action, device_key); g_debug ("Received uevent %s on device %s", action, device_key);
@ -230,6 +320,14 @@ uevent_signal_handler_cb (UpEnumeratorUdev *self,
if (g_strcmp0 (g_udev_device_get_subsystem (device), "power_supply") == 0) if (g_strcmp0 (g_udev_device_get_subsystem (device), "power_supply") == 0)
device_key = g_udev_device_get_name (device); device_key = g_udev_device_get_name (device);
if (g_strcmp0 (g_udev_device_get_subsystem (device), "leds") == 0) {
if (g_strrstr (device_key, "kbd_backlight") == NULL)
return;
is_kbd_backlight = TRUE;
}
g_debug ("uevent subsystem %s", g_udev_device_get_subsystem (device));
/* It appears that we may not always receive an "add" event. As such, /* It appears that we may not always receive an "add" event. As such,
* treat "add"/"change" in the same way, by first checking if we have * treat "add"/"change" in the same way, by first checking if we have
* seen the device. * seen the device.
@ -250,56 +348,10 @@ uevent_signal_handler_cb (UpEnumeratorUdev *self,
} }
if (!obj) { if (!obj) {
g_autoptr(UpDevice) up_dev = NULL; if (is_kbd_backlight)
g_autofree char *parent_id = NULL; kbd_backlight_add_helper (self, action, device, client, obj, device_key);
up_dev = device_new (self, device);
/* We work with `obj` further down, which is the UpDevice
* if we have it, or the GUdevDevice if not. */
if (up_dev)
obj = G_OBJECT (up_dev);
else else
obj = G_OBJECT (device); power_supply_add_helper (self, action, device, client, obj, device_key);
g_hash_table_insert (self->known, (char*) device_key, g_object_ref (obj));
/* Fire relevant sibling events and insert into lookup table */
parent_id = device_parent_id (device);
g_debug ("device %s has parent id: %s", device_key, parent_id);
if (parent_id) {
GPtrArray *devices = NULL;
char *parent_id_key = NULL;
int i;
g_hash_table_lookup_extended (self->siblings, parent_id,
(gpointer*)&parent_id_key, (gpointer*)&devices);
if (!devices)
devices = g_ptr_array_new_with_free_func (g_object_unref);
for (i = 0; i < devices->len; i++) {
GObject *sibling = g_ptr_array_index (devices, i);
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);
}
g_ptr_array_add (devices, g_object_ref (obj));
if (!parent_id_key) {
parent_id_key = g_strdup (parent_id);
g_hash_table_insert (self->siblings, parent_id_key, devices);
}
/* Just a reference to the hash table key */
g_object_set_data (obj, "udev-parent-id", parent_id_key);
}
if (up_dev)
g_signal_emit_by_name (self, "device-added", up_dev);
} else { } else {
if (!UP_IS_DEVICE (obj)) { if (!UP_IS_DEVICE (obj)) {
@ -326,6 +378,11 @@ uevent_signal_handler_cb (UpEnumeratorUdev *self,
g_debug ("removing device for path %s", g_udev_device_get_sysfs_path (device)); g_debug ("removing device for path %s", g_udev_device_get_sysfs_path (device));
if (is_kbd_backlight) {
g_signal_emit_by_name (self, "device-removed", obj);
return;
}
parent_id = g_object_get_data (obj, "udev-parent-id"); parent_id = g_object_get_data (obj, "udev-parent-id");
/* Remove from siblings table. */ /* Remove from siblings table. */