186 lines
5.1 KiB
Python
186 lines
5.1 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
import platform
|
|
|
|
device_ids = {
|
|
"k:0000:0000", # cros_ec keyboard
|
|
"k:0001:0001", # AT keyboard
|
|
"k:18d1:503c", # Google Inc. Hammer
|
|
"k:18d1:5050", # Google Inc. Hammer
|
|
"k:18d1:504c", # Google Inc. Hammer
|
|
"k:18d1:5052", # Google Inc. Hammer
|
|
"k:18d1:5057", # Google Inc. Hammer
|
|
"k:18d1:505b", # Google Inc. Hammer
|
|
"k:18d1:5030", # Google Inc. Hammer
|
|
"k:18d1:503d", # Google Inc. Hammer
|
|
"k:18d1:5044", # Google Inc. Hammer
|
|
"k:18d1:5061", # Google Inc. Hammer
|
|
"k:18d1:502b", # Google Inc. Hammer
|
|
}
|
|
|
|
vivaldi_keys = {
|
|
"x86_64": {
|
|
"90": "previoussong",
|
|
"91": "zoom",
|
|
"92": "scale",
|
|
"93": "sysrq",
|
|
"94": "brightnessdown",
|
|
"95": "brightnessup",
|
|
"97": "kbdillumdown",
|
|
"98": "kbdillumup",
|
|
"99": "nextsong",
|
|
"9A": "playpause",
|
|
"9B": "micmute",
|
|
"9E": "kbdillumtoggle",
|
|
"A0": "mute",
|
|
"AE": "volumedown",
|
|
"B0": "volumeup",
|
|
"E9": "forward",
|
|
"EA": "back",
|
|
"E7": "refresh",
|
|
},
|
|
"arm": {
|
|
"158": "back",
|
|
"159": "forward",
|
|
"173": "refresh",
|
|
"372": "zoom",
|
|
"120": "scale",
|
|
"224": "brightnessdown",
|
|
"225": "brightnessup",
|
|
"113": "mute",
|
|
"114": "volumedown",
|
|
"115": "volumeup",
|
|
"99" : "sysrq",
|
|
}
|
|
}
|
|
|
|
def get_arch():
|
|
return platform.uname().machine
|
|
|
|
def get_ids_string(device_ids):
|
|
return "\n".join(device_ids)
|
|
|
|
def get_dt_layout():
|
|
keys = []
|
|
keycodes = []
|
|
|
|
fdt = libfdt.Fdt(open("/sys/firmware/fdt", "rb").read())
|
|
currentnode = fdt.first_subnode(0)
|
|
|
|
while True:
|
|
try:
|
|
if fdt.get_name(currentnode) == "keyboard-controller":
|
|
prop = fdt.getprop(currentnode, "linux,keymap")
|
|
keys = prop.as_uint32_list()
|
|
currentnode = fdt.next_node(currentnode, 10)[0]
|
|
except:
|
|
break
|
|
|
|
if not keys:
|
|
return ""
|
|
|
|
for key in keys:
|
|
keycode = str(key & 0xFFFF)
|
|
if keycode in vivaldi_keys["arm"]:
|
|
keycodes.append(keycode)
|
|
return keycodes
|
|
|
|
def get_physmap_data():
|
|
if get_arch() == "x86_64":
|
|
try:
|
|
with open("/sys/bus/platform/devices/i8042/serio0/function_row_physmap", "r") as file:
|
|
return file.read().strip().split()
|
|
except FileNotFoundError:
|
|
return ""
|
|
else:
|
|
return get_dt_layout()
|
|
|
|
def get_functional_row(physmap, use_vivaldi, super_is_held, super_inverted):
|
|
arch = get_arch()
|
|
if arch != "x86_64":
|
|
arch = "arm"
|
|
|
|
i = 0
|
|
result = ""
|
|
for code in physmap:
|
|
i += 1
|
|
# Map zoom to f11 since most applications wont listen to zoom
|
|
mapping = "f11" if vivaldi_keys[arch][code] == "zoom" \
|
|
else vivaldi_keys[arch][code]
|
|
|
|
match [super_is_held, use_vivaldi, super_inverted]:
|
|
case [True, True, False] | [False, True, True]:
|
|
result += f"{vivaldi_keys[arch][code]} = f{i}\n"
|
|
case [True, False, False] | [False, False, True]:
|
|
result += f"f{i} = f{i}\n"
|
|
case [False, True, False] | [True, True, True]:
|
|
result += f"{vivaldi_keys[arch][code]} = {mapping}\n"
|
|
case [False, False, False] | [True, False, True]:
|
|
result += f"f{i} = {mapping}\n"
|
|
|
|
return result
|
|
|
|
def get_keyd_config(physmap, inverted):
|
|
config = f"""\
|
|
[ids]
|
|
{get_ids_string(device_ids)}
|
|
|
|
[main]
|
|
{get_functional_row(physmap, use_vivaldi=False, super_is_held=False, super_inverted=inverted)}
|
|
{get_functional_row(physmap, use_vivaldi=True, super_is_held=False, super_inverted=inverted)}
|
|
f13=coffee
|
|
sleep=coffee
|
|
|
|
[meta]
|
|
{get_functional_row(physmap, use_vivaldi=False, super_is_held=True, super_inverted=inverted)}
|
|
{get_functional_row(physmap, use_vivaldi=True, super_is_held=True, super_inverted=inverted)}
|
|
|
|
[alt]
|
|
backspace = delete
|
|
brightnessdown = kbdillumdown
|
|
brightnessup = kbdillumup
|
|
f6 = kbdillumdown
|
|
f7 = kbdillumup
|
|
|
|
[control]
|
|
f5 = sysrq
|
|
scale = sysrq
|
|
|
|
[altgr]
|
|
backspace = delete
|
|
left = home
|
|
right = end
|
|
up = pageup
|
|
down = pagedown
|
|
|
|
[control+alt]
|
|
backspace = C-A-delete
|
|
"""
|
|
return config
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("-f", "--file", default="cros.conf", help="path to save config (default: cros.conf)")
|
|
parser.add_argument("-i", "--inverted", action="store_true",
|
|
help="use functional keys by default and media keys when super is held")
|
|
args = vars(parser.parse_args())
|
|
|
|
|
|
|
|
physmap = get_physmap_data()
|
|
if not physmap:
|
|
print("no function row mapping found, using default mapping")
|
|
if get_arch() == "x86_64":
|
|
physmap = ['EA', 'E9', 'E7', '91', '92', '94', '95', 'A0', 'AE', 'B0']
|
|
else:
|
|
physmap = ['158', '159', '173', '372', '120', '224', '225', '113', '114', '115']
|
|
|
|
config = get_keyd_config(physmap, args["inverted"])
|
|
with open(args["file"], "w") as conf:
|
|
conf.write(config)
|
|
|
|
if __name__ == "__main__":
|
|
if get_arch() != "x86_64":
|
|
import libfdt
|
|
main()
|