4

Keymaps have a similar flow to the OSI model, though not nearly as well defined. I'm currently remapping at a higher level than I would like. Obviously Layer 1 corresponds to the physical keyboard and Layer 7 to the application, but I'm not sure how many other layers there are or where they fall in line.

If this were a desktop with a dedicated programmable physical keyboard, I'd be set, but alas, it's a laptop, and I need to maintain the remaps while using the built-in keyboard.

FWIW, I'm swapping the following pairs of keys: [Tilde/Esc], [Caps/LCtrl], [Back{space,slash}]. I also use Dvorak, but that's configured in the OS in the standard way.

Currently, I'm modifying /usr/share/X11/xkb/keycodes/evdev to make my changes in X (and creating a custom layout file for consoles, but that's not relevant here). I'm not sure where this falls in the "layer stack."

The issue: My keymap doesn't translate to Proxmox console sessions, which uses a web VNC client. (The layout also doesn't apply, but that's expected.) The issue is clearly that the VNC client is hooking the keyboard at a lower layer where the evdev remap isn't yet applied.

In Windows, I use a utility called KeyTweak to generate scancode maps for the registry, which seems to basically be "Layer 3." I've played games that apparently hooked the keyboard at "Layer 2," but that's barely an issue since there's very little typing in most games.

In conclusion, I'm not sure where evdev falls in my imaginary OSI keyboard model, but how can I remap at a lower layer? I have no need to swap out of the remap for any reason, so this change can basically be permanent. If I could do it in the BIOS I would.

Joe Fruchey
  • 201
  • 1
  • 4
  • There's some background in https://unix.stackexchange.com/questions/116629/how-do-keyboard-input-and-text-output-work/116630#116630, but I don't think it goes into enough detail to solve your problem. Your problem looks similar to https://unix.stackexchange.com/questions/188164/override-a-few-keycodes-with-xkb, but I think your solution is similar to the solution there. That solution remaps XKB keycodes and I thought this was the lowest layer that an X application could access. Is the VNC client running under X? Is it actually X and not e.g. Wayland? – Gilles 'SO- stop being evil' Oct 20 '21 at 12:59
  • 1
    A lower layer would be the kernel scancode/keycode mapping, which you can configure with setkeycodes. – Gilles 'SO- stop being evil' Oct 20 '21 at 13:00
  • The VNC client is a web-based component of Proxmox. I'm running it in Firefox. Yes, I'm on Xorg, not Wayland. And thanks for the suggestion on setkeycodes! I'm looking into that now. – Joe Fruchey Oct 20 '21 at 18:47
  • The browser is an important factor! It may be part of the problem or part of the solution. Do other browsers behave in the same way? – Gilles 'SO- stop being evil' Oct 20 '21 at 19:01
  • Just installed Chromium to test and yes, it does the same. According to a comment here, setkeycodes doesn't work on USB. On OpenSUSE Tumbleweed, the manpage is dated 8 Nov 1994 and mentions kernel 2.6! Currently looking into udev for a possible solution – Joe Fruchey Oct 20 '21 at 19:29

1 Answers1

6

The answer turned out to be udev. I basically followed this post, but the gist is:

  • Install evtest
  • Run evtest and press the keys you want to remap to see both the scancodes and keycodes.
  • Create a new file in /etc/udev/hwdb.d/ called something like 70-keyremap.hwdb with the contents below
    • I'm assuming the number is the order of the file, but I didn't have any existing files to base it off of, so I'm not sure what its prereqs are that it may need to have a higher number than. Actually, the hwdb.d dir didn't exist for me on Tumbleweed, so I had to create it, but it still worked.
  • Run systemd-hwdb update.
  • Reboot

_

# This is from the brokkr.net post I linked above
# Format can be found on [https://wiki.archlinux.org/title/Map_scancodes_to_keycodes].

$ cat 70-keymap.hwdb evdev:atkbd:dmi:bvn:bvr:bd:svn:pn:pvr KEYBOARD_KEY_01=41 # Remap Tilde to Esc KEYBOARD_KEY_29=01 # Remap Esc to Tilde (evtest showed "1" but when I put that without the leading zero, it was interpreted as the literal [1] key.) KEYBOARD_KEY_3A=29 # Remap Caps to LCtrl KEYBOARD_KEY_1D=58 # Remap LCtrl to Caps KEYBOARD_KEY_0E=43 # Remap Backspace to Backslash KEYBOARD_KEY_2B=14 # Remap Backslash to Backspace


Update: The above method worked great on my laptop, but when I docked it, external keyboards were still using the default keymap. Turns out this is because the internal keyboard is communicating using PS/2, which still uses the AT scancodes (atkbd in the device string), but USB is entirely different. I ended up having to run evtest again to grab the scancodes from a USB board and write another map. Here's my resulting file:

evdev:atkbd:dmi:*
 KEYBOARD_KEY_01=41
 KEYBOARD_KEY_29=01
 KEYBOARD_KEY_3A=29
 KEYBOARD_KEY_1D=58
 KEYBOARD_KEY_0E=43
 KEYBOARD_KEY_2B=14

evdev:input:b0003v* KEYBOARD_KEY_70029=41 KEYBOARD_KEY_70035=01 KEYBOARD_KEY_70039=29 KEYBOARD_KEY_700e0=58 KEYBOARD_KEY_7002a=43 KEYBOARD_KEY_70031=14

Joe Fruchey
  • 201
  • 1
  • 4
  • An archlinux link, the hwdb man page saying where files are found, and another blog by Peter Hutterer explaining what goes on. – meuh Oct 21 '21 at 07:06
  • There is also some explanation on the evdev: line matching mechanism in a comment at the top of file /lib/udev/hwdb.d/60-keyboard.hwdb, and some of the other files in that directory for mice and so on. Do not use the same filename as any of these files in your /etc/ version, or you will override the whole /lib version file. – meuh Oct 21 '21 at 07:28
  • @meuh This is fantastic info. Thanks!! – Joe Fruchey Oct 22 '21 at 13:37