From: Denis Benato <benato.denis96@gmail.com>
To: Bartu Alev <bartualev@gmail.com>, linux-kernel@vger.kernel.org
Cc: platform-driver-x86@vger.kernel.org,
"Hans de Goede" <hansg@kernel.org>,
"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>,
"Luke D . Jones" <luke@ljones.dev>
Subject: Re: [PATCH v1] platform/x86: asus-wmi: add TUF keyboard RGB readback support
Date: Fri, 25 Sep 2026 22:25:13 +0200 [thread overview]
Message-ID: <27BF6C3B-C341-4122-B1E9-F540345C29F6@gmail.com> (raw)
In-Reply-To: <20260925200744.129714-1-bartualev@gmail.com>
Il 25 settembre 2026 22:07:44 CEST, Bartu Alev <bartualev@gmail.com> ha scritto:
>TUF Gaming laptops support setting keyboard RGB lighting modes and
>power states via kbd_rgb_mode and kbd_rgb_state, but both attributes
>are currently write-only (DEVICE_ATTR_WO). Consequently, userspace
>utilities have no way to query the active hardware configuration.
>
>Add readback support by querying the TUF status device ID 0x0010005B
>through the WMI DSTS method. On supported platforms, this evaluates the
>ACPI DSDT method EC0.KBLS(), which returns a 16-byte status buffer
>containing the active lighting mode, RGB color channels, effect speed,
>and power-state bitmask.
>
>Introduce kbd_rgb_read_status() to retrieve and validate the KBLS
>buffer. Convert kbd_rgb_mode and kbd_rgb_state to DEVICE_ATTR_RW. Map the
>hardware speed codes (0xe1, 0xeb, 0xf5) to their sysfs indices (0, 1, 2).
>Since the status buffer reports the active state rather than an action
>command, emit a synthetic leading '1' to maintain format symmetry with
>the input format expected by userspace.
>
1 or 0 is for immediate vs save to flash... Which one of the two is the reported one?
>Additionally, relabel the fourth field in kbd_rgb_state_index from
>"keyboard" to "shutdown". When the interface was originally introduced,
>the purpose of BIT(7) was unknown and noted as having no effect. In
>hardware, this bit gates whether the keyboard LED remains powered during
>the ACPI S5 sequence. Relabeling it accurately reflects its
>actual hardware behavior.
>
Good finding.
This however goes in its own.patch with an appropriate Fixes tag.
>Assisted-by: GLM-5.3
>Signed-off-by: Bartu Alev <bartualev@gmail.com>
>---
>- Tested on ASUS TUF Gaming A15 (FA507NV) running Linux 7.2.6
>
> drivers/platform/x86/asus-wmi.c | 87 ++++++++++++++++++++--
> include/linux/platform_data/x86/asus-wmi.h | 3 +
> 2 files changed, 84 insertions(+), 6 deletions(-)
>
>diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
>index a65090429ca7..36eff5adac52 100644
>--- a/drivers/platform/x86/asus-wmi.c
>+++ b/drivers/platform/x86/asus-wmi.c
>@@ -1046,7 +1046,58 @@ static ssize_t gpu_mux_mode_store(struct device *dev,
> static DEVICE_ATTR_RW(gpu_mux_mode);
> #endif /* IS_ENABLED(CONFIG_ASUS_WMI_DEPRECATED_ATTRS) */
>
>+static int kbd_rgb_read_status(u8 data[16])
>+{
>+ int err;
>+
>+ err = asus_wmi_evaluate_method_buf(ASUS_WMI_METHODID_DSTS,
>+ ASUS_WMI_DEVID_TUF_RGB_STATUS,
>+ 0, data, 16);
>+
>+ if (err)
>+ return err < 0 ? err : -ENODEV;
>+
>+ /* DUBF[0] is a constant 1 set by the AML: anything else is not KBLS */
>+ if (data[0] != 1)
>+ return -ENODEV;
>+
>+ return 0;
>+}
>+
> /* TUF Laptop Keyboard RGB Modes **********************************************/
>+static ssize_t kbd_rgb_mode_show(struct device *dev,
>+ struct device_attribute *attr,
>+ char *buf)
>+{
>+ u8 data[16] = {};
>+ u32 speed;
>+ int err;
>+
>+ err = kbd_rgb_read_status(data);
>+ if (err)
>+ return err;
>+
>+ /* Map hardware speed codes back to sysfs index:
>+ * 0xe1 -> 0 (slow), 0xeb -> 1 (normal), 0xf5 -> 2 (fast)
>+ */
>+ switch (data[5]) {
>+ case 0xe1:
>+ speed = 0;
>+ break;
>+ case 0xeb:
>+ speed = 1;
>+ break;
>+ case 0xf5:
>+ speed = 2;
>+ break;
>+ default:
>+ speed = 1;
>+ break;
>+ }
>+
>+ return sysfs_emit(buf, "1 %d %d %d %d %d\n",
>+ data[1], data[2], data[3], data[4], speed);
>+}
> static ssize_t kbd_rgb_mode_store(struct device *dev,
> struct device_attribute *attr,
> const char *buf, size_t count)
>@@ -1099,7 +1150,7 @@ static ssize_t kbd_rgb_mode_store(struct device *dev,
>
> return count;
> }
>-static DEVICE_ATTR_WO(kbd_rgb_mode);
>+static DEVICE_ATTR_RW(kbd_rgb_mode);
>
> static DEVICE_STRING_ATTR_RO(kbd_rgb_mode_index, 0444,
> "cmd mode red green blue speed");
>@@ -1115,14 +1166,38 @@ static const struct attribute_group kbd_rgb_mode_group = {
> };
>
> /* TUF Laptop Keyboard RGB State **********************************************/
>+static ssize_t kbd_rgb_state_show(struct device *dev,
>+ struct device_attribute *attr,
>+ char *buf)
>+{
>+ u8 data[16] = {};
>+ u8 flags;
>+ int err;
>+
>+ err = kbd_rgb_read_status(data);
>+ if (err)
>+ return err;
>+
>+ /*
>+ * data[6] power-state bitmask:
>+ * BIT(1) boot, BIT(3) awake, BIT(5) sleep, BIT(7) shutdown
>+ */
>+ flags = data[6];
>+
>+ return sysfs_emit(buf, "1 %d %d %d %d\n",
>+ !!(flags & BIT(1)),
>+ !!(flags & BIT(3)),
>+ !!(flags & BIT(5)),
>+ !!(flags & BIT(7)));
>+}
> static ssize_t kbd_rgb_state_store(struct device *dev,
> struct device_attribute *attr,
> const char *buf, size_t count)
> {
>- u32 flags, cmd, boot, awake, sleep, keyboard;
>+ u32 flags, cmd, boot, awake, sleep, shutdown;
> int err;
>
>- if (sscanf(buf, "%d %d %d %d %d", &cmd, &boot, &awake, &sleep, &keyboard) != 5)
>+ if (sscanf(buf, "%d %d %d %d %d", &cmd, &boot, &awake, &sleep, &shutdown) != 5)
> return -EINVAL;
>
> if (cmd)
>@@ -1135,7 +1210,7 @@ static ssize_t kbd_rgb_state_store(struct device *dev,
> flags |= BIT(3);
> if (sleep)
> flags |= BIT(5);
>- if (keyboard)
>+ if (shutdown)
> flags |= BIT(7);
>
> /* 0xbd is the required default arg0 for the method. Nothing happens otherwise */
>@@ -1146,10 +1221,10 @@ static ssize_t kbd_rgb_state_store(struct device *dev,
>
> return count;
> }
>-static DEVICE_ATTR_WO(kbd_rgb_state);
>+static DEVICE_ATTR_RW(kbd_rgb_state);
>
> static DEVICE_STRING_ATTR_RO(kbd_rgb_state_index, 0444,
>- "cmd boot awake sleep keyboard");
>+ "cmd boot awake sleep shutdown");
>
> static struct attribute *kbd_rgb_state_attrs[] = {
> &dev_attr_kbd_rgb_state.attr,
>diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
>index b5ed8c83ace1..a6eb8f8cf159 100644
>--- a/include/linux/platform_data/x86/asus-wmi.h
>+++ b/include/linux/platform_data/x86/asus-wmi.h
>@@ -161,6 +161,9 @@
> /* TUF laptop RGB power/state */
> #define ASUS_WMI_DEVID_TUF_RGB_STATE 0x00100057
>
>+/* TUF laptop RGB keyboard status */
>+#define ASUS_WMI_DEVID_TUF_RGB_STATUS 0x0010005B
State versus status... Uhm...
>+
> /* Bootup sound control */
> #define ASUS_WMI_DEVID_BOOT_SOUND 0x00130022
>
Hi,
Thanks for this!
next prev parent reply other threads:[~2026-09-25 20:25 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-25 20:07 Bartu Alev
2026-09-25 20:25 ` Denis Benato [this message]
2026-09-26 0:56 ` [PATCH v2 0/2] platform/x86: asus-wmi: Fix TUF keyboard shutdown naming and add RGB readback Bartu Alev
2026-09-26 0:56 ` [PATCH v2 1/2] platform/x86: asus-wmi: fix TUF keyboard power state shutdown naming Bartu Alev
2026-09-26 0:56 ` [PATCH v2 2/2] platform/x86: asus-wmi: add TUF keyboard RGB readback support Bartu Alev
2026-09-26 1:41 ` Denis Benato
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=27BF6C3B-C341-4122-B1E9-F540345C29F6@gmail.com \
--to=benato.denis96@gmail.com \
--cc=bartualev@gmail.com \
--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®