Changed my keyboard layout in hardware to colemak!

Hi everyone,

since @DHowett released his docs and tools for working with the framework EC, I’ve wanted to change the keyboard to my preferred layout, colemak. Today was the day! First I made sure I could remove a keyboard key without breaking it. Turns out it’s really easy, and I didn’t break a single one. I can send a video for anyone interested, but it’s basically just use the back of the provided screwdriver to pry up the top corners of the key until it pops off.

Then I wrote a script that changes each key one by one into the corresponding colemak key. Here’s that script:

#!/bin/bash
# Framework en-us qwerty >>> colemak (caps lock unchanged) 

sudo fw-ectool raw 0x3E0C d1,d1,b3,b2,w0d # Tab > Tab
sudo fw-ectool raw 0x3E0C d1,d1,b0,b2,w15 # q > q
sudo fw-ectool raw 0x3E0C d1,d1,b6,b5,w1d # w > w
sudo fw-ectool raw 0x3E0C d1,d1,b2,b4,w2b # e > f
sudo fw-ectool raw 0x3E0C d1,d1,b6,b6,w4d # r > p
sudo fw-ectool raw 0x3E0C d1,d1,b3,b6,w34 # t > g
sudo fw-ectool raw 0x3E0C d1,d1,b3,b7,w3b # y > j
sudo fw-ectool raw 0x3E0C d1,d1,b6,b7,w4b # u > l
sudo fw-ectool raw 0x3E0C d1,d1,b6,ba,w3c # i > u
sudo fw-ectool raw 0x3E0C d1,d1,b3,b8,w35 # o > y
sudo fw-ectool raw 0x3E0C d1,d1,b5,bd,w4c # p > ;
sudo fw-ectool raw 0x3E0C d1,d1,b6,bd,w54 # [ > [
sudo fw-ectool raw 0x3E0C d1,d1,b6,be,w5b # ] > ]
sudo fw-ectool raw 0x3E0C d1,d1,b2,b8,w5d # \ > \

sudo fw-ectool raw 0x3E0C d1,d1,b4,b4,w58 # Caps > Caps (w66 for Bkspc)
sudo fw-ectool raw 0x3E0C d1,d1,b7,b2,w1c # a > a
sudo fw-ectool raw 0x3E0C d1,d1,b4,b5,w2d # s > r
sudo fw-ectool raw 0x3E0C d1,d1,b7,be,w1b # d > s
sudo fw-ectool raw 0x3E0C d1,d1,b7,b6,w2c # f > t
sudo fw-ectool raw 0x3E0C d1,d1,b2,b6,w23 # g > d
sudo fw-ectool raw 0x3E0C d1,d1,b2,b7,w33 # h > h
sudo fw-ectool raw 0x3E0C d1,d1,b7,b7,w31 # j > n
sudo fw-ectool raw 0x3E0C d1,d1,b7,ba,w24 # k > e
sudo fw-ectool raw 0x3E0C d1,d1,b7,b8,w43 # l > i
sudo fw-ectool raw 0x3E0C d1,d1,b7,bd,w44 # ; > o
sudo fw-ectool raw 0x3E0C d1,d1,b0,be,w52 # ' > '

sudo fw-ectool raw 0x3E0C d1,d1,b1,b5,w1a # z > z
sudo fw-ectool raw 0x3E0C d1,d1,b0,b5,w22 # x > x
sudo fw-ectool raw 0x3E0C d1,d1,b0,b0,w21 # c > c
sudo fw-ectool raw 0x3E0C d1,d1,b0,b6,w2a # v > v
sudo fw-ectool raw 0x3E0C d1,d1,b1,b6,w32 # b > b
sudo fw-ectool raw 0x3E0C d1,d1,b1,b7,w42 # n > k
sudo fw-ectool raw 0x3E0C d1,d1,b0,b7,w3a # m > m
sudo fw-ectool raw 0x3E0C d1,d1,b0,ba,w41 # , > ,
sudo fw-ectool raw 0x3E0C d1,d1,b0,b8,w49 # . > .
sudo fw-ectool raw 0x3E0C d1,d1,b0,bd,w4a # / > /

