free5lot / hid-apple-patched

Allows to swap the Fn key and left Control key and other tweaks on Macbook Pro and Apple keyboards in GNU/Linux
GNU General Public License v2.0
349 stars 61 forks source link

How does key mapping work exactly? #61

Closed a3desu closed 4 years ago

a3desu commented 4 years ago

Hi! I'm using Oklick 840S Wireless Keyboard: external-content duckduckgo com

It connected over bluetooth and here is dmesg part:

[ 2643.114442] input: Bluetooth Keyboard as /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4
/1-1.4:1.0/bluetooth/hci0/hci0:70/0005:05AC:0239.000A/input/input11
[ 2643.115475] apple 0005:05AC:0239.000A: input,hidraw2: BLUETOOTH HID v1.1b Keyboard [Bluetooth Keyboard] on 00:1a:7d:da:71:13

So it uses this driver. I had some problems with getting fn key working and now it behave like that:

  1. When fn_mode==0 || fn_mode==2, fn key works as default
  2. When fn_mode==1 function keys did not work at all

I have patched driver to log some events like this:

diff --git a/hid-apple.c b/hid-apple.c
index 843f111..f902dd6 100644
--- a/hid-apple.c
+++ b/hid-apple.c
@@ -222,6 +222,7 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
                return 1;
        }

