summaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/xiaomi-wmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/xiaomi-wmi.c')
-rw-r--r--drivers/platform/x86/xiaomi-wmi.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/platform/x86/xiaomi-wmi.c b/drivers/platform/x86/xiaomi-wmi.c
index 54a2546bb..be80f0bda 100644
--- a/drivers/platform/x86/xiaomi-wmi.c
+++ b/drivers/platform/x86/xiaomi-wmi.c
@@ -2,8 +2,10 @@
/* WMI driver for Xiaomi Laptops */
#include <linux/acpi.h>
+#include <linux/device.h>
#include <linux/input.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/wmi.h>
#include <uapi/linux/input-event-codes.h>
@@ -20,12 +22,21 @@
struct xiaomi_wmi {
struct input_dev *input_dev;
+ struct mutex key_lock; /* Protects the key event sequence */
unsigned int key_code;
};
+static void xiaomi_mutex_destroy(void *data)
+{
+ struct mutex *lock = data;
+
+ mutex_destroy(lock);
+}
+
static int xiaomi_wmi_probe(struct wmi_device *wdev, const void *context)
{
struct xiaomi_wmi *data;
+ int ret;
if (wdev == NULL || context == NULL)
return -EINVAL;
@@ -35,6 +46,11 @@ static int xiaomi_wmi_probe(struct wmi_device *wdev, const void *context)
return -ENOMEM;
dev_set_drvdata(&wdev->dev, data);
+ mutex_init(&data->key_lock);
+ ret = devm_add_action_or_reset(&wdev->dev, xiaomi_mutex_destroy, &data->key_lock);
+ if (ret < 0)
+ return ret;
+
data->input_dev = devm_input_allocate_device(&wdev->dev);
if (data->input_dev == NULL)
return -ENOMEM;
@@ -59,10 +75,12 @@ static void xiaomi_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy)
if (data == NULL)
return;
+ mutex_lock(&data->key_lock);
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);
+ mutex_unlock(&data->key_lock);
}
static const struct wmi_device_id xiaomi_wmi_id_table[] = {