Skip to content

Commit aacb455

Browse files
committed
platform/x86: panasonic-laptop: filter out duplicate volume up/down/mute keypresses
On some Panasonic models the volume up/down/mute keypresses get reported both through the Panasonic ACPI HKEY interface as well as through the atkbd device. Filter out the atkbd scan-codes for these to avoid reporting presses twice. Note normally we would leave the filtering of these to userspace by mapping the scan-codes to KEY_UNKNOWN through /lib/udev/hwdb.d/60-keyboard.hwdb. However in this case that would cause regressions since we were filtering the Panasonic ACPI HKEY events before, so filter these in the kernel. Fixes: ed83c91 ("platform/x86: panasonic-laptop: Resolve hotkey double trigger bug") Reported-and-tested-by: Stefan Seyfried <[email protected]> Reported-and-tested-by: Kenneth Chan <[email protected]> Signed-off-by: Hans de Goede <[email protected]> Reviewed-by: Andy Shevchenko <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 1f2c9de commit aacb455

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

drivers/platform/x86/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,7 @@ config PANASONIC_LAPTOP
946946
depends on INPUT && ACPI
947947
depends on BACKLIGHT_CLASS_DEVICE
948948
depends on ACPI_VIDEO=n || ACPI_VIDEO
949+
depends on SERIO_I8042 || SERIO_I8042 = n
949950
select INPUT_SPARSEKMAP
950951
help
951952
This driver adds support for access to backlight control and hotkeys

drivers/platform/x86/panasonic-laptop.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,15 @@
122122
#include <linux/acpi.h>
123123
#include <linux/backlight.h>
124124
#include <linux/ctype.h>
125+
#include <linux/i8042.h>
125126
#include <linux/init.h>
126127
#include <linux/input.h>
127128
#include <linux/input/sparse-keymap.h>
128129
#include <linux/kernel.h>
129130
#include <linux/module.h>
130131
#include <linux/platform_device.h>
131132
#include <linux/seq_file.h>
133+
#include <linux/serio.h>
132134
#include <linux/slab.h>
133135
#include <linux/types.h>
134136
#include <linux/uaccess.h>
@@ -241,6 +243,42 @@ struct pcc_acpi {
241243
struct platform_device *platform;
242244
};
243245

246+
/*
247+
* On some Panasonic models the volume up / down / mute keys send duplicate
248+
* keypress events over the PS/2 kbd interface, filter these out.
249+
*/
250+
static bool panasonic_i8042_filter(unsigned char data, unsigned char str,
251+
struct serio *port)
252+
{
253+
static bool extended;
254+
255+
if (str & I8042_STR_AUXDATA)
256+
return false;
257+
258+
if (data == 0xe0) {
259+
extended = true;
260+
return true;
261+
} else if (extended) {
262+
extended = false;
263+
264+
switch (data & 0x7f) {
265+
case 0x20: /* e0 20 / e0 a0, Volume Mute press / release */
266+
case 0x2e: /* e0 2e / e0 ae, Volume Down press / release */
267+
case 0x30: /* e0 30 / e0 b0, Volume Up press / release */
268+
return true;
269+
default:
270+
/*
271+
* Report the previously filtered e0 before continuing
272+
* with the next non-filtered byte.
273+
*/
274+
serio_interrupt(port, 0xe0, 0);
275+
return false;
276+
}
277+
}
278+
279+
return false;
280+
}
281+
244282
/* method access functions */
245283
static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val)
246284
{
@@ -1006,6 +1044,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
10061044
pcc->platform = NULL;
10071045
}
10081046

1047+
i8042_install_filter(panasonic_i8042_filter);
10091048
return 0;
10101049

10111050
out_platform:
@@ -1029,6 +1068,8 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device)
10291068
if (!device || !pcc)
10301069
return -EINVAL;
10311070

1071+
i8042_remove_filter(panasonic_i8042_filter);
1072+
10321073
if (pcc->platform) {
10331074
device_remove_file(&pcc->platform->dev, &dev_attr_cdpower);
10341075
platform_device_unregister(pcc->platform);

0 commit comments

Comments
 (0)