* [PATCH 0/1] platform/x86: add Xiaomi WMI key driver
@ 2026-06-01 15:14 Lucy Wong
2026-06-01 15:14 ` [PATCH 1/1] " Lucy Wong
2026-10-22 18:56 ` [PATCH v2] " Lucy Wong
0 siblings, 2 replies; 5+ messages in thread
From: Lucy Wong @ 2026-06-01 15:14 UTC (permalink / raw)
To: Hans de Goede, Ilpo Järvinen
Cc: platform-driver-x86, linux-kernel, Lucy Wong
This adds a driver for extra function keys on certain Xiaomi laptops.
Unlike the existing xiaomi-wmi driver where each key has its own WMI
GUID, this machine delivers all keys through a single event GUID
(B74AF83F-...), encoding the event type and keycode in the event buffer.
I was unsure whether this should be merged into the existing xiaomi-wmi.c
or kept separate due to the different mechanism. I chose a separate file
for clarity; happy to merge if preferred.
Tested on Xiaomi Mi Gaming Laptop (8th gen Intel).
Lucy Wong (1):
platform/x86: add Xiaomi WMI key driver
MAINTAINERS | 6 ++
drivers/platform/x86/Kconfig | 11 ++
drivers/platform/x86/Makefile | 1 +
drivers/platform/x86/xiaomi-wmi-keys.c | 139 +++++++++++++++++++++++++
4 files changed, 157 insertions(+)
create mode 100644 drivers/platform/x86/xiaomi-wmi-keys.c
--
2.54.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/1] platform/x86: add Xiaomi WMI key driver
2026-06-01 15:14 [PATCH 0/1] platform/x86: add Xiaomi WMI key driver Lucy Wong
@ 2026-06-01 15:14 ` Lucy Wong
2026-10-22 18:56 ` [PATCH v2] " Lucy Wong
1 sibling, 0 replies; 5+ messages in thread
From: Lucy Wong @ 2026-06-01 15:14 UTC (permalink / raw)
To: Hans de Goede, Ilpo Järvinen
Cc: platform-driver-x86, linux-kernel, Lucy Wong
Certain Xiaomi laptops expose extra function keys through a single WMI
event GUID (B74AF83F-8B2F-4069-ACAC-36D176F62FC0). Unlike the existing
xiaomi-wmi driver where each key has its own GUID, here all keys share
one GUID and the event buffer encodes both an event type and a keycode:
buffer[1] = event type
0x02: press/release keys (5 keys with abstract icons)
0x03: firmware-handled toggles (touchpad, Fn lock)
buffer[2] = keycode within that type
The keys with abstract icons are mapped to programmable macro keys for
userspace to bind. The touchpad and Fn lock keys are handled by the EC
and are reported for notification purposes only.
Signed-off-by: Lucy Wong <lucywong2778@gmail.com>
---
MAINTAINERS | 6 ++
drivers/platform/x86/Kconfig | 11 ++
drivers/platform/x86/Makefile | 1 +
drivers/platform/x86/xiaomi-wmi-keys.c | 139 +++++++++++++++++++++++++
4 files changed, 157 insertions(+)
create mode 100644 drivers/platform/x86/xiaomi-wmi-keys.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 839e39825455..7969b82c8315 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -29124,6 +29124,12 @@ F: fs/xfs/
F: include/uapi/linux/dqblk_xfs.h
F: include/uapi/linux/fsmap.h
+XIAOMI WMI KEYS DRIVER
+M: Lucy Wong <lucywong2778@gmail.com>
+L: platform-driver-x86@vger.kernel.org
+S: Maintained
+F: drivers/platform/x86/xiaomi-wmi-keys.c
+
XILINX AMS DRIVER
M: Salih Erim <salih.erim@amd.com>
M: Conall O'Griofa <conall.ogriofa@amd.com>
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index b54b5212b204..541b0a255daa 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -90,6 +90,17 @@ config XIAOMI_WMI
To compile this driver as a module, choose M here: the module will
be called xiaomi-wmi.
+config XIAOMI_WMI_KEYS
+ tristate "Xiaomi WMI key events driver"
+ depends on ACPI_WMI
+ depends on INPUT
+ help
+ Say Y here if you want to support WMI-based hotkey events on certain
+ Xiaomi laptops.
+
+ To compile this driver as a module, choose M here: the module will
+ be called xiaomi-wmi-keys.
+
config REDMI_WMI
tristate "Redmibook WMI key driver"
depends on ACPI_WMI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 872ac3842391..d852bb0bf61b 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_HUAWEI_WMI) += huawei-wmi.o
obj-$(CONFIG_MXM_WMI) += mxm-wmi.o
obj-$(CONFIG_NVIDIA_WMI_EC_BACKLIGHT) += nvidia-wmi-ec-backlight.o
obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o
+obj-$(CONFIG_XIAOMI_WMI_KEYS) += xiaomi-wmi-keys.o
obj-$(CONFIG_REDMI_WMI) += redmi-wmi.o
obj-$(CONFIG_GIGABYTE_WMI) += gigabyte-wmi.o
obj-$(CONFIG_BITLAND_MIFS_WMI) += bitland-mifs-wmi.o
diff --git a/drivers/platform/x86/xiaomi-wmi-keys.c b/drivers/platform/x86/xiaomi-wmi-keys.c
new file mode 100644
index 000000000000..524ede0e64eb
--- /dev/null
+++ b/drivers/platform/x86/xiaomi-wmi-keys.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xiaomi laptop WMI hotkey driver
+ *
+ * Copyright (C) 2026 Lucy Wong <lucywong2778@gmail.com>
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/wmi.h>
+
+#define XIAOMI_WMI_EVENT_GUID "B74AF83F-8B2F-4069-ACAC-36D176F62FC0"
+
+#define XIAOMI_TYPE_BACKLIGHT 0x01 /* keyboard backlight level (EC handled) */
+#define XIAOMI_TYPE_KEY 0x02 /* press/release keys */
+#define XIAOMI_TYPE_TOGGLE 0x03 /* firmware toggle keys (notify only) */
+
+#define XIAOMI_KEY_PRESS_MIN 0x01
+#define XIAOMI_KEY_PRESS_MAX 0x05
+#define XIAOMI_KEY_RELEASE_OFF 0x05
+
+#define XIAOMI_TOGGLE_DEDUP_MS 50
+
+struct xiaomi_wmi {
+ struct input_dev *input_dev;
+ unsigned long last_toggle;
+ u8 last_toggle_code;
+};
+
+static const struct key_entry xiaomi_wmi_keymap[] = {
+ /* type 0x02: programmable keys with abstract icons */
+ { KE_KEY, 0x0201, { KEY_MACRO1 } },
+ { KE_KEY, 0x0202, { KEY_MACRO2 } },
+ { KE_KEY, 0x0203, { KEY_MACRO3 } },
+ { KE_KEY, 0x0204, { KEY_MACRO4 } },
+ { KE_KEY, 0x0205, { KEY_MACRO5 } },
+ /* type 0x03: firmware-handled toggles, reported for OSD only */
+ { KE_KEY, 0x0300, { KEY_F21 } }, /* touchpad toggle */
+ { KE_KEY, 0x0301, { KEY_FN_ESC } }, /* Fn lock */
+ { KE_END, 0 },
+};
+
+static int xiaomi_wmi_probe(struct wmi_device *wdev, const void *context)
+{
+ struct xiaomi_wmi *data;
+ int ret;
+
+ data = devm_kzalloc(&wdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ dev_set_drvdata(&wdev->dev, data);
+
+ data->input_dev = devm_input_allocate_device(&wdev->dev);
+ if (!data->input_dev)
+ return -ENOMEM;
+
+ data->input_dev->name = "Xiaomi WMI keys";
+ data->input_dev->phys = "wmi/input0";
+ data->input_dev->id.bustype = BUS_HOST;
+
+ ret = sparse_keymap_setup(data->input_dev, xiaomi_wmi_keymap, NULL);
+ if (ret)
+ return ret;
+
+ return input_register_device(data->input_dev);
+}
+
+static void xiaomi_wmi_notify(struct wmi_device *wdev, union acpi_object *obj)
+{
+ struct xiaomi_wmi *data = dev_get_drvdata(&wdev->dev);
+ u8 type, code;
+
+ if (obj->type != ACPI_TYPE_BUFFER || obj->buffer.length < 3)
+ return;
+
+ type = obj->buffer.pointer[1];
+ code = obj->buffer.pointer[2];
+
+ switch (type) {
+ case XIAOMI_TYPE_KEY:
+ if (code >= XIAOMI_KEY_PRESS_MIN &&
+ code <= XIAOMI_KEY_PRESS_MAX) {
+ sparse_keymap_report_event(data->input_dev,
+ 0x0200 | code, 1, false);
+ } else if (code > XIAOMI_KEY_PRESS_MAX &&
+ code <= XIAOMI_KEY_PRESS_MAX +
+ XIAOMI_KEY_RELEASE_OFF) {
+ code -= XIAOMI_KEY_RELEASE_OFF;
+ sparse_keymap_report_event(data->input_dev,
+ 0x0200 | code, 0, false);
+ }
+ break;
+
+ case XIAOMI_TYPE_TOGGLE:
+ /* deduplicate: each press emits two identical events */
+ if (data->last_toggle_code == code &&
+ time_before(jiffies, data->last_toggle +
+ msecs_to_jiffies(XIAOMI_TOGGLE_DEDUP_MS)))
+ return;
+ data->last_toggle_code = code;
+ data->last_toggle = jiffies;
+ sparse_keymap_report_event(data->input_dev,
+ 0x0300 | code, 1, true);
+ break;
+
+ case XIAOMI_TYPE_BACKLIGHT:
+ /* keyboard backlight handled by EC, nothing to do */
+ break;
+
+ default:
+ dev_dbg(&wdev->dev, "unknown event type 0x%02x\n", type);
+ break;
+ }
+}
+
+static const struct wmi_device_id xiaomi_wmi_id_table[] = {
+ { .guid_string = XIAOMI_WMI_EVENT_GUID },
+ { }
+};
+MODULE_DEVICE_TABLE(wmi, xiaomi_wmi_id_table);
+
+static struct wmi_driver xiaomi_wmi_driver = {
+ .driver = {
+ .name = "xiaomi-wmi-keys",
+ },
+ .id_table = xiaomi_wmi_id_table,
+ .probe = xiaomi_wmi_probe,
+ .notify = xiaomi_wmi_notify,
+ .no_singleton = true,
+};
+module_wmi_driver(xiaomi_wmi_driver);
+
+MODULE_AUTHOR("Lucy Wong <lucywong2778@gmail.com>");
+MODULE_DESCRIPTION("Xiaomi laptop WMI hotkey driver");
+MODULE_LICENSE("GPL");
--
2.54.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2] platform/x86: add Xiaomi WMI key driver
2026-06-01 15:14 [PATCH 0/1] platform/x86: add Xiaomi WMI key driver Lucy Wong
2026-06-01 15:14 ` [PATCH 1/1] " Lucy Wong
@ 2026-10-22 18:56 ` Lucy Wong
2026-11-01 17:32 ` Armin Wolf
1 sibling, 1 reply; 5+ messages in thread
From: Lucy Wong @ 2026-10-22 18:56 UTC (permalink / raw)
To: Hans de Goede, Ilpo Järvinen
Cc: platform-driver-x86, linux-kernel, Armin Wolf, Lucy Wong
Certain Xiaomi laptops expose extra function keys through a single WMI
event GUID (B74AF83F-8B2F-4069-ACAC-36D176F62FC0). Unlike the existing
xiaomi-wmi driver where each key has its own GUID, here all keys share
one GUID and the event buffer encodes both an event type and a keycode:
buffer[1] = event type
0x02: press/release keys (5 keys with abstract icons)
0x03: firmware-handled toggles (touchpad, Fn lock)
buffer[2] = keycode within that type
The keys with abstract icons are mapped to programmable macro keys for
userspace to bind. The touchpad and Fn lock toggles, as well as the
keyboard backlight level events, are handled by the firmware and are
ignored.
Link: https://lore.kernel.org/platform-driver-x86/20260601151404.93049-1-lucywong2778@gmail.com/
Signed-off-by: Lucy Wong <lucywong2778@gmail.com>
---
Changes in v2:
- Convert to .notify_new and set .min_event_size
- Ignore firmware-handled backlight and toggle events, which removes the
toggle deduplication state
- Add the missing select INPUT_SPARSEKMAP
- Name the event codes and align the defines
- Add the dev_printk.h include
---
MAINTAINERS | 6 ++
drivers/platform/x86/Kconfig | 12 +++
drivers/platform/x86/Makefile | 1 +
drivers/platform/x86/xiaomi-wmi-keys.c | 123 +++++++++++++++++++++++++
4 files changed, 142 insertions(+)
create mode 100644 drivers/platform/x86/xiaomi-wmi-keys.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 839e39825455..7969b82c8315 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -29124,6 +29124,12 @@ F: fs/xfs/
F: include/uapi/linux/dqblk_xfs.h
F: include/uapi/linux/fsmap.h
+XIAOMI WMI KEYS DRIVER
+M: Lucy Wong <lucywong2778@gmail.com>
+L: platform-driver-x86@vger.kernel.org
+S: Maintained
+F: drivers/platform/x86/xiaomi-wmi-keys.c
+
XILINX AMS DRIVER
M: Salih Erim <salih.erim@amd.com>
M: Conall O'Griofa <conall.ogriofa@amd.com>
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index b54b5212b204..1e7128f88adf 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -90,6 +90,18 @@ config XIAOMI_WMI
To compile this driver as a module, choose M here: the module will
be called xiaomi-wmi.
+config XIAOMI_WMI_KEYS
+ tristate "Xiaomi WMI key events driver"
+ depends on ACPI_WMI
+ depends on INPUT
+ select INPUT_SPARSEKMAP
+ help
+ Say Y here if you want to support WMI-based hotkey events on certain
+ Xiaomi laptops.
+
+ To compile this driver as a module, choose M here: the module will
+ be called xiaomi-wmi-keys.
+
config REDMI_WMI
tristate "Redmibook WMI key driver"
depends on ACPI_WMI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 872ac3842391..d852bb0bf61b 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_HUAWEI_WMI) += huawei-wmi.o
obj-$(CONFIG_MXM_WMI) += mxm-wmi.o
obj-$(CONFIG_NVIDIA_WMI_EC_BACKLIGHT) += nvidia-wmi-ec-backlight.o
obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o
+obj-$(CONFIG_XIAOMI_WMI_KEYS) += xiaomi-wmi-keys.o
obj-$(CONFIG_REDMI_WMI) += redmi-wmi.o
obj-$(CONFIG_GIGABYTE_WMI) += gigabyte-wmi.o
obj-$(CONFIG_BITLAND_MIFS_WMI) += bitland-mifs-wmi.o
diff --git a/drivers/platform/x86/xiaomi-wmi-keys.c b/drivers/platform/x86/xiaomi-wmi-keys.c
new file mode 100644
index 000000000000..a01ef01e501e
--- /dev/null
+++ b/drivers/platform/x86/xiaomi-wmi-keys.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xiaomi laptop WMI hotkey driver
+ *
+ * Copyright (C) 2026 Lucy Wong <lucywong2778@gmail.com>
+ */
+
+#include <linux/device.h>
+#include <linux/dev_printk.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+#include <linux/module.h>
+#include <linux/wmi.h>
+
+#define XIAOMI_WMI_EVENT_GUID "B74AF83F-8B2F-4069-ACAC-36D176F62FC0"
+
+#define XIAOMI_EVENT_TYPE_KEY 0x02
+
+#define XIAOMI_KEY_PRESS_FIRST 0x01
+#define XIAOMI_KEY_COUNT 5
+#define XIAOMI_KEY_RELEASE_FIRST \
+ (XIAOMI_KEY_PRESS_FIRST + XIAOMI_KEY_COUNT)
+
+struct xiaomi_wmi_keys_event {
+ u8 reserved;
+ u8 type;
+ u8 code;
+};
+
+struct xiaomi_wmi_keys {
+ struct input_dev *input_dev;
+};
+
+static const struct key_entry xiaomi_wmi_keys_keymap[] = {
+ /* programmable keys with abstract icons */
+ { KE_KEY, 0x01, { KEY_MACRO1 } },
+ { KE_KEY, 0x02, { KEY_MACRO2 } },
+ { KE_KEY, 0x03, { KEY_MACRO3 } },
+ { KE_KEY, 0x04, { KEY_MACRO4 } },
+ { KE_KEY, 0x05, { KEY_MACRO5 } },
+ { KE_END, 0 },
+};
+
+static int xiaomi_wmi_keys_probe(struct wmi_device *wdev, const void *context)
+{
+ struct xiaomi_wmi_keys *data;
+ int ret;
+
+ data = devm_kzalloc(&wdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ dev_set_drvdata(&wdev->dev, data);
+
+ data->input_dev = devm_input_allocate_device(&wdev->dev);
+ if (!data->input_dev)
+ return -ENOMEM;
+
+ data->input_dev->name = "Xiaomi WMI keys";
+ data->input_dev->phys = "wmi/input0";
+ data->input_dev->id.bustype = BUS_HOST;
+
+ ret = sparse_keymap_setup(data->input_dev, xiaomi_wmi_keys_keymap, NULL);
+ if (ret)
+ return ret;
+
+ return input_register_device(data->input_dev);
+}
+
+static void xiaomi_wmi_keys_notify(struct wmi_device *wdev,
+ const struct wmi_buffer *buffer)
+{
+ const struct xiaomi_wmi_keys_event *event = buffer->data;
+ struct xiaomi_wmi_keys *data = dev_get_drvdata(&wdev->dev);
+ unsigned int code;
+ bool pressed;
+
+ /*
+ * Only the press/release keys are reported. Event types 0x01
+ * (backlight) and 0x03 (touchpad and Fn-lock toggles) are handled by
+ * the firmware and need no action from the driver.
+ */
+ if (event->type != XIAOMI_EVENT_TYPE_KEY) {
+ dev_dbg(&wdev->dev, "ignoring event type 0x%02x\n", event->type);
+ return;
+ }
+
+ if (event->code >= XIAOMI_KEY_PRESS_FIRST &&
+ event->code < XIAOMI_KEY_PRESS_FIRST + XIAOMI_KEY_COUNT) {
+ code = event->code;
+ pressed = true;
+ } else if (event->code >= XIAOMI_KEY_RELEASE_FIRST &&
+ event->code < XIAOMI_KEY_RELEASE_FIRST + XIAOMI_KEY_COUNT) {
+ code = event->code - XIAOMI_KEY_COUNT;
+ pressed = false;
+ } else {
+ dev_dbg(&wdev->dev, "ignoring key code 0x%02x\n", event->code);
+ return;
+ }
+
+ sparse_keymap_report_event(data->input_dev, code, pressed, false);
+}
+
+static const struct wmi_device_id xiaomi_wmi_keys_id_table[] = {
+ { .guid_string = XIAOMI_WMI_EVENT_GUID },
+ { }
+};
+MODULE_DEVICE_TABLE(wmi, xiaomi_wmi_keys_id_table);
+
+static struct wmi_driver xiaomi_wmi_keys_driver = {
+ .driver = {
+ .name = "xiaomi-wmi-keys",
+ },
+ .id_table = xiaomi_wmi_keys_id_table,
+ .min_event_size = sizeof(struct xiaomi_wmi_keys_event),
+ .probe = xiaomi_wmi_keys_probe,
+ .notify_new = xiaomi_wmi_keys_notify,
+ .no_singleton = true,
+};
+module_wmi_driver(xiaomi_wmi_keys_driver);
+
+MODULE_AUTHOR("Lucy Wong <lucywong2778@gmail.com>");
+MODULE_DESCRIPTION("Xiaomi laptop WMI hotkey driver");
+MODULE_LICENSE("GPL");
--
2.56.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] platform/x86: add Xiaomi WMI key driver
2026-10-22 18:56 ` [PATCH v2] " Lucy Wong
@ 2026-11-01 17:32 ` Armin Wolf
2026-11-02 20:46 ` [PATCH v3] " Lucy Wong
0 siblings, 1 reply; 5+ messages in thread
From: Armin Wolf @ 2026-11-01 17:32 UTC (permalink / raw)
To: Lucy Wong, Hans de Goede, Ilpo Järvinen
Cc: platform-driver-x86, linux-kernel
Am 22.10.26 um 20:56 schrieb Lucy Wong:
> Certain Xiaomi laptops expose extra function keys through a single WMI
> event GUID (B74AF83F-8B2F-4069-ACAC-36D176F62FC0). Unlike the existing
> xiaomi-wmi driver where each key has its own GUID, here all keys share
> one GUID and the event buffer encodes both an event type and a keycode:
>
> buffer[1] = event type
> 0x02: press/release keys (5 keys with abstract icons)
> 0x03: firmware-handled toggles (touchpad, Fn lock)
> buffer[2] = keycode within that type
>
> The keys with abstract icons are mapped to programmable macro keys for
> userspace to bind. The touchpad and Fn lock toggles, as well as the
> keyboard backlight level events, are handled by the firmware and are
> ignored.
>
> Link: https://lore.kernel.org/platform-driver-x86/20260601151404.93049-1-lucywong2778@gmail.com/
> Signed-off-by: Lucy Wong <lucywong2778@gmail.com>
> ---
> Changes in v2:
> - Convert to .notify_new and set .min_event_size
> - Ignore firmware-handled backlight and toggle events, which removes the
> toggle deduplication state
> - Add the missing select INPUT_SPARSEKMAP
> - Name the event codes and align the defines
> - Add the dev_printk.h include
> ---
> MAINTAINERS | 6 ++
> drivers/platform/x86/Kconfig | 12 +++
> drivers/platform/x86/Makefile | 1 +
> drivers/platform/x86/xiaomi-wmi-keys.c | 123 +++++++++++++++++++++++++
> 4 files changed, 142 insertions(+)
> create mode 100644 drivers/platform/x86/xiaomi-wmi-keys.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 839e39825455..7969b82c8315 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -29124,6 +29124,12 @@ F: fs/xfs/
> F: include/uapi/linux/dqblk_xfs.h
> F: include/uapi/linux/fsmap.h
>
> +XIAOMI WMI KEYS DRIVER
> +M: Lucy Wong <lucywong2778@gmail.com>
> +L: platform-driver-x86@vger.kernel.org
> +S: Maintained
> +F: drivers/platform/x86/xiaomi-wmi-keys.c
> +
> XILINX AMS DRIVER
> M: Salih Erim <salih.erim@amd.com>
> M: Conall O'Griofa <conall.ogriofa@amd.com>
> diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> index b54b5212b204..1e7128f88adf 100644
> --- a/drivers/platform/x86/Kconfig
> +++ b/drivers/platform/x86/Kconfig
> @@ -90,6 +90,18 @@ config XIAOMI_WMI
> To compile this driver as a module, choose M here: the module will
> be called xiaomi-wmi.
>
> +config XIAOMI_WMI_KEYS
> + tristate "Xiaomi WMI key events driver"
> + depends on ACPI_WMI
> + depends on INPUT
> + select INPUT_SPARSEKMAP
> + help
> + Say Y here if you want to support WMI-based hotkey events on certain
> + Xiaomi laptops.
> +
> + To compile this driver as a module, choose M here: the module will
> + be called xiaomi-wmi-keys.
> +
> config REDMI_WMI
> tristate "Redmibook WMI key driver"
> depends on ACPI_WMI
> diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
> index 872ac3842391..d852bb0bf61b 100644
> --- a/drivers/platform/x86/Makefile
> +++ b/drivers/platform/x86/Makefile
> @@ -12,6 +12,7 @@ obj-$(CONFIG_HUAWEI_WMI) += huawei-wmi.o
> obj-$(CONFIG_MXM_WMI) += mxm-wmi.o
> obj-$(CONFIG_NVIDIA_WMI_EC_BACKLIGHT) += nvidia-wmi-ec-backlight.o
> obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o
> +obj-$(CONFIG_XIAOMI_WMI_KEYS) += xiaomi-wmi-keys.o
> obj-$(CONFIG_REDMI_WMI) += redmi-wmi.o
> obj-$(CONFIG_GIGABYTE_WMI) += gigabyte-wmi.o
> obj-$(CONFIG_BITLAND_MIFS_WMI) += bitland-mifs-wmi.o
> diff --git a/drivers/platform/x86/xiaomi-wmi-keys.c b/drivers/platform/x86/xiaomi-wmi-keys.c
> new file mode 100644
> index 000000000000..a01ef01e501e
> --- /dev/null
> +++ b/drivers/platform/x86/xiaomi-wmi-keys.c
> @@ -0,0 +1,123 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Xiaomi laptop WMI hotkey driver
> + *
> + * Copyright (C) 2026 Lucy Wong <lucywong2778@gmail.com>
> + */
> +
> +#include <linux/device.h>
> +#include <linux/dev_printk.h>
> +#include <linux/input.h>
> +#include <linux/input/sparse-keymap.h>
> +#include <linux/module.h>
> +#include <linux/wmi.h>
> +
> +#define XIAOMI_WMI_EVENT_GUID "B74AF83F-8B2F-4069-ACAC-36D176F62FC0"
> +
> +#define XIAOMI_EVENT_TYPE_KEY 0x02
Please also document event type 0x03 and 0x01. Does your device contain embedded BMOF data?
I would be interested in taking a look at it.
> +
> +#define XIAOMI_KEY_PRESS_FIRST 0x01
> +#define XIAOMI_KEY_COUNT 5
> +#define XIAOMI_KEY_RELEASE_FIRST \
> + (XIAOMI_KEY_PRESS_FIRST + XIAOMI_KEY_COUNT)
> +
> +struct xiaomi_wmi_keys_event {
> + u8 reserved;
> + u8 type;
> + u8 code;
> +};
> +
> +struct xiaomi_wmi_keys {
> + struct input_dev *input_dev;
> +};
> +
> +static const struct key_entry xiaomi_wmi_keys_keymap[] = {
> + /* programmable keys with abstract icons */
> + { KE_KEY, 0x01, { KEY_MACRO1 } },
> + { KE_KEY, 0x02, { KEY_MACRO2 } },
> + { KE_KEY, 0x03, { KEY_MACRO3 } },
> + { KE_KEY, 0x04, { KEY_MACRO4 } },
> + { KE_KEY, 0x05, { KEY_MACRO5 } },
> + { KE_END, 0 },
> +};
> +
> +static int xiaomi_wmi_keys_probe(struct wmi_device *wdev, const void *context)
> +{
> + struct xiaomi_wmi_keys *data;
> + int ret;
> +
> + data = devm_kzalloc(&wdev->dev, sizeof(*data), GFP_KERNEL);
> + if (!data)
> + return -ENOMEM;
> + dev_set_drvdata(&wdev->dev, data);
You need a mutex to sync each invocation of sparse_keymap_report_event().
> +
> + data->input_dev = devm_input_allocate_device(&wdev->dev);
> + if (!data->input_dev)
> + return -ENOMEM;
> +
> + data->input_dev->name = "Xiaomi WMI keys";
> + data->input_dev->phys = "wmi/input0";
> + data->input_dev->id.bustype = BUS_HOST;
> +
> + ret = sparse_keymap_setup(data->input_dev, xiaomi_wmi_keys_keymap, NULL);
> + if (ret)
> + return ret;
> +
> + return input_register_device(data->input_dev);
> +}
> +
> +static void xiaomi_wmi_keys_notify(struct wmi_device *wdev,
> + const struct wmi_buffer *buffer)
> +{
> + const struct xiaomi_wmi_keys_event *event = buffer->data;
> + struct xiaomi_wmi_keys *data = dev_get_drvdata(&wdev->dev);
Reverse XMAS tree ordering please, move the above assignment to the top.
> + unsigned int code;
> + bool pressed;
> +
> + /*
> + * Only the press/release keys are reported. Event types 0x01
> + * (backlight) and 0x03 (touchpad and Fn-lock toggles) are handled by
> + * the firmware and need no action from the driver.
> + */
> + if (event->type != XIAOMI_EVENT_TYPE_KEY) {
> + dev_dbg(&wdev->dev, "ignoring event type 0x%02x\n", event->type);
> + return;
> + }
> +
> + if (event->code >= XIAOMI_KEY_PRESS_FIRST &&
> + event->code < XIAOMI_KEY_PRESS_FIRST + XIAOMI_KEY_COUNT) {
> + code = event->code;
> + pressed = true;
> + } else if (event->code >= XIAOMI_KEY_RELEASE_FIRST &&
> + event->code < XIAOMI_KEY_RELEASE_FIRST + XIAOMI_KEY_COUNT) {
> + code = event->code - XIAOMI_KEY_COUNT;
> + pressed = false;
> + } else {
> + dev_dbg(&wdev->dev, "ignoring key code 0x%02x\n", event->code);
Maybe use dev_notice() here to notify users that a unknown key index was received.
> + return;
> + }
> +
> + sparse_keymap_report_event(data->input_dev, code, pressed, false);
> +}
> +
> +static const struct wmi_device_id xiaomi_wmi_keys_id_table[] = {
> + { .guid_string = XIAOMI_WMI_EVENT_GUID },
> + { }
> +};
> +MODULE_DEVICE_TABLE(wmi, xiaomi_wmi_keys_id_table);
> +
> +static struct wmi_driver xiaomi_wmi_keys_driver = {
> + .driver = {
> + .name = "xiaomi-wmi-keys",
Please add .probe_type = PROBE_PREFER_ASYNCHRONOUS here.
Other than that the driver looks promising.
Thanks,
Armin Wolf
> + },
> + .id_table = xiaomi_wmi_keys_id_table,
> + .min_event_size = sizeof(struct xiaomi_wmi_keys_event),
> + .probe = xiaomi_wmi_keys_probe,
> + .notify_new = xiaomi_wmi_keys_notify,
> + .no_singleton = true,
> +};
> +module_wmi_driver(xiaomi_wmi_keys_driver);
> +
> +MODULE_AUTHOR("Lucy Wong <lucywong2778@gmail.com>");
> +MODULE_DESCRIPTION("Xiaomi laptop WMI hotkey driver");
> +MODULE_LICENSE("GPL");
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3] platform/x86: add Xiaomi WMI key driver
2026-11-01 17:32 ` Armin Wolf
@ 2026-11-02 20:46 ` Lucy Wong
0 siblings, 0 replies; 5+ messages in thread
From: Lucy Wong @ 2026-11-02 20:46 UTC (permalink / raw)
To: Hans de Goede, Ilpo Järvinen, Armin Wolf
Cc: platform-driver-x86, linux-kernel, Lucy Wong
Certain Xiaomi laptops expose extra function keys through a single WMI
event GUID (B74AF83F-8B2F-4069-ACAC-36D176F62FC0). Unlike the existing
xiaomi-wmi driver where each key has its own GUID, here all keys share
one GUID and the event buffer encodes both an event type and a keycode:
buffer[1] = event type
0x01: keyboard backlight level (EC handled)
0x02: press/release keys (5 keys with abstract icons)
0x03: firmware-handled toggles (touchpad, Fn lock)
buffer[2] = keycode within that type
The keys with abstract icons are mapped to programmable macro keys for
userspace to bind. The backlight and toggle events are handled by the
firmware and are ignored.
Link: https://lore.kernel.org/platform-driver-x86/20260601151404.93049-1-lucywong2778@gmail.com/
Signed-off-by: Lucy Wong <lucywong2778@gmail.com>
---
Changes in v3:
- Add a mutex to serialize sparse_keymap_report_event() calls
- Document event types 0x01 and 0x03 with named defines
- Use dev_notice() for unknown key indices
- Fix reverse XMAS tree ordering of the notify() locals
- Set .probe_type = PROBE_PREFER_ASYNCHRONOUS
Changes in v2:
- Convert to .notify_new and set .min_event_size
- Ignore firmware-handled backlight and toggle events, which removes the
toggle deduplication state
- Add the missing select INPUT_SPARSEKMAP
- Name the event codes and align the defines
- Add the dev_printk.h include
Re: BMOF data -- the WMI device does not expose embedded BMOF data; there
is no bmof sysfs attribute for B74AF83F-8B2F-4069-ACAC-36D176F62FC0.
---
MAINTAINERS | 6 ++
drivers/platform/x86/Kconfig | 12 +++
drivers/platform/x86/Makefile | 1 +
drivers/platform/x86/xiaomi-wmi-keys.c | 134 +++++++++++++++++++++++++
4 files changed, 153 insertions(+)
create mode 100644 drivers/platform/x86/xiaomi-wmi-keys.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 748ce4d1c6a2..0a280e6773a7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -30546,6 +30546,12 @@ F: fs/xfs/
F: include/uapi/linux/dqblk_xfs.h
F: include/uapi/linux/fsmap.h
+XIAOMI WMI KEYS DRIVER
+M: Lucy Wong <lucywong2778@gmail.com>
+L: platform-driver-x86@vger.kernel.org
+S: Maintained
+F: drivers/platform/x86/xiaomi-wmi-keys.c
+
XILINX AMS DRIVER
M: Sai Krishna Potthuri <sai.krishna.potthuri@amd.com>
M: Conall O'Griofa <conall.ogriofa@amd.com>
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 9ce384e0475e..efebf9e55b98 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -78,6 +78,18 @@ config XIAOMI_WMI
To compile this driver as a module, choose M here: the module will
be called xiaomi-wmi.
+config XIAOMI_WMI_KEYS
+ tristate "Xiaomi WMI key events driver"
+ depends on ACPI_WMI
+ depends on INPUT
+ select INPUT_SPARSEKMAP
+ help
+ Say Y here if you want to support WMI-based hotkey events on certain
+ Xiaomi laptops.
+
+ To compile this driver as a module, choose M here: the module will
+ be called xiaomi-wmi-keys.
+
config REDMI_WMI
tristate "Redmibook WMI key driver"
depends on ACPI_WMI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 229057234d00..e77959052776 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_HUAWEI_WMI) += huawei-wmi.o
obj-$(CONFIG_MXM_WMI) += mxm-wmi.o
obj-$(CONFIG_NVIDIA_WMI_EC_BACKLIGHT) += nvidia-wmi-ec-backlight.o
obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o
+obj-$(CONFIG_XIAOMI_WMI_KEYS) += xiaomi-wmi-keys.o
obj-$(CONFIG_REDMI_WMI) += redmi-wmi.o
obj-$(CONFIG_GIGABYTE_WMI) += gigabyte-wmi.o
obj-$(CONFIG_BITLAND_MIFS_WMI) += bitland-mifs-wmi.o
diff --git a/drivers/platform/x86/xiaomi-wmi-keys.c b/drivers/platform/x86/xiaomi-wmi-keys.c
new file mode 100644
index 000000000000..7452c6eb8eca
--- /dev/null
+++ b/drivers/platform/x86/xiaomi-wmi-keys.c
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xiaomi laptop WMI hotkey driver
+ *
+ * Copyright (C) 2026 Lucy Wong <lucywong2778@gmail.com>
+ */
+
+#include <linux/device.h>
+#include <linux/dev_printk.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/wmi.h>
+
+#define XIAOMI_WMI_EVENT_GUID "B74AF83F-8B2F-4069-ACAC-36D176F62FC0"
+
+#define XIAOMI_EVENT_TYPE_BACKLIGHT 0x01 /* keyboard backlight (EC handled) */
+#define XIAOMI_EVENT_TYPE_KEY 0x02 /* press/release keys */
+#define XIAOMI_EVENT_TYPE_TOGGLE 0x03 /* touchpad/Fn-lock toggles (EC handled) */
+
+#define XIAOMI_KEY_PRESS_FIRST 0x01
+#define XIAOMI_KEY_COUNT 5
+#define XIAOMI_KEY_RELEASE_FIRST \
+ (XIAOMI_KEY_PRESS_FIRST + XIAOMI_KEY_COUNT)
+
+struct xiaomi_wmi_keys_event {
+ u8 reserved;
+ u8 type;
+ u8 code;
+};
+
+struct xiaomi_wmi_keys {
+ struct input_dev *input_dev;
+ struct mutex key_lock; /* Serializes sparse_keymap_report_event() */
+};
+
+static const struct key_entry xiaomi_wmi_keys_keymap[] = {
+ /* programmable keys with abstract icons */
+ { KE_KEY, 0x01, { KEY_MACRO1 } },
+ { KE_KEY, 0x02, { KEY_MACRO2 } },
+ { KE_KEY, 0x03, { KEY_MACRO3 } },
+ { KE_KEY, 0x04, { KEY_MACRO4 } },
+ { KE_KEY, 0x05, { KEY_MACRO5 } },
+ { KE_END, 0 },
+};
+
+static int xiaomi_wmi_keys_probe(struct wmi_device *wdev, const void *context)
+{
+ struct xiaomi_wmi_keys *data;
+ int ret;
+
+ data = devm_kzalloc(&wdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ dev_set_drvdata(&wdev->dev, data);
+
+ ret = devm_mutex_init(&wdev->dev, &data->key_lock);
+ if (ret)
+ return ret;
+
+ data->input_dev = devm_input_allocate_device(&wdev->dev);
+ if (!data->input_dev)
+ return -ENOMEM;
+
+ data->input_dev->name = "Xiaomi WMI keys";
+ data->input_dev->phys = "wmi/input0";
+ data->input_dev->id.bustype = BUS_HOST;
+
+ ret = sparse_keymap_setup(data->input_dev, xiaomi_wmi_keys_keymap, NULL);
+ if (ret)
+ return ret;
+
+ return input_register_device(data->input_dev);
+}
+
+static void xiaomi_wmi_keys_notify(struct wmi_device *wdev,
+ const struct wmi_buffer *buffer)
+{
+ struct xiaomi_wmi_keys *data = dev_get_drvdata(&wdev->dev);
+ const struct xiaomi_wmi_keys_event *event = buffer->data;
+ unsigned int code;
+ bool pressed;
+
+ /*
+ * Only the press/release keys are reported. Event types 0x01
+ * (backlight) and 0x03 (touchpad and Fn-lock toggles) are handled by
+ * the firmware and need no action from the driver.
+ */
+ if (event->type != XIAOMI_EVENT_TYPE_KEY) {
+ dev_dbg(&wdev->dev, "ignoring event type 0x%02x\n", event->type);
+ return;
+ }
+
+ if (event->code >= XIAOMI_KEY_PRESS_FIRST &&
+ event->code < XIAOMI_KEY_PRESS_FIRST + XIAOMI_KEY_COUNT) {
+ code = event->code;
+ pressed = true;
+ } else if (event->code >= XIAOMI_KEY_RELEASE_FIRST &&
+ event->code < XIAOMI_KEY_RELEASE_FIRST + XIAOMI_KEY_COUNT) {
+ code = event->code - XIAOMI_KEY_COUNT;
+ pressed = false;
+ } else {
+ dev_notice(&wdev->dev, "unknown key index 0x%02x\n", event->code);
+ return;
+ }
+
+ mutex_lock(&data->key_lock);
+ sparse_keymap_report_event(data->input_dev, code, pressed, false);
+ mutex_unlock(&data->key_lock);
+}
+
+static const struct wmi_device_id xiaomi_wmi_keys_id_table[] = {
+ { .guid_string = XIAOMI_WMI_EVENT_GUID },
+ { }
+};
+MODULE_DEVICE_TABLE(wmi, xiaomi_wmi_keys_id_table);
+
+static struct wmi_driver xiaomi_wmi_keys_driver = {
+ .driver = {
+ .name = "xiaomi-wmi-keys",
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ },
+ .id_table = xiaomi_wmi_keys_id_table,
+ .min_event_size = sizeof(struct xiaomi_wmi_keys_event),
+ .probe = xiaomi_wmi_keys_probe,
+ .notify_new = xiaomi_wmi_keys_notify,
+ .no_singleton = true,
+};
+module_wmi_driver(xiaomi_wmi_keys_driver);
+
+MODULE_AUTHOR("Lucy Wong <lucywong2778@gmail.com>");
+MODULE_DESCRIPTION("Xiaomi laptop WMI hotkey driver");
+MODULE_LICENSE("GPL");
--
2.56.0
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-11-02 20:46 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-01 15:14 [PATCH 0/1] platform/x86: add Xiaomi WMI key driver Lucy Wong
2026-06-01 15:14 ` [PATCH 1/1] " Lucy Wong
2026-10-22 18:56 ` [PATCH v2] " Lucy Wong
2026-11-01 17:32 ` Armin Wolf
2026-11-02 20:46 ` [PATCH v3] " Lucy Wong
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®