* [PATCH] platform/x86: asus-wmi: Add user-status LED support
@ 2026-10-03 22:06 Vovan Nikolaevich
0 siblings, 0 replies; only message in thread
From: Vovan Nikolaevich @ 2026-10-03 22:06 UTC (permalink / raw)
To: Corentin Chary, Luke D . Jones, Denis Benato
Cc: Hans de Goede, Ilpo Järvinen, platform-driver-x86, linux-kernel
Some ASUS laptops expose a user-status LED through WMI DEVID 0x00040019.
On the tested ExpertBook B5402 this is the orange user-status indicator
used, among other things, as an "in a meeting" signal. DSTS reports
presence and the current state, and DEVS 0/1 switches the LED off and on.
The official ASUS userspace controls the same binary WMI capability and
applies any Auto/Busy/Off policy in userspace; this driver exports only
the physical LED.
Register a binary LED class device when a state read succeeds. A
successful read is used instead of asus_wmi_dev_is_present() because
some firmware returns ASUS_WMI_UNSUPPORTED_METHOD (0xFFFFFFFE) for
this DEVID, and that value still has the DSTS presence bit set.
The LED is named ":status": LED_FUNCTION_STATUS describes the binary
on/off state, the device name is omitted since the LED is not tied to
another kernel device, and the colour is left out because it is only
verified to be orange on the tested model.
The WMI interface and firmware behavior across public ASUS DSDT tables
were investigated, and the LED class naming and patch were developed
and reviewed, with LLM assistance.
The same WMI LED support was built and runtime-tested by the author as
a local patch against gentoo-kernel-7.2.8 on an ASUS ExpertBook
B5402CBA (BIOS B5402CBA.314), including physical LED on/off validation.
This upstream version was additionally build-tested against the current
platform-drivers-x86 for-next branch.
Assisted-by: LLM
Signed-off-by: Vovan Nikolaevich <vov4ik533@gmail.com>
---
drivers/platform/x86/asus-wmi.c | 37 ++++++++++++++++++++++
include/linux/platform_data/x86/asus-wmi.h | 1 +
2 files changed, 38 insertions(+)
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 711f59c1aa62..7cb954c22db3 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -263,6 +263,7 @@ struct asus_wmi {
struct led_classdev micmute_led;
struct led_classdev mute_led;
struct led_classdev camera_led;
+ struct led_classdev user_status_led;
struct workqueue_struct *led_workqueue;
struct work_struct tpd_led_work;
struct work_struct wlan_led_work;
@@ -2085,6 +2086,24 @@ static int camera_led_set(struct led_classdev *led_cdev,
return err < 0 ? err : 0;
}
+static enum led_brightness user_status_led_get(struct led_classdev *led_cdev)
+{
+ struct asus_wmi *asus;
+
+ asus = container_of(led_cdev, struct asus_wmi, user_status_led);
+ return asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_USER_STATUS_LED);
+}
+
+static int user_status_led_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ int state = brightness != LED_OFF;
+ int err;
+
+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_USER_STATUS_LED, state, NULL);
+ return err < 0 ? err : 0;
+}
+
static void asus_wmi_led_exit(struct asus_wmi *asus)
{
scoped_guard(spinlock_irqsave, &asus_ref.lock)
@@ -2096,6 +2115,7 @@ static void asus_wmi_led_exit(struct asus_wmi *asus)
led_classdev_unregister(&asus->micmute_led);
led_classdev_unregister(&asus->mute_led);
led_classdev_unregister(&asus->camera_led);
+ led_classdev_unregister(&asus->user_status_led);
if (asus->led_workqueue)
destroy_workqueue(asus->led_workqueue);
@@ -2228,6 +2248,23 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
goto error;
}
+ /*
+ * Gate on a successful state read rather than asus_wmi_dev_is_present():
+ * some firmware returns ASUS_WMI_UNSUPPORTED_METHOD (0xFFFFFFFE) for
+ * this DEVID, which still has the DSTS presence bit set.
+ */
+ if (asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_USER_STATUS_LED) >= 0) {
+ asus->user_status_led.name = ":" LED_FUNCTION_STATUS;
+ asus->user_status_led.max_brightness = 1;
+ asus->user_status_led.brightness_get = user_status_led_get;
+ asus->user_status_led.brightness_set_blocking = user_status_led_set;
+
+ rv = led_classdev_register(&asus->platform_device->dev,
+ &asus->user_status_led);
+ if (rv)
+ goto error;
+ }
+
if (asus->oobe_state_available) {
/*
* Disable OOBE state, so that e.g. the keyboard backlight
diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
index be4d2873ffc9..b2f54d865689 100644
--- a/include/linux/platform_data/x86/asus-wmi.h
+++ b/include/linux/platform_data/x86/asus-wmi.h
@@ -54,6 +54,7 @@
#define ASUS_WMI_DEVID_LED5 0x00020015
#define ASUS_WMI_DEVID_LED6 0x00020016
#define ASUS_WMI_DEVID_MICMUTE_LED 0x00040017
+#define ASUS_WMI_DEVID_USER_STATUS_LED 0x00040019
#define ASUS_WMI_DEVID_MUTE_LED 0x0004001C
/* Disable Camera LED */
base-commit: fe5030c8cc7156223f48530e9b49aa87c0305bcd
--
2.55.0
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-03 22:07 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-03 22:06 [PATCH] platform/x86: asus-wmi: Add user-status LED support Vovan Nikolaevich
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®