I kept caps lock the same because I use it as a modifier with sway.

to change it back to QWERTY:

#!/bin/bash
# Framework en-us qwerty defaults

sudo fw-ectool raw 0x3E0C d1,d1,b3,b2,w0d # Tab > Tab
sudo fw-ectool raw 0x3E0C d1,d1,b0,b2,w15 # q > q
sudo fw-ectool raw 0x3E0C d1,d1,b6,b5,w1d # w > w
sudo fw-ectool raw 0x3E0C d1,d1,b2,b4,w24 # e > e
sudo fw-ectool raw 0x3E0C d1,d1,b6,b6,w2d # r > r
sudo fw-ectool raw 0x3E0C d1,d1,b3,b6,w2c # t > t
sudo fw-ectool raw 0x3E0C d1,d1,b3,b7,w35 # y > y
sudo fw-ectool raw 0x3E0C d1,d1,b6,b7,w3c # u > u
sudo fw-ectool raw 0x3E0C d1,d1,b6,ba,w43 # i > i
sudo fw-ectool raw 0x3E0C d1,d1,b3,b8,w44 # o > o
sudo fw-ectool raw 0x3E0C d1,d1,b5,bd,w4d # p > p
sudo fw-ectool raw 0x3E0C d1,d1,b6,bd,w54 # [ > [
sudo fw-ectool raw 0x3E0C d1,d1,b6,be,w5b # ] > ]
sudo fw-ectool raw 0x3E0C d1,d1,b2,b8,w5d # \ > \

sudo fw-ectool raw 0x3E0C d1,d1,b4,b4,w58 # Caps > Caps
sudo fw-ectool raw 0x3E0C d1,d1,b7,b2,w1c # a > a
sudo fw-ectool raw 0x3E0C d1,d1,b4,b5,w1b # s > s
sudo fw-ectool raw 0x3E0C d1,d1,b7,be,w23 # d > d
sudo fw-ectool raw 0x3E0C d1,d1,b7,b6,w2b # f > f
sudo fw-ectool raw 0x3E0C d1,d1,b2,b6,w34 # g > g
sudo fw-ectool raw 0x3E0C d1,d1,b2,b7,w33 # h > h
sudo fw-ectool raw 0x3E0C d1,d1,b7,b7,w3b # j > j
sudo fw-ectool raw 0x3E0C d1,d1,b7,ba,w42 # k > k
sudo fw-ectool raw 0x3E0C d1,d1,b7,b8,w4b # l > l
sudo fw-ectool raw 0x3E0C d1,d1,b7,bd,w4c # ; > ;
sudo fw-ectool raw 0x3E0C d1,d1,b0,be,w52 # ' > '

sudo fw-ectool raw 0x3E0C d1,d1,b1,b5,w1a # z > z
sudo fw-ectool raw 0x3E0C d1,d1,b0,b5,w22 # x > x
sudo fw-ectool raw 0x3E0C d1,d1,b0,b0,w21 # c > c
sudo fw-ectool raw 0x3E0C d1,d1,b0,b6,w2a # v > v
sudo fw-ectool raw 0x3E0C d1,d1,b1,b6,w32 # b > b
sudo fw-ectool raw 0x3E0C d1,d1,b1,b7,w31 # n > n
sudo fw-ectool raw 0x3E0C d1,d1,b0,b7,w3a # m > m
sudo fw-ectool raw 0x3E0C d1,d1,b0,ba,w41 # , > ,
sudo fw-ectool raw 0x3E0C d1,d1,b0,b8,w49 # . > .
sudo fw-ectool raw 0x3E0C d1,d1,b0,bd,w4a # / > /

fw-ectool is an alias to ectool --interface=fwk that comes with my AUR package fw-ectool-git for Howett’s ectool.

