提交 aec256d0 编写于 作者: J Joao Moreno 提交者: Benjamin Tissoires

HID: apple: Fix stuck function keys when using FN

This fixes an issue in which key down events for function keys would be
repeatedly emitted even after the user has raised the physical key. For
example, the driver fails to emit the F5 key up event when going through
the following steps:
- fnmode=1: hold FN, hold F5, release FN, release F5
- fnmode=2: hold F5, hold FN, release F5, release FN

The repeated F5 key down events can be easily verified using xev.
Signed-off-by: NJoao Moreno <mail@joaomoreno.com>
Co-developed-by: NBenjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: NBenjamin Tissoires <benjamin.tissoires@redhat.com>
上级 15d90b24
...@@ -54,7 +54,6 @@ MODULE_PARM_DESC(swap_opt_cmd, "Swap the Option (\"Alt\") and Command (\"Flag\") ...@@ -54,7 +54,6 @@ MODULE_PARM_DESC(swap_opt_cmd, "Swap the Option (\"Alt\") and Command (\"Flag\")
struct apple_sc { struct apple_sc {
unsigned long quirks; unsigned long quirks;
unsigned int fn_on; unsigned int fn_on;
DECLARE_BITMAP(pressed_fn, KEY_CNT);
DECLARE_BITMAP(pressed_numlock, KEY_CNT); DECLARE_BITMAP(pressed_numlock, KEY_CNT);
}; };
...@@ -181,6 +180,8 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, ...@@ -181,6 +180,8 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
{ {
struct apple_sc *asc = hid_get_drvdata(hid); struct apple_sc *asc = hid_get_drvdata(hid);
const struct apple_key_translation *trans, *table; const struct apple_key_translation *trans, *table;
bool do_translate;
u16 code = 0;
if (usage->code == KEY_FN) { if (usage->code == KEY_FN) {
asc->fn_on = !!value; asc->fn_on = !!value;
...@@ -189,8 +190,6 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, ...@@ -189,8 +190,6 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
} }
if (fnmode) { if (fnmode) {
int do_translate;
if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI && if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI &&
hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS)
table = macbookair_fn_keys; table = macbookair_fn_keys;
...@@ -202,26 +201,34 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, ...@@ -202,26 +201,34 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
trans = apple_find_translation (table, usage->code); trans = apple_find_translation (table, usage->code);
if (trans) { if (trans) {
if (test_bit(usage->code, asc->pressed_fn)) if (test_bit(trans->from, input->key))
do_translate = 1; code = trans->from;
else if (trans->flags & APPLE_FLAG_FKEY) else if (test_bit(trans->to, input->key))
do_translate = (fnmode == 2 && asc->fn_on) || code = trans->to;
(fnmode == 1 && !asc->fn_on);
else if (!code) {
if (trans->flags & APPLE_FLAG_FKEY) {
switch (fnmode) {
case 1:
do_translate = !asc->fn_on;
break;
case 2:
do_translate = asc->fn_on; do_translate = asc->fn_on;
break;
default:
/* should never happen */
do_translate = false;
}
} else {
do_translate = asc->fn_on;
}
if (do_translate) { code = do_translate ? trans->to : trans->from;
if (value) }
set_bit(usage->code, asc->pressed_fn);
else
clear_bit(usage->code, asc->pressed_fn);
input_event(input, usage->type, trans->to,
value);
input_event(input, usage->type, code, value);
return 1; return 1;
} }
}
if (asc->quirks & APPLE_NUMLOCK_EMULATION && if (asc->quirks & APPLE_NUMLOCK_EMULATION &&
(test_bit(usage->code, asc->pressed_numlock) || (test_bit(usage->code, asc->pressed_numlock) ||
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册