--- /dev/null
+COMMON_DIR = common
+SRC += $(COMMON_DIR)/host.c \
+ $(COMMON_DIR)/keyboard.c \
+ $(COMMON_DIR)/action.c \
+ $(COMMON_DIR)/action_tapping.c \
+ $(COMMON_DIR)/action_macro.c \
+ $(COMMON_DIR)/action_layer.c \
+ $(COMMON_DIR)/action_util.c \
+ $(COMMON_DIR)/print.c \
+ $(COMMON_DIR)/debug.c \
+ $(COMMON_DIR)/util.c \
++ $(COMMON_DIR)/hook.c \
+ $(COMMON_DIR)/avr/suspend.c \
+ $(COMMON_DIR)/avr/xprintf.S \
+ $(COMMON_DIR)/avr/timer.c \
+ $(COMMON_DIR)/avr/bootloader.c
+
+
+# Option modules
+ifdef ACTIONMAP_ENABLE
+ SRC += $(COMMON_DIR)/actionmap.c
+ OPT_DEFS += -DACTIONMAP_ENABLE
+else
+ SRC += $(COMMON_DIR)/keymap.c
+endif
+
+ifdef BOOTMAGIC_ENABLE
+ SRC += $(COMMON_DIR)/bootmagic.c
+ SRC += $(COMMON_DIR)/avr/eeconfig.c
+ OPT_DEFS += -DBOOTMAGIC_ENABLE
+endif
+
+ifdef MOUSEKEY_ENABLE
+ SRC += $(COMMON_DIR)/mousekey.c
+ OPT_DEFS += -DMOUSEKEY_ENABLE
+ OPT_DEFS += -DMOUSE_ENABLE
+endif
+
+ifdef EXTRAKEY_ENABLE
+ OPT_DEFS += -DEXTRAKEY_ENABLE
+endif
+
+ifdef CONSOLE_ENABLE
+ OPT_DEFS += -DCONSOLE_ENABLE
+else
+ OPT_DEFS += -DNO_PRINT
+ OPT_DEFS += -DNO_DEBUG
+endif
+
+ifdef COMMAND_ENABLE
+ SRC += $(COMMON_DIR)/command.c
+ OPT_DEFS += -DCOMMAND_ENABLE
+endif
+
+ifdef NKRO_ENABLE
+ OPT_DEFS += -DNKRO_ENABLE
+endif
+
+ifdef USB_6KRO_ENABLE
+ OPT_DEFS += -DUSB_6KRO_ENABLE
+endif
+
+ifdef KEYBOARD_LOCK_ENABLE
+ OPT_DEFS += -DKEYBOARD_LOCK_ENABLE
+endif
+
+ifdef SLEEP_LED_ENABLE
+ SRC += $(COMMON_DIR)/avr/sleep_led.c
+ OPT_DEFS += -DSLEEP_LED_ENABLE
+ OPT_DEFS += -DNO_SUSPEND_POWER_DOWN
+endif
+
+ifdef BACKLIGHT_ENABLE
+ SRC += $(COMMON_DIR)/backlight.c
+ OPT_DEFS += -DBACKLIGHT_ENABLE
+endif
+
+ifdef KEYMAP_SECTION_ENABLE
+ OPT_DEFS += -DKEYMAP_SECTION_ENABLE
+
+ ifeq ($(strip $(MCU)),atmega32u2)
+ EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr35.x
+ else ifeq ($(strip $(MCU)),atmega32u4)
+ EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr5.x
+ else
+ EXTRALDFLAGS = $(error no ldscript for keymap section)
+ endif
+endif
+
+# Version string
+VERSION := $(shell (git describe --always --dirty || echo 'unknown') 2> /dev/null)
+OPT_DEFS += -DVERSION=$(VERSION)
+
+
+# Search Path
+VPATH += $(TMK_DIR)/common
--- /dev/null
+#include <stdint.h>
+#include "keyboard.h"
+#include "action.h"
+#include "util.h"
+#include "action_layer.h"
++#include "hook.h"
+
+#ifdef DEBUG_ACTION
+#include "debug.h"
+#else
+#include "nodebug.h"
+#endif
+
+
+/*
+ * Default Layer State
+ */
+uint32_t default_layer_state = 0;
+
+static void default_layer_state_set(uint32_t state)
+{
+ debug("default_layer_state: ");
+ default_layer_debug(); debug(" to ");
+ default_layer_state = state;
+ default_layer_debug(); debug("\n");
+ clear_keyboard_but_mods(); // To avoid stuck keys
+}
+
+void default_layer_debug(void)
+{
+ dprintf("%08lX(%u)", default_layer_state, biton32(default_layer_state));
+}
+
+void default_layer_set(uint32_t state)
+{
+ default_layer_state_set(state);
+}
+
+#ifndef NO_ACTION_LAYER
+void default_layer_or(uint32_t state)
+{
+ default_layer_state_set(default_layer_state | state);
+}
+void default_layer_and(uint32_t state)
+{
+ default_layer_state_set(default_layer_state & state);
+}
+void default_layer_xor(uint32_t state)
+{
+ default_layer_state_set(default_layer_state ^ state);
+}
+#endif
+
+
+#ifndef NO_ACTION_LAYER
+/*
+ * Keymap Layer State
+ */
+uint32_t layer_state = 0;
+
+static void layer_state_set(uint32_t state)
+{
+ dprint("layer_state: ");
+ layer_debug(); dprint(" to ");
+ layer_state = state;
++ hook_layer_change(layer_state);
+ layer_debug(); dprintln();
+ clear_keyboard_but_mods(); // To avoid stuck keys
+}
+
+void layer_clear(void)
+{
+ layer_state_set(0);
+}
+
+void layer_move(uint8_t layer)
+{
+ layer_state_set(1UL<<layer);
+}
+
+void layer_on(uint8_t layer)
+{
+ layer_state_set(layer_state | (1UL<<layer));
+}
+
+void layer_off(uint8_t layer)
+{
+ layer_state_set(layer_state & ~(1UL<<layer));
+}
+
+void layer_invert(uint8_t layer)
+{
+ layer_state_set(layer_state ^ (1UL<<layer));
+}
+
+void layer_or(uint32_t state)
+{
+ layer_state_set(layer_state | state);
+}
+void layer_and(uint32_t state)
+{
+ layer_state_set(layer_state & state);
+}
+void layer_xor(uint32_t state)
+{
+ layer_state_set(layer_state ^ state);
+}
+
+void layer_debug(void)
+{
+ dprintf("%08lX(%u)", layer_state, biton32(layer_state));
+}
+#endif
+
+
+
+action_t layer_switch_get_action(keypos_t key)
+{
+ action_t action = { .code = ACTION_TRANSPARENT };
+
+#ifndef NO_ACTION_LAYER
+ uint32_t layers = layer_state | default_layer_state;
+ /* check top layer first */
+ for (int8_t i = 31; i >= 0; i--) {
+ if (layers & (1UL<<i)) {
+ action = action_for_key(i, key);
+ if (action.code != ACTION_TRANSPARENT) {
+ return action;
+ }
+ }
+ }
+ /* fall back to layer 0 */
+ action = action_for_key(0, key);
+ return action;
+#else
+ action = action_for_key(biton32(default_layer_state), key);
+ return action;
+#endif
+}
--- /dev/null
+#include <stdint.h>
+#include <stdbool.h>
+#include "wait.h"
+#include "matrix.h"
+#include "bootloader.h"
+#include "debug.h"
+#include "keymap.h"
+#include "actionmap.h"
+#include "host.h"
+#include "action_layer.h"
+#include "eeconfig.h"
+#include "bootmagic.h"
++#include "hook.h"
+
+keymap_config_t keymap_config;
+
+void bootmagic(void)
+{
+ /* check signature */
+ if (!eeconfig_is_enabled()) {
+ eeconfig_init();
+ }
+
+ /* do scans in case of bounce */
+ print("bootmagic scan: ... ");
+ uint8_t scan = 100;
+ while (scan--) { matrix_scan(); wait_ms(10); }
+ print("done.\n");
+
+ /* bootmagic skip */
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_SKIP)) {
+ return;
+ }
+
+ /* eeconfig clear */
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_EEPROM_CLEAR)) {
+ eeconfig_init();
+ }
+
+ /* bootloader */
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_BOOTLOADER)) {
+ bootloader_jump();
+ }
+
++ /* user-defined checks */
++ hook_bootmagic();
++
+ /* debug enable */
+ debug_config.raw = eeconfig_read_debug();
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_DEBUG_ENABLE)) {
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_DEBUG_MATRIX)) {
+ debug_config.matrix = !debug_config.matrix;
+ } else if (bootmagic_scan_key(BOOTMAGIC_KEY_DEBUG_KEYBOARD)) {
+ debug_config.keyboard = !debug_config.keyboard;
+ } else if (bootmagic_scan_key(BOOTMAGIC_KEY_DEBUG_MOUSE)) {
+ debug_config.mouse = !debug_config.mouse;
+ } else {
+ debug_config.enable = !debug_config.enable;
+ }
+ }
+ eeconfig_write_debug(debug_config.raw);
+
+ /* keymap config */
+ keymap_config.raw = eeconfig_read_keymap();
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK)) {
+ keymap_config.swap_control_capslock = !keymap_config.swap_control_capslock;
+ }
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL)) {
+ keymap_config.capslock_to_control = !keymap_config.capslock_to_control;
+ }
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_SWAP_LALT_LGUI)) {
+ keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui;
+ }
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_SWAP_RALT_RGUI)) {
+ keymap_config.swap_ralt_rgui = !keymap_config.swap_ralt_rgui;
+ }
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_NO_GUI)) {
+ keymap_config.no_gui = !keymap_config.no_gui;
+ }
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_SWAP_GRAVE_ESC)) {
+ keymap_config.swap_grave_esc = !keymap_config.swap_grave_esc;
+ }
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE)) {
+ keymap_config.swap_backslash_backspace = !keymap_config.swap_backslash_backspace;
+ }
+ if (bootmagic_scan_key(BOOTMAGIC_HOST_NKRO)) {
+ keymap_config.nkro = !keymap_config.nkro;
+ }
+ eeconfig_write_keymap(keymap_config.raw);
+
+#ifdef NKRO_ENABLE
+ keyboard_nkro = keymap_config.nkro;
+#endif
+
+ /* default layer */
+ uint8_t default_layer = 0;
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_DEFAULT_LAYER_0)) { default_layer |= (1<<0); }
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_DEFAULT_LAYER_1)) { default_layer |= (1<<1); }
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_DEFAULT_LAYER_2)) { default_layer |= (1<<2); }
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_DEFAULT_LAYER_3)) { default_layer |= (1<<3); }
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_DEFAULT_LAYER_4)) { default_layer |= (1<<4); }
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_DEFAULT_LAYER_5)) { default_layer |= (1<<5); }
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_DEFAULT_LAYER_6)) { default_layer |= (1<<6); }
+ if (bootmagic_scan_key(BOOTMAGIC_KEY_DEFAULT_LAYER_7)) { default_layer |= (1<<7); }
+ if (default_layer) {
+ eeconfig_write_default_layer(default_layer);
+ default_layer_set((uint32_t)default_layer);
+ } else {
+ default_layer = eeconfig_read_default_layer();
+ default_layer_set((uint32_t)default_layer);
+ }
+}
+
+static bool scan_key(uint16_t code)
+{
+ for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
+ matrix_row_t matrix_row = matrix_get_row(r);
+ for (uint8_t c = 0; c < MATRIX_COLS; c++) {
+ if (matrix_row & ((matrix_row_t)1<<c)) {
+ // read key from Layer 0
+ action_t action = action_for_key(0, (keypos_t){ .row = r, .col = c });
+ if (action.code == code ||
+ ((action.kind.id == ACT_LMODS ||
+ action.kind.id == ACT_RMODS ||
+ action.kind.id == ACT_LMODS_TAP ||
+ action.kind.id == ACT_RMODS_TAP ||
+ action.kind.id == ACT_LAYER_TAP ||
+ action.kind.id == ACT_LAYER_TAP_EXT) &&
+ action.key.code == code)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool bootmagic_scan_key(uint16_t code)
+{
+ if (!scan_key(BOOTMAGIC_KEY_SALT)) return false;
+
+ return scan_key(code);
+}