diff options
Diffstat (limited to '.gitlab-ci/generate-evdev-keycodes.py')
-rwxr-xr-x | .gitlab-ci/generate-evdev-keycodes.py | 183 |
1 files changed, 0 insertions, 183 deletions
diff --git a/.gitlab-ci/generate-evdev-keycodes.py b/.gitlab-ci/generate-evdev-keycodes.py deleted file mode 100755 index 5ee18465..00000000 --- a/.gitlab-ci/generate-evdev-keycodes.py +++ /dev/null @@ -1,183 +0,0 @@ -#!/usr/bin/env python3 -# -# Usage: generate-evdev-keycodes.py keycodes/evdev.in > keycodes/evdev -# -# Generate the keycodes/evdev file from the names defined in -# linux/input-event-codes.h -# -# Note that this script relies on libevdev to provide the key names and -# those are compiled in. Ensure you have a recent-enough libevdev to -# generate this list. -# - -import argparse -import contextlib -import re -import sys -try: - import libevdev -except ImportError: - print('WARNING: python-libevdev not available, cannot check for new evdev keycodes', file=sys.stderr) - sys.exit(77) - - -# The marker to search for in the template file, replaced with our generated -# codes. -replacement_marker = '@evdevkeys@' - -# These markers are put into the result file and are used to detect -# the section that we added when parsing an existing file. -section_header = 'Key codes below are autogenerated' -section_footer = 'End of autogenerated key codes' - - -def evdev_codes(): - ''' - Return the dict {code, name} for all known evdev codes. - - The list of names is compiled into libevdev.so, use a recent libevdev - release to get the most up-to-date list. - ''' - codes = {} - for c in libevdev.EV_KEY.codes: - # 112 because that's where our 1:1 keycode entries historically - # started. - # Undefined keys are those with a code < KEY_MAX but without a - # #define in the kernel header file - if c.value < 112 or not c.is_defined: - continue - - if c.name.startswith('BTN_') or c.name == 'KEY_MAX': - continue - - codes[c.value] = c.name - - return codes - - -def generate_keycodes_file(template, codes): - ''' - Generate a new keycodes/evdev file with line containing @evdevkeys@ - replaced by the full list of known evdev key codes, including our - section_header/footer. Expected output: - - :: - - // $section_header - <I$keycode> = <$keycode + 8> // #define $kernel_name - ... - // $section_footer - - ''' - output = [] - for line in template.readlines(): - if replacement_marker not in line: - output.append(line) - continue - - output.append(f'\t// {section_header}\n') - - warned = False - for code, name in codes.items(): - xkeycode = code + 8 - - if xkeycode > 255 and not warned: - warned = True - output.append('\n') - output.append('\t// Key codes below cannot be used in X\n') - output.append('\n') - - # Special keys that need a comment - special_keys = { - 211: 'conflicts with AB11', - } - - comment = special_keys.get(xkeycode, '') - if comment: - comment = f' {comment}' - - output.append(f'\t<I{xkeycode}> = {xkeycode};\t// #define {name:23s} {code}{comment}\n') - output.append(f'\t// {section_footer}\n') - - return output - - -def extract_generated_keycodes(oldfile): - in_generated_section = False - pattern = re.compile('.*<I([0-9]*)>.*') - - for line in oldfile: - if section_header in line: - in_generated_section = True - continue - elif section_footer in line: - return - elif in_generated_section: - match = pattern.match(line) - if match: - yield int(match[1]) - - -def compare_with(codes, oldfile): - ''' - Extract the <I123> keycodes from between the section_header/footer of - oldfile and return a list of keycodes that are in codes but not in - oldfile. - ''' - old_keycodes = extract_generated_keycodes(oldfile) - keycodes = [c + 8 for c in codes] # X keycode offset - - # This does not detect keycodes in old_keycode but not in the new - # generated list - should never happen anyway. - return sorted(set(keycodes).difference(old_keycodes)) - - -def log_msg(msg): - print(msg, file=sys.stderr) - - -def main(): - parser = argparse.ArgumentParser(description='Generate the evdev keycode lists.') - parser.add_argument('--template', type=argparse.FileType('r'), - default=open('keycodes/evdev.in'), - help='The template file, usually keycodes/evdev.in') - parser.add_argument('--output', type=str, default=None, required=True, - help='The file to be written to') - parser.add_argument('--compare-with', type=argparse.FileType('r'), - help='Compare generated output with the given file') - parser.add_argument('--verbose', action=argparse.BooleanOptionalAction, - help='Print verbose output to stderr') - ns = parser.parse_args() - - codes = evdev_codes() - rc = 0 - if ns.verbose: - kmin, kmax = min(codes.keys()), max(codes.keys()) - log_msg(f'evdev keycode range: {kmin} ({kmin:#x}) → {kmax} ({kmax:#x})') - - # We compare before writing so we can use the same filename for - # --compare-with and --output. That's also why --output has to be type - # str instead of FileType('w'). - if ns.compare_with: - diff = compare_with(codes, ns.compare_with) - if diff: - rc = 1 - if ns.verbose: - log_msg(f'File {ns.compare_with.name} is out of date, missing keycodes:') - for k in diff: - name = codes[k - 8] # remove the X offset - log_msg(f' <I{k}> // #define {name}') - - with contextlib.ExitStack() as stack: - if ns.output == '-': - fd = sys.stdout - else: - fd = stack.enter_context(open(ns.output, 'w')) - output = generate_keycodes_file(ns.template, codes) - fd.write(''.join(output)) - - sys.exit(rc) - - -if __name__ == '__main__': - main() |