Skip to content

Commit

Permalink
platform/x86: ideapad-laptop: Send KEY_TOUCHPAD_TOGGLE on some models
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jwrdegoede committed Nov 21, 2022
1 parent c69e7d8 commit 5829f8a
Showing 1 changed file with 19 additions and 5 deletions.
24 changes: 19 additions & 5 deletions drivers/platform/x86/ideapad-laptop.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand All @@ -669,6 +672,8 @@ static ssize_t touchpad_store(struct device *dev,
if (err)
return err;

priv->r_touchpad_val = state;

return count;
}

Expand Down Expand Up @@ -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 } },

/*
Expand Down Expand Up @@ -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)
Expand All @@ -1518,9 +1521,20 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_
i8042_command(&param, 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)
Expand Down

0 comments on commit 5829f8a

Please sign in to comment.