[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <8e7f2cde-f068-4696-8298-f83619dfaf76@gmx.de>
Date: Wed, 30 Jul 2025 18:33:21 +0200
From: Armin Wolf <W_Armin@....de>
To: Gladyshev Ilya <foxido@...ido.dev>
Cc: linux-input@...r.kernel.org, nikita.nikita.krasnov@...il.com,
Hans de Goede <hansg@...nel.org>,
Ilpo Järvinen <ilpo.jarvinen@...ux.intel.com>,
linux-kernel@...r.kernel.org, platform-driver-x86@...r.kernel.org
Subject: Re: [PATCH v2] platform/x86: Add WMI driver for Redmibook keyboard.
Am 29.07.25 um 21:05 schrieb Gladyshev Ilya:
> This driver implements support for various Fn keys (like Cut) and Xiaomi
> specific AI button.
>
> Signed-off-by: Gladyshev Ilya <foxido@...ido.dev>
> ---
>
> Changes from v1:
> - Use sparse-keymap instead of manual matching
> - Fix GUID case so it actually autoloads
> - Other fixes from v1 review
>
> Link to v1: https://lore.kernel.org/platform-driver-x86/20250727223516.29244-1-foxido@foxido.dev/
>
> ---
> MAINTAINERS | 6 ++
> drivers/platform/x86/Kconfig | 11 +++
> drivers/platform/x86/Makefile | 1 +
> drivers/platform/x86/redmi-wmi.c | 129 +++++++++++++++++++++++++++++++
> 4 files changed, 147 insertions(+)
> create mode 100644 drivers/platform/x86/redmi-wmi.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index c0b444e5fd5a..eb25fb10e751 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -20965,6 +20965,12 @@ S: Maintained
> T: git https://github.com/pkshih/rtw.git
> F: drivers/net/wireless/realtek/rtw89/
>
> +REDMIBOOK WMI DRIVERS
> +M: Gladyshev Ilya <foxido@...ido.dev>
> +L: platform-driver-x86@...r.kernel.org
> +S: Maintained
> +F: drivers/platform/x86/redmi-wmi.c
> +
> REDPINE WIRELESS DRIVER
> L: linux-wireless@...r.kernel.org
> S: Orphan
> diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> index e5cbd58a99f3..3c570cb398d3 100644
> --- a/drivers/platform/x86/Kconfig
> +++ b/drivers/platform/x86/Kconfig
> @@ -109,6 +109,17 @@ config XIAOMI_WMI
> To compile this driver as a module, choose M here: the module will
> be called xiaomi-wmi.
>
> +config REDMI_WMI
> + tristate "Redmibook WMI key driver"
> + depends on ACPI_WMI
> + depends on INPUT
Please also select INPUT_SPARSEKMAP.
> + help
> + Say Y here if you want support for WMI-based hotkey events on
> + Xiaomi Redmibook devices.
> +
> + To compile this driver as a module, choose M here: the module will
> + be called redmi-wmi.
> +
> config GIGABYTE_WMI
> tristate "Gigabyte WMI temperature driver"
> depends on ACPI_WMI
> diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
> index bea87a85ae75..406dd0807ba7 100644
> --- a/drivers/platform/x86/Makefile
> +++ b/drivers/platform/x86/Makefile
> @@ -13,6 +13,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_REDMI_WMI) += redmi-wmi.o
> obj-$(CONFIG_GIGABYTE_WMI) += gigabyte-wmi.o
>
> # Acer
> diff --git a/drivers/platform/x86/redmi-wmi.c b/drivers/platform/x86/redmi-wmi.c
> new file mode 100644
> index 000000000000..732688fb94e0
> --- /dev/null
> +++ b/drivers/platform/x86/redmi-wmi.c
> @@ -0,0 +1,129 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* WMI driver for Xiaomi Redmibooks */
> +
> +#include <linux/acpi.h>
> +#include <linux/device.h>
> +#include <linux/input.h>
> +#include <linux/input/sparse-keymap.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/unaligned.h>
> +#include <linux/wmi.h>
> +
> +#include <uapi/linux/input-event-codes.h>
> +
> +#define WMI_REDMIBOOK_KEYBOARD_EVENT_GUID "46C93E13-EE9B-4262-8488-563BCA757FEF"
> +
> +#define AI_KEY_VALUE_MASK 0x00000100
> +
> +static const struct key_entry redmi_wmi_keymap[] = {
> + {KE_KEY, 0x00000201, {KEY_SELECTIVE_SCREENSHOT}},
> + {KE_KEY, 0x00000301, {KEY_ALL_APPLICATIONS}},
> + {KE_KEY, 0x00001b01, {KEY_SETUP}},
> +
> + /* AI button has code for each position */
> + {KE_KEY, 0x00011801, {KEY_ASSISTANT}},
> + {KE_KEY, 0x00011901, {KEY_ASSISTANT}},
> +
> + /* Keyboard backlight */
> + {KE_IGNORE, 0x00000501, {}},
> + {KE_IGNORE, 0x00800501, {}},
> + {KE_IGNORE, 0x00050501, {}},
> + {KE_IGNORE, 0x000a0501, {}},
> +
> + {KE_END}
> +};
> +
> +struct redmi_wmi {
> + struct input_dev *input_dev;
> + /* Protects the key event sequence */
> + struct mutex key_lock;
> +};
> +
> +static int redmi_wmi_probe(struct wmi_device *wdev, const void *context)
> +{
> + struct redmi_wmi *data;
> + int err;
> +
> + /* Init dev */
> + data = devm_kzalloc(&wdev->dev, sizeof(*data), GFP_KERNEL);
> + if (!data)
> + return -ENOMEM;
> +
> + dev_set_drvdata(&wdev->dev, data);
> +
> + err = devm_mutex_init(&wdev->dev, &data->key_lock);
> + if (err)
> + return err;
> +
> + /* Setup input device */
> + data->input_dev = devm_input_allocate_device(&wdev->dev);
> + if (!data->input_dev)
> + return -ENOMEM;
> + data->input_dev->name = "Redmibook WMI keys";
> + data->input_dev->phys = "wmi/input0";
> +
> + err = sparse_keymap_setup(data->input_dev, redmi_wmi_keymap, NULL);
> + if (err)
> + return err;
> +
> + return input_register_device(data->input_dev);
> +}
> +
> +static void redmi_wmi_notify(struct wmi_device *wdev, union acpi_object *obj)
> +{
> + struct redmi_wmi *data = dev_get_drvdata(&wdev->dev);
> + int value = 1;
> + bool autorelease = true;
Please order the variable declarations using reverse xmas tree order.
> +
> + if (obj->type != ACPI_TYPE_BUFFER) {
> + dev_err(&wdev->dev, "Bad response type %u\n", obj->type);
> + return;
> + }
> +
> + if (obj->buffer.length != 32) {
Please also accept oversized buffers.
> + dev_err(&wdev->dev, "Invalid buffer length %u\n", obj->buffer.length);
> + return;
> + }
> +
> + /* For linearizability */
> + guard(mutex)(&data->key_lock);
> +
> + u32 payload = get_unaligned_le32(obj->buffer.pointer);
> + struct key_entry *entry = sparse_keymap_entry_from_scancode(data->input_dev, payload);
> +
> + if (!entry) {
> + dev_dbg(&wdev->dev, "Unknown WMI event with payload %u", payload);
> + return;
> + }
> +
> + /* AI key quirk */
> + if (entry->keycode == KEY_ASSISTANT) {
> + value = !(payload & AI_KEY_VALUE_MASK);
I would rather check the payload for 0x00011901 here.
Thanks,
Armin Wolf
> + autorelease = false;
> + }
> +
> + sparse_keymap_report_entry(data->input_dev, entry, value, autorelease);
> +}
> +
> +static const struct wmi_device_id redmi_wmi_id_table[] = {
> + { .guid_string = WMI_REDMIBOOK_KEYBOARD_EVENT_GUID },
> + { }
> +};
> +
> +static struct wmi_driver redmi_wmi_driver = {
> + .driver = {
> + .name = "redmi-wmi",
> + .probe_type = PROBE_PREFER_ASYNCHRONOUS
> + },
> + .id_table = redmi_wmi_id_table,
> + .probe = redmi_wmi_probe,
> + .notify = redmi_wmi_notify,
> + .no_singleton = true,
> +};
> +module_wmi_driver(redmi_wmi_driver);
> +
> +MODULE_DEVICE_TABLE(wmi, redmi_wmi_id_table);
> +MODULE_AUTHOR("Gladyshev Ilya <foxido@...ido.dev>");
> +MODULE_DESCRIPTION("Redmibook WMI driver");
> +MODULE_LICENSE("GPL");
Powered by blists - more mailing lists