+       printk(KERN_INFO "KBD: fnmode=%d, code=%d\n", fnmode, usage->code);
        if (fnmode) {
                int do_translate;

@@ -236,6 +237,9 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
                trans = apple_find_translation (table, usage->code);

                if (trans) {
+                       printk(KERN_INFO "KBD: trans\n");
+
+
                        if (test_bit(usage->code, asc->pressed_fn))
                                do_translate = 1;
                        else if (trans->flags & APPLE_FLAG_FKEY)
@@ -245,6 +249,7 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
                                do_translate = asc->fn_on;

                        if (do_translate) {
+                               printk(KERN_INFO "KBD: do_trans\n");
                                if (value)
                                        set_bit(usage->code, asc->pressed_fn);
                                else

And got this: Here when I press F1, fn_mode==2

Mar 20 20:14:29 pi4 kernel: [ 7371.909785] KBD: fnmode=2, code=172
Mar 20 20:14:29 pi4 kernel: [ 7371.909801] KBD: fnmode=2, code=217
Mar 20 20:14:29 pi4 kernel: [ 7371.909827] KBD: fnmode=2, code=155
Mar 20 20:14:29 pi4 kernel: [ 7371.909839] KBD: fnmode=2, code=128
Mar 20 20:14:29 pi4 kernel: [ 7371.909848] KBD: fnmode=2, code=165
Mar 20 20:14:29 pi4 kernel: [ 7371.909858] KBD: fnmode=2, code=164
Mar 20 20:14:29 pi4 kernel: [ 7371.909868] KBD: fnmode=2, code=163
Mar 20 20:14:29 pi4 kernel: [ 7371.909877] KBD: fnmode=2, code=113
Mar 20 20:14:29 pi4 kernel: [ 7371.909887] KBD: fnmode=2, code=114
Mar 20 20:14:29 pi4 kernel: [ 7371.909896] KBD: fnmode=2, code=115
Mar 20 20:14:29 pi4 kernel: [ 7371.909906] KBD: fnmode=2, code=144
Mar 20 20:14:29 pi4 kernel: [ 7371.909915] KBD: fnmode=2, code=140
Mar 20 20:14:29 pi4 kernel: [ 7371.909926] KBD: fnmode=2, code=158
Mar 20 20:14:29 pi4 kernel: [ 7371.909935] KBD: fnmode=2, code=159
Mar 20 20:14:29 pi4 kernel: [ 7371.909945] KBD: fnmode=2, code=156
Mar 20 20:14:29 pi4 kernel: [ 7371.909954] KBD: fnmode=2, code=173
Mar 20 20:14:29 pi4 kernel: [ 7371.909964] KBD: fnmode=2, code=171
Mar 20 20:14:29 pi4 kernel: [ 7371.909974] KBD: fnmode=2, code=161
Mar 20 20:14:29 pi4 kernel: [ 7371.909983] KBD: fnmode=2, code=581
Mar 20 20:14:29 pi4 kernel: [ 7371.909993] KBD: fnmode=2, code=116
Mar 20 20:14:29 pi4 kernel: [ 7371.910002] KBD: fnmode=2, code=405
Mar 20 20:14:29 pi4 kernel: [ 7371.910960] KBD: fnmode=2, code=172
Mar 20 20:14:29 pi4 kernel: [ 7371.910972] KBD: fnmode=2, code=217
Mar 20 20:14:29 pi4 kernel: [ 7371.910990] KBD: fnmode=2, code=155
Mar 20 20:14:29 pi4 kernel: [ 7371.911000] KBD: fnmode=2, code=128
Mar 20 20:14:29 pi4 kernel: [ 7371.911011] KBD: fnmode=2, code=165
Mar 20 20:14:29 pi4 kernel: [ 7371.911021] KBD: fnmode=2, code=164
Mar 20 20:14:29 pi4 kernel: [ 7371.911030] KBD: fnmode=2, code=163
Mar 20 20:14:29 pi4 kernel: [ 7371.911040] KBD: fnmode=2, code=113
Mar 20 20:14:29 pi4 kernel: [ 7371.911050] KBD: fnmode=2, code=114
Mar 20 20:14:29 pi4 kernel: [ 7371.911059] KBD: fnmode=2, code=115
Mar 20 20:14:29 pi4 kernel: [ 7371.911069] KBD: fnmode=2, code=144
Mar 20 20:14:29 pi4 kernel: [ 7371.911078] KBD: fnmode=2, code=140
Mar 20 20:14:29 pi4 kernel: [ 7371.911088] KBD: fnmode=2, code=158
Mar 20 20:14:29 pi4 kernel: [ 7371.911100] KBD: fnmode=2, code=159
Mar 20 20:14:29 pi4 kernel: [ 7371.911109] KBD: fnmode=2, code=156
Mar 20 20:14:29 pi4 kernel: [ 7371.911120] KBD: fnmode=2, code=173
Mar 20 20:14:29 pi4 kernel: [ 7371.911130] KBD: fnmode=2, code=171
Mar 20 20:14:29 pi4 kernel: [ 7371.911140] KBD: fnmode=2, code=161
Mar 20 20:14:29 pi4 kernel: [ 7371.911150] KBD: fnmode=2, code=581
Mar 20 20:14:29 pi4 kernel: [ 7371.911159] KBD: fnmode=2, code=116
Mar 20 20:14:29 pi4 kernel: [ 7371.911170] KBD: fnmode=2, code=405

And here fn+F1, fn_mode==2:

Mar 20 20:15:35 pi4 kernel: [ 7438.237137] KBD: fnmode=2, code=29
Mar 20 20:15:35 pi4 kernel: [ 7438.237151] KBD: fnmode=2, code=42
Mar 20 20:15:35 pi4 kernel: [ 7438.237162] KBD: fnmode=2, code=56
Mar 20 20:15:35 pi4 kernel: [ 7438.237172] KBD: fnmode=2, code=125
Mar 20 20:15:35 pi4 kernel: [ 7438.237182] KBD: fnmode=2, code=97
Mar 20 20:15:35 pi4 kernel: [ 7438.237193] KBD: fnmode=2, code=54
Mar 20 20:15:35 pi4 kernel: [ 7438.237203] KBD: fnmode=2, code=100
Mar 20 20:15:35 pi4 kernel: [ 7438.237213] KBD: fnmode=2, code=126
Mar 20 20:15:35 pi4 kernel: [ 7438.237225] KBD: fnmode=2, code=59
Mar 20 20:15:35 pi4 kernel: [ 7438.237234] KBD: trans
Mar 20 20:15:36 pi4 kernel: [ 7438.387096] KBD: fnmode=2, code=29
Mar 20 20:15:36 pi4 kernel: [ 7438.387106] KBD: fnmode=2, code=42
Mar 20 20:15:36 pi4 kernel: [ 7438.387113] KBD: fnmode=2, code=56
Mar 20 20:15:36 pi4 kernel: [ 7438.387119] KBD: fnmode=2, code=125
Mar 20 20:15:36 pi4 kernel: [ 7438.387125] KBD: fnmode=2, code=97
Mar 20 20:15:36 pi4 kernel: [ 7438.387131] KBD: fnmode=2, code=54
Mar 20 20:15:36 pi4 kernel: [ 7438.387137] KBD: fnmode=2, code=100
Mar 20 20:15:36 pi4 kernel: [ 7438.387142] KBD: fnmode=2, code=126
Mar 20 20:15:36 pi4 kernel: [ 7438.387151] KBD: fnmode=2, code=59
Mar 20 20:15:36 pi4 kernel: [ 7438.387156] KBD: trans

At this point I have F1 key input just as planned.

If I set fn_mode to 1, then fn+F1 gets me to this:

Mar 20 20:17:25 pi4 kernel: [ 7547.890980] KBD: fnmode=1, code=29
Mar 20 20:17:25 pi4 kernel: [ 7547.890995] KBD: fnmode=1, code=42
Mar 20 20:17:25 pi4 kernel: [ 7547.891006] KBD: fnmode=1, code=56
Mar 20 20:17:25 pi4 kernel: [ 7547.891016] KBD: fnmode=1, code=125
Mar 20 20:17:25 pi4 kernel: [ 7547.891026] KBD: fnmode=1, code=97
Mar 20 20:17:25 pi4 kernel: [ 7547.891036] KBD: fnmode=1, code=54
Mar 20 20:17:25 pi4 kernel: [ 7547.891046] KBD: fnmode=1, code=100
Mar 20 20:17:25 pi4 kernel: [ 7547.891056] KBD: fnmode=1, code=126
Mar 20 20:17:25 pi4 kernel: [ 7547.891069] KBD: fnmode=1, code=59
Mar 20 20:17:25 pi4 kernel: [ 7547.891077] KBD: trans
Mar 20 20:17:25 pi4 kernel: [ 7547.891086] KBD: do_trans
Mar 20 20:17:25 pi4 kernel: [ 7547.990972] KBD: fnmode=1, code=29
Mar 20 20:17:25 pi4 kernel: [ 7547.990989] KBD: fnmode=1, code=42
Mar 20 20:17:25 pi4 kernel: [ 7547.990999] KBD: fnmode=1, code=56
Mar 20 20:17:25 pi4 kernel: [ 7547.991009] KBD: fnmode=1, code=125
Mar 20 20:17:25 pi4 kernel: [ 7547.991019] KBD: fnmode=1, code=97
Mar 20 20:17:25 pi4 kernel: [ 7547.991029] KBD: fnmode=1, code=54
Mar 20 20:17:25 pi4 kernel: [ 7547.991039] KBD: fnmode=1, code=100
Mar 20 20:17:25 pi4 kernel: [ 7547.991048] KBD: fnmode=1, code=126
Mar 20 20:17:25 pi4 kernel: [ 7547.991061] KBD: fnmode=1, code=59
Mar 20 20:17:25 pi4 kernel: [ 7547.991070] KBD: trans
Mar 20 20:17:25 pi4 kernel: [ 7547.991078] KBD: do_trans

So it actually translated but i did not get F1 key input to the system at this point.

Also I noticed that FN key had no event on this keyboard. Looks like it kind of integrated in hardware. So fn_mode did not help in this case at all!

I want to make fn keys work by default and it looks like I need special translation table specially for my keyboard but I cant understand exactly why I get so many events and how to handle them properly.

F1 key sends a lot of events, twice. As I understand one is for press and one for depressing of the key.

Is it normal that this driver looks for each code in translation table? For example in this case:

Mar 20 20:17:25 pi4 kernel: [ 7547.990972] KBD: fnmode=1, code=29
Mar 20 20:17:25 pi4 kernel: [ 7547.990989] KBD: fnmode=1, code=42
Mar 20 20:17:25 pi4 kernel: [ 7547.990999] KBD: fnmode=1, code=56
Mar 20 20:17:25 pi4 kernel: [ 7547.991009] KBD: fnmode=1, code=125
Mar 20 20:17:25 pi4 kernel: [ 7547.991019] KBD: fnmode=1, code=97
Mar 20 20:17:25 pi4 kernel: [ 7547.991029] KBD: fnmode=1, code=54
Mar 20 20:17:25 pi4 kernel: [ 7547.991039] KBD: fnmode=1, code=100
Mar 20 20:17:25 pi4 kernel: [ 7547.991048] KBD: fnmode=1, code=126
Mar 20 20:17:25 pi4 kernel: [ 7547.991061] KBD: fnmode=1, code=59

Only last code matched but what with others? Is this actual pressed keys? I think this is like a HID message but in this driver each of the codes checked for existence in translation table.

free5lot commented 4 years ago

Well, technically it's quite possible that there is physical limitation as you mentioned. E.g. with external apple keyboard we had similar situation when combination Fn(Ctrl)+Shift+T was not passed to kernel at all (look issues #6 #46). This situation was considered unsolvable on software level.

free5lot commented 4 years ago

Currently the issue is being closed as it's not directly related to apple keyboards, but one may feel free to add comments or discussions about Oklick keyboards here if they please.