Don’t run this if you don’t know what those commands do! make sure you have an extra USB keyboard on hand in case you mess up - while I didn’t need it, if I had accidentally overwrote some of the more critical letter keys or like enter I wouldn’t be able to set it back.

the basis of this is from The Framework Laptop's Embedded Controller (EC) :: HowettNET

ideally I would like to do this in a more automated/cleaner way, so that the commands above are actually readable without multiple tables on screen. but to create the layout I had to first get the layout location for each key, then get the PC/AT keycodes for each target key from pdf page 52 (labeled 1-33) of this document. I would be willing to help with anyone wanting to do e.g. dvorak as well.

Benefits of doing it this way over setting layout in the OS include that it works anywhere the keyboard works, so bios, windows, linux, or whatever I install will be immediately correct with the OS set to the default en-us layout. it also survives reboots and shutdowns, I believe the only ways to wipe the config is a bios update / EC firmware update or to set the config back manually with the QWERTY script above.

22 Likes

Wow, the firmware level key customizing! And you swapped each physical key cap! Amazing. I didn’t know DHowett’s ec tool can do this. As I didn’t know the colemak layout, I checked it on the Wikipedia, and I put the link here just in case.

If you don’t mind, could you share the video on Youtube or etc? I also want to see the video you are typing! Congrats!

YES! So glad somebody’s using this stuff.

Ah, you’re in for a surprise! :smile:

These modifications will survive in EC RAM until the EC reboots. When you power off the machine, the EC loses power about 30 seconds later. You’ll want to apply this on each boot.

I wrote an EFI driver to remap Caps to Esc before the OS starts; perhaps we can do something similar here? Imagine! A pre-OS driver that applies a saved keyboard layout no matter what it is.

FYI: the remap command can take up to 21 (EDIT: NOPE! 32) (good job Dustin with that hex value) key positions and scancodes, which could make your script much shorter/faster at the cost of some clarity.

4 Likes

Hah, I was impatient and only tested a 10 sec or so shutdown. I’ll put it as a systemd service & suspend wakeup script (for hibernation resume)

I’ll keep it as is, simply to have the little readability that I do have :stuck_out_tongue: I timed it, it only takes 1.05 sec to run the commands, and I could shorten it by getting rid of keys that are the same for both layouts. If I were to figure out your EFI driver thing, it could be compressed into a single command to keep it simple for adapting it there.

Here’s me removing a keycap: https://www.youtube.com/watch?v=p8tTETq-WGE

Turn up sound to hear the clicks from the clips on top disconnecting. Don’t try to pry from the bottom, because the clips there go behind the keyswitch, so it would probably break the keycap. the clips in the top though are basically just friction based, as long as you pull in the general direction of up they will come off. If the ones on the bottom are still connected after you disconnect the top ones, just wiggle the cap forward and back a bit.

I won’t post a video of me typing for now because 1) I don’t have a good way to mount my phone, 2) my phone camera and mic is waterlogged (the waterproof seals gave up on me) so it looks like shit as you can see above, and 3) despite picking this keyboard layout, I’m not actually a very good typer. It’s just colemak is a little better than QWERTY for me. when I get my new phone soon I might take a video.

3 Likes

And here’s my systemd script. After enabling it, it runs both after resuming from hibernate, and during a normal boot. /usr/local/bin/fw-ec-setup is just a script that runs my remap script as well as a little light sequence with the LEDs to let me know it worked.

$ cat /etc/systemd/system/fw-ec.service 
[Unit]
Description=Setup EC for keyboard layout, lights, etc.
After=hibernate.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/fw-ec-setup
RemainAfterExit=false
StandardOutput=journal

[Install]
WantedBy=multi-user.target hibernate.target
1 Like

Very interested in using this to get a native Colemak layout, have there been any problems in the interim?
I don’t completely understand what ectool does, but does this introduce any extra latency in key presses, even just theoretically?

1 Like

I’ve not heard of any problems caused by people remapping their keys. This method overwrites the key lookup tables in memory on the keyboard controller[^1], so it almost provably does not introduce any extra latency.

