[PATCH v2 2/2] platform/x86: ideapad-laptop: support for more special keys in WMI

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The event data of the WMI event 0xD0, which is assumed to be the
fn_lock, is used to indicate several special keys on newer Yoga 7/9
laptops.

Add support for these keys using the wmi_get_event_data_with_guid()
function.

Signed-off-by: Philipp Jungkamp <p.jungkamp@xxxxxxx>
---
I can't really judge how this would affect other devices which depend on the
event to toggle their fn-lock light unconditionally.

One could check whether the event data on those devices makes it clear when
exactly the eval_hals()/exec_sals() path is needed. This should be observable
through the dev_dbg() put before the ideapad_input_report().

 drivers/platform/x86/ideapad-laptop.c | 46 +++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index 33b3dfdd1b08..2ade423c7813 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -1074,6 +1074,7 @@ static void ideapad_sysfs_exit(struct ideapad_private *priv)
 /*
  * input device
  */
+#define IDEAPAD_WMI_KEY 0x100
 static const struct key_entry ideapad_keymap[] = {
 	{ KE_KEY,   6, { KEY_SWITCHVIDEOMODE } },
 	{ KE_KEY,   7, { KEY_CAMERA } },
@@ -1087,6 +1088,26 @@ static const struct key_entry ideapad_keymap[] = {
 	{ KE_KEY,  66, { KEY_TOUCHPAD_OFF } },
 	{ KE_KEY,  67, { KEY_TOUCHPAD_ON } },
 	{ KE_KEY, 128, { KEY_ESC } },
+
+	/*
+	 * WMI keys
+	 */
+
+	/* FnLock (handled by the firmware) */
+	{ KE_IGNORE,	0x02 | IDEAPAD_WMI_KEY },
+	/* Customizable Lenovo Hotkey ("star" with 'S' inside) */
+	{ KE_KEY,	0x01 | IDEAPAD_WMI_KEY, { KEY_FAVORITES } },
+	/* Dark mode toggle */
+	{ KE_KEY,	0x13 | IDEAPAD_WMI_KEY, { KEY_PROG1 } },
+	/* Sound profile switch */
+	{ KE_KEY,	0x12 | IDEAPAD_WMI_KEY, { KEY_PROG2 } },
+	/* Lenovo Virtual Background application */
+	{ KE_KEY,	0x28 | IDEAPAD_WMI_KEY, { KEY_PROG3 } },
+	/* Lenovo Support */
+	{ KE_KEY,	0x27 | IDEAPAD_WMI_KEY, { KEY_HELP } },
+	/* Refresh Rate Toggle */
+	{ KE_KEY,	0x0a | IDEAPAD_WMI_KEY, { KEY_DISPLAYTOGGLE } },
+
 	{ KE_END },
 };

@@ -1496,6 +1517,10 @@ static void ideapad_wmi_notify(u32 value, void *context)
 	struct ideapad_private *priv = context;
 	unsigned long result;

+	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *data;
+	acpi_status status;
+
 	switch (value) {
 	case 128:
 		ideapad_input_report(priv, value);
@@ -1506,6 +1531,27 @@ static void ideapad_wmi_notify(u32 value, void *context)

 			exec_sals(priv->adev->handle, state ? SALS_FNLOCK_ON : SALS_FNLOCK_OFF);
 		}
+
+		status = wmi_get_event_data_with_guid(priv->fnesc_guid, value, &response);
+		if (ACPI_FAILURE(status)) {
+			dev_warn(&priv->platform_device->dev,
+				"Bad WMI event data 0x%x\n", status);
+			break;
+		}
+
+		data = (union acpi_object *) response.pointer;
+		if (data->type != ACPI_TYPE_INTEGER) {
+			dev_warn(&priv->platform_device->dev,
+				"WMI event data is not an integer\n");
+		} else {
+			dev_dbg(&priv->platform_device->dev,
+				"WMI event: notify_id=%d, data=%d\n",
+				value,
+				data->integer.value);
+			ideapad_input_report(priv, data->integer.value | IDEAPAD_WMI_KEY);
+		}
+
+		kfree(response.pointer);
 		break;
 	default:
 		dev_info(&priv->platform_device->dev,
--
2.38.1




[Index of Archives]     [Linux Kernel Development]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux