summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/platform/x86/Kconfig10
-rw-r--r--drivers/platform/x86/Makefile1
-rw-r--r--drivers/platform/x86/xiaomi-wmi.c92
3 files changed, 103 insertions, 0 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index ae1e74d5e888..58494a12a9b0 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -780,6 +780,16 @@ config INTEL_WMI_THUNDERBOLT
To compile this driver as a module, choose M here: the module will
be called intel-wmi-thunderbolt.
+config XIAOMI_WMI
+ tristate "Xiaomi WMI key driver"
+ depends on ACPI_WMI
+ depends on INPUT
+ help
+ Say Y here if you want to support WMI-based keys on Xiaomi notebooks.
+
+ To compile this driver as a module, choose M here: the module will
+ be called xiaomi-wmi.
+
config MSI_WMI
tristate "MSI WMI extras"
depends on ACPI_WMI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 87b0069bd781..f64445d69f99 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_SURFACE3_WMI) += surface3-wmi.o
obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o
obj-$(CONFIG_WMI_BMOF) += wmi-bmof.o
obj-$(CONFIG_INTEL_WMI_THUNDERBOLT) += intel-wmi-thunderbolt.o
+obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o
# toshiba_acpi must link after wmi to ensure that wmi devices are found
# before toshiba_acpi initializes
diff --git a/drivers/platform/x86/xiaomi-wmi.c b/drivers/platform/x86/xiaomi-wmi.c
new file mode 100644
index 000000000000..601cbb282f54
--- /dev/null
+++ b/drivers/platform/x86/xiaomi-wmi.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0
+/* WMI driver for Xiaomi Laptops */
+
+#include <linux/acpi.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/wmi.h>
+
+#include <uapi/linux/input-event-codes.h>
+
+#define XIAOMI_KEY_FN_ESC_0 "A2095CCE-0491-44E7-BA27-F8ED8F88AA86"
+#define XIAOMI_KEY_FN_ESC_1 "7BBE8E39-B486-473D-BA13-66F75C5805CD"
+#define XIAOMI_KEY_FN_FN "409B028D-F06B-4C7C-8BBB-EE133A6BD87E"
+#define XIAOMI_KEY_CAPSLOCK "83FE7607-053A-4644-822A-21532C621FC7"
+#define XIAOMI_KEY_FN_F7 "76E9027C-95D0-4180-8692-DA6747DD1C2D"
+
+#define XIAOMI_DEVICE(guid, key) \
+ .guid_string = (guid), \
+ .context = &(const unsigned int){key}
+
+struct xiaomi_wmi {
+ struct input_dev *input_dev;
+ unsigned int key_code;
+};
+
+int xiaomi_wmi_probe(struct wmi_device *wdev, const void *context)
+{
+ struct xiaomi_wmi *data;
+
+ if (wdev == NULL || context == NULL)
+ return -EINVAL;
+
+ data = devm_kzalloc(&wdev->dev, sizeof(struct xiaomi_wmi), GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+ dev_set_drvdata(&wdev->dev, data);
+
+ data->input_dev = devm_input_allocate_device(&wdev->dev);
+ if (data->input_dev == NULL)
+ return -ENOMEM;
+ data->input_dev->name = "Xiaomi WMI keys";
+ data->input_dev->phys = "wmi/input0";
+
+ data->key_code = *((const unsigned int *)context);
+ set_bit(EV_KEY, data->input_dev->evbit);
+ set_bit(data->key_code, data->input_dev->keybit);
+
+ return input_register_device(data->input_dev);
+}
+
+void xiaomi_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy)
+{
+ struct xiaomi_wmi *data;
+
+ if (wdev == NULL)
+ return;
+
+ data = dev_get_drvdata(&wdev->dev);
+ if (data == NULL)
+ return;
+
+ input_report_key(data->input_dev, data->key_code, 1);
+ input_sync(data->input_dev);
+ input_report_key(data->input_dev, data->key_code, 0);
+ input_sync(data->input_dev);
+}
+
+static const struct wmi_device_id xiaomi_wmi_id_table[] = {
+ // { XIAOMI_DEVICE(XIAOMI_KEY_FN_ESC_0, KEY_FN_ESC) },
+ // { XIAOMI_DEVICE(XIAOMI_KEY_FN_ESC_1, KEY_FN_ESC) },
+ { XIAOMI_DEVICE(XIAOMI_KEY_FN_FN, KEY_PROG1) },
+ // { XIAOMI_DEVICE(XIAOMI_KEY_CAPSLOCK, KEY_CAPSLOCK) },
+ { XIAOMI_DEVICE(XIAOMI_KEY_FN_F7, KEY_CUT) },
+
+ /* Terminating entry */
+ { }
+};
+
+static struct wmi_driver xiaomi_wmi_driver = {
+ .driver = {
+ .name = "xiaomi-wmi",
+ },
+ .id_table = xiaomi_wmi_id_table,
+ .probe = xiaomi_wmi_probe,
+ .notify = xiaomi_wmi_notify,
+};
+module_wmi_driver(xiaomi_wmi_driver);
+
+MODULE_DEVICE_TABLE(wmi, xiaomi_wmi_id_table);
+MODULE_AUTHOR("Mattias Jacobsson");
+MODULE_DESCRIPTION("Xiaomi WMI driver");
+MODULE_LICENSE("GPL v2");