[^1]: really the Embedded Controller, but it is also acting as the keyboard controller.

@DHowett @shark Thanks for all the work y’all have put in on this topic.

I need a little help,
I am trying write a bash script to remap several keys at startup. I have been reading both of your blogs and posts for guidance.

The main issue is that I dont know what to do for FN Key.

This is what I have so far

#!/bin/bash

# Remap Lctrl to Lalt
sudo fw-ectool 0x3E0C d1,d1,b1,bc,w56

# Remap Lalt to FN
sudo fw-ectool 0x3E0C d1,d1,b1,b3,????

# Remap FN to Rctrl
sudo fw-ectool raw 0x3E0C d1,d1,b2,b2,w97

My goal is for the bottom row of my keyboard to be as follows:

| Ctrl | Alt | Meta | Ctrl | Space Bar | Alt | Fn | :arrow_backward: | :arrow_up: / :arrow_down: | :arrow_forward: |

I used a macbook for many years and got used to using the command key which does some of what ctrl does on other systems so I like having ctrl next to the spacebar. the Fn key would be nice to have next to the arrow keys for easily jumping around the the terminal.

I use a lot of virtual machines also so I would like to have a method to setup the keyboard system wide.

Any help would be much appreciated.

1 Like

As of today, Fn has the scancode 0xFF.

You can remap the key in Left Alt’s position to emit Fn with ectool raw 0x3e0c d1,d1,b1,b3,wff

Don’t forget the raw on those first few commands!

EDIT: Though, reading over your proposal I don’t think that you’ll get what you’re looking for with the commands you have.

The key mapping host command maps positions to new scancodes and not the other way around.

In the line you’ve commented “Remap FN to Rctrl,” what you’re doing is remapping the key at position 2,2 to emit the scancode for Right Ctrl; this will effectively make the key labelled Fn into a Right Ctrl key.

The first one is also unexpected. It will remap the key at position 1, 12 (labelled Left Ctrl) to emit scancode 0x56 (I do not believe that this is a valid 8042 scancode.).

2 Likes

You can achieve what you’re looking for with the following mappings:

sudo fw-ectool raw 0x3e0c d7,d1,b1,bC,w14, \
                                b2,b2,w11, \
                                b3,b1,wE01F, \
                                b1,b3,wE014, \
                                b1,b4,w29, \
                                b0,b3,wE011, \
                                b0,bC,wFF
# This will remap:
# R, C
# 1, 12 (LCtrl) -> LCtrl (Unchanged)
# 2,  2 (Fn)    -> Alt
# 3,  1 (LMeta) -> LMeta (Unchanged)
# 1,  3 (LAlt)  -> RCtrl
# 1,  4 (Space) -> Space (unchanged)
# 0,  3 (RAlt)  -> RAlt (unchanged)
# 0, 12 (RCtrl) -> Fn

Wow, it is really hard to get used to this mapping!

5 Likes

@ DHowett Thanks for the quick response.

Yeah I think my head was spinning when I 1st attempted to write the script. I really appreciate you making sense of it.

I didn’t realize my layout was so strange. Now that I think about it though it probably is because I used parallels on mac to run linux VMs for years which mapped keys oddly. cmd as ctrl and alt as meta.

The FN on the right was an idea I got from another post which made sense to me.

having ctrl under shift also makes sense for a lot of shortcuts.

But I guess it is pretty odd now that I tried to justify it.

Thanks Again!

3 Likes

for mapping itself - yes, but the whole “cmd” button in macOS puts much less strain on you left hand. i used windows then linux for 9 years before trying macOS for the first time. it took me 4 days to get used to cmd+c/v/x/etc combinations and now I can’t go back to ctrl+stuff the reason is simple: your left thumb in resting position will be approximately between space and “cmd” (alt on windows standard keyboards) and your pinky will be in area of caps lock and tab. your thumb so called “strong” finger, while your pinky is “weak” finger. because of that generally cmd-based combinations put muuuch lest strain on your hand. i strongly recommend trying that yourself :slight_smile: the only inconvenience outside macOS is the fact that apps and OS are not unified and in 99% use ctrl-based shortcuts exclusively. this gets annoying with copy/paste conflicting with terminal shortcuts

