Services.evdevremapkeys.settings and YAML in configuration.nix

I am trying to configure services.evdevremapkeys.settings which appear to expect a "YAML value’

I have looked at the examples from what appears to be the source in github, searched, queried and tried out dozens of configurations, so far to no avail.

The following config snippet from configuration.nix rebuilds ok but the service fails to start. I have also attached journalctl output below.

I assumed I should be able to find a file somewhere with the config the evdevremapkeys expects to see what was being produced but couldn’t find this.

I have seen mentions that remappings should be mappings but this seemed to make no difference.

Can anyone assist with what the structure of the config should be please or some pointers to where this is documented?

From configuration.nix

services = {
	evdevremapkeys = {
		enable = true;
		settings = {
			devices = [
				{
					input_name = "AT Translated Set 2 keyboard";
					input_fn = "/dev/input/event0";
					output_name = "AT Translated Set 2 keyboard remapped";
					remappings = {
						KEY_LEFTALT = "KEY_A";
					};
				}
			];
		};
	};
};

From journalctl

May 24 07:59:40 d systemd[1]: evdevremapkeys.service: Main process exited, code=exited, status=1/FAILURE
May 24 07:59:40 d evdevremapkeys[24690]: KeyError: ‘K’
May 24 07:59:40 d evdevremapkeys[24690]: ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
May 24 07:59:40 d evdevremapkeys[24690]: mapping[‘code’] = ecodes.ecodes[mapping[‘code’]]
May 24 07:59:40 d evdevremapkeys[24690]: File "/nix/store/65h8ql6gi82v91c0xxpzc9jykwxw963f-python3.11-evdevremapkeys-unstable-2021-05-04/lib/python3.11/site-packages/evdevremapkeys/evdevremapkey>
May 24 07:59:40 d evdevremapkeys[24690]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
May 24 07:59:40 d evdevremapkeys[24690]: return {ecodes.ecodes[key]: list(map(resolve_mapping, mappings))
May 24 07:59:40 d evdevremapkeys[24690]: File "/nix/store/65h8ql6gi82v91c0xxpzc9jykwxw963f-python3.11-evdevremapkeys-unstable-2021-05-04/lib/python3.11/site-packages/evdevremapkeys/evdevremapkey>
May 24 07:59:40 d evdevremapkeys[24690]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
May 24 07:59:40 d evdevremapkeys[24690]: return {ecodes.ecodes[key]: list(map(resolve_mapping, mappings))
May 24 07:59:40 d evdevremapkeys[24690]: File "/nix/store/65h8ql6gi82v91c0xxpzc9jykwxw963f-python3.11-evdevremapkeys-unstable-2021-05-04/lib/python3.11/site-packages/evdevremapkeys/evdevremapkey>
May 24 07:59:40 d evdevremapkeys[24690]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
May 24 07:59:40 d evdevremapkeys[24690]: device[‘remappings’] = resolve_ecodes(device[‘remappings’])
May 24 07:59:40 d evdevremapkeys[24690]: File "/nix/store/65h8ql6gi82v91c0xxpzc9jykwxw963f-python3.11-evdevremapkeys-unstable-2021-05-04/lib/python3.11/site-packages/evdevremapkeys/evdevremapkey>
May 24 07:59:40 d evdevremapkeys[24690]: ^^^^^^^^^^^^^^^^^^^^
May 24 07:59:40 d evdevremapkeys[24690]: return parse_config(config)
May 24 07:59:40 d evdevremapkeys[24690]: File "/nix/store/65h8ql6gi82v91c0xxpzc9jykwxw963f-python3.11-evdevremapkeys-unstable-2021-05-04/lib/python3.11/site-packages/evdevremapkeys/evdevremapkey>
May 24 07:59:40 d evdevremapkeys[24690]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
May 24 07:59:40 d evdevremapkeys[24690]: config = load_config(args.config_file)
May 24 07:59:40 d evdevremapkeys[24690]: File "/nix/store/65h8ql6gi82v91c0xxpzc9jykwxw963f-python3.11-evdevremapkeys-unstable-2021-05-04/lib/python3.11/site-packages/evdevremapkeys/evdevremapkey>
May 24 07:59:40 d evdevremapkeys[24690]: run_loop(args)
May 24 07:59:40 d evdevremapkeys[24690]: File "/nix/store/65h8ql6gi82v91c0xxpzc9jykwxw963f-python3.11-evdevremapkeys-unstable-2021-05-04/lib/python3.11/site-packages/evdevremapkeys/evdevremapkey>
May 24 07:59:40 d evdevremapkeys[24690]: ^^^^^^
May 24 07:59:40 d evdevremapkeys[24690]: sys.exit(main())
May 24 07:59:40 d evdevremapkeys[24690]: File “/nix/store/65h8ql6gi82v91c0xxpzc9jykwxw963f-python3.11-evdevremapkeys-unstable-2021-05-04/bin/.evdevremapkeys-wrapped”, line 9, in
May 24 07:59:40 d evdevremapkeys[24690]: Traceback (most recent call last):
May 24 07:59:40 d systemd[1]: Started evdevremapkeys.

I converted the example evdevremapkeys config file from YAML → JSON → Nix and this is the result:

Config (Nix)
  settings = {
    devices = [
      {
        input_name = "Kingsis Peripherals Evoluent VerticalMouse 4";
        output_name = "remap-mouse";
        remappings = {
          BTN_EXTRA = [
            "KEY_LEFTMETA"
            "KEY_Z"
          ];
          BTN_FORWARD = [
            "KEY_LEFTMETA"
            "KEY_W"
          ];
          BTN_MIDDLE = [ "BTN_RIGHT" ];
          BTN_RIGHT = [
            "KEY_LEFTMETA"
            "KEY_A"
          ];
          BTN_SIDE = [ "BTN_MIDDLE" ];
        };
      }
      {
        input_name = "KINESIS FREESTYLE KB800 KB800 Kine
sis Freestyle";
        input_phys = "usb-0000:00:14.0-3.3/input0";
        output_name = "remap-kbd";
        remappings = {
          KEY_CAPSLOCK = [ "KEY_LEFTCTRL" ];
          KEY_LEFTCTRL = [ "KEY_CAPSLOCK" ];
        };
      }
    ];
  };

Here is also the advanced config in Nix, as a plus:

Advanced config (Nix)
  settings = {
    devices = [
      {
        input_fn = "/dev/input/event7";
        input_name = "Compx 2.4G Receiver";
        output_name = "remap-mouse";
        remappings = {
          BTN_EXTRA = [
            {
              code = "REL_WHEEL";
              rate = 0.3;
              repeat = true;
              type = "EV_REL";
              value = 1;
            }
          ];
          BTN_RIGHT = [
            {
              code = "BTN_LEFT";
              count = 2;
              repeat = true;
              value = [
                1
                0
              ];
            }
          ];
          BTN_SIDE = [
            {
              code = "REL_WHEEL";
              repeat = true;
              type = "EV_REL";
              value = -1;
            }
          ];
          REL_WHEEL = [
            {
              code = "BTN_RIGHT";
              count = 4;
              delay = true;
            }
          ];
        };
      }
      {
        input_fn = "/dev/input/event4";
        input_name = "AT Translated Set 2 keyboard";
        output_name = "remap-kbd";
        remappings = {
          KEY_LEFTALT = [
            {
              code = "KEY_A";
              repeat = true;
              value = [
                1
                0
                1
                0
              ];
            }
          ];
          KEY_LEFTSHIFT = [
            {
              code = "KEY_A";
              count = 6;
              repeat = true;
              value = [
                1
                0
              ];
            }
          ];
          KEY_RIGHTSHIFT = [
            {
              code = "KEY_A";
              count = 3;
              repeat = true;
              value = [
                1
                0
                1
                0
              ];
            }
          ];
        };
      }
    ];
  };

From this, we can see that keys should be written in lists for it to work correctly:

	remappings = {
-	  KEY_LEFTALT = "KEY_A";
+	  KEY_LEFTALT = [ "KEY_A" ];
	};

Alternatively, you can convert the config from YAML to JSON and import the file with:

  services = {
    evdevremapkeys = {
      enable = true;
      settings = lib.importJSON ./path/to/config.json;
    };
  };

We have to convert to JSON because currently there isn’t any function that imports YAML, unless you do something like this:

1 Like

Thanks for this. I was close (IMHO! :rofl:) I had tried putting the keys in a list but I had put both sides! :frowning:

So, have confirmed the examples work, I tried to remap a keycode 255 / XF86RFKill and was rewarded with an error that my input option appears to not be in . So now hunting for the list of acceptable keycodes.

1 Like

You’ve done a great job indeed :grin:

If you want a list of all the keycodes, you should check out the input-event-codes.h file, which you can find in the following locations, depending on your kernel:

$ nix-locate input-event-codes.h | grep "^linuxKernel.kernels."
linuxKernel.kernels.linux_latest_libre.dev       30,015 r /nix/store/11dxary43rbjk2zmg3zxpn0s21sn24p5-linux-6.8.9-dev/lib/modules/6.8.9-gnu/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_xanmod.dev             30,015 r /nix/store/xjvcx7srv7f2myi7vdz4znf86nsc1fs4-linux-6.6.30-dev/lib/modules/6.6.30-xanmod1/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_hardened.dev           29,943 r /nix/store/m61py17l08p3h025hjy1g8avkrwaga1d-linux-6.6.21-dev/lib/modules/6.6.21-hardened1/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_rt_5_15.dev            28,767 r /nix/store/s8m7ml69h9f5wcdb9xhqfq754qba4lr8-linux-5.15.153-rt75-dev/lib/modules/5.15.153-rt75/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_5_15.dev               28,839 r /nix/store/ka7qirbisbq5g1p0p8pzqgw49ak6nh2s-linux-5.15.158-dev/lib/modules/5.15.158/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_5_10_hardened.dev      28,767 r /nix/store/kycdn9s0jdjvl0civs288nbqddlwjv4b-linux-5.10.212-dev/lib/modules/5.10.212-hardened1/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_6_8.dev                30,015 r /nix/store/l88l8sfks132lqp8q3zdmm864q3hbv9k-linux-6.8.9-dev/lib/modules/6.8.9/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_testing.dev            30,015 r /nix/store/46d1nzj0nd65pjsjphdbfrcdb6v6xf04-linux-6.9-rc6-dev/lib/modules/6.9.0-rc6/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_xanmod_latest.dev      30,015 r /nix/store/n0bqm8b8988mljgr9888iymwcpw6axmd-linux-6.8.9-dev/lib/modules/6.8.9-xanmod1/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_rt_6_1.dev             29,626 r /nix/store/10ipmdawc6yacw9qprnhc4qbqbwlbhbr-linux-6.1.83-rt28-dev/lib/modules/6.1.83-rt28/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_6_1_hardened.dev       29,626 r /nix/store/gv7n1zhk9najb806an2x7cn6n511w04m-linux-6.1.81-dev/lib/modules/6.1.81-hardened1/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_5_15_hardened.dev      28,767 r /nix/store/gww9l8gd6f77sf4fpx7kns5dqj86kiax-linux-5.15.151-dev/lib/modules/5.15.151-hardened1/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_5_4.dev                25,578 r /nix/store/ml64ciwl2ypf29m2n396wv96159vg4f3-linux-5.4.275-dev/lib/modules/5.4.275/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_5_4_hardened.dev       25,506 r /nix/store/yhp7simxvxh2vs1dx154jnvxk3hl2r73-linux-5.4.271-dev/lib/modules/5.4.271-hardened1/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_4_19_hardened.dev      24,768 r /nix/store/j31hra8axzvpjb55n6xs81k2023sln0s-linux-4.19.309-dev/lib/modules/4.19.309-hardened1/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_6_1.dev                29,698 r /nix/store/j0f5gxj58h03g1y8pf8gbm719bqla5b3-linux-6.1.90-dev/lib/modules/6.1.90/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_zen.dev                30,015 r /nix/store/svbm9bqyr9sahwvg4d3vjnaalplzmndh-linux-6.8.6-dev/lib/modules/6.8.6-zen1/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_4_19.dev               24,840 r /nix/store/0q5cpplaf5nyg3d3ihpg5byfr88wcif9-linux-4.19.313-dev/lib/modules/4.19.313/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_5_10.dev               28,839 r /nix/store/53pglfhavwqn14rq2m4mpvzdbqjgm0ys-linux-5.10.216-dev/lib/modules/5.10.216/source/include/uapi/linux/input-event-codes.h
linuxKernel.kernels.linux_rt_5_10.dev            28,839 r /nix/store/1l50nisybd4p7jixn3n4h7ilbx7f067n-linux-5.10.215-rt107-dev/lib/modules/5.10.215-rt107/source/include/uapi/linux/input-event-codes.h
1 Like

Thanks for the pointer! That’s a useful reference. I need to work out or understand how to find these type of details inside *nix. When I have some free time I am hoping to have a crack at Linux-from-scratch to try and fill in some gaps in my knowledge.

I found three related comments in input-event-codes.h…

#define KEY_RFKILL 247 /* Key that controls all radios */

KEY_RFKILL - I had tried this previously but it doesn’t work.

/* Code 255 is reserved for special needs of AT keyboard driver */

Interesting comment as 255 is the keycode that ‘xev’ returns when I press Fn+F11 which is redirected to XF86RFKill (code 247).

#define KEY_FN_F11 0x1dc

KEY_FN_F11 - I tried this too, but no joy.

Not exactly sure why this one key combo on my laptop is giving me such grief. :thinking:

Given that ‘xev’ sees the key press you think I’d be able to get at somehow but all methods I have tried so far have failed.

How curious… I’ve tried to run xev but it didn’t give me keycodes for FN combinations, so I used showkey instead:

$ nix-shell -p kbd
$ sudo showkey -k
keycode 247 press
keycode 247 release

When I toggle the airplane mode on my keyboard (FN+F8) it shows me that its keycode is 247.

Edit: However, xmodmap tells me that it’s 255 :thinking:

$ nix-shell -p xorg.xmodmap --run "xmodmap -pk" | grep XF86RFKill
    255         0x1008ffb5 (XF86RFKill) 0x0000 (NoSymbol)       0x1008ffb5 (XF86RFKill) 0x0000 (NoSymbol)       0x1008ffb5 (XF86RFKill) 0x1008ffb5 (XF86RFKill)

PS: I got the tip about the keycode list from makima, which is another key-mapping program that I’ve discovered a while ago. You might want to give that a try and see if that works for you.

1 Like

showkey -k also returns keycode 247 press/release for me which I press Fn+F11. showkey -s (scancodes) returns nothing for Fn+F11.

xev returns;

state 0x11, keycode 255 (keysym 0x1008ffb5, XF86RFKill), same_screen YES,

My xmodmap result is almost identical to yours.

xkeyboard-config - X11/xkb/keycodes/evdev lists
<I255> = 255; // #define KEY_RFKILL 247

There is clearly another big gap in my knowledge, :man_facepalming: I’m determined to try and understand this though… :crossed_fingers: Thanks for all you help.

1 Like

I’m glad I could help, I’m curious, though, what are you trying to map XF86RFKill to?

1 Like

It doesn’t work in my setup but I can turn off WiFi and Bluetooth with a service, so I was trying to remap to toggle the service. I also want to be able to stop an attached LORA radio.

1 Like

That’s really interesting. I don’t think I can be of further help, in this case, but I wish you the best on your journey and if I learn something new I’ll let you know :smile:

1 Like