From: Vovan Nikolaevich <vov4ik533@gmail.com>
To: Corentin Chary <corentin.chary@gmail.com>,
"Luke D . Jones" <luke@ljones.dev>,
Denis Benato <denis.benato@linux.dev>
Cc: "Hans de Goede" <hansg@kernel.org>,
"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>,
platform-driver-x86@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH] platform/x86: asus-wmi: Add user-status LED support
Date: Sun, 4 Oct 2026 01:06:53 +0300 [thread overview]
Message-ID: <20261003220653.123909-1-vov4ik533@gmail.com> (raw)
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
reply other threads:[~2026-10-03 22:07 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261003220653.123909-1-vov4ik533@gmail.com \
--to=vov4ik533@gmail.com \
--cc=corentin.chary@gmail.com \
--cc=denis.benato@linux.dev \
--cc=hansg@kernel.org \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=luke@ljones.dev \
--cc=platform-driver-x86@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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®