Skip to content

Commit aec256d

Browse files
joaomorenobentiss
authored andcommitted
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: Joao Moreno <[email protected]> Co-developed-by: Benjamin Tissoires <[email protected]> Signed-off-by: Benjamin Tissoires <[email protected]>
1 parent 15d90b2 commit aec256d

File tree

1 file changed

+28
-21
lines changed

1 file changed

+28
-21
lines changed

drivers/hid/hid-apple.c

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ MODULE_PARM_DESC(swap_opt_cmd, "Swap the Option (\"Alt\") and Command (\"Flag\")
5454
struct apple_sc {
5555
unsigned long quirks;
5656
unsigned int fn_on;
57-
DECLARE_BITMAP(pressed_fn, KEY_CNT);
5857
DECLARE_BITMAP(pressed_numlock, KEY_CNT);
5958
};
6059

@@ -181,6 +180,8 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
181180
{
182181
struct apple_sc *asc = hid_get_drvdata(hid);
183182
const struct apple_key_translation *trans, *table;
183+
bool do_translate;
184+
u16 code = 0;
184185

185186
if (usage->code == KEY_FN) {
186187
asc->fn_on = !!value;
@@ -189,8 +190,6 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
189190
}
190191

191192
if (fnmode) {
192-
int do_translate;
193-
194193
if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI &&
195194
hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS)
196195
table = macbookair_fn_keys;
@@ -202,25 +201,33 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
202201
trans = apple_find_translation (table, usage->code);
203202

204203
if (trans) {
205-
if (test_bit(usage->code, asc->pressed_fn))
206-
do_translate = 1;
207-
else if (trans->flags & APPLE_FLAG_FKEY)
208-
do_translate = (fnmode == 2 && asc->fn_on) ||
209-
(fnmode == 1 && !asc->fn_on);
210-
else
211-
do_translate = asc->fn_on;
212-
213-
if (do_translate) {
214-
if (value)
215-
set_bit(usage->code, asc->pressed_fn);
216-
else
217-
clear_bit(usage->code, asc->pressed_fn);
218-
219-
input_event(input, usage->type, trans->to,
220-
value);
221-
222-
return 1;
204+
if (test_bit(trans->from, input->key))
205+
code = trans->from;
206+
else if (test_bit(trans->to, input->key))
207+
code = trans->to;
208+
209+
if (!code) {
210+
if (trans->flags & APPLE_FLAG_FKEY) {
211+
switch (fnmode) {
212+
case 1:
213+
do_translate = !asc->fn_on;
214+
break;
215+
case 2:
216+
do_translate = asc->fn_on;
217+
break;
218+
default:
219+
/* should never happen */
220+
do_translate = false;
221+
}
222+
} else {
223+
do_translate = asc->fn_on;
224+
}
225+
226+
code = do_translate ? trans->to : trans->from;
223227
}
228+
229+
input_event(input, usage->type, code, value);
230+
return 1;
224231
}
225232

226233
if (asc->quirks & APPLE_NUMLOCK_EMULATION &&

0 commit comments

Comments
 (0)