1 Like

I also prefer Mac keyboard layout and I configure my laptop to have the following order of bottom keys: ctrl, fn, alt, logo, space, logo, alt. Logo key is then used for ctrl shortcuts in X11 (so logo key is mapped to ctrl, while ctrl key is mapped to super key). While I patch Ubuntu/Gnome Terminal to use super key as ctrl key, so that visually you press ctrl-c and it sends super-c to Terminal which then interprets it as ctrl-c (and you send and interrupt). If you press logo-c, that sends ctrl-c to Terminal and window program copies selection to a clipboard.

I would love if Framework could support a custom keyboard layout like this, including making a keyboard cover which would match those keys.

3 Likes

Will this run before LUKS so that my LUKS password will be typed using the remapped keys?

Cc @DHowett

Here’s Dvorak with the Caps mapped to Escape

#!/bin/env bash
# Framework en-us dvorak

ectool raw 0x3E0C d1,d1,b3,b2,w0d # Tab > Tab
ectool raw 0x3E0C d1,d1,b0,b2,w52 # q > '
ectool raw 0x3E0C d1,d1,b6,b5,w41 # w > ,
ectool raw 0x3E0C d1,d1,b2,b4,w49 # e > .
ectool raw 0x3E0C d1,d1,b6,b6,w4d # r > p
ectool raw 0x3E0C d1,d1,b3,b6,w35 # t > y
ectool raw 0x3E0C d1,d1,b3,b7,w2b # y > f
ectool raw 0x3E0C d1,d1,b6,b7,w34 # u > g
ectool raw 0x3E0C d1,d1,b6,ba,w21 # i > c
ectool raw 0x3E0C d1,d1,b3,b8,w2d # o > r
ectool raw 0x3E0C d1,d1,b5,bd,w4b # p > l
ectool raw 0x3E0C d1,d1,b6,bd,w4a # [ > /
ectool raw 0x3E0C d1,d1,b6,be,w55 # ] > =
ectool raw 0x3E0C d1,d1,b2,b8,w5d # \ > \

ectool raw 0x3E0C d1,d1,b4,b4,w76 # Caps > Escape
ectool raw 0x3E0C d1,d1,b7,b2,w1c # a > a
ectool raw 0x3E0C d1,d1,b4,b5,w44 # s > o
ectool raw 0x3E0C d1,d1,b7,be,w24 # d > e
ectool raw 0x3E0C d1,d1,b7,b6,w3c # f > u
ectool raw 0x3E0C d1,d1,b2,b6,w43 # g > i
ectool raw 0x3E0C d1,d1,b2,b7,w23 # h > d
ectool raw 0x3E0C d1,d1,b7,b7,w33 # j > h
ectool raw 0x3E0C d1,d1,b7,ba,w2c # k > t
ectool raw 0x3E0C d1,d1,b7,b8,w31 # l > n
ectool raw 0x3E0C d1,d1,b7,bd,w1b # ; > s
ectool raw 0x3E0C d1,d1,b0,be,w4e # ' > -

ectool raw 0x3E0C d1,d1,b1,b5,w4c # z > ;
ectool raw 0x3E0C d1,d1,b0,b5,w15 # x > q
ectool raw 0x3E0C d1,d1,b0,b0,w3b # c > j
ectool raw 0x3E0C d1,d1,b0,b6,w42 # v > k
ectool raw 0x3E0C d1,d1,b1,b6,w22 # b > x
ectool raw 0x3E0C d1,d1,b1,b7,w32 # n > b
ectool raw 0x3E0C d1,d1,b0,b7,w3a # m > m
ectool raw 0x3E0C d1,d1,b0,ba,w1d # , > w
ectool raw 0x3E0C d1,d1,b0,b8,w2a # . > v
ectool raw 0x3E0C d1,d1,b0,bd,w1a # / > z
2 Likes

