diff --git a/builddefs/build_keyboard.mk b/builddefs/build_keyboard.mk index 2b9ec48e70..ee9ec3a3ab 100644 --- a/builddefs/build_keyboard.mk +++ b/builddefs/build_keyboard.mk @@ -344,7 +344,12 @@ $(KEYBOARD_OUTPUT)/src/layouts.h: $(INFO_JSON_FILES) $(eval CMD=$(QMK_BIN) generate-layouts --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/layouts.h) @$(BUILD_CMD) -generated-files: $(KEYBOARD_OUTPUT)/src/info_config.h $(KEYBOARD_OUTPUT)/src/default_keyboard.c $(KEYBOARD_OUTPUT)/src/default_keyboard.h $(KEYBOARD_OUTPUT)/src/layouts.h +$(KEYBOARD_OUTPUT)/src/keymap_hash.h: + @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD) + $(eval CMD=$(QMK_BIN) generate-keymap-hash -q -o "$(KEYMAP_OUTPUT)/src/keymap_hash.h" -kb $(KEYBOARD) -km $(KEYMAP)) + @$(BUILD_CMD) + +generated-files: $(KEYBOARD_OUTPUT)/src/keymap_hash.h $(KEYBOARD_OUTPUT)/src/info_config.h $(KEYBOARD_OUTPUT)/src/default_keyboard.c $(KEYBOARD_OUTPUT)/src/default_keyboard.h $(KEYBOARD_OUTPUT)/src/layouts.h .INTERMEDIATE : generated-files diff --git a/lib/python/qmk/cli/__init__.py b/lib/python/qmk/cli/__init__.py index 8bfba924cd..fe9f1c78b3 100644 --- a/lib/python/qmk/cli/__init__.py +++ b/lib/python/qmk/cli/__init__.py @@ -55,6 +55,7 @@ subcommands = [ 'qmk.cli.generate.info_json', 'qmk.cli.generate.keyboard_c', 'qmk.cli.generate.keyboard_h', + 'qmk.cli.generate.keymap_hash', 'qmk.cli.generate.layouts', 'qmk.cli.generate.rgb_breathe_table', 'qmk.cli.generate.rules_mk', diff --git a/lib/python/qmk/cli/generate/keymap_hash.py b/lib/python/qmk/cli/generate/keymap_hash.py new file mode 100644 index 0000000000..4a0bff83a4 --- /dev/null +++ b/lib/python/qmk/cli/generate/keymap_hash.py @@ -0,0 +1,36 @@ +"""Used by the make system to generate header. +""" +from fnvhash import fnv1a_32 + +from milc import cli + +from qmk.commands import dump_lines +from qmk.keymap import locate_keymap +from qmk.keyboard import keyboard_completer, keyboard_folder +from qmk.path import normpath +from qmk.constants import GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE + + +@cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to') +@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") +@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, required=True, help='Keyboard to generate header for.') +@cli.argument('-km', '--keymap', arg_only=True, required=True, help='Keymap to generate header for.') +@cli.subcommand('Used by the make system to generate header', hidden=True) +def generate_keymap_hash(cli): + # Build the header file. + header_lines = [GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE, '#pragma once'] + + keymap_folder = locate_keymap(cli.args.keyboard, cli.args.keymap).parent + + keymap_files = list(keymap_folder.glob('**/*')) + keymap_files.sort() + + content = "" + for file in keymap_files: + content += file.read_text(encoding='utf-8') + + val = fnv1a_32(bytes(content, 'utf-8')) + header_lines.append(f'#define KEYMAP_HASH 0x{val:08X}ul') + + # Show the results + dump_lines(cli.args.output, header_lines, cli.args.quiet) diff --git a/quantum/eeconfig.c b/quantum/eeconfig.c index c829e9d263..0698b1bd14 100644 --- a/quantum/eeconfig.c +++ b/quantum/eeconfig.c @@ -16,6 +16,9 @@ bool via_eeprom_is_valid(void); void via_eeprom_set_valid(bool valid); void eeconfig_init_via(void); +#elif defined(DYNAMIC_KEYMAP_ENABLE) +# include "keymap_hash.h" +void dynamic_keymap_reset(void); #endif /** \brief eeconfig enable @@ -81,10 +84,9 @@ void eeconfig_init_quantum(void) { // properly re-initialized. via_eeprom_set_valid(false); eeconfig_init_via(); -#elif defined(XAP_ENABLE) - // TODO: define XAP reset behaviour - void dynamic_keymap_reset(void); +#elif defined(DYNAMIC_KEYMAP_ENABLE) dynamic_keymap_reset(); + eeprom_update_dword(EECONFIG_KEYMAP_HASH, KEYMAP_HASH); #endif eeconfig_init_kb(); @@ -123,10 +125,14 @@ void eeconfig_disable(void) { */ bool eeconfig_is_enabled(void) { bool is_eeprom_enabled = (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER); -#ifdef VIA_ENABLE +#if defined(VIA_ENABLE) if (is_eeprom_enabled) { is_eeprom_enabled = via_eeprom_is_valid(); } +#elif defined(DYNAMIC_KEYMAP_ENABLE) + if (is_eeprom_enabled) { + is_eeprom_enabled = (eeprom_read_dword(EECONFIG_KEYMAP_HASH) == KEYMAP_HASH); + } #endif return is_eeprom_enabled; } @@ -137,10 +143,14 @@ bool eeconfig_is_enabled(void) { */ bool eeconfig_is_disabled(void) { bool is_eeprom_disabled = (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER_OFF); -#ifdef VIA_ENABLE +#if defined(VIA_ENABLE) if (!is_eeprom_disabled) { is_eeprom_disabled = !via_eeprom_is_valid(); } +#elif defined(DYNAMIC_KEYMAP_ENABLE) + if (!is_eeprom_disabled) { + is_eeprom_disabled = (eeprom_read_dword(EECONFIG_KEYMAP_HASH) != KEYMAP_HASH); + } #endif return is_eeprom_disabled; } diff --git a/quantum/eeconfig.h b/quantum/eeconfig.h index 44f42b60e3..c3709c1ee2 100644 --- a/quantum/eeconfig.h +++ b/quantum/eeconfig.h @@ -53,8 +53,11 @@ along with this program. If not, see . // TODO: Combine these into a single word and single block of EEPROM #define EECONFIG_KEYMAP_UPPER_BYTE (uint8_t *)34 + +#define EECONFIG_KEYMAP_HASH (uint32_t *)35 + // Size of EEPROM being used, other code can refer to this for available EEPROM -#define EECONFIG_SIZE 35 +#define EECONFIG_SIZE 39 /* debug bit */ #define EECONFIG_DEBUG_ENABLE (1 << 0) #define EECONFIG_DEBUG_MATRIX (1 << 1)