| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * USB HID quirks support for Linux |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 9 | 10 | */ |
|---|
| 10 | 11 | |
|---|
| 11 | 12 | /* |
|---|
| 12 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 13 | | - * under the terms of the GNU General Public License as published by the Free |
|---|
| 14 | | - * Software Foundation; either version 2 of the License, or (at your option) |
|---|
| 15 | | - * any later version. |
|---|
| 16 | 13 | */ |
|---|
| 17 | 14 | |
|---|
| 18 | 15 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| .. | .. |
|---|
| 53 | 50 | MODULE_PARM_DESC(swap_opt_cmd, "Swap the Option (\"Alt\") and Command (\"Flag\") keys. " |
|---|
| 54 | 51 | "(For people who want to keep Windows PC keyboard muscle memory. " |
|---|
| 55 | 52 | "[0] = as-is, Mac layout. 1 = swapped, Windows layout.)"); |
|---|
| 53 | + |
|---|
| 54 | +static unsigned int swap_fn_leftctrl; |
|---|
| 55 | +module_param(swap_fn_leftctrl, uint, 0644); |
|---|
| 56 | +MODULE_PARM_DESC(swap_fn_leftctrl, "Swap the Fn and left Control keys. " |
|---|
| 57 | + "(For people who want to keep PC keyboard muscle memory. " |
|---|
| 58 | + "[0] = as-is, Mac layout, 1 = swapped, PC layout)"); |
|---|
| 56 | 59 | |
|---|
| 57 | 60 | struct apple_sc { |
|---|
| 58 | 61 | unsigned long quirks; |
|---|
| .. | .. |
|---|
| 166 | 169 | { } |
|---|
| 167 | 170 | }; |
|---|
| 168 | 171 | |
|---|
| 172 | +static const struct apple_key_translation swapped_fn_leftctrl_keys[] = { |
|---|
| 173 | + { KEY_FN, KEY_LEFTCTRL }, |
|---|
| 174 | + { } |
|---|
| 175 | +}; |
|---|
| 176 | + |
|---|
| 169 | 177 | static const struct apple_key_translation *apple_find_translation( |
|---|
| 170 | 178 | const struct apple_key_translation *table, u16 from) |
|---|
| 171 | 179 | { |
|---|
| .. | .. |
|---|
| 187 | 195 | bool do_translate; |
|---|
| 188 | 196 | u16 code = 0; |
|---|
| 189 | 197 | |
|---|
| 190 | | - if (usage->code == KEY_FN) { |
|---|
| 198 | + u16 fn_keycode = (swap_fn_leftctrl) ? (KEY_LEFTCTRL) : (KEY_FN); |
|---|
| 199 | + |
|---|
| 200 | + if (usage->code == fn_keycode) { |
|---|
| 191 | 201 | asc->fn_on = !!value; |
|---|
| 192 | | - input_event(input, usage->type, usage->code, value); |
|---|
| 202 | + input_event(input, usage->type, KEY_FN, value); |
|---|
| 193 | 203 | return 1; |
|---|
| 194 | 204 | } |
|---|
| 195 | 205 | |
|---|
| .. | .. |
|---|
| 274 | 284 | } |
|---|
| 275 | 285 | } |
|---|
| 276 | 286 | |
|---|
| 287 | + if (swap_fn_leftctrl) { |
|---|
| 288 | + trans = apple_find_translation(swapped_fn_leftctrl_keys, usage->code); |
|---|
| 289 | + if (trans) { |
|---|
| 290 | + input_event(input, usage->type, trans->to, value); |
|---|
| 291 | + return 1; |
|---|
| 292 | + } |
|---|
| 293 | + } |
|---|
| 294 | + |
|---|
| 277 | 295 | return 0; |
|---|
| 278 | 296 | } |
|---|
| 279 | 297 | |
|---|
| .. | .. |
|---|
| 344 | 362 | |
|---|
| 345 | 363 | for (trans = apple_iso_keyboard; trans->from; trans++) |
|---|
| 346 | 364 | set_bit(trans->to, input->keybit); |
|---|
| 365 | + |
|---|
| 366 | + if (swap_fn_leftctrl) { |
|---|
| 367 | + for (trans = swapped_fn_leftctrl_keys; trans->from; trans++) |
|---|
| 368 | + set_bit(trans->to, input->keybit); |
|---|
| 369 | + } |
|---|
| 347 | 370 | } |
|---|
| 348 | 371 | |
|---|
| 349 | 372 | static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi, |
|---|
| .. | .. |
|---|
| 487 | 510 | .driver_data = APPLE_HAS_FN }, |
|---|
| 488 | 511 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO), |
|---|
| 489 | 512 | .driver_data = APPLE_HAS_FN }, |
|---|
| 513 | + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO), |
|---|
| 514 | + .driver_data = APPLE_HAS_FN }, |
|---|
| 490 | 515 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS), |
|---|
| 491 | 516 | .driver_data = APPLE_HAS_FN }, |
|---|
| 492 | 517 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI), |
|---|