]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
HID: asus: listen to the asus-wmi brightness device instead of creating one
authorAntheas Kapenekakis <lkml@antheas.dev>
Thu, 22 Jan 2026 07:50:41 +0000 (08:50 +0100)
committerIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Wed, 28 Jan 2026 12:02:32 +0000 (14:02 +0200)
Some ROG laptops expose multiple interfaces for controlling the
keyboard/RGB brightness. This creates a name conflict under
asus::kbd_brightness, where the second device ends up being
named asus::kbd_brightness_1 and they are both broken.

Therefore, register a listener to the asus-wmi brightness device
instead of creating a new one.

Reviewed-by: Luke D. Jones <luke@ljones.dev>
Reviewed-by: Benjamin Tissoires <bentiss@kernel.org>
Reviewed-by: Denis Benato <benato.denis96@gmail.com>
Acked-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
Link: https://patch.msgid.link/20260122075044.5070-9-lkml@antheas.dev
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
drivers/hid/hid-asus.c

index 6084ec66a134321efe1474f34bb501251298eb98..415629ebee15efc2992ee2bd09d1358058fb3c39 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/hid.h>
 #include <linux/module.h>
 #include <linux/platform_data/x86/asus-wmi.h>
-#include <linux/platform_data/x86/asus-wmi-leds-ids.h>
 #include <linux/input/mt.h>
 #include <linux/usb.h> /* For to_usb_interface for T100 touchpad intf check */
 #include <linux/power_supply.h>
@@ -103,7 +102,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
 #define TRKID_SGN       ((TRKID_MAX + 1) >> 1)
 
 struct asus_kbd_leds {
-       struct led_classdev cdev;
+       struct asus_hid_listener listener;
        struct hid_device *hdev;
        struct work_struct work;
        unsigned int brightness;
@@ -495,11 +494,11 @@ static void asus_schedule_work(struct asus_kbd_leds *led)
        spin_unlock_irqrestore(&led->lock, flags);
 }
 
-static void asus_kbd_backlight_set(struct led_classdev *led_cdev,
-                                  enum led_brightness brightness)
+static void asus_kbd_backlight_set(struct asus_hid_listener *listener,
+                                  int brightness)
 {
-       struct asus_kbd_leds *led = container_of(led_cdev, struct asus_kbd_leds,
-                                                cdev);
+       struct asus_kbd_leds *led = container_of(listener, struct asus_kbd_leds,
+                                                listener);
        unsigned long flags;
 
        spin_lock_irqsave(&led->lock, flags);
@@ -509,20 +508,6 @@ static void asus_kbd_backlight_set(struct led_classdev *led_cdev,
        asus_schedule_work(led);
 }
 
-static enum led_brightness asus_kbd_backlight_get(struct led_classdev *led_cdev)
-{
-       struct asus_kbd_leds *led = container_of(led_cdev, struct asus_kbd_leds,
-                                                cdev);
-       enum led_brightness brightness;
-       unsigned long flags;
-
-       spin_lock_irqsave(&led->lock, flags);
-       brightness = led->brightness;
-       spin_unlock_irqrestore(&led->lock, flags);
-
-       return brightness;
-}
-
 static void asus_kbd_backlight_work(struct work_struct *work)
 {
        struct asus_kbd_leds *led = container_of(work, struct asus_kbd_leds, work);
@@ -539,34 +524,6 @@ static void asus_kbd_backlight_work(struct work_struct *work)
                hid_err(led->hdev, "Asus failed to set keyboard backlight: %d\n", ret);
 }
 
-/* WMI-based keyboard backlight LED control (via asus-wmi driver) takes
- * precedence. We only activate HID-based backlight control when the
- * WMI control is not available.
- */
-static bool asus_kbd_wmi_led_control_present(struct hid_device *hdev)
-{
-       struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
-       u32 value;
-       int ret;
-
-       if (!IS_ENABLED(CONFIG_ASUS_WMI))
-               return false;
-
-       if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD &&
-                       dmi_check_system(asus_use_hid_led_dmi_ids)) {
-               hid_info(hdev, "using HID for asus::kbd_backlight\n");
-               return false;
-       }
-
-       ret = asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS,
-                                      ASUS_WMI_DEVID_KBD_BACKLIGHT, 0, &value);
-       hid_dbg(hdev, "WMI backlight check: rc %d value %x", ret, value);
-       if (ret)
-               return false;
-
-       return !!(value & ASUS_WMI_DSTS_PRESENCE_BIT);
-}
-
 /*
  * We don't care about any other part of the string except the version section.
  * Example strings: FGA80100.RC72LA.312_T01, FGA80100.RC71LS.318_T01
@@ -706,14 +663,11 @@ static int asus_kbd_register_leds(struct hid_device *hdev)
        drvdata->kbd_backlight->removed = false;
        drvdata->kbd_backlight->brightness = 0;
        drvdata->kbd_backlight->hdev = hdev;
-       drvdata->kbd_backlight->cdev.name = "asus::kbd_backlight";
-       drvdata->kbd_backlight->cdev.max_brightness = 3;
-       drvdata->kbd_backlight->cdev.brightness_set = asus_kbd_backlight_set;
-       drvdata->kbd_backlight->cdev.brightness_get = asus_kbd_backlight_get;
+       drvdata->kbd_backlight->listener.brightness_set = asus_kbd_backlight_set;
        INIT_WORK(&drvdata->kbd_backlight->work, asus_kbd_backlight_work);
        spin_lock_init(&drvdata->kbd_backlight->lock);
 
-       ret = devm_led_classdev_register(&hdev->dev, &drvdata->kbd_backlight->cdev);
+       ret = asus_hid_register_listener(&drvdata->kbd_backlight->listener);
        if (ret < 0) {
                /* No need to have this still around */
                devm_kfree(&hdev->dev, drvdata->kbd_backlight);
@@ -1102,7 +1056,7 @@ static int __maybe_unused asus_resume(struct hid_device *hdev) {
 
        if (drvdata->kbd_backlight) {
                const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0xba, 0xc5, 0xc4,
-                               drvdata->kbd_backlight->cdev.brightness };
+                               drvdata->kbd_backlight->brightness };
                ret = asus_kbd_set_report(hdev, buf, sizeof(buf));
                if (ret < 0) {
                        hid_err(hdev, "Asus failed to set keyboard backlight: %d\n", ret);
@@ -1228,7 +1182,6 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
        }
 
        if (is_vendor && (drvdata->quirks & QUIRK_USE_KBD_BACKLIGHT) &&
-           !asus_kbd_wmi_led_control_present(hdev) &&
            asus_kbd_register_leds(hdev))
                hid_warn(hdev, "Failed to initialize backlight.\n");
 
@@ -1275,6 +1228,8 @@ static void asus_remove(struct hid_device *hdev)
        unsigned long flags;
 
        if (drvdata->kbd_backlight) {
+               asus_hid_unregister_listener(&drvdata->kbd_backlight->listener);
+
                spin_lock_irqsave(&drvdata->kbd_backlight->lock, flags);
                drvdata->kbd_backlight->removed = true;
                spin_unlock_irqrestore(&drvdata->kbd_backlight->lock, flags);