diff options
author | Hans de Goede | 2022-11-17 12:02:42 +0100 |
---|---|---|
committer | Greg Kroah-Hartman | 2023-01-07 11:11:42 +0100 |
commit | bda3399b5abbaec5a173da6194a5d0d2c84e2bf6 (patch) | |
tree | 9c34afcb59817e72b6eb470bba0631a5758056f3 | |
parent | f5820b413962d0a7edf4ba97f62430f3f9ee60ff (diff) |
platform/x86: ideapad-laptop: Send KEY_TOUCHPAD_TOGGLE on some models
[ Upstream commit 5829f8a897e4f030cd2d32a930eea8954ab5dcd3 ]
On recent Ideapad models the EC does not control the touchpad at all,
so instead of sending KEY_TOUCHPAD_ON/ _OFF on touchpad toggle hotkey
events, ideapad-laptop should send KEY_TOUCHPAD_TOGGLE and let userspace
handle the toggling.
Check for this by checking if the value read from VPCCMD_R_TOUCHPAD
actually changes when receiving a touchpad-toggle hotkey event; and
if it does not change send KEY_TOUCHPAD_TOGGLE to userspace to let
userspace enable/disable the touchpad in software.
Note this also drops the priv->features.touchpad_ctrl_via_ec check from
ideapad_sync_touchpad_state() so that KEY_TOUCHPAD_TOGGLE will be send
on laptops where this is not set too. This can be safely dropped now
because the i8042_command(I8042_CMD_AUX_ENABLE/_DISABLE) call is now
guarded by its own feature flag.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Tested-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Tested-by: Maxim Mikityanskiy <maxtram95@gmail.com>
Link: https://lore.kernel.org/r/20221117110244.67811-5-hdegoede@redhat.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r-- | drivers/platform/x86/ideapad-laptop.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 1d86fb988d56..9b36cfddd36f 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -134,6 +134,7 @@ struct ideapad_private { struct ideapad_dytc_priv *dytc; struct dentry *debug; unsigned long cfg; + unsigned long r_touchpad_val; struct { bool conservation_mode : 1; bool dytc : 1; @@ -650,6 +651,8 @@ static ssize_t touchpad_show(struct device *dev, if (err) return err; + priv->r_touchpad_val = result; + return sysfs_emit(buf, "%d\n", !!result); } @@ -669,6 +672,8 @@ static ssize_t touchpad_store(struct device *dev, if (err) return err; + priv->r_touchpad_val = state; + return count; } @@ -1159,6 +1164,7 @@ static const struct key_entry ideapad_keymap[] = { { KE_KEY, 65, { KEY_PROG4 } }, { KE_KEY, 66, { KEY_TOUCHPAD_OFF } }, { KE_KEY, 67, { KEY_TOUCHPAD_ON } }, + { KE_KEY, 68, { KEY_TOUCHPAD_TOGGLE } }, { KE_KEY, 128, { KEY_ESC } }, /* @@ -1500,9 +1506,6 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_ unsigned char param; int ret; - if (!priv->features.touchpad_ctrl_via_ec) - return; - /* Without reading from EC touchpad LED doesn't switch state */ ret = read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value); if (ret) @@ -1518,9 +1521,20 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_ i8042_command(¶m, value ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE); if (send_events) { - ideapad_input_report(priv, value ? 67 : 66); - sysfs_notify(&priv->platform_device->dev.kobj, NULL, "touchpad"); + /* + * On older models the EC controls the touchpad and toggles it + * on/off itself, in this case we report KEY_TOUCHPAD_ON/_OFF. + * If the EC did not toggle, report KEY_TOUCHPAD_TOGGLE. + */ + if (value != priv->r_touchpad_val) { + ideapad_input_report(priv, value ? 67 : 66); + sysfs_notify(&priv->platform_device->dev.kobj, NULL, "touchpad"); + } else { + ideapad_input_report(priv, 68); + } } + + priv->r_touchpad_val = value; } static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data) |