For all my colemak-dh lovers out there. (ANSI variant). With caps lock replaced with backspace.

#!/bin/bash
# Framework en-us qwerty >>> colemak-dh (caps lock changed to backspace) 

ectool raw 0x3E0C d1,d1,b3,b2,w0d # Tab > Tab
ectool raw 0x3E0C d1,d1,b0,b2,w15 # q > q
ectool raw 0x3E0C d1,d1,b6,b5,w1d # w > w
ectool raw 0x3E0C d1,d1,b2,b4,w2b # e > f
ectool raw 0x3E0C d1,d1,b6,b6,w4d # r > p
ectool raw 0x3E0C d1,d1,b3,b6,w32 # t > b
ectool raw 0x3E0C d1,d1,b3,b7,w3b # y > j
ectool raw 0x3E0C d1,d1,b6,b7,w4b # u > l
ectool raw 0x3E0C d1,d1,b6,ba,w3c # i > u
ectool raw 0x3E0C d1,d1,b3,b8,w35 # o > y
ectool raw 0x3E0C d1,d1,b5,bd,w4c # p > ;
ectool raw 0x3E0C d1,d1,b6,bd,w54 # [ > [
ectool raw 0x3E0C d1,d1,b6,be,w5b # ] > ]
ectool raw 0x3E0C d1,d1,b2,b8,w5d # \ > \

ectool raw 0x3E0C d1,d1,b4,b4,w66 # Caps > Bkspc
ectool raw 0x3E0C d1,d1,b7,b2,w1c # a > a
ectool raw 0x3E0C d1,d1,b4,b5,w2d # s > r
ectool raw 0x3E0C d1,d1,b7,be,w1b # d > s
ectool raw 0x3E0C d1,d1,b7,b6,w2c # f > t
ectool raw 0x3E0C d1,d1,b2,b6,w34 # g > g
ectool raw 0x3E0C d1,d1,b2,b7,w3a # h > m
ectool raw 0x3E0C d1,d1,b7,b7,w31 # j > n
ectool raw 0x3E0C d1,d1,b7,ba,w24 # k > e
ectool raw 0x3E0C d1,d1,b7,b8,w43 # l > i
ectool raw 0x3E0C d1,d1,b7,bd,w44 # ; > o
ectool raw 0x3E0C d1,d1,b0,be,w52 # ' > '

ectool raw 0x3E0C d1,d1,b1,b5,w22 # z > x
ectool raw 0x3E0C d1,d1,b0,b5,w21 # x > c
ectool raw 0x3E0C d1,d1,b0,b0,w23 # c > d
ectool raw 0x3E0C d1,d1,b0,b6,w2a # v > v
ectool raw 0x3E0C d1,d1,b1,b6,w1a # b > z
ectool raw 0x3E0C d1,d1,b1,b7,w42 # n > k
ectool raw 0x3E0C d1,d1,b0,b7,w33 # m > h
ectool raw 0x3E0C d1,d1,b0,ba,w41 # , > ,
ectool raw 0x3E0C d1,d1,b0,b8,w49 # . > .
ectool raw 0x3E0C d1,d1,b0,bd,w4a # / > /

So does this approach work to remap the airplane mode key on F10, which seems to be the only function key that you can’t change from the OS? (Disabling Flight Mode / Airplane Mode Function Key F10 - is it possible?).
I’m a bit confused by some of the complex ins and outs of this low level system-dependent stuff.
I concur with the poster there that the Airplane key is obsolete, and my goal would be:

remap the Airplane mode key on my Framework to “Home” (so “Home” is airplane key and “End” is the Framework cog, since I have no use for physical buttons for those features)

In particular, does anyone have an example that would do that, on a Framework 13, that I can run on Linux (Ubuntu 22.04).