aboutsummaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
Diffstat (limited to 'quantum')
-rw-r--r--quantum/action.c20
-rw-r--r--quantum/action.h6
-rw-r--r--quantum/action_layer.c19
-rw-r--r--quantum/action_layer.h3
-rw-r--r--quantum/action_tapping.c212
-rw-r--r--quantum/action_tapping.h60
-rw-r--r--quantum/action_util.c9
-rw-r--r--quantum/audio/audio.h4
-rw-r--r--quantum/backlight/backlight.h4
-rw-r--r--quantum/bits.h2
-rw-r--r--quantum/command.c7
-rw-r--r--quantum/compiler_support.h15
-rw-r--r--quantum/connection/connection.c141
-rw-r--r--quantum/connection/connection.h112
-rw-r--r--quantum/dynamic_keymap.c4
-rw-r--r--quantum/eeconfig.c50
-rw-r--r--quantum/eeconfig.h10
-rw-r--r--quantum/haptic.h4
-rw-r--r--quantum/keyboard.c7
-rw-r--r--quantum/keycode_config.h6
-rw-r--r--quantum/keycodes.h6
-rw-r--r--quantum/keymap_common.c2
-rw-r--r--quantum/keymap_extras/keymap_belgian.h6
-rw-r--r--quantum/keymap_extras/keymap_bepo.h6
-rw-r--r--quantum/keymap_extras/keymap_brazilian_abnt2.h6
-rw-r--r--quantum/keymap_extras/keymap_canadian_french.h6
-rw-r--r--quantum/keymap_extras/keymap_canadian_multilingual.h6
-rw-r--r--quantum/keymap_extras/keymap_colemak.h6
-rw-r--r--quantum/keymap_extras/keymap_croatian.h6
-rw-r--r--quantum/keymap_extras/keymap_czech.h6
-rw-r--r--quantum/keymap_extras/keymap_czech_mac_ansi.h6
-rw-r--r--quantum/keymap_extras/keymap_czech_mac_iso.h6
-rw-r--r--quantum/keymap_extras/keymap_danish.h6
-rw-r--r--quantum/keymap_extras/keymap_dvorak.h6
-rw-r--r--quantum/keymap_extras/keymap_dvorak_fr.h6
-rw-r--r--quantum/keymap_extras/keymap_dvorak_programmer.h6
-rw-r--r--quantum/keymap_extras/keymap_estonian.h6
-rw-r--r--quantum/keymap_extras/keymap_eurkey.h6
-rw-r--r--quantum/keymap_extras/keymap_farsi.h6
-rw-r--r--quantum/keymap_extras/keymap_finnish.h6
-rw-r--r--quantum/keymap_extras/keymap_french.h6
-rw-r--r--quantum/keymap_extras/keymap_french_afnor.h6
-rw-r--r--quantum/keymap_extras/keymap_french_mac_iso.h6
-rw-r--r--quantum/keymap_extras/keymap_german.h6
-rw-r--r--quantum/keymap_extras/keymap_german_mac_iso.h6
-rw-r--r--quantum/keymap_extras/keymap_greek.h6
-rw-r--r--quantum/keymap_extras/keymap_hebrew.h6
-rw-r--r--quantum/keymap_extras/keymap_hungarian.h6
-rw-r--r--quantum/keymap_extras/keymap_icelandic.h6
-rw-r--r--quantum/keymap_extras/keymap_irish.h6
-rw-r--r--quantum/keymap_extras/keymap_italian.h6
-rw-r--r--quantum/keymap_extras/keymap_italian_mac_ansi.h6
-rw-r--r--quantum/keymap_extras/keymap_italian_mac_iso.h6
-rw-r--r--quantum/keymap_extras/keymap_japanese.h6
-rw-r--r--quantum/keymap_extras/keymap_korean.h6
-rw-r--r--quantum/keymap_extras/keymap_latvian.h6
-rw-r--r--quantum/keymap_extras/keymap_lithuanian_azerty.h6
-rw-r--r--quantum/keymap_extras/keymap_lithuanian_qwerty.h6
-rw-r--r--quantum/keymap_extras/keymap_neo2.h6
-rw-r--r--quantum/keymap_extras/keymap_nordic.h6
-rw-r--r--quantum/keymap_extras/keymap_norman.h6
-rw-r--r--quantum/keymap_extras/keymap_norwegian.h6
-rw-r--r--quantum/keymap_extras/keymap_plover.h6
-rw-r--r--quantum/keymap_extras/keymap_plover_dvorak.h6
-rw-r--r--quantum/keymap_extras/keymap_polish.h6
-rw-r--r--quantum/keymap_extras/keymap_portuguese.h6
-rw-r--r--quantum/keymap_extras/keymap_portuguese_mac_iso.h6
-rw-r--r--quantum/keymap_extras/keymap_romanian.h6
-rw-r--r--quantum/keymap_extras/keymap_russian.h6
-rw-r--r--quantum/keymap_extras/keymap_russian_typewriter.h6
-rw-r--r--quantum/keymap_extras/keymap_serbian.h6
-rw-r--r--quantum/keymap_extras/keymap_serbian_latin.h6
-rw-r--r--quantum/keymap_extras/keymap_slovak.h6
-rw-r--r--quantum/keymap_extras/keymap_slovenian.h6
-rw-r--r--quantum/keymap_extras/keymap_spanish.h6
-rw-r--r--quantum/keymap_extras/keymap_spanish_dvorak.h6
-rw-r--r--quantum/keymap_extras/keymap_spanish_latin_america.h6
-rw-r--r--quantum/keymap_extras/keymap_swedish.h6
-rw-r--r--quantum/keymap_extras/keymap_swedish_mac_ansi.h6
-rw-r--r--quantum/keymap_extras/keymap_swedish_mac_iso.h6
-rw-r--r--quantum/keymap_extras/keymap_swedish_pro_mac_ansi.h6
-rw-r--r--quantum/keymap_extras/keymap_swedish_pro_mac_iso.h6
-rw-r--r--quantum/keymap_extras/keymap_swiss_de.h6
-rw-r--r--quantum/keymap_extras/keymap_swiss_fr.h6
-rw-r--r--quantum/keymap_extras/keymap_turkish_f.h6
-rw-r--r--quantum/keymap_extras/keymap_turkish_q.h6
-rw-r--r--quantum/keymap_extras/keymap_uk.h6
-rw-r--r--quantum/keymap_extras/keymap_ukrainian.h6
-rw-r--r--quantum/keymap_extras/keymap_us.h6
-rw-r--r--quantum/keymap_extras/keymap_us_extended.h6
-rw-r--r--quantum/keymap_extras/keymap_us_international.h6
-rw-r--r--quantum/keymap_extras/keymap_us_international_linux.h6
-rw-r--r--quantum/keymap_extras/keymap_workman.h6
-rw-r--r--quantum/keymap_extras/keymap_workman_zxcvm.h6
-rw-r--r--quantum/keymap_introspection.c13
-rw-r--r--quantum/led_matrix/led_matrix.c78
-rw-r--r--quantum/led_matrix/led_matrix.h10
-rw-r--r--quantum/led_matrix/led_matrix_types.h4
-rw-r--r--quantum/nvm/eeprom/nvm_dynamic_keymap.c7
-rw-r--r--quantum/nvm/eeprom/nvm_eeconfig.c13
-rw-r--r--quantum/nvm/eeprom/nvm_eeprom_eeconfig_internal.h6
-rw-r--r--quantum/nvm/nvm_eeconfig.h6
-rw-r--r--quantum/os_detection.c26
-rw-r--r--quantum/painter/qff.h9
-rw-r--r--quantum/painter/qgf.h17
-rw-r--r--quantum/painter/qp_draw_core.c3
-rw-r--r--quantum/painter/qp_internal.c4
-rw-r--r--quantum/painter/qp_internal_formats.h3
-rw-r--r--quantum/pointing_device/pointing_device.c86
-rw-r--r--quantum/pointing_device/pointing_device.h42
-rw-r--r--quantum/process_keycode/process_caps_word.c7
-rw-r--r--quantum/process_keycode/process_connection.c24
-rw-r--r--quantum/process_keycode/process_leader.c6
-rw-r--r--quantum/process_keycode/process_oneshot.c25
-rw-r--r--quantum/process_keycode/process_oneshot.h10
-rw-r--r--quantum/process_keycode/process_quantum.c76
-rw-r--r--quantum/process_keycode/process_quantum.h10
-rw-r--r--quantum/process_keycode/process_repeat_key.c5
-rw-r--r--quantum/process_keycode/process_underglow.c5
-rw-r--r--quantum/quantum.c111
-rw-r--r--quantum/quantum.h1
-rw-r--r--quantum/quantum_keycodes.h122
-rw-r--r--quantum/quantum_keycodes_legacy.h2
-rw-r--r--quantum/raw_hid.c15
-rw-r--r--quantum/rgb_matrix/animations/pixel_flow_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/rgb_matrix_effects.inc1
-rw-r--r--quantum/rgb_matrix/animations/starlight_smooth_anim.h26
-rw-r--r--quantum/rgb_matrix/rgb_matrix.c79
-rw-r--r--quantum/rgb_matrix/rgb_matrix.h10
-rw-r--r--quantum/rgb_matrix/rgb_matrix_types.h4
-rw-r--r--quantum/rgblight/rgblight.c8
-rw-r--r--quantum/rgblight/rgblight.h4
-rw-r--r--quantum/split_common/split_util.c8
-rw-r--r--quantum/split_common/transaction_id_define.h4
-rw-r--r--quantum/split_common/transport.c3
-rw-r--r--quantum/unicode/unicode.c1
-rw-r--r--quantum/unicode/unicode.h4
-rw-r--r--quantum/via.c1
-rw-r--r--quantum/wear_leveling/wear_leveling.c1
-rw-r--r--quantum/wear_leveling/wear_leveling_drivers.h13
-rw-r--r--quantum/wear_leveling/wear_leveling_internal.h14
141 files changed, 1769 insertions, 297 deletions
diff --git a/quantum/action.c b/quantum/action.c
index be85192d25..dd82c9ec99 100644
--- a/quantum/action.c
+++ b/quantum/action.c
@@ -281,6 +281,9 @@ void process_record(keyrecord_t *record) {
if (IS_NOEVENT(record->event)) {
return;
}
+#ifdef FLOW_TAP_TERM
+ flow_tap_update_last_event(record);
+#endif // FLOW_TAP_TERM
if (!process_record_quantum(record)) {
#ifndef NO_ACTION_ONESHOT
@@ -1183,6 +1186,23 @@ bool is_tap_action(action_t action) {
return false;
}
+uint16_t get_tap_keycode(uint16_t keycode) {
+ switch (keycode) {
+ case QK_MOD_TAP ... QK_MOD_TAP_MAX:
+ return QK_MOD_TAP_GET_TAP_KEYCODE(keycode);
+ case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
+ return QK_LAYER_TAP_GET_TAP_KEYCODE(keycode);
+ case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX:
+ // IS_SWAP_HANDS_KEYCODE() tests for the special action keycodes
+ // like SH_TOGG, SH_TT, ..., which overlap the SH_T(kc) range.
+ if (!IS_SWAP_HANDS_KEYCODE(keycode)) {
+ return QK_SWAP_HANDS_GET_TAP_KEYCODE(keycode);
+ }
+ break;
+ }
+ return keycode;
+}
+
/** \brief Debug print (FIXME: Needs better description)
*
* FIXME: Needs documentation.
diff --git a/quantum/action.h b/quantum/action.h
index 7596688f31..7616486c6d 100644
--- a/quantum/action.h
+++ b/quantum/action.h
@@ -128,6 +128,12 @@ void layer_switch(uint8_t new_layer);
bool is_tap_record(keyrecord_t *record);
bool is_tap_action(action_t action);
+/**
+ * Given an MT or LT keycode, returns the tap keycode. Otherwise returns the
+ * original keycode unchanged.
+ */
+uint16_t get_tap_keycode(uint16_t keycode);
+
#ifndef NO_ACTION_TAPPING
void process_record_tap_hint(keyrecord_t *record);
#endif
diff --git a/quantum/action_layer.c b/quantum/action_layer.c
index 7c09a5bd1e..5828dcb824 100644
--- a/quantum/action_layer.c
+++ b/quantum/action_layer.c
@@ -27,11 +27,20 @@ __attribute__((weak)) layer_state_t default_layer_state_set_kb(layer_state_t sta
return default_layer_state_set_user(state);
}
+/** \brief Default Layer State Set At Module Level
+ *
+ * Run module code on default layer state change
+ */
+__attribute__((weak)) layer_state_t default_layer_state_set_modules(layer_state_t state) {
+ return state;
+}
+
/** \brief Default Layer State Set
*
* Static function to set the default layer state, prints debug info and clears keys
*/
static void default_layer_state_set(layer_state_t state) {
+ state = default_layer_state_set_modules(state);
state = default_layer_state_set_kb(state);
ac_dprintf("default_layer_state: ");
default_layer_debug();
@@ -107,11 +116,21 @@ __attribute__((weak)) layer_state_t layer_state_set_kb(layer_state_t state) {
return layer_state_set_user(state);
}
+/** \brief Layer state set modules
+ *
+ * Runs module code on layer state change
+ */
+
+__attribute__((weak)) layer_state_t layer_state_set_modules(layer_state_t state) {
+ return state;
+}
+
/** \brief Layer state set
*
* Sets the layer to match the specified state (a bitmask)
*/
void layer_state_set(layer_state_t state) {
+ state = layer_state_set_modules(state);
state = layer_state_set_kb(state);
ac_dprintf("layer_state: ");
layer_debug();
diff --git a/quantum/action_layer.h b/quantum/action_layer.h
index a2410d49a5..067e33cdb5 100644
--- a/quantum/action_layer.h
+++ b/quantum/action_layer.h
@@ -78,6 +78,7 @@ extern layer_state_t default_layer_state;
void default_layer_debug(void);
void default_layer_set(layer_state_t state);
+__attribute__((weak)) layer_state_t default_layer_state_set_modules(layer_state_t state);
__attribute__((weak)) layer_state_t default_layer_state_set_kb(layer_state_t state);
__attribute__((weak)) layer_state_t default_layer_state_set_user(layer_state_t state);
@@ -114,6 +115,7 @@ void layer_and(layer_state_t state);
void layer_xor(layer_state_t state);
layer_state_t layer_state_set_user(layer_state_t state);
layer_state_t layer_state_set_kb(layer_state_t state);
+layer_state_t layer_state_set_modules(layer_state_t state);
/**
* @brief Applies the tri layer to global layer state. Not be used in layer_state_set_(kb|user) functions.
@@ -149,6 +151,7 @@ layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_
# define layer_or(state) (void)state
# define layer_and(state) (void)state
# define layer_xor(state) (void)state
+# define layer_state_set_modules(state) (void)state
# define layer_state_set_kb(state) (void)state
# define layer_state_set_user(state) (void)state
# define update_tri_layer(layer1, layer2, layer3)
diff --git a/quantum/action_tapping.c b/quantum/action_tapping.c
index e42a98554d..b105cd60a9 100644
--- a/quantum/action_tapping.c
+++ b/quantum/action_tapping.c
@@ -4,7 +4,9 @@
#include "action.h"
#include "action_layer.h"
#include "action_tapping.h"
+#include "action_util.h"
#include "keycode.h"
+#include "quantum_keycodes.h"
#include "timer.h"
#ifndef NO_ACTION_TAPPING
@@ -49,9 +51,7 @@ __attribute__((weak)) bool get_permissive_hold(uint16_t keycode, keyrecord_t *re
}
# endif
-# if defined(CHORDAL_HOLD)
-extern const char chordal_hold_layout[MATRIX_ROWS][MATRIX_COLS] PROGMEM;
-
+# if defined(CHORDAL_HOLD) || defined(FLOW_TAP_TERM)
# define REGISTERED_TAPS_SIZE 8
// Array of tap-hold keys that have been settled as tapped but not yet released.
static keypos_t registered_taps[REGISTERED_TAPS_SIZE] = {};
@@ -66,6 +66,14 @@ static void registered_taps_del_index(uint8_t i);
/** Logs the registered_taps array for debugging. */
static void debug_registered_taps(void);
+static bool is_mt_or_lt(uint16_t keycode) {
+ return IS_QK_MOD_TAP(keycode) || IS_QK_LAYER_TAP(keycode);
+}
+# endif // defined(CHORDAL_HOLD) || defined(FLOW_TAP_TERM)
+
+# if defined(CHORDAL_HOLD)
+extern const char chordal_hold_layout[MATRIX_ROWS][MATRIX_COLS] PROGMEM;
+
/** \brief Finds which queued events should be held according to Chordal Hold.
*
* In a situation with multiple unsettled tap-hold key presses, scan the queue
@@ -82,10 +90,6 @@ static void waiting_buffer_chordal_hold_taps_until(keypos_t key);
/** \brief Processes and pops buffered events until the first tap-hold event. */
static void waiting_buffer_process_regular(void);
-
-static bool is_mt_or_lt(uint16_t keycode) {
- return IS_QK_MOD_TAP(keycode) || IS_QK_LAYER_TAP(keycode);
-}
# endif // CHORDAL_HOLD
# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
@@ -98,6 +102,14 @@ __attribute__((weak)) bool get_hold_on_other_key_press(uint16_t keycode, keyreco
# include "process_auto_shift.h"
# endif
+# if defined(FLOW_TAP_TERM)
+static uint16_t flow_tap_prev_keycode = KC_NO;
+static uint16_t flow_tap_prev_time = 0;
+static bool flow_tap_expired = true;
+
+static bool flow_tap_key_if_within_term(keyrecord_t *record, uint16_t prev_time);
+# endif // defined(FLOW_TAP_TERM)
+
static keyrecord_t tapping_key = {};
static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
static uint8_t waiting_buffer_head = 0;
@@ -148,6 +160,12 @@ void action_tapping_process(keyrecord_t record) {
}
if (IS_EVENT(record.event)) {
ac_dprintf("\n");
+ } else {
+# ifdef FLOW_TAP_TERM
+ if (!flow_tap_expired && TIMER_DIFF_16(record.event.time, flow_tap_prev_time) >= INT16_MAX / 2) {
+ flow_tap_expired = true;
+ }
+# endif // FLOW_TAP_TERM
}
}
@@ -205,7 +223,7 @@ void action_tapping_process(keyrecord_t record) {
bool process_tapping(keyrecord_t *keyp) {
const keyevent_t event = keyp->event;
-# if defined(CHORDAL_HOLD)
+# if defined(CHORDAL_HOLD) || defined(FLOW_TAP_TERM)
if (!event.pressed) {
const int8_t i = registered_tap_find(event.key);
if (i != -1) {
@@ -217,7 +235,7 @@ bool process_tapping(keyrecord_t *keyp) {
debug_registered_taps();
}
}
-# endif // CHORDAL_HOLD
+# endif // defined(CHORDAL_HOLD) || defined(FLOW_TAP_TERM)
// state machine is in the "reset" state, no tapping key is to be
// processed
@@ -227,6 +245,13 @@ bool process_tapping(keyrecord_t *keyp) {
} else if (event.pressed && is_tap_record(keyp)) {
// the currently pressed key is a tapping key, therefore transition
// into the "pressed" tapping key state
+
+# if defined(FLOW_TAP_TERM)
+ if (flow_tap_key_if_within_term(keyp, flow_tap_prev_time)) {
+ return true;
+ }
+# endif // defined(FLOW_TAP_TERM)
+
ac_dprintf("Tapping: Start(Press tap key).\n");
tapping_key = *keyp;
process_record_tap_hint(&tapping_key);
@@ -263,6 +288,27 @@ bool process_tapping(keyrecord_t *keyp) {
// copy tapping state
keyp->tap = tapping_key.tap;
+
+# if defined(FLOW_TAP_TERM)
+ // Now that tapping_key has settled as tapped, check whether
+ // Flow Tap applies to following yet-unsettled keys.
+ uint16_t prev_time = tapping_key.event.time;
+ for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) {
+ keyrecord_t *record = &waiting_buffer[waiting_buffer_tail];
+ if (!record->event.pressed) {
+ break;
+ }
+ const int16_t next_time = record->event.time;
+ if (!is_tap_record(record)) {
+ process_record(record);
+ } else if (!flow_tap_key_if_within_term(record, prev_time)) {
+ break;
+ }
+ prev_time = next_time;
+ }
+ debug_waiting_buffer();
+# endif // defined(FLOW_TAP_TERM)
+
// enqueue
return false;
}
@@ -538,6 +584,13 @@ bool process_tapping(keyrecord_t *keyp) {
return true;
} else if (is_tap_record(keyp)) {
// Sequential tap can be interfered with other tap key.
+# if defined(FLOW_TAP_TERM)
+ if (flow_tap_key_if_within_term(keyp, flow_tap_prev_time)) {
+ tapping_key = (keyrecord_t){0};
+ debug_tapping_key();
+ return true;
+ }
+# endif // defined(FLOW_TAP_TERM)
ac_dprintf("Tapping: Start with interfering other tap.\n");
tapping_key = *keyp;
waiting_buffer_scan_tap();
@@ -655,28 +708,7 @@ void waiting_buffer_scan_tap(void) {
}
}
-# ifdef CHORDAL_HOLD
-__attribute__((weak)) bool get_chordal_hold(uint16_t tap_hold_keycode, keyrecord_t *tap_hold_record, uint16_t other_keycode, keyrecord_t *other_record) {
- return get_chordal_hold_default(tap_hold_record, other_record);
-}
-
-bool get_chordal_hold_default(keyrecord_t *tap_hold_record, keyrecord_t *other_record) {
- if (tap_hold_record->event.type != KEY_EVENT || other_record->event.type != KEY_EVENT) {
- return true; // Return true on combos or other non-key events.
- }
-
- char tap_hold_hand = chordal_hold_handedness(tap_hold_record->event.key);
- if (tap_hold_hand == '*') {
- return true;
- }
- char other_hand = chordal_hold_handedness(other_record->event.key);
- return other_hand == '*' || tap_hold_hand != other_hand;
-}
-
-__attribute__((weak)) char chordal_hold_handedness(keypos_t key) {
- return (char)pgm_read_byte(&chordal_hold_layout[key.row][key.col]);
-}
-
+# if defined(CHORDAL_HOLD) || defined(FLOW_TAP_TERM)
static void registered_taps_add(keypos_t key) {
if (num_registered_taps >= REGISTERED_TAPS_SIZE) {
ac_dprintf("TAPS OVERFLOW: CLEAR ALL STATES\n");
@@ -714,6 +746,30 @@ static void debug_registered_taps(void) {
ac_dprintf("}\n");
}
+# endif // defined(CHORDAL_HOLD) || defined(FLOW_TAP_TERM)
+
+# ifdef CHORDAL_HOLD
+__attribute__((weak)) bool get_chordal_hold(uint16_t tap_hold_keycode, keyrecord_t *tap_hold_record, uint16_t other_keycode, keyrecord_t *other_record) {
+ return get_chordal_hold_default(tap_hold_record, other_record);
+}
+
+bool get_chordal_hold_default(keyrecord_t *tap_hold_record, keyrecord_t *other_record) {
+ if (tap_hold_record->event.type != KEY_EVENT || other_record->event.type != KEY_EVENT) {
+ return true; // Return true on combos or other non-key events.
+ }
+
+ char tap_hold_hand = chordal_hold_handedness(tap_hold_record->event.key);
+ if (tap_hold_hand == '*') {
+ return true;
+ }
+ char other_hand = chordal_hold_handedness(other_record->event.key);
+ return other_hand == '*' || tap_hold_hand != other_hand;
+}
+
+__attribute__((weak)) char chordal_hold_handedness(keypos_t key) {
+ return (char)pgm_read_byte(&chordal_hold_layout[key.row][key.col]);
+}
+
static uint8_t waiting_buffer_find_chordal_hold_tap(void) {
keyrecord_t *prev = &tapping_key;
uint16_t prev_keycode = get_record_keycode(&tapping_key, false);
@@ -761,6 +817,100 @@ static void waiting_buffer_process_regular(void) {
}
# endif // CHORDAL_HOLD
+# ifdef FLOW_TAP_TERM
+void flow_tap_update_last_event(keyrecord_t *record) {
+ const uint16_t keycode = get_record_keycode(record, false);
+ // Don't update while a tap-hold key is unsettled.
+ if (record->tap.count == 0 && (waiting_buffer_tail != waiting_buffer_head || (tapping_key.event.pressed && tapping_key.tap.count == 0))) {
+ return;
+ }
+ // Ignore releases of modifiers and held layer switches.
+ if (!record->event.pressed) {
+ switch (keycode) {
+ case MODIFIER_KEYCODE_RANGE:
+ case QK_MOMENTARY ... QK_MOMENTARY_MAX:
+ case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX:
+# ifndef NO_ACTION_ONESHOT // Ignore one-shot keys.
+ case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:
+ case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX:
+# endif // NO_ACTION_ONESHOT
+# ifdef TRI_LAYER_ENABLE // Ignore Tri Layer keys.
+ case QK_TRI_LAYER_LOWER:
+ case QK_TRI_LAYER_UPPER:
+# endif // TRI_LAYER_ENABLE
+ return;
+ case QK_MODS ... QK_MODS_MAX:
+ if (QK_MODS_GET_BASIC_KEYCODE(keycode) == KC_NO) {
+ return;
+ }
+ break;
+ case QK_MOD_TAP ... QK_MOD_TAP_MAX:
+ case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
+ if (record->tap.count == 0) {
+ return;
+ }
+ break;
+ }
+ }
+
+ flow_tap_prev_keycode = keycode;
+ flow_tap_prev_time = record->event.time;
+ flow_tap_expired = false;
+}
+
+static bool flow_tap_key_if_within_term(keyrecord_t *record, uint16_t prev_time) {
+ const uint16_t idle_time = TIMER_DIFF_16(record->event.time, prev_time);
+ if (flow_tap_expired || idle_time >= 500) {
+ return false;
+ }
+
+ const uint16_t keycode = get_record_keycode(record, false);
+ if (is_mt_or_lt(keycode)) {
+ uint16_t term = get_flow_tap_term(keycode, record, flow_tap_prev_keycode);
+ if (term > 500) {
+ term = 500;
+ }
+ if (idle_time < term) {
+ debug_event(record->event);
+ ac_dprintf(" within flow tap term (%u < %u) considered a tap\n", idle_time, term);
+ record->tap.count = 1;
+ registered_taps_add(record->event.key);
+ debug_registered_taps();
+ process_record(record);
+ return true;
+ }
+ }
+ return false;
+}
+
+// By default, enable Flow Tap for the keys in the main alphas area and Space.
+// This should work reasonably even if the layout is remapped on the host to an
+// alt layout or international layout (e.g. Dvorak or AZERTY), where these same
+// key positions are mostly used for typing letters.
+__attribute__((weak)) bool is_flow_tap_key(uint16_t keycode) {
+ if ((get_mods() & (MOD_MASK_CG | MOD_BIT_LALT)) != 0) {
+ return false; // Disable Flow Tap on hotkeys.
+ }
+ switch (get_tap_keycode(keycode)) {
+ case KC_SPC:
+ case KC_A ... KC_Z:
+ case KC_DOT:
+ case KC_COMM:
+ case KC_SCLN:
+ case KC_SLSH:
+ return true;
+ }
+ return false;
+}
+
+__attribute__((weak)) uint16_t get_flow_tap_term(uint16_t keycode, keyrecord_t *record, uint16_t prev_keycode) {
+ if (is_flow_tap_key(keycode) && is_flow_tap_key(prev_keycode)) {
+ return FLOW_TAP_TERM;
+ }
+ return 0;
+}
+# endif // FLOW_TAP_TERM
+
/** \brief Logs tapping key if ACTION_DEBUG is enabled. */
static void debug_tapping_key(void) {
ac_dprintf("TAPPING_KEY=");
diff --git a/quantum/action_tapping.h b/quantum/action_tapping.h
index c3c7b999ec..0cf4aa1200 100644
--- a/quantum/action_tapping.h
+++ b/quantum/action_tapping.h
@@ -111,6 +111,66 @@ char chordal_hold_handedness(keypos_t key);
extern const char chordal_hold_layout[MATRIX_ROWS][MATRIX_COLS] PROGMEM;
#endif
+#ifdef FLOW_TAP_TERM
+/**
+ * Callback to specify the keys where Flow Tap is enabled.
+ *
+ * Flow Tap is constrained to certain keys by the following rule: this callback
+ * is called for both the tap-hold key *and* the key press immediately preceding
+ * it. If the callback returns true for both keycodes, Flow Tap is enabled.
+ *
+ * The default implementation of this callback corresponds to
+ *
+ * bool is_flow_tap_key(uint16_t keycode) {
+ * switch (get_tap_keycode(keycode)) {
+ * case KC_SPC:
+ * case KC_A ... KC_Z:
+ * case KC_DOT:
+ * case KC_COMM:
+ * case KC_SCLN:
+ * case KC_SLSH:
+ * return true;
+ * }
+ * return false;
+ * }
+ *
+ * @param keycode Keycode of the key.
+ * @return Whether to enable Flow Tap for this key.
+ */
+bool is_flow_tap_key(uint16_t keycode);
+
+/**
+ * Callback to customize Flow Tap filtering.
+ *
+ * Flow Tap acts only when key events are closer together than this time.
+ *
+ * Return a time of 0 to disable filtering. In this way, Flow Tap may be
+ * disabled for certain tap-hold keys, or when following certain previous keys.
+ *
+ * The default implementation of this callback is
+ *
+ * uint16_t get_flow_tap_term(uint16_t keycode, keyrecord_t* record,
+ * uint16_t prev_keycode) {
+ * if (is_flow_tap_key(keycode) && is_flow_tap_key(prev_keycode)) {
+ * return g_flow_tap_term;
+ * }
+ * return 0;
+ * }
+ *
+ * NOTE: If both `is_flow_tap_key()` and `get_flow_tap_term()` are defined, then
+ * `get_flow_tap_term()` takes precedence.
+ *
+ * @param keycode Keycode of the tap-hold key.
+ * @param record keyrecord_t of the tap-hold event.
+ * @param prev_keycode Keycode of the previously pressed key.
+ * @return Time in milliseconds.
+ */
+uint16_t get_flow_tap_term(uint16_t keycode, keyrecord_t *record, uint16_t prev_keycode);
+
+/** Updates the Flow Tap last key and timer. */
+void flow_tap_update_last_event(keyrecord_t *record);
+#endif // FLOW_TAP_TERM
+
#ifdef DYNAMIC_TAPPING_TERM_ENABLE
extern uint16_t g_tapping_term;
#endif
diff --git a/quantum/action_util.c b/quantum/action_util.c
index 9fe17f2124..e821e113ef 100644
--- a/quantum/action_util.c
+++ b/quantum/action_util.c
@@ -21,7 +21,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "action_layer.h"
#include "timer.h"
#include "keycode_config.h"
-#include "usb_device_state.h"
#include <string.h>
extern keymap_config_t keymap_config;
@@ -319,14 +318,12 @@ void send_nkro_report(void) {
*/
void send_keyboard_report(void) {
#ifdef NKRO_ENABLE
- if (usb_device_state_get_protocol() == USB_PROTOCOL_REPORT && keymap_config.nkro) {
+ if (host_can_send_nkro() && keymap_config.nkro) {
send_nkro_report();
- } else {
- send_6kro_report();
+ return;
}
-#else
- send_6kro_report();
#endif
+ send_6kro_report();
}
/** \brief Get mods
diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h
index 93dc6f62b1..647744a686 100644
--- a/quantum/audio/audio.h
+++ b/quantum/audio/audio.h
@@ -18,6 +18,8 @@
#include <stdint.h>
#include <stdbool.h>
+
+#include "compiler_support.h"
#include "musical_notes.h"
#include "song_list.h"
#include "voices.h"
@@ -38,7 +40,7 @@ typedef union audio_config_t {
};
} audio_config_t;
-_Static_assert(sizeof(audio_config_t) == sizeof(uint8_t), "Audio EECONFIG out of spec.");
+STATIC_ASSERT(sizeof(audio_config_t) == sizeof(uint8_t), "Audio EECONFIG out of spec.");
/*
* a 'musical note' is represented by pitch and duration; a 'musical tone' adds intensity and timbre
diff --git a/quantum/backlight/backlight.h b/quantum/backlight/backlight.h
index 561c7f8a94..2faa8fc4f2 100644
--- a/quantum/backlight/backlight.h
+++ b/quantum/backlight/backlight.h
@@ -20,6 +20,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdint.h>
#include <stdbool.h>
+#include "compiler_support.h"
+
#ifndef BACKLIGHT_LEVELS
# define BACKLIGHT_LEVELS 3
#elif BACKLIGHT_LEVELS > 31
@@ -44,7 +46,7 @@ typedef union backlight_config_t {
};
} backlight_config_t;
-_Static_assert(sizeof(backlight_config_t) == sizeof(uint8_t), "Backlight EECONFIG out of spec.");
+STATIC_ASSERT(sizeof(backlight_config_t) == sizeof(uint8_t), "Backlight EECONFIG out of spec.");
void backlight_init(void);
void backlight_toggle(void);
diff --git a/quantum/bits.h b/quantum/bits.h
index 2f3c343762..41f11e7b9c 100644
--- a/quantum/bits.h
+++ b/quantum/bits.h
@@ -4,7 +4,7 @@
#include <stdint.h>
-/* Remove these once we transitioned to C23 across all platfroms */
+/* Remove these once we transitioned to C23 across all platforms */
#define UINT32_WIDTH 32
#define UINT64_WIDTH 64
diff --git a/quantum/command.c b/quantum/command.c
index 96b637f842..ea2fd68e2b 100644
--- a/quantum/command.c
+++ b/quantum/command.c
@@ -28,7 +28,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "action_layer.h"
#include "action_util.h"
#include "eeconfig.h"
-#include "sleep_led.h"
#include "led.h"
#include "command.h"
#include "quantum.h"
@@ -39,6 +38,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# include "backlight.h"
#endif
+#ifdef SLEEP_LED_ENABLE
+# include "sleep_led.h"
+#endif
+
#if defined(MOUSEKEY_ENABLE)
# include "mousekey.h"
#endif
@@ -243,7 +246,7 @@ static void print_status(void) {
#if !defined(NO_PRINT) && !defined(USER_PRINT)
static void print_eeconfig(void) {
- xprintf("eeconfig:\ndefault_layer: %u\n", eeconfig_read_default_layer());
+ xprintf("eeconfig:\ndefault_layer: %" PRIu32 "\n", (uint32_t)eeconfig_read_default_layer());
debug_config_t dc;
eeconfig_read_debug(&dc);
diff --git a/quantum/compiler_support.h b/quantum/compiler_support.h
new file mode 100644
index 0000000000..5c0c4d2835
--- /dev/null
+++ b/quantum/compiler_support.h
@@ -0,0 +1,15 @@
+// Copyright 2025 QMK Contributors
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/**
+ * @brief Perfom an assertion at compile time.
+ *
+ * `_Static_assert` is C<23, while `static_assert` is C++/C23.
+ */
+#if !defined(STATIC_ASSERT)
+# ifdef __cplusplus
+# define STATIC_ASSERT static_assert
+# else
+# define STATIC_ASSERT _Static_assert
+# endif
+#endif
diff --git a/quantum/connection/connection.c b/quantum/connection/connection.c
new file mode 100644
index 0000000000..1ff8876876
--- /dev/null
+++ b/quantum/connection/connection.c
@@ -0,0 +1,141 @@
+// Copyright 2025 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include "connection.h"
+#include "eeconfig.h"
+#include "usb_util.h"
+#include "util.h"
+
+#ifdef BLUETOOTH_ENABLE
+# include "bluetooth.h"
+#endif
+
+// ======== DEPRECATED DEFINES - DO NOT USE ========
+#ifdef OUTPUT_DEFAULT
+# undef CONNECTION_HOST_DEFAULT
+# define CONNECTION_HOST_DEFAULT OUTPUT_DEFAULT
+#endif
+
+__attribute__((weak)) void set_output_user(uint8_t output) {}
+// ========
+
+#define CONNECTION_HOST_INVALID 0xFF
+
+#ifndef CONNECTION_HOST_DEFAULT
+# define CONNECTION_HOST_DEFAULT CONNECTION_HOST_AUTO
+#endif
+
+static const connection_host_t host_candidates[] = {
+ CONNECTION_HOST_AUTO,
+ CONNECTION_HOST_USB,
+#ifdef BLUETOOTH_ENABLE
+ CONNECTION_HOST_BLUETOOTH,
+#endif
+#if 0
+ CONNECTION_HOST_2P4GHZ,
+#endif
+};
+
+#define HOST_CANDIDATES_COUNT ARRAY_SIZE(host_candidates)
+
+static connection_config_t config = {.desired_host = CONNECTION_HOST_INVALID};
+
+void eeconfig_update_connection_default(void) {
+ config.desired_host = CONNECTION_HOST_DEFAULT;
+
+ eeconfig_update_connection(&config);
+}
+
+void connection_init(void) {
+ eeconfig_read_connection(&config);
+ if (config.desired_host == CONNECTION_HOST_INVALID) {
+ eeconfig_update_connection_default();
+ }
+}
+
+__attribute__((weak)) void connection_host_changed_user(connection_host_t host) {}
+__attribute__((weak)) void connection_host_changed_kb(connection_host_t host) {}
+
+static void handle_host_changed(void) {
+ connection_host_changed_user(config.desired_host);
+ connection_host_changed_kb(config.desired_host);
+
+ // TODO: Remove deprecated callback
+ set_output_user(config.desired_host);
+}
+
+void connection_set_host_noeeprom(connection_host_t host) {
+ if (config.desired_host == host) {
+ return;
+ }
+
+ config.desired_host = host;
+
+ handle_host_changed();
+}
+
+void connection_set_host(connection_host_t host) {
+ connection_set_host_noeeprom(host);
+
+ eeconfig_update_connection(&config);
+}
+
+void connection_next_host_noeeprom(void) {
+ uint8_t next = 0;
+ for (uint8_t i = 0; i < HOST_CANDIDATES_COUNT; i++) {
+ if (host_candidates[i] == config.desired_host) {
+ next = i == HOST_CANDIDATES_COUNT - 1 ? 0 : i + 1;
+ break;
+ }
+ }
+
+ connection_set_host_noeeprom(host_candidates[next]);
+}
+
+void connection_next_host(void) {
+ connection_next_host_noeeprom();
+
+ eeconfig_update_connection(&config);
+}
+
+void connection_prev_host_noeeprom(void) {
+ uint8_t next = 0;
+ for (uint8_t i = 0; i < HOST_CANDIDATES_COUNT; i++) {
+ if (host_candidates[i] == config.desired_host) {
+ next = i == 0 ? HOST_CANDIDATES_COUNT - 1 : i - 1;
+ break;
+ }
+ }
+
+ connection_set_host_noeeprom(host_candidates[next]);
+}
+
+void connection_prev_host(void) {
+ connection_prev_host_noeeprom();
+
+ eeconfig_update_connection(&config);
+}
+
+connection_host_t connection_get_host_raw(void) {
+ return config.desired_host;
+}
+
+connection_host_t connection_auto_detect_host(void) {
+ if (usb_connected_state()) {
+ return CONNECTION_HOST_USB;
+ }
+
+#ifdef BLUETOOTH_ENABLE
+ if (bluetooth_is_connected()) {
+ return CONNECTION_HOST_BLUETOOTH;
+ }
+#endif
+
+ return CONNECTION_HOST_NONE;
+}
+
+connection_host_t connection_get_host(void) {
+ if (config.desired_host == CONNECTION_HOST_AUTO) {
+ return connection_auto_detect_host();
+ }
+ return config.desired_host;
+}
diff --git a/quantum/connection/connection.h b/quantum/connection/connection.h
new file mode 100644
index 0000000000..b25160c759
--- /dev/null
+++ b/quantum/connection/connection.h
@@ -0,0 +1,112 @@
+// Copyright 2025 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+#include <stdint.h>
+
+#include "compiler_support.h"
+#include "util.h"
+
+/**
+ * \enum connection_host_t
+ *
+ * An enumeration of the possible hosts.
+ */
+typedef enum connection_host_t {
+ CONNECTION_HOST_AUTO,
+
+ CONNECTION_HOST_NONE,
+ CONNECTION_HOST_USB,
+ CONNECTION_HOST_BLUETOOTH,
+ CONNECTION_HOST_2P4GHZ
+} connection_host_t;
+
+/**
+ * \union connection_config_t
+ *
+ * Configuration structure for the connection subsystem.
+ */
+typedef union connection_config_t {
+ uint8_t raw;
+ connection_host_t desired_host : 8;
+} PACKED connection_config_t;
+
+STATIC_ASSERT(sizeof(connection_config_t) == sizeof(uint8_t), "Connection EECONFIG out of spec.");
+
+/**
+ * \brief Initialize the subsystem.
+ *
+ * This function must be called only once, before any of the below functions can be called.
+ */
+void connection_init(void);
+
+/**
+ * \brief Get currently configured host. Does not resolve 'CONNECTION_HOST_AUTO'.
+ *
+ * \return 'connection_host_t' of the configured host.
+ */
+connection_host_t connection_get_host_raw(void);
+
+/**
+ * \brief Get current active host.
+ *
+ * \return 'connection_host_t' of the configured host.
+ */
+connection_host_t connection_auto_detect_host(void);
+
+/**
+ * \brief Get currently configured host. Resolves 'CONNECTION_HOST_AUTO' using 'connection_auto_detect_host()'.
+ *
+ * \return 'connection_host_t' of the configured host.
+ */
+connection_host_t connection_get_host(void);
+
+/**
+ * \brief Get current host. New state is not written to EEPROM.
+ *
+ * \param host The host to configure.
+ */
+void connection_set_host_noeeprom(connection_host_t host);
+
+/**
+ * \brief Get current host.
+ *
+ * \param host The host to configure.
+ */
+void connection_set_host(connection_host_t host);
+
+/**
+ * \brief Move to the next potential host. New state is not written to EEPROM.
+ *
+ */
+void connection_next_host_noeeprom(void);
+
+/**
+ * \brief Move to the next potential host.
+ *
+ */
+void connection_next_host(void);
+
+/**
+ * \brief Move to the previous potential host. New state is not written to EEPROM.
+ *
+ */
+void connection_prev_host_noeeprom(void);
+
+/**
+ * \brief Move to the previous potential host.
+ *
+ */
+void connection_prev_host(void);
+
+/**
+ * \brief user hook called when changing configured host
+ *
+ */
+void connection_host_changed_user(connection_host_t host);
+
+/**
+ * \brief keyboard hook called when changing configured host
+ *
+ */
+void connection_host_changed_kb(connection_host_t host);
diff --git a/quantum/dynamic_keymap.c b/quantum/dynamic_keymap.c
index 756b232f59..25029e39c4 100644
--- a/quantum/dynamic_keymap.c
+++ b/quantum/dynamic_keymap.c
@@ -18,8 +18,6 @@
#include "dynamic_keymap.h"
#include "keymap_introspection.h"
#include "action.h"
-#include "eeprom.h"
-#include "progmem.h"
#include "send_string.h"
#include "keycodes.h"
#include "nvm_dynamic_keymap.h"
@@ -168,6 +166,6 @@ void dynamic_keymap_macro_send(uint8_t id) {
++offset;
}
- send_string_nvm_state_t state = {.offset = 0};
+ send_string_nvm_state_t state = {.offset = offset};
send_string_with_delay_impl(send_string_get_next_nvm, &state, DYNAMIC_KEYMAP_MACRO_DELAY);
}
diff --git a/quantum/eeconfig.c b/quantum/eeconfig.c
index 9aa60fc968..f14e6ddf97 100644
--- a/quantum/eeconfig.c
+++ b/quantum/eeconfig.c
@@ -2,16 +2,11 @@
#include <stdint.h>
#include <stdbool.h>
#include "debug.h"
-#include "eeprom.h"
#include "eeconfig.h"
#include "action_layer.h"
#include "nvm_eeconfig.h"
#include "keycode_config.h"
-#ifdef EEPROM_DRIVER
-# include "eeprom_driver.h"
-#endif // EEPROM_DRIVER
-
#ifdef BACKLIGHT_ENABLE
# include "backlight.h"
#endif // BACKLIGHT_ENABLE
@@ -40,6 +35,10 @@
# include "haptic.h"
#endif // HAPTIC_ENABLE
+#ifdef CONNECTION_ENABLE
+# include "connection.h"
+#endif // CONNECTION_ENABLE
+
#ifdef VIA_ENABLE
bool via_eeprom_is_valid(void);
void via_eeprom_set_valid(bool valid);
@@ -48,6 +47,10 @@ void eeconfig_init_via(void);
void dynamic_keymap_reset(void);
#endif // VIA_ENABLE
+#ifndef NKRO_DEFAULT_ON
+# define NKRO_DEFAULT_ON false
+#endif
+
__attribute__((weak)) void eeconfig_init_user(void) {
#if (EECONFIG_USER_DATA_SIZE) == 0
// Reset user EEPROM value to blank, rather than to a set value
@@ -83,7 +86,7 @@ void eeconfig_init_quantum(void) {
.no_gui = false,
.swap_grave_esc = false,
.swap_backslash_backspace = false,
- .nkro = false,
+ .nkro = NKRO_DEFAULT_ON,
.swap_lctl_lgui = false,
.swap_rctl_rgui = false,
.oneshot_enable = true, // Enable oneshot by default
@@ -103,8 +106,8 @@ void eeconfig_init_quantum(void) {
#endif // AUDIO_ENABLE
#ifdef RGBLIGHT_ENABLE
- rgblight_config_t rgblight_config = {0};
- eeconfig_update_rgblight(&rgblight_config);
+ extern void eeconfig_update_rgblight_default(void);
+ eeconfig_update_rgblight_default();
#endif // RGBLIGHT_ENABLE
#ifdef UNICODE_COMMON_ENABLE
@@ -117,13 +120,13 @@ void eeconfig_init_quantum(void) {
#endif // STENO_ENABLE
#ifdef RGB_MATRIX_ENABLE
- rgb_config_t rgb_matrix_config = {0};
- eeconfig_update_rgb_matrix(&rgb_matrix_config);
+ extern void eeconfig_update_rgb_matrix_default(void);
+ eeconfig_update_rgb_matrix_default();
#endif
#ifdef LED_MATRIX_ENABLE
- led_eeconfig_t led_matrix_config = {0};
- eeconfig_update_led_matrix(&led_matrix_config);
+ extern void eeconfig_update_led_matrix_default(void);
+ eeconfig_update_led_matrix_default();
#endif // LED_MATRIX_ENABLE
#ifdef HAPTIC_ENABLE
@@ -132,6 +135,11 @@ void eeconfig_init_quantum(void) {
haptic_reset();
#endif // HAPTIC_ENABLE
+#ifdef CONNECTION_ENABLE
+ extern void eeconfig_update_connection_default(void);
+ eeconfig_update_connection_default();
+#endif // CONNECTION_ENABLE
+
#if (EECONFIG_KB_DATA_SIZE) > 0
eeconfig_init_kb_datablock();
#endif // (EECONFIG_KB_DATA_SIZE) > 0
@@ -150,6 +158,15 @@ void eeconfig_init_quantum(void) {
#endif
eeconfig_init_kb();
+
+#ifdef RGB_MATRIX_ENABLE
+ extern void eeconfig_force_flush_rgb_matrix(void);
+ eeconfig_force_flush_rgb_matrix();
+#endif // RGB_MATRIX_ENABLE
+#ifdef LED_MATRIX_ENABLE
+ extern void eeconfig_force_flush_led_matrix(void);
+ eeconfig_force_flush_led_matrix();
+#endif // LED_MATRIX_ENABLE
}
void eeconfig_init(void) {
@@ -295,6 +312,15 @@ void eeconfig_update_haptic(const haptic_config_t *haptic_config) {
}
#endif // HAPTIC_ENABLE
+#ifdef CONNECTION_ENABLE
+void eeconfig_read_connection(connection_config_t *config) {
+ nvm_eeconfig_read_connection(config);
+}
+void eeconfig_update_connection(const connection_config_t *config) {
+ nvm_eeconfig_update_connection(config);
+}
+#endif // CONNECTION_ENABLE
+
bool eeconfig_read_handedness(void) {
return nvm_eeconfig_read_handedness();
}
diff --git a/quantum/eeconfig.h b/quantum/eeconfig.h
index 4044f1c294..66f8934a99 100644
--- a/quantum/eeconfig.h
+++ b/quantum/eeconfig.h
@@ -131,6 +131,12 @@ void eeconfig_read_haptic(haptic_config_t *haptic_confi
void eeconfig_update_haptic(const haptic_config_t *haptic_config) __attribute__((nonnull));
#endif
+#ifdef CONNECTION_ENABLE
+typedef union connection_config_t connection_config_t;
+void eeconfig_read_connection(connection_config_t *config);
+void eeconfig_update_connection(const connection_config_t *config);
+#endif
+
bool eeconfig_read_handedness(void);
void eeconfig_update_handedness(bool val);
@@ -148,8 +154,8 @@ bool eeconfig_is_user_datablock_valid(void);
uint32_t eeconfig_read_user_datablock(void *data, uint32_t offset, uint32_t length) __attribute__((nonnull));
uint32_t eeconfig_update_user_datablock(const void *data, uint32_t offset, uint32_t length) __attribute__((nonnull));
void eeconfig_init_user_datablock(void);
-# define eeconfig_read_user_datablock_field(__object, __field) eeconfig_read_user_datablock(&(__object.__field), offsetof(__object, __field), sizeof(__object.__field))
-# define eeconfig_update_user_datablock_field(__object, __field) eeconfig_update_user_datablock(&(__object.__field), offsetof(__object, __field), sizeof(__object.__field))
+# define eeconfig_read_user_datablock_field(__object, __field) eeconfig_read_user_datablock(&(__object.__field), offsetof(typeof(__object), __field), sizeof(__object.__field))
+# define eeconfig_update_user_datablock_field(__object, __field) eeconfig_update_user_datablock(&(__object.__field), offsetof(typeof(__object), __field), sizeof(__object.__field))
#endif // (EECONFIG_USER_DATA_SIZE) > 0
// Any "checked" debounce variant used requires implementation of:
diff --git a/quantum/haptic.h b/quantum/haptic.h
index e27f546d40..f854c75ec3 100644
--- a/quantum/haptic.h
+++ b/quantum/haptic.h
@@ -20,6 +20,8 @@
#include <stdint.h>
#include <stdbool.h>
+#include "compiler_support.h"
+
#ifndef HAPTIC_DEFAULT_FEEDBACK
# define HAPTIC_DEFAULT_FEEDBACK 0
#endif
@@ -42,7 +44,7 @@ typedef union haptic_config_t {
};
} haptic_config_t;
-_Static_assert(sizeof(haptic_config_t) == sizeof(uint32_t), "Haptic EECONFIG out of spec.");
+STATIC_ASSERT(sizeof(haptic_config_t) == sizeof(uint32_t), "Haptic EECONFIG out of spec.");
typedef enum HAPTIC_FEEDBACK {
KEY_PRESS,
diff --git a/quantum/keyboard.c b/quantum/keyboard.c
index 0671b0461f..c1a6d444a5 100644
--- a/quantum/keyboard.c
+++ b/quantum/keyboard.c
@@ -146,6 +146,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef LAYER_LOCK_ENABLE
# include "layer_lock.h"
#endif
+#ifdef CONNECTION_ENABLE
+# include "connection.h"
+#endif
static uint32_t last_input_modification_time = 0;
uint32_t last_input_activity_time(void) {
@@ -465,6 +468,9 @@ void keyboard_init(void) {
#endif
matrix_init();
quantum_init();
+#ifdef CONNECTION_ENABLE
+ connection_init();
+#endif
led_init_ports();
#ifdef BACKLIGHT_ENABLE
backlight_init_ports();
@@ -503,6 +509,7 @@ void keyboard_init(void) {
steno_init();
#endif
#if defined(NKRO_ENABLE) && defined(FORCE_NKRO)
+# pragma message "FORCE_NKRO option is now deprecated - Please migrate to NKRO_DEFAULT_ON instead."
keymap_config.nkro = 1;
eeconfig_update_keymap(&keymap_config);
#endif
diff --git a/quantum/keycode_config.h b/quantum/keycode_config.h
index 529cd0e127..804f1381d0 100644
--- a/quantum/keycode_config.h
+++ b/quantum/keycode_config.h
@@ -16,9 +16,7 @@
#pragma once
-#ifdef __cplusplus
-# define _Static_assert static_assert
-#endif
+#include "compiler_support.h"
#include "eeconfig.h"
#include "keycode.h"
@@ -47,6 +45,6 @@ typedef union keymap_config_t {
};
} keymap_config_t;
-_Static_assert(sizeof(keymap_config_t) == sizeof(uint16_t), "Keycode (magic) EECONFIG out of spec.");
+STATIC_ASSERT(sizeof(keymap_config_t) == sizeof(uint16_t), "Keycode (magic) EECONFIG out of spec.");
extern keymap_config_t keymap_config;
diff --git a/quantum/keycodes.h b/quantum/keycodes.h
index b4fc38f5ff..6a59aa376d 100644
--- a/quantum/keycodes.h
+++ b/quantum/keycodes.h
@@ -26,6 +26,12 @@
#pragma once
// clang-format off
+#define QMK_KEYCODES_VERSION "0.0.7"
+#define QMK_KEYCODES_VERSION_BCD 0x00000007
+#define QMK_KEYCODES_VERSION_MAJOR 0
+#define QMK_KEYCODES_VERSION_MINOR 0
+#define QMK_KEYCODES_VERSION_PATCH 7
+
enum qk_keycode_ranges {
// Ranges
QK_BASIC = 0x0000,
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c
index abdcd5c7ba..9be9bae943 100644
--- a/quantum/keymap_common.c
+++ b/quantum/keymap_common.c
@@ -156,7 +156,7 @@ action_t action_for_keycode(uint16_t keycode) {
case QK_LAYER_MOD ... QK_LAYER_MOD_MAX:
mod = mod_config(QK_LAYER_MOD_GET_MODS(keycode));
action_layer = QK_LAYER_MOD_GET_LAYER(keycode);
- action.code = ACTION_LAYER_MODS(action_layer, (mod & 0x10) ? mod << 4 : mod);
+ action.code = ACTION_LAYER_MODS(action_layer, (mod & 0x10) ? (mod & 0xF) << 4 : mod);
break;
#endif // NO_ACTION_LAYER
case QK_MOD_TAP ... QK_MOD_TAP_MAX:
diff --git a/quantum/keymap_extras/keymap_belgian.h b/quantum/keymap_extras/keymap_belgian.h
index 1869e66d9a..b41ed9d20b 100644
--- a/quantum/keymap_extras/keymap_belgian.h
+++ b/quantum/keymap_extras/keymap_belgian.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_BELGIAN_KEYCODES_VERSION "0.0.1"
+#define QMK_BELGIAN_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_BELGIAN_KEYCODES_VERSION_MAJOR 0
+#define QMK_BELGIAN_KEYCODES_VERSION_MINOR 0
+#define QMK_BELGIAN_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define BE_SUP2 KC_GRV // ²
#define BE_AMPR KC_1 // &
diff --git a/quantum/keymap_extras/keymap_bepo.h b/quantum/keymap_extras/keymap_bepo.h
index f2ddb99180..c0bb703ecc 100644
--- a/quantum/keymap_extras/keymap_bepo.h
+++ b/quantum/keymap_extras/keymap_bepo.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_BEPO_KEYCODES_VERSION "0.0.1"
+#define QMK_BEPO_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_BEPO_KEYCODES_VERSION_MAJOR 0
+#define QMK_BEPO_KEYCODES_VERSION_MINOR 0
+#define QMK_BEPO_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define BP_DLR KC_GRV // $
#define BP_DQUO KC_1 // "
diff --git a/quantum/keymap_extras/keymap_brazilian_abnt2.h b/quantum/keymap_extras/keymap_brazilian_abnt2.h
index 730fe5069f..267b5490c9 100644
--- a/quantum/keymap_extras/keymap_brazilian_abnt2.h
+++ b/quantum/keymap_extras/keymap_brazilian_abnt2.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_BRAZILIAN_ABNT2_KEYCODES_VERSION "0.0.1"
+#define QMK_BRAZILIAN_ABNT2_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_BRAZILIAN_ABNT2_KEYCODES_VERSION_MAJOR 0
+#define QMK_BRAZILIAN_ABNT2_KEYCODES_VERSION_MINOR 0
+#define QMK_BRAZILIAN_ABNT2_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define BR_QUOT KC_GRV // '
#define BR_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_canadian_french.h b/quantum/keymap_extras/keymap_canadian_french.h
index 5771cf6193..df9c73c016 100644
--- a/quantum/keymap_extras/keymap_canadian_french.h
+++ b/quantum/keymap_extras/keymap_canadian_french.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_CANADIAN_FRENCH_KEYCODES_VERSION "0.0.1"
+#define QMK_CANADIAN_FRENCH_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_CANADIAN_FRENCH_KEYCODES_VERSION_MAJOR 0
+#define QMK_CANADIAN_FRENCH_KEYCODES_VERSION_MINOR 0
+#define QMK_CANADIAN_FRENCH_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define FR_HASH KC_GRV // #
#define FR_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_canadian_multilingual.h b/quantum/keymap_extras/keymap_canadian_multilingual.h
index 2a4326b406..4b42457396 100644
--- a/quantum/keymap_extras/keymap_canadian_multilingual.h
+++ b/quantum/keymap_extras/keymap_canadian_multilingual.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_CANADIAN_MULTILINGUAL_KEYCODES_VERSION "0.0.1"
+#define QMK_CANADIAN_MULTILINGUAL_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_CANADIAN_MULTILINGUAL_KEYCODES_VERSION_MAJOR 0
+#define QMK_CANADIAN_MULTILINGUAL_KEYCODES_VERSION_MINOR 0
+#define QMK_CANADIAN_MULTILINGUAL_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define CA_SLSH KC_GRV // /
#define CA_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_colemak.h b/quantum/keymap_extras/keymap_colemak.h
index 0170339aad..a4fc77e80f 100644
--- a/quantum/keymap_extras/keymap_colemak.h
+++ b/quantum/keymap_extras/keymap_colemak.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_COLEMAK_KEYCODES_VERSION "0.0.1"
+#define QMK_COLEMAK_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_COLEMAK_KEYCODES_VERSION_MAJOR 0
+#define QMK_COLEMAK_KEYCODES_VERSION_MINOR 0
+#define QMK_COLEMAK_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define CM_GRV KC_GRV // `
#define CM_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_croatian.h b/quantum/keymap_extras/keymap_croatian.h
index 7e11a85710..cdc032a9eb 100644
--- a/quantum/keymap_extras/keymap_croatian.h
+++ b/quantum/keymap_extras/keymap_croatian.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_CROATIAN_KEYCODES_VERSION "0.0.1"
+#define QMK_CROATIAN_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_CROATIAN_KEYCODES_VERSION_MAJOR 0
+#define QMK_CROATIAN_KEYCODES_VERSION_MINOR 0
+#define QMK_CROATIAN_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define HR_CEDL KC_GRV // ¸ (dead)
#define HR_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_czech.h b/quantum/keymap_extras/keymap_czech.h
index 8e65a4ed0a..cae16cdb9f 100644
--- a/quantum/keymap_extras/keymap_czech.h
+++ b/quantum/keymap_extras/keymap_czech.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_CZECH_KEYCODES_VERSION "0.0.1"
+#define QMK_CZECH_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_CZECH_KEYCODES_VERSION_MAJOR 0
+#define QMK_CZECH_KEYCODES_VERSION_MINOR 0
+#define QMK_CZECH_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define CZ_SCLN KC_GRV // ;
#define CZ_PLUS KC_1 // +
diff --git a/quantum/keymap_extras/keymap_czech_mac_ansi.h b/quantum/keymap_extras/keymap_czech_mac_ansi.h
index ed46a78f1c..bdfda933b0 100644
--- a/quantum/keymap_extras/keymap_czech_mac_ansi.h
+++ b/quantum/keymap_extras/keymap_czech_mac_ansi.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_CZECH_MAC_ANSI_KEYCODES_VERSION "0.0.1"
+#define QMK_CZECH_MAC_ANSI_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_CZECH_MAC_ANSI_KEYCODES_VERSION_MAJOR 0
+#define QMK_CZECH_MAC_ANSI_KEYCODES_VERSION_MINOR 0
+#define QMK_CZECH_MAC_ANSI_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define CZ_BSLS KC_GRV // (backslash)
#define CZ_PLUS KC_1 // +
diff --git a/quantum/keymap_extras/keymap_czech_mac_iso.h b/quantum/keymap_extras/keymap_czech_mac_iso.h
index 08285b7952..9c05d8dae0 100644
--- a/quantum/keymap_extras/keymap_czech_mac_iso.h
+++ b/quantum/keymap_extras/keymap_czech_mac_iso.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_CZECH_MAC_ISO_KEYCODES_VERSION "0.0.1"
+#define QMK_CZECH_MAC_ISO_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_CZECH_MAC_ISO_KEYCODES_VERSION_MAJOR 0
+#define QMK_CZECH_MAC_ISO_KEYCODES_VERSION_MINOR 0
+#define QMK_CZECH_MAC_ISO_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define CZ_PLUS KC_1 // +
#define CZ_ECAR KC_2 // ě
diff --git a/quantum/keymap_extras/keymap_danish.h b/quantum/keymap_extras/keymap_danish.h
index a84923007c..1f1ee90e23 100644
--- a/quantum/keymap_extras/keymap_danish.h
+++ b/quantum/keymap_extras/keymap_danish.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_DANISH_KEYCODES_VERSION "0.0.1"
+#define QMK_DANISH_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_DANISH_KEYCODES_VERSION_MAJOR 0
+#define QMK_DANISH_KEYCODES_VERSION_MINOR 0
+#define QMK_DANISH_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define DK_HALF KC_GRV // ½
#define DK_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_dvorak.h b/quantum/keymap_extras/keymap_dvorak.h
index a926e48295..5cb2c4564a 100644
--- a/quantum/keymap_extras/keymap_dvorak.h
+++ b/quantum/keymap_extras/keymap_dvorak.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_DVORAK_KEYCODES_VERSION "0.0.1"
+#define QMK_DVORAK_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_DVORAK_KEYCODES_VERSION_MAJOR 0
+#define QMK_DVORAK_KEYCODES_VERSION_MINOR 0
+#define QMK_DVORAK_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define DV_GRV KC_GRV // `
#define DV_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_dvorak_fr.h b/quantum/keymap_extras/keymap_dvorak_fr.h
index 6e6498e598..d01bf7fec7 100644
--- a/quantum/keymap_extras/keymap_dvorak_fr.h
+++ b/quantum/keymap_extras/keymap_dvorak_fr.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_DVORAK_FR_KEYCODES_VERSION "0.0.1"
+#define QMK_DVORAK_FR_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_DVORAK_FR_KEYCODES_VERSION_MAJOR 0
+#define QMK_DVORAK_FR_KEYCODES_VERSION_MINOR 0
+#define QMK_DVORAK_FR_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define DV_LDAQ KC_GRV // «
#define DV_RDAQ KC_1 // »
diff --git a/quantum/keymap_extras/keymap_dvorak_programmer.h b/quantum/keymap_extras/keymap_dvorak_programmer.h
index 43d9a702bb..f17900105f 100644
--- a/quantum/keymap_extras/keymap_dvorak_programmer.h
+++ b/quantum/keymap_extras/keymap_dvorak_programmer.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_DVORAK_PROGRAMMER_KEYCODES_VERSION "0.0.1"
+#define QMK_DVORAK_PROGRAMMER_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_DVORAK_PROGRAMMER_KEYCODES_VERSION_MAJOR 0
+#define QMK_DVORAK_PROGRAMMER_KEYCODES_VERSION_MINOR 0
+#define QMK_DVORAK_PROGRAMMER_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define DP_DLR KC_GRV // $
#define DP_AMPR KC_1 // &
diff --git a/quantum/keymap_extras/keymap_estonian.h b/quantum/keymap_extras/keymap_estonian.h
index 3e87bbc5f8..5fbeedcbe9 100644
--- a/quantum/keymap_extras/keymap_estonian.h
+++ b/quantum/keymap_extras/keymap_estonian.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_ESTONIAN_KEYCODES_VERSION "0.0.1"
+#define QMK_ESTONIAN_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_ESTONIAN_KEYCODES_VERSION_MAJOR 0
+#define QMK_ESTONIAN_KEYCODES_VERSION_MINOR 0
+#define QMK_ESTONIAN_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define EE_CARN KC_GRV // ˇ (dead)
#define EE_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_eurkey.h b/quantum/keymap_extras/keymap_eurkey.h
index 20f7f58683..5a13d48163 100644
--- a/quantum/keymap_extras/keymap_eurkey.h
+++ b/quantum/keymap_extras/keymap_eurkey.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_EURKEY_KEYCODES_VERSION "0.0.1"
+#define QMK_EURKEY_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_EURKEY_KEYCODES_VERSION_MAJOR 0
+#define QMK_EURKEY_KEYCODES_VERSION_MINOR 0
+#define QMK_EURKEY_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define EU_GRV KC_GRV // `
#define EU_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_farsi.h b/quantum/keymap_extras/keymap_farsi.h
index 4f34b08d92..e115d9c1c0 100644
--- a/quantum/keymap_extras/keymap_farsi.h
+++ b/quantum/keymap_extras/keymap_farsi.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_FARSI_KEYCODES_VERSION "0.0.1"
+#define QMK_FARSI_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_FARSI_KEYCODES_VERSION_MAJOR 0
+#define QMK_FARSI_KEYCODES_VERSION_MINOR 0
+#define QMK_FARSI_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define FA_ZWJ KC_GRV // (zero-width joiner)
#define FA_1A KC_1 // ۱
diff --git a/quantum/keymap_extras/keymap_finnish.h b/quantum/keymap_extras/keymap_finnish.h
index 045f7295a0..cb21da9962 100644
--- a/quantum/keymap_extras/keymap_finnish.h
+++ b/quantum/keymap_extras/keymap_finnish.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_FINNISH_KEYCODES_VERSION "0.0.1"
+#define QMK_FINNISH_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_FINNISH_KEYCODES_VERSION_MAJOR 0
+#define QMK_FINNISH_KEYCODES_VERSION_MINOR 0
+#define QMK_FINNISH_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define FI_SECT KC_GRV // §
#define FI_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_french.h b/quantum/keymap_extras/keymap_french.h
index 9ff3694a73..d4352c6481 100644
--- a/quantum/keymap_extras/keymap_french.h
+++ b/quantum/keymap_extras/keymap_french.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_FRENCH_KEYCODES_VERSION "0.0.1"
+#define QMK_FRENCH_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_FRENCH_KEYCODES_VERSION_MAJOR 0
+#define QMK_FRENCH_KEYCODES_VERSION_MINOR 0
+#define QMK_FRENCH_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define FR_SUP2 KC_GRV // ²
#define FR_AMPR KC_1 // &
diff --git a/quantum/keymap_extras/keymap_french_afnor.h b/quantum/keymap_extras/keymap_french_afnor.h
index 07506e0f6e..8e6905cc01 100644
--- a/quantum/keymap_extras/keymap_french_afnor.h
+++ b/quantum/keymap_extras/keymap_french_afnor.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_FRENCH_AFNOR_KEYCODES_VERSION "0.0.1"
+#define QMK_FRENCH_AFNOR_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_FRENCH_AFNOR_KEYCODES_VERSION_MAJOR 0
+#define QMK_FRENCH_AFNOR_KEYCODES_VERSION_MINOR 0
+#define QMK_FRENCH_AFNOR_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define FR_AT KC_GRV // @
#define FR_AGRV KC_1 // à
diff --git a/quantum/keymap_extras/keymap_french_mac_iso.h b/quantum/keymap_extras/keymap_french_mac_iso.h
index b036ca2009..ad9d280f2a 100644
--- a/quantum/keymap_extras/keymap_french_mac_iso.h
+++ b/quantum/keymap_extras/keymap_french_mac_iso.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_FRENCH_MAC_ISO_KEYCODES_VERSION "0.0.1"
+#define QMK_FRENCH_MAC_ISO_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_FRENCH_MAC_ISO_KEYCODES_VERSION_MAJOR 0
+#define QMK_FRENCH_MAC_ISO_KEYCODES_VERSION_MINOR 0
+#define QMK_FRENCH_MAC_ISO_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define FR_AT KC_GRV // @
#define FR_AMPR KC_1 // &
diff --git a/quantum/keymap_extras/keymap_german.h b/quantum/keymap_extras/keymap_german.h
index 7ac807934b..bc98daa2fd 100644
--- a/quantum/keymap_extras/keymap_german.h
+++ b/quantum/keymap_extras/keymap_german.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_GERMAN_KEYCODES_VERSION "0.0.1"
+#define QMK_GERMAN_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_GERMAN_KEYCODES_VERSION_MAJOR 0
+#define QMK_GERMAN_KEYCODES_VERSION_MINOR 0
+#define QMK_GERMAN_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define DE_CIRC KC_GRV // ^ (dead)
#define DE_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_german_mac_iso.h b/quantum/keymap_extras/keymap_german_mac_iso.h
index 56d077c36c..ba3143c570 100644
--- a/quantum/keymap_extras/keymap_german_mac_iso.h
+++ b/quantum/keymap_extras/keymap_german_mac_iso.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_GERMAN_MAC_ISO_KEYCODES_VERSION "0.0.1"
+#define QMK_GERMAN_MAC_ISO_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_GERMAN_MAC_ISO_KEYCODES_VERSION_MAJOR 0
+#define QMK_GERMAN_MAC_ISO_KEYCODES_VERSION_MINOR 0
+#define QMK_GERMAN_MAC_ISO_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define DE_CIRC KC_GRV // ^ (dead)
#define DE_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_greek.h b/quantum/keymap_extras/keymap_greek.h
index 0d2e15dfd8..fb2f02a04f 100644
--- a/quantum/keymap_extras/keymap_greek.h
+++ b/quantum/keymap_extras/keymap_greek.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_GREEK_KEYCODES_VERSION "0.0.1"
+#define QMK_GREEK_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_GREEK_KEYCODES_VERSION_MAJOR 0
+#define QMK_GREEK_KEYCODES_VERSION_MINOR 0
+#define QMK_GREEK_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define GR_GRV KC_GRV // `
#define GR_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_hebrew.h b/quantum/keymap_extras/keymap_hebrew.h
index a927364737..5d1d4a29c6 100644
--- a/quantum/keymap_extras/keymap_hebrew.h
+++ b/quantum/keymap_extras/keymap_hebrew.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_HEBREW_KEYCODES_VERSION "0.0.1"
+#define QMK_HEBREW_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_HEBREW_KEYCODES_VERSION_MAJOR 0
+#define QMK_HEBREW_KEYCODES_VERSION_MINOR 0
+#define QMK_HEBREW_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define IL_SCLN KC_GRV // ;
#define IL_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_hungarian.h b/quantum/keymap_extras/keymap_hungarian.h
index 81a842a0fe..27236553e8 100644
--- a/quantum/keymap_extras/keymap_hungarian.h
+++ b/quantum/keymap_extras/keymap_hungarian.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_HUNGARIAN_KEYCODES_VERSION "0.0.1"
+#define QMK_HUNGARIAN_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_HUNGARIAN_KEYCODES_VERSION_MAJOR 0
+#define QMK_HUNGARIAN_KEYCODES_VERSION_MINOR 0
+#define QMK_HUNGARIAN_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define HU_0 KC_GRV // 0
#define HU_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_icelandic.h b/quantum/keymap_extras/keymap_icelandic.h
index 8e4e04b0f1..409be27b77 100644
--- a/quantum/keymap_extras/keymap_icelandic.h
+++ b/quantum/keymap_extras/keymap_icelandic.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_ICELANDIC_KEYCODES_VERSION "0.0.1"
+#define QMK_ICELANDIC_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_ICELANDIC_KEYCODES_VERSION_MAJOR 0
+#define QMK_ICELANDIC_KEYCODES_VERSION_MINOR 0
+#define QMK_ICELANDIC_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define IS_RNGA KC_GRV // ° (dead)
#define IS_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_irish.h b/quantum/keymap_extras/keymap_irish.h
index 6cb85dc7a7..587467bcbe 100644
--- a/quantum/keymap_extras/keymap_irish.h
+++ b/quantum/keymap_extras/keymap_irish.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_IRISH_KEYCODES_VERSION "0.0.1"
+#define QMK_IRISH_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_IRISH_KEYCODES_VERSION_MAJOR 0
+#define QMK_IRISH_KEYCODES_VERSION_MINOR 0
+#define QMK_IRISH_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define IE_GRV KC_GRV // `
#define IE_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_italian.h b/quantum/keymap_extras/keymap_italian.h
index 57c12ba9b6..9fd7f1b15c 100644
--- a/quantum/keymap_extras/keymap_italian.h
+++ b/quantum/keymap_extras/keymap_italian.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_ITALIAN_KEYCODES_VERSION "0.0.1"
+#define QMK_ITALIAN_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_ITALIAN_KEYCODES_VERSION_MAJOR 0
+#define QMK_ITALIAN_KEYCODES_VERSION_MINOR 0
+#define QMK_ITALIAN_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define IT_BSLS KC_GRV // (backslash)
#define IT_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_italian_mac_ansi.h b/quantum/keymap_extras/keymap_italian_mac_ansi.h
index 4774c2d5ee..9ef38c0d87 100644
--- a/quantum/keymap_extras/keymap_italian_mac_ansi.h
+++ b/quantum/keymap_extras/keymap_italian_mac_ansi.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_ITALIAN_MAC_ANSI_KEYCODES_VERSION "0.0.1"
+#define QMK_ITALIAN_MAC_ANSI_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_ITALIAN_MAC_ANSI_KEYCODES_VERSION_MAJOR 0
+#define QMK_ITALIAN_MAC_ANSI_KEYCODES_VERSION_MINOR 0
+#define QMK_ITALIAN_MAC_ANSI_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define IT_LABK KC_GRV // <
#define IT_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_italian_mac_iso.h b/quantum/keymap_extras/keymap_italian_mac_iso.h
index 35ec978ef9..e80cfa450c 100644
--- a/quantum/keymap_extras/keymap_italian_mac_iso.h
+++ b/quantum/keymap_extras/keymap_italian_mac_iso.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_ITALIAN_MAC_ISO_KEYCODES_VERSION "0.0.1"
+#define QMK_ITALIAN_MAC_ISO_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_ITALIAN_MAC_ISO_KEYCODES_VERSION_MAJOR 0
+#define QMK_ITALIAN_MAC_ISO_KEYCODES_VERSION_MINOR 0
+#define QMK_ITALIAN_MAC_ISO_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define IT_BSLS KC_GRV // (backslash)
#define IT_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_japanese.h b/quantum/keymap_extras/keymap_japanese.h
index 3ad9495353..55df86e16d 100644
--- a/quantum/keymap_extras/keymap_japanese.h
+++ b/quantum/keymap_extras/keymap_japanese.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_JAPANESE_KEYCODES_VERSION "0.0.1"
+#define QMK_JAPANESE_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_JAPANESE_KEYCODES_VERSION_MAJOR 0
+#define QMK_JAPANESE_KEYCODES_VERSION_MINOR 0
+#define QMK_JAPANESE_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define JP_ZKHK KC_GRV // Zenkaku ↔ Hankaku ↔ Kanji (半角 ↔ 全角 ↔ 漢字)
#define JP_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_korean.h b/quantum/keymap_extras/keymap_korean.h
index 644837734e..7bf64c4841 100644
--- a/quantum/keymap_extras/keymap_korean.h
+++ b/quantum/keymap_extras/keymap_korean.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_KOREAN_KEYCODES_VERSION "0.0.1"
+#define QMK_KOREAN_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_KOREAN_KEYCODES_VERSION_MAJOR 0
+#define QMK_KOREAN_KEYCODES_VERSION_MINOR 0
+#define QMK_KOREAN_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define KR_GRV KC_GRV // `
#define KR_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_latvian.h b/quantum/keymap_extras/keymap_latvian.h
index b1750ed759..4d60c45163 100644
--- a/quantum/keymap_extras/keymap_latvian.h
+++ b/quantum/keymap_extras/keymap_latvian.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_LATVIAN_KEYCODES_VERSION "0.0.1"
+#define QMK_LATVIAN_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_LATVIAN_KEYCODES_VERSION_MAJOR 0
+#define QMK_LATVIAN_KEYCODES_VERSION_MINOR 0
+#define QMK_LATVIAN_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define LV_GRV KC_GRV // `
#define LV_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_lithuanian_azerty.h b/quantum/keymap_extras/keymap_lithuanian_azerty.h
index 9d6c1b92f0..e88cc75e07 100644
--- a/quantum/keymap_extras/keymap_lithuanian_azerty.h
+++ b/quantum/keymap_extras/keymap_lithuanian_azerty.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_LITHUANIAN_AZERTY_KEYCODES_VERSION "0.0.1"
+#define QMK_LITHUANIAN_AZERTY_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_LITHUANIAN_AZERTY_KEYCODES_VERSION_MAJOR 0
+#define QMK_LITHUANIAN_AZERTY_KEYCODES_VERSION_MINOR 0
+#define QMK_LITHUANIAN_AZERTY_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define LT_GRV KC_GRV // `
#define LT_EXLM KC_1 // !
diff --git a/quantum/keymap_extras/keymap_lithuanian_qwerty.h b/quantum/keymap_extras/keymap_lithuanian_qwerty.h
index 84df4c8bd2..3321615c1e 100644
--- a/quantum/keymap_extras/keymap_lithuanian_qwerty.h
+++ b/quantum/keymap_extras/keymap_lithuanian_qwerty.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_LITHUANIAN_QWERTY_KEYCODES_VERSION "0.0.1"
+#define QMK_LITHUANIAN_QWERTY_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_LITHUANIAN_QWERTY_KEYCODES_VERSION_MAJOR 0
+#define QMK_LITHUANIAN_QWERTY_KEYCODES_VERSION_MINOR 0
+#define QMK_LITHUANIAN_QWERTY_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define LT_GRV KC_GRV // `
#define LT_AOGO KC_1 // Ą
diff --git a/quantum/keymap_extras/keymap_neo2.h b/quantum/keymap_extras/keymap_neo2.h
index ad285f7d18..5d10f19fd5 100644
--- a/quantum/keymap_extras/keymap_neo2.h
+++ b/quantum/keymap_extras/keymap_neo2.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_NEO2_KEYCODES_VERSION "0.0.1"
+#define QMK_NEO2_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_NEO2_KEYCODES_VERSION_MAJOR 0
+#define QMK_NEO2_KEYCODES_VERSION_MINOR 0
+#define QMK_NEO2_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define NE_CIRC KC_GRV // ^ (dead)
#define NE_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_nordic.h b/quantum/keymap_extras/keymap_nordic.h
index ff952e6c43..3a11b29fc8 100644
--- a/quantum/keymap_extras/keymap_nordic.h
+++ b/quantum/keymap_extras/keymap_nordic.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_NORDIC_KEYCODES_VERSION "0.0.1"
+#define QMK_NORDIC_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_NORDIC_KEYCODES_VERSION_MAJOR 0
+#define QMK_NORDIC_KEYCODES_VERSION_MINOR 0
+#define QMK_NORDIC_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define NO_HALF KC_GRV
#define NO_PLUS KC_MINS
diff --git a/quantum/keymap_extras/keymap_norman.h b/quantum/keymap_extras/keymap_norman.h
index 166a2f22a1..d47c2ff8a7 100644
--- a/quantum/keymap_extras/keymap_norman.h
+++ b/quantum/keymap_extras/keymap_norman.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_NORMAN_KEYCODES_VERSION "0.0.1"
+#define QMK_NORMAN_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_NORMAN_KEYCODES_VERSION_MAJOR 0
+#define QMK_NORMAN_KEYCODES_VERSION_MINOR 0
+#define QMK_NORMAN_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define NM_GRV KC_GRV // `
#define NM_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_norwegian.h b/quantum/keymap_extras/keymap_norwegian.h
index 0b0cf65813..021b8c3b9c 100644
--- a/quantum/keymap_extras/keymap_norwegian.h
+++ b/quantum/keymap_extras/keymap_norwegian.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_NORWEGIAN_KEYCODES_VERSION "0.0.1"
+#define QMK_NORWEGIAN_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_NORWEGIAN_KEYCODES_VERSION_MAJOR 0
+#define QMK_NORWEGIAN_KEYCODES_VERSION_MINOR 0
+#define QMK_NORWEGIAN_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define NO_PIPE KC_GRV // |
#define NO_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_plover.h b/quantum/keymap_extras/keymap_plover.h
index a01a23c8a3..e7facfd623 100644
--- a/quantum/keymap_extras/keymap_plover.h
+++ b/quantum/keymap_extras/keymap_plover.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_PLOVER_KEYCODES_VERSION "0.0.1"
+#define QMK_PLOVER_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_PLOVER_KEYCODES_VERSION_MAJOR 0
+#define QMK_PLOVER_KEYCODES_VERSION_MINOR 0
+#define QMK_PLOVER_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define PV_NUM KC_1
#define PV_LS KC_Q
diff --git a/quantum/keymap_extras/keymap_plover_dvorak.h b/quantum/keymap_extras/keymap_plover_dvorak.h
index 0ec7b9acd3..5c8a4f9ada 100644
--- a/quantum/keymap_extras/keymap_plover_dvorak.h
+++ b/quantum/keymap_extras/keymap_plover_dvorak.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_PLOVER_DVORAK_KEYCODES_VERSION "0.0.1"
+#define QMK_PLOVER_DVORAK_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_PLOVER_DVORAK_KEYCODES_VERSION_MAJOR 0
+#define QMK_PLOVER_DVORAK_KEYCODES_VERSION_MINOR 0
+#define QMK_PLOVER_DVORAK_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define PD_NUM DV_1
#define PD_LS DV_Q
diff --git a/quantum/keymap_extras/keymap_polish.h b/quantum/keymap_extras/keymap_polish.h
index 2448ef1fef..e5e48097f7 100644
--- a/quantum/keymap_extras/keymap_polish.h
+++ b/quantum/keymap_extras/keymap_polish.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_POLISH_KEYCODES_VERSION "0.0.1"
+#define QMK_POLISH_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_POLISH_KEYCODES_VERSION_MAJOR 0
+#define QMK_POLISH_KEYCODES_VERSION_MINOR 0
+#define QMK_POLISH_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define PL_GRV KC_GRV // `
#define PL_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_portuguese.h b/quantum/keymap_extras/keymap_portuguese.h
index 9f79862679..44abaf6537 100644
--- a/quantum/keymap_extras/keymap_portuguese.h
+++ b/quantum/keymap_extras/keymap_portuguese.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_PORTUGUESE_KEYCODES_VERSION "0.0.1"
+#define QMK_PORTUGUESE_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_PORTUGUESE_KEYCODES_VERSION_MAJOR 0
+#define QMK_PORTUGUESE_KEYCODES_VERSION_MINOR 0
+#define QMK_PORTUGUESE_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define PT_BSLS KC_GRV // (backslash)
#define PT_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_portuguese_mac_iso.h b/quantum/keymap_extras/keymap_portuguese_mac_iso.h
index 5381956b4c..f2d04440fb 100644
--- a/quantum/keymap_extras/keymap_portuguese_mac_iso.h
+++ b/quantum/keymap_extras/keymap_portuguese_mac_iso.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_PORTUGUESE_MAC_ISO_KEYCODES_VERSION "0.0.1"
+#define QMK_PORTUGUESE_MAC_ISO_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_PORTUGUESE_MAC_ISO_KEYCODES_VERSION_MAJOR 0
+#define QMK_PORTUGUESE_MAC_ISO_KEYCODES_VERSION_MINOR 0
+#define QMK_PORTUGUESE_MAC_ISO_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define PT_SECT KC_GRV // §
#define PT_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_romanian.h b/quantum/keymap_extras/keymap_romanian.h
index 6410fbbe48..9a7239e032 100644
--- a/quantum/keymap_extras/keymap_romanian.h
+++ b/quantum/keymap_extras/keymap_romanian.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_ROMANIAN_KEYCODES_VERSION "0.0.1"
+#define QMK_ROMANIAN_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_ROMANIAN_KEYCODES_VERSION_MAJOR 0
+#define QMK_ROMANIAN_KEYCODES_VERSION_MINOR 0
+#define QMK_ROMANIAN_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define RO_DLQU KC_GRV // „
#define RO_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_russian.h b/quantum/keymap_extras/keymap_russian.h
index 364e7aba5c..b756a657df 100644
--- a/quantum/keymap_extras/keymap_russian.h
+++ b/quantum/keymap_extras/keymap_russian.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_RUSSIAN_KEYCODES_VERSION "0.0.1"
+#define QMK_RUSSIAN_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_RUSSIAN_KEYCODES_VERSION_MAJOR 0
+#define QMK_RUSSIAN_KEYCODES_VERSION_MINOR 0
+#define QMK_RUSSIAN_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define RU_YO KC_GRV // Ё
#define RU_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_russian_typewriter.h b/quantum/keymap_extras/keymap_russian_typewriter.h
index 18157726ad..45fb1ede04 100644
--- a/quantum/keymap_extras/keymap_russian_typewriter.h
+++ b/quantum/keymap_extras/keymap_russian_typewriter.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_RUSSIAN_TYPEWRITER_KEYCODES_VERSION "0.0.1"
+#define QMK_RUSSIAN_TYPEWRITER_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_RUSSIAN_TYPEWRITER_KEYCODES_VERSION_MAJOR 0
+#define QMK_RUSSIAN_TYPEWRITER_KEYCODES_VERSION_MINOR 0
+#define QMK_RUSSIAN_TYPEWRITER_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define RU_PIPE KC_GRV // |
#define RU_NUM KC_1 // №
diff --git a/quantum/keymap_extras/keymap_serbian.h b/quantum/keymap_extras/keymap_serbian.h
index 6421577c22..202322b591 100644
--- a/quantum/keymap_extras/keymap_serbian.h
+++ b/quantum/keymap_extras/keymap_serbian.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_SERBIAN_KEYCODES_VERSION "0.0.1"
+#define QMK_SERBIAN_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_SERBIAN_KEYCODES_VERSION_MAJOR 0
+#define QMK_SERBIAN_KEYCODES_VERSION_MINOR 0
+#define QMK_SERBIAN_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define RS_GRV KC_GRV // `
#define RS_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_serbian_latin.h b/quantum/keymap_extras/keymap_serbian_latin.h
index 358c6c76ed..e863aa4ed8 100644
--- a/quantum/keymap_extras/keymap_serbian_latin.h
+++ b/quantum/keymap_extras/keymap_serbian_latin.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_SERBIAN_LATIN_KEYCODES_VERSION "0.0.1"
+#define QMK_SERBIAN_LATIN_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_SERBIAN_LATIN_KEYCODES_VERSION_MAJOR 0
+#define QMK_SERBIAN_LATIN_KEYCODES_VERSION_MINOR 0
+#define QMK_SERBIAN_LATIN_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define RS_SLQU KC_GRV // ‚ (dead)
#define RS_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_slovak.h b/quantum/keymap_extras/keymap_slovak.h
index a777fce16f..f5848a6aaf 100644
--- a/quantum/keymap_extras/keymap_slovak.h
+++ b/quantum/keymap_extras/keymap_slovak.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_SLOVAK_KEYCODES_VERSION "0.0.1"
+#define QMK_SLOVAK_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_SLOVAK_KEYCODES_VERSION_MAJOR 0
+#define QMK_SLOVAK_KEYCODES_VERSION_MINOR 0
+#define QMK_SLOVAK_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define SK_SCLN KC_GRV // ;
#define SK_PLUS KC_1 // +
diff --git a/quantum/keymap_extras/keymap_slovenian.h b/quantum/keymap_extras/keymap_slovenian.h
index 402a53cd44..502f06ad64 100644
--- a/quantum/keymap_extras/keymap_slovenian.h
+++ b/quantum/keymap_extras/keymap_slovenian.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_SLOVENIAN_KEYCODES_VERSION "0.0.1"
+#define QMK_SLOVENIAN_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_SLOVENIAN_KEYCODES_VERSION_MAJOR 0
+#define QMK_SLOVENIAN_KEYCODES_VERSION_MINOR 0
+#define QMK_SLOVENIAN_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define SI_CEDL KC_GRV // ¸ (dead)
#define SI_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_spanish.h b/quantum/keymap_extras/keymap_spanish.h
index 714c8cbb7c..dc23aea639 100644
--- a/quantum/keymap_extras/keymap_spanish.h
+++ b/quantum/keymap_extras/keymap_spanish.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_SPANISH_KEYCODES_VERSION "0.0.1"
+#define QMK_SPANISH_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_SPANISH_KEYCODES_VERSION_MAJOR 0
+#define QMK_SPANISH_KEYCODES_VERSION_MINOR 0
+#define QMK_SPANISH_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define ES_MORD KC_GRV // º
#define ES_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_spanish_dvorak.h b/quantum/keymap_extras/keymap_spanish_dvorak.h
index b5a6463452..e19a84b7e5 100644
--- a/quantum/keymap_extras/keymap_spanish_dvorak.h
+++ b/quantum/keymap_extras/keymap_spanish_dvorak.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_SPANISH_DVORAK_KEYCODES_VERSION "0.0.1"
+#define QMK_SPANISH_DVORAK_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_SPANISH_DVORAK_KEYCODES_VERSION_MAJOR 0
+#define QMK_SPANISH_DVORAK_KEYCODES_VERSION_MINOR 0
+#define QMK_SPANISH_DVORAK_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define DV_MORD KC_GRV // º
#define DV_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_spanish_latin_america.h b/quantum/keymap_extras/keymap_spanish_latin_america.h
index 651212d4bf..57329d20cd 100644
--- a/quantum/keymap_extras/keymap_spanish_latin_america.h
+++ b/quantum/keymap_extras/keymap_spanish_latin_america.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_SPANISH_LATIN_AMERICA_KEYCODES_VERSION "0.0.1"
+#define QMK_SPANISH_LATIN_AMERICA_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_SPANISH_LATIN_AMERICA_KEYCODES_VERSION_MAJOR 0
+#define QMK_SPANISH_LATIN_AMERICA_KEYCODES_VERSION_MINOR 0
+#define QMK_SPANISH_LATIN_AMERICA_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define ES_PIPE KC_GRV // |
#define ES_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_swedish.h b/quantum/keymap_extras/keymap_swedish.h
index 23ec4102d8..a50f8af30d 100644
--- a/quantum/keymap_extras/keymap_swedish.h
+++ b/quantum/keymap_extras/keymap_swedish.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_SWEDISH_KEYCODES_VERSION "0.0.1"
+#define QMK_SWEDISH_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_SWEDISH_KEYCODES_VERSION_MAJOR 0
+#define QMK_SWEDISH_KEYCODES_VERSION_MINOR 0
+#define QMK_SWEDISH_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define SE_SECT KC_GRV // §
#define SE_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_swedish_mac_ansi.h b/quantum/keymap_extras/keymap_swedish_mac_ansi.h
index 18061f0be9..642c161dab 100644
--- a/quantum/keymap_extras/keymap_swedish_mac_ansi.h
+++ b/quantum/keymap_extras/keymap_swedish_mac_ansi.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_SWEDISH_MAC_ANSI_KEYCODES_VERSION "0.0.1"
+#define QMK_SWEDISH_MAC_ANSI_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_SWEDISH_MAC_ANSI_KEYCODES_VERSION_MAJOR 0
+#define QMK_SWEDISH_MAC_ANSI_KEYCODES_VERSION_MINOR 0
+#define QMK_SWEDISH_MAC_ANSI_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define SE_LABK KC_GRV // <
#define SE_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_swedish_mac_iso.h b/quantum/keymap_extras/keymap_swedish_mac_iso.h
index 0c68ffcbd4..50387364cf 100644
--- a/quantum/keymap_extras/keymap_swedish_mac_iso.h
+++ b/quantum/keymap_extras/keymap_swedish_mac_iso.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_SWEDISH_MAC_ISO_KEYCODES_VERSION "0.0.1"
+#define QMK_SWEDISH_MAC_ISO_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_SWEDISH_MAC_ISO_KEYCODES_VERSION_MAJOR 0
+#define QMK_SWEDISH_MAC_ISO_KEYCODES_VERSION_MINOR 0
+#define QMK_SWEDISH_MAC_ISO_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define SE_SECT KC_GRV // §
#define SE_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_swedish_pro_mac_ansi.h b/quantum/keymap_extras/keymap_swedish_pro_mac_ansi.h
index 043a7c9fc2..be1581bb3d 100644
--- a/quantum/keymap_extras/keymap_swedish_pro_mac_ansi.h
+++ b/quantum/keymap_extras/keymap_swedish_pro_mac_ansi.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_SWEDISH_PRO_MAC_ANSI_KEYCODES_VERSION "0.0.1"
+#define QMK_SWEDISH_PRO_MAC_ANSI_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_SWEDISH_PRO_MAC_ANSI_KEYCODES_VERSION_MAJOR 0
+#define QMK_SWEDISH_PRO_MAC_ANSI_KEYCODES_VERSION_MINOR 0
+#define QMK_SWEDISH_PRO_MAC_ANSI_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define SE_LABK KC_GRV // <
#define SE_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_swedish_pro_mac_iso.h b/quantum/keymap_extras/keymap_swedish_pro_mac_iso.h
index 1d691feef1..d50213f987 100644
--- a/quantum/keymap_extras/keymap_swedish_pro_mac_iso.h
+++ b/quantum/keymap_extras/keymap_swedish_pro_mac_iso.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_SWEDISH_PRO_MAC_ISO_KEYCODES_VERSION "0.0.1"
+#define QMK_SWEDISH_PRO_MAC_ISO_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_SWEDISH_PRO_MAC_ISO_KEYCODES_VERSION_MAJOR 0
+#define QMK_SWEDISH_PRO_MAC_ISO_KEYCODES_VERSION_MINOR 0
+#define QMK_SWEDISH_PRO_MAC_ISO_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define SE_SECT KC_GRV // §
#define SE_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_swiss_de.h b/quantum/keymap_extras/keymap_swiss_de.h
index 5411353a5f..4ebdb5c610 100644
--- a/quantum/keymap_extras/keymap_swiss_de.h
+++ b/quantum/keymap_extras/keymap_swiss_de.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_SWISS_DE_KEYCODES_VERSION "0.0.1"
+#define QMK_SWISS_DE_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_SWISS_DE_KEYCODES_VERSION_MAJOR 0
+#define QMK_SWISS_DE_KEYCODES_VERSION_MINOR 0
+#define QMK_SWISS_DE_KEYCODES_VERSION_PATCH 1
+
#undef CH_H
// Aliases
diff --git a/quantum/keymap_extras/keymap_swiss_fr.h b/quantum/keymap_extras/keymap_swiss_fr.h
index a9a9cab162..11fcc6536d 100644
--- a/quantum/keymap_extras/keymap_swiss_fr.h
+++ b/quantum/keymap_extras/keymap_swiss_fr.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_SWISS_FR_KEYCODES_VERSION "0.0.1"
+#define QMK_SWISS_FR_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_SWISS_FR_KEYCODES_VERSION_MAJOR 0
+#define QMK_SWISS_FR_KEYCODES_VERSION_MINOR 0
+#define QMK_SWISS_FR_KEYCODES_VERSION_PATCH 1
+
#undef CH_H
// Aliases
diff --git a/quantum/keymap_extras/keymap_turkish_f.h b/quantum/keymap_extras/keymap_turkish_f.h
index dcf9e815d7..bbdaa3af25 100644
--- a/quantum/keymap_extras/keymap_turkish_f.h
+++ b/quantum/keymap_extras/keymap_turkish_f.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_TURKISH_F_KEYCODES_VERSION "0.0.1"
+#define QMK_TURKISH_F_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_TURKISH_F_KEYCODES_VERSION_MAJOR 0
+#define QMK_TURKISH_F_KEYCODES_VERSION_MINOR 0
+#define QMK_TURKISH_F_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define TR_PLUS KC_GRV // +
#define TR_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_turkish_q.h b/quantum/keymap_extras/keymap_turkish_q.h
index a86af180cd..d3fa00d7ae 100644
--- a/quantum/keymap_extras/keymap_turkish_q.h
+++ b/quantum/keymap_extras/keymap_turkish_q.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_TURKISH_Q_KEYCODES_VERSION "0.0.1"
+#define QMK_TURKISH_Q_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_TURKISH_Q_KEYCODES_VERSION_MAJOR 0
+#define QMK_TURKISH_Q_KEYCODES_VERSION_MINOR 0
+#define QMK_TURKISH_Q_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define TR_DQUO KC_GRV // "
#define TR_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_uk.h b/quantum/keymap_extras/keymap_uk.h
index 30f9b972db..7490af6cf6 100644
--- a/quantum/keymap_extras/keymap_uk.h
+++ b/quantum/keymap_extras/keymap_uk.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_UK_KEYCODES_VERSION "0.0.1"
+#define QMK_UK_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_UK_KEYCODES_VERSION_MAJOR 0
+#define QMK_UK_KEYCODES_VERSION_MINOR 0
+#define QMK_UK_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define UK_GRV KC_GRV // `
#define UK_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_ukrainian.h b/quantum/keymap_extras/keymap_ukrainian.h
index d3f82a2194..78e39f8c75 100644
--- a/quantum/keymap_extras/keymap_ukrainian.h
+++ b/quantum/keymap_extras/keymap_ukrainian.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_UKRAINIAN_KEYCODES_VERSION "0.0.1"
+#define QMK_UKRAINIAN_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_UKRAINIAN_KEYCODES_VERSION_MAJOR 0
+#define QMK_UKRAINIAN_KEYCODES_VERSION_MINOR 0
+#define QMK_UKRAINIAN_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define UA_QUOT KC_GRV // '
#define UA_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_us.h b/quantum/keymap_extras/keymap_us.h
index 74c9b8e7f8..b6e380ab23 100644
--- a/quantum/keymap_extras/keymap_us.h
+++ b/quantum/keymap_extras/keymap_us.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_US_KEYCODES_VERSION "0.0.1"
+#define QMK_US_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_US_KEYCODES_VERSION_MAJOR 0
+#define QMK_US_KEYCODES_VERSION_MINOR 0
+#define QMK_US_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define KC_TILD S(KC_GRAVE) // ~
#define KC_EXLM S(KC_1) // !
diff --git a/quantum/keymap_extras/keymap_us_extended.h b/quantum/keymap_extras/keymap_us_extended.h
index d17d3e603e..4262a7c44e 100644
--- a/quantum/keymap_extras/keymap_us_extended.h
+++ b/quantum/keymap_extras/keymap_us_extended.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_US_EXTENDED_KEYCODES_VERSION "0.0.1"
+#define QMK_US_EXTENDED_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_US_EXTENDED_KEYCODES_VERSION_MAJOR 0
+#define QMK_US_EXTENDED_KEYCODES_VERSION_MINOR 0
+#define QMK_US_EXTENDED_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define US_GRV KC_GRV // `
#define US_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_us_international.h b/quantum/keymap_extras/keymap_us_international.h
index a9617494a8..adc7051fe4 100644
--- a/quantum/keymap_extras/keymap_us_international.h
+++ b/quantum/keymap_extras/keymap_us_international.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_US_INTERNATIONAL_KEYCODES_VERSION "0.0.1"
+#define QMK_US_INTERNATIONAL_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_US_INTERNATIONAL_KEYCODES_VERSION_MAJOR 0
+#define QMK_US_INTERNATIONAL_KEYCODES_VERSION_MINOR 0
+#define QMK_US_INTERNATIONAL_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define US_DGRV KC_GRV // ` (dead)
#define US_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_us_international_linux.h b/quantum/keymap_extras/keymap_us_international_linux.h
index b13039be05..db315968d6 100644
--- a/quantum/keymap_extras/keymap_us_international_linux.h
+++ b/quantum/keymap_extras/keymap_us_international_linux.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_US_INTERNATIONAL_LINUX_KEYCODES_VERSION "0.0.1"
+#define QMK_US_INTERNATIONAL_LINUX_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_US_INTERNATIONAL_LINUX_KEYCODES_VERSION_MAJOR 0
+#define QMK_US_INTERNATIONAL_LINUX_KEYCODES_VERSION_MINOR 0
+#define QMK_US_INTERNATIONAL_LINUX_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define US_DGRV KC_GRV // ` (dead)
#define US_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_workman.h b/quantum/keymap_extras/keymap_workman.h
index 29396fdec1..727e44512c 100644
--- a/quantum/keymap_extras/keymap_workman.h
+++ b/quantum/keymap_extras/keymap_workman.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_WORKMAN_KEYCODES_VERSION "0.0.1"
+#define QMK_WORKMAN_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_WORKMAN_KEYCODES_VERSION_MAJOR 0
+#define QMK_WORKMAN_KEYCODES_VERSION_MINOR 0
+#define QMK_WORKMAN_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define WK_GRV KC_GRV // `
#define WK_1 KC_1 // 1
diff --git a/quantum/keymap_extras/keymap_workman_zxcvm.h b/quantum/keymap_extras/keymap_workman_zxcvm.h
index f7a5689f0f..4655af60d6 100644
--- a/quantum/keymap_extras/keymap_workman_zxcvm.h
+++ b/quantum/keymap_extras/keymap_workman_zxcvm.h
@@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
+#define QMK_WORKMAN_ZXCVM_KEYCODES_VERSION "0.0.1"
+#define QMK_WORKMAN_ZXCVM_KEYCODES_VERSION_BCD 0x00000001
+#define QMK_WORKMAN_ZXCVM_KEYCODES_VERSION_MAJOR 0
+#define QMK_WORKMAN_ZXCVM_KEYCODES_VERSION_MINOR 0
+#define QMK_WORKMAN_ZXCVM_KEYCODES_VERSION_PATCH 1
+
// Aliases
#define WK_GRV KC_GRV // `
#define WK_1 KC_1 // 1
diff --git a/quantum/keymap_introspection.c b/quantum/keymap_introspection.c
index 23e842353a..99fd3f929e 100644
--- a/quantum/keymap_introspection.c
+++ b/quantum/keymap_introspection.c
@@ -13,6 +13,7 @@
# include INTROSPECTION_KEYMAP_C
#endif // INTROSPECTION_KEYMAP_C
+#include "compiler_support.h"
#include "keymap_introspection.h"
#include "util.h"
@@ -30,9 +31,9 @@ __attribute__((weak)) uint8_t keymap_layer_count(void) {
}
#ifdef DYNAMIC_KEYMAP_ENABLE
-_Static_assert(NUM_KEYMAP_LAYERS_RAW <= MAX_LAYER, "Number of keymap layers exceeds maximum set by DYNAMIC_KEYMAP_LAYER_COUNT");
+STATIC_ASSERT(NUM_KEYMAP_LAYERS_RAW <= MAX_LAYER, "Number of keymap layers exceeds maximum set by DYNAMIC_KEYMAP_LAYER_COUNT");
#else
-_Static_assert(NUM_KEYMAP_LAYERS_RAW <= MAX_LAYER, "Number of keymap layers exceeds maximum set by LAYER_STATE_(8|16|32)BIT");
+STATIC_ASSERT(NUM_KEYMAP_LAYERS_RAW <= MAX_LAYER, "Number of keymap layers exceeds maximum set by LAYER_STATE_(8|16|32)BIT");
#endif
uint16_t keycode_at_keymap_location_raw(uint8_t layer_num, uint8_t row, uint8_t column) {
@@ -61,7 +62,7 @@ __attribute__((weak)) uint8_t encodermap_layer_count(void) {
return encodermap_layer_count_raw();
}
-_Static_assert(NUM_KEYMAP_LAYERS_RAW == NUM_ENCODERMAP_LAYERS_RAW, "Number of encoder_map layers doesn't match the number of keymap layers");
+STATIC_ASSERT(NUM_KEYMAP_LAYERS_RAW == NUM_ENCODERMAP_LAYERS_RAW, "Number of encoder_map layers doesn't match the number of keymap layers");
uint16_t keycode_at_encodermap_location_raw(uint8_t layer_num, uint8_t encoder_idx, bool clockwise) {
if (layer_num < NUM_ENCODERMAP_LAYERS_RAW && encoder_idx < NUM_ENCODERS) {
@@ -106,7 +107,7 @@ __attribute__((weak)) uint16_t combo_count(void) {
return combo_count_raw();
}
-_Static_assert(ARRAY_SIZE(key_combos) <= (QK_KB), "Number of combos is abnormally high. Are you using SAFE_RANGE in an enum for combos?");
+STATIC_ASSERT(ARRAY_SIZE(key_combos) <= (QK_KB), "Number of combos is abnormally high. Are you using SAFE_RANGE in an enum for combos?");
combo_t* combo_get_raw(uint16_t combo_idx) {
if (combo_idx >= combo_count_raw()) {
@@ -133,7 +134,7 @@ __attribute__((weak)) uint16_t tap_dance_count(void) {
return tap_dance_count_raw();
}
-_Static_assert(ARRAY_SIZE(tap_dance_actions) <= (QK_TAP_DANCE_MAX - QK_TAP_DANCE), "Number of tap dance actions exceeds maximum. Are you using SAFE_RANGE in tap dance enum?");
+STATIC_ASSERT(ARRAY_SIZE(tap_dance_actions) <= (QK_TAP_DANCE_MAX - QK_TAP_DANCE), "Number of tap dance actions exceeds maximum. Are you using SAFE_RANGE in tap dance enum?");
tap_dance_action_t* tap_dance_get_raw(uint16_t tap_dance_idx) {
if (tap_dance_idx >= tap_dance_count_raw()) {
@@ -161,7 +162,7 @@ __attribute__((weak)) uint16_t key_override_count(void) {
return key_override_count_raw();
}
-_Static_assert(ARRAY_SIZE(key_overrides) <= (QK_KB), "Number of key overrides is abnormally high. Are you using SAFE_RANGE in an enum for key overrides?");
+STATIC_ASSERT(ARRAY_SIZE(key_overrides) <= (QK_KB), "Number of key overrides is abnormally high. Are you using SAFE_RANGE in an enum for key overrides?");
const key_override_t* key_override_get_raw(uint16_t key_override_idx) {
if (key_override_idx >= key_override_count_raw()) {
diff --git a/quantum/led_matrix/led_matrix.c b/quantum/led_matrix/led_matrix.c
index 2e107a66e9..9c8004cc17 100644
--- a/quantum/led_matrix/led_matrix.c
+++ b/quantum/led_matrix/led_matrix.c
@@ -19,7 +19,6 @@
#include "led_matrix.h"
#include "progmem.h"
-#include "eeprom.h"
#include "eeconfig.h"
#include "keyboard.h"
#include "sync_timer.h"
@@ -46,6 +45,9 @@ const led_point_t k_led_matrix_center = LED_MATRIX_CENTER;
#define LED_MATRIX_CUSTOM_EFFECT_IMPLS
#include "led_matrix_effects.inc"
+#ifdef COMMUNITY_MODULES_ENABLE
+# include "led_matrix_community_modules.inc"
+#endif
#ifdef LED_MATRIX_CUSTOM_KB
# include "led_matrix_kb.inc"
#endif
@@ -105,7 +107,11 @@ void eeconfig_update_led_matrix_default(void) {
void eeconfig_debug_led_matrix(void) {
dprintf("led_matrix_eeconfig EEPROM\n");
dprintf("led_matrix_eeconfig.enable = %d\n", led_matrix_eeconfig.enable);
+#ifdef LED_MATRIX_MODE_NAME_ENABLE
+ dprintf("led_matrix_eeconfig.mode = %d (%s)\n", led_matrix_eeconfig.mode, led_matrix_get_mode_name(led_matrix_eeconfig.mode));
+#else
dprintf("led_matrix_eeconfig.mode = %d\n", led_matrix_eeconfig.mode);
+#endif // LED_MATRIX_MODE_NAME_ENABLE
dprintf("led_matrix_eeconfig.val = %d\n", led_matrix_eeconfig.val);
dprintf("led_matrix_eeconfig.speed = %d\n", led_matrix_eeconfig.speed);
dprintf("led_matrix_eeconfig.flags = %d\n", led_matrix_eeconfig.flags);
@@ -283,6 +289,15 @@ static void led_task_render(uint8_t effect) {
#include "led_matrix_effects.inc"
#undef LED_MATRIX_EFFECT
+#ifdef COMMUNITY_MODULES_ENABLE
+# define LED_MATRIX_EFFECT(name, ...) \
+ case LED_MATRIX_COMMUNITY_MODULE_##name: \
+ rendering = name(&led_effect_params); \
+ break;
+# include "led_matrix_community_modules.inc"
+# undef LED_MATRIX_EFFECT
+#endif
+
#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER)
# define LED_MATRIX_EFFECT(name, ...) \
case LED_MATRIX_CUSTOM_##name: \
@@ -359,7 +374,12 @@ void led_matrix_task(void) {
}
}
+__attribute__((weak)) bool led_matrix_indicators_modules(void) {
+ return true;
+}
+
void led_matrix_indicators(void) {
+ led_matrix_indicators_modules();
led_matrix_indicators_kb();
}
@@ -371,6 +391,10 @@ __attribute__((weak)) bool led_matrix_indicators_user(void) {
return true;
}
+__attribute__((weak)) bool led_matrix_indicators_advanced_modules(uint8_t led_min, uint8_t led_max) {
+ return true;
+}
+
void led_matrix_indicators_advanced(effect_params_t *params) {
/* special handling is needed for "params->iter", since it's already been incremented.
* Could move the invocations to led_task_render, but then it's missing a few checks
@@ -378,6 +402,7 @@ void led_matrix_indicators_advanced(effect_params_t *params) {
* led_task_render, right before the iter++ line.
*/
LED_MATRIX_USE_LIMITS_ITER(min, max, params->iter - 1);
+ led_matrix_indicators_advanced_modules(min, max);
led_matrix_indicators_advanced_kb(min, max);
}
@@ -504,7 +529,11 @@ void led_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
}
led_task_state = STARTING;
eeconfig_flag_led_matrix(write_to_eeprom);
- dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.mode);
+#ifdef LED_MATRIX_MODE_NAME_ENABLE
+ dprintf("led matrix mode [%s]: %u (%s)\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", (unsigned)led_matrix_eeconfig.mode, led_matrix_get_mode_name(led_matrix_eeconfig.mode));
+#else
+ dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", (unsigned)led_matrix_eeconfig.mode);
+#endif // LED_MATRIX_MODE_NAME_ENABLE
}
void led_matrix_mode_noeeprom(uint8_t mode) {
led_matrix_mode_eeprom_helper(mode, false);
@@ -631,3 +660,48 @@ void led_matrix_set_flags(led_flags_t flags) {
void led_matrix_set_flags_noeeprom(led_flags_t flags) {
led_matrix_set_flags_eeprom_helper(flags, false);
}
+
+// LED Matrix naming
+#undef LED_MATRIX_EFFECT
+#ifdef LED_MATRIX_MODE_NAME_ENABLE
+const char *led_matrix_get_mode_name(uint8_t mode) {
+ switch (mode) {
+ case LED_MATRIX_NONE:
+ return "NONE";
+
+# define LED_MATRIX_EFFECT(name, ...) \
+ case LED_MATRIX_##name: \
+ return #name;
+# include "led_matrix_effects.inc"
+# undef LED_MATRIX_EFFECT
+
+# ifdef COMMUNITY_MODULES_ENABLE
+# define LED_MATRIX_EFFECT(name, ...) \
+ case LED_MATRIX_COMMUNITY_MODULE_##name: \
+ return #name;
+# include "led_matrix_community_modules.inc"
+# undef LED_MATRIX_EFFECT
+# endif // COMMUNITY_MODULES_ENABLE
+
+# if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER)
+# define LED_MATRIX_EFFECT(name, ...) \
+ case LED_MATRIX_CUSTOM_##name: \
+ return #name;
+
+# ifdef LED_MATRIX_CUSTOM_KB
+# include "led_matrix_kb.inc"
+# endif // LED_MATRIX_CUSTOM_KB
+
+# ifdef LED_MATRIX_CUSTOM_USER
+# include "led_matrix_user.inc"
+# endif // LED_MATRIX_CUSTOM_USER
+
+# undef LED_MATRIX_EFFECT
+# endif // LED_MATRIX_CUSTOM_KB || LED_MATRIX_CUSTOM_USER
+
+ default:
+ return "UNKNOWN";
+ }
+}
+# undef LED_MATRIX_EFFECT
+#endif // LED_MATRIX_MODE_NAME_ENABLE
diff --git a/quantum/led_matrix/led_matrix.h b/quantum/led_matrix/led_matrix.h
index 0006d487e9..9a49515ab2 100644
--- a/quantum/led_matrix/led_matrix.h
+++ b/quantum/led_matrix/led_matrix.h
@@ -98,6 +98,12 @@ enum led_matrix_effects {
#include "led_matrix_effects.inc"
#undef LED_MATRIX_EFFECT
+#ifdef COMMUNITY_MODULES_ENABLE
+# define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_COMMUNITY_MODULE_##name,
+# include "led_matrix_community_modules.inc"
+# undef LED_MATRIX_EFFECT
+#endif
+
#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER)
# define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_CUSTOM_##name,
# ifdef LED_MATRIX_CUSTOM_KB
@@ -178,6 +184,10 @@ led_flags_t led_matrix_get_flags(void);
void led_matrix_set_flags(led_flags_t flags);
void led_matrix_set_flags_noeeprom(led_flags_t flags);
+#ifdef LED_MATRIX_MODE_NAME_ENABLE
+const char *led_matrix_get_mode_name(uint8_t mode);
+#endif // LED_MATRIX_MODE_NAME_ENABLE
+
static inline bool led_matrix_check_finished_leds(uint8_t led_idx) {
#if defined(LED_MATRIX_SPLIT)
if (is_keyboard_left()) {
diff --git a/quantum/led_matrix/led_matrix_types.h b/quantum/led_matrix/led_matrix_types.h
index 810420f46f..26a199701e 100644
--- a/quantum/led_matrix/led_matrix_types.h
+++ b/quantum/led_matrix/led_matrix_types.h
@@ -18,6 +18,8 @@
#include <stdint.h>
#include <stdbool.h>
+
+#include "compiler_support.h"
#include "util.h"
#if defined(LED_MATRIX_KEYPRESSES) || defined(LED_MATRIX_KEYRELEASES)
@@ -82,4 +84,4 @@ typedef union led_eeconfig_t {
};
} led_eeconfig_t;
-_Static_assert(sizeof(led_eeconfig_t) == sizeof(uint32_t), "LED Matrix EECONFIG out of spec.");
+STATIC_ASSERT(sizeof(led_eeconfig_t) == sizeof(uint32_t), "LED Matrix EECONFIG out of spec.");
diff --git a/quantum/nvm/eeprom/nvm_dynamic_keymap.c b/quantum/nvm/eeprom/nvm_dynamic_keymap.c
index 5f514acc1a..5ff49795b2 100644
--- a/quantum/nvm/eeprom/nvm_dynamic_keymap.c
+++ b/quantum/nvm/eeprom/nvm_dynamic_keymap.c
@@ -1,6 +1,7 @@
// Copyright 2024 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
+#include "compiler_support.h"
#include "keycodes.h"
#include "eeprom.h"
#include "dynamic_keymap.h"
@@ -25,10 +26,10 @@
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR (TOTAL_EEPROM_BYTE_COUNT - 1)
#endif
-_Static_assert(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR <= (TOTAL_EEPROM_BYTE_COUNT - 1), "DYNAMIC_KEYMAP_EEPROM_MAX_ADDR is configured to use more space than what is available for the selected EEPROM driver");
+STATIC_ASSERT(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR <= (TOTAL_EEPROM_BYTE_COUNT - 1), "DYNAMIC_KEYMAP_EEPROM_MAX_ADDR is configured to use more space than what is available for the selected EEPROM driver");
// Due to usage of uint16_t check for max 65535
-_Static_assert(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR <= 65535, "DYNAMIC_KEYMAP_EEPROM_MAX_ADDR must be less than 65536");
+STATIC_ASSERT(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR <= 65535, "DYNAMIC_KEYMAP_EEPROM_MAX_ADDR must be less than 65536");
// If DYNAMIC_KEYMAP_EEPROM_ADDR not explicitly defined in config.h,
#ifndef DYNAMIC_KEYMAP_EEPROM_ADDR
@@ -56,7 +57,7 @@ _Static_assert(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR <= 65535, "DYNAMIC_KEYMAP_EEPROM_M
// The keyboard should override DYNAMIC_KEYMAP_LAYER_COUNT to reduce it,
// or DYNAMIC_KEYMAP_EEPROM_MAX_ADDR to increase it, *only if* the microcontroller has
// more than the default.
-_Static_assert((DYNAMIC_KEYMAP_EEPROM_MAX_ADDR) - (DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR) >= 100, "Dynamic keymaps are configured to use more EEPROM than is available.");
+STATIC_ASSERT((int64_t)(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR) - (int64_t)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR) >= 100, "Dynamic keymaps are configured to use more EEPROM than is available.");
#ifndef TOTAL_EEPROM_BYTE_COUNT
# error Unknown total EEPROM size. Cannot derive maximum for dynamic keymaps.
diff --git a/quantum/nvm/eeprom/nvm_eeconfig.c b/quantum/nvm/eeprom/nvm_eeconfig.c
index d6c388f3bc..d9495d2753 100644
--- a/quantum/nvm/eeprom/nvm_eeconfig.c
+++ b/quantum/nvm/eeprom/nvm_eeconfig.c
@@ -41,6 +41,10 @@
# include "haptic.h"
#endif
+#ifdef CONNECTION_ENABLE
+# include "connection.h"
+#endif
+
void nvm_eeconfig_erase(void) {
#ifdef EEPROM_DRIVER
eeprom_driver_format(false);
@@ -196,6 +200,15 @@ void nvm_eeconfig_update_haptic(const haptic_config_t *haptic_config) {
}
#endif // HAPTIC_ENABLE
+#ifdef CONNECTION_ENABLE
+void nvm_eeconfig_read_connection(connection_config_t *config) {
+ config->raw = eeprom_read_byte(EECONFIG_CONNECTION);
+}
+void nvm_eeconfig_update_connection(const connection_config_t *config) {
+ eeprom_update_byte(EECONFIG_CONNECTION, config->raw);
+}
+#endif // CONNECTION_ENABLE
+
bool nvm_eeconfig_read_handedness(void) {
return !!eeprom_read_byte(EECONFIG_HANDEDNESS);
}
diff --git a/quantum/nvm/eeprom/nvm_eeprom_eeconfig_internal.h b/quantum/nvm/eeprom/nvm_eeprom_eeconfig_internal.h
index 6efbf9480b..78b8190eaf 100644
--- a/quantum/nvm/eeprom/nvm_eeprom_eeconfig_internal.h
+++ b/quantum/nvm/eeprom/nvm_eeprom_eeconfig_internal.h
@@ -4,6 +4,8 @@
#include <stdint.h>
#include <stddef.h> // offsetof
+
+#include "compiler_support.h"
#include "eeconfig.h"
#include "util.h"
@@ -27,6 +29,7 @@ typedef struct PACKED {
};
uint32_t haptic;
uint8_t rgblight_ext;
+ uint8_t connection;
} eeprom_core_t;
/* EEPROM parameter address */
@@ -46,6 +49,7 @@ typedef struct PACKED {
#define EECONFIG_RGB_MATRIX (uint64_t *)(offsetof(eeprom_core_t, rgb_matrix))
#define EECONFIG_HAPTIC (uint32_t *)(offsetof(eeprom_core_t, haptic))
#define EECONFIG_RGBLIGHT_EXTENDED (uint8_t *)(offsetof(eeprom_core_t, rgblight_ext))
+#define EECONFIG_CONNECTION (uint8_t *)(offsetof(eeprom_core_t, connection))
// Size of EEPROM being used for core data storage
#define EECONFIG_BASE_SIZE ((uint8_t)sizeof(eeprom_core_t))
@@ -56,4 +60,4 @@ typedef struct PACKED {
// Size of EEPROM being used, other code can refer to this for available EEPROM
#define EECONFIG_SIZE ((EECONFIG_BASE_SIZE) + (EECONFIG_KB_DATA_SIZE) + (EECONFIG_USER_DATA_SIZE))
-_Static_assert((intptr_t)EECONFIG_HANDEDNESS == 14, "EEPROM handedness offset is incorrect");
+STATIC_ASSERT((intptr_t)EECONFIG_HANDEDNESS == 14, "EEPROM handedness offset is incorrect");
diff --git a/quantum/nvm/nvm_eeconfig.h b/quantum/nvm/nvm_eeconfig.h
index 131f61d534..40827361ca 100644
--- a/quantum/nvm/nvm_eeconfig.h
+++ b/quantum/nvm/nvm_eeconfig.h
@@ -87,6 +87,12 @@ void nvm_eeconfig_read_haptic(haptic_config_t *haptic_c
void nvm_eeconfig_update_haptic(const haptic_config_t *haptic_config);
#endif // HAPTIC_ENABLE
+#ifdef CONNECTION_ENABLE
+typedef union connection_config_t connection_config_t;
+void nvm_eeconfig_read_connection(connection_config_t *config);
+void nvm_eeconfig_update_connection(const connection_config_t *config);
+#endif // CONNECTION_ENABLE
+
bool nvm_eeconfig_read_handedness(void);
void nvm_eeconfig_update_handedness(bool val);
diff --git a/quantum/os_detection.c b/quantum/os_detection.c
index 9a9f9052f2..552375f61c 100644
--- a/quantum/os_detection.c
+++ b/quantum/os_detection.c
@@ -68,6 +68,15 @@ static volatile bool first_report = true;
static volatile struct usb_device_state current_usb_device_state = {.configure_state = USB_DEVICE_STATE_NO_INIT};
static volatile struct usb_device_state maxprev_usb_device_state = {.configure_state = USB_DEVICE_STATE_NO_INIT};
+// to reset the keyboard on USB state change
+#ifdef OS_DETECTION_KEYBOARD_RESET
+# ifndef OS_DETECTION_RESET_DEBOUNCE
+# define OS_DETECTION_RESET_DEBOUNCE OS_DETECTION_DEBOUNCE
+# endif
+static volatile fast_timer_t configured_since = 0;
+static volatile bool reset_pending = false;
+#endif
+
// the OS detection might be unstable for a while, "debounce" it
static volatile bool debouncing = false;
static volatile fast_timer_t last_time = 0;
@@ -77,7 +86,10 @@ bool process_detected_host_os_modules(os_variant_t os);
void os_detection_task(void) {
#ifdef OS_DETECTION_KEYBOARD_RESET
// resetting the keyboard on the USB device state change callback results in instability, so delegate that to this task
- // only take action if it's been stable at least once, to avoid issues with some KVMs
+ if (reset_pending) {
+ soft_reset_keyboard();
+ }
+ // reset the keyboard if it is stuck in the init state for longer than debounce duration, which can happen with some KVMs
if (current_usb_device_state.configure_state <= USB_DEVICE_STATE_INIT && maxprev_usb_device_state.configure_state >= USB_DEVICE_STATE_CONFIGURED) {
if (debouncing && timer_elapsed_fast(last_time) >= OS_DETECTION_DEBOUNCE) {
soft_reset_keyboard();
@@ -187,6 +199,18 @@ void os_detection_notify_usb_device_state_change(struct usb_device_state usb_dev
current_usb_device_state = usb_device_state;
last_time = timer_read_fast();
debouncing = true;
+
+#ifdef OS_DETECTION_KEYBOARD_RESET
+ if (configured_since == 0 && current_usb_device_state.configure_state == USB_DEVICE_STATE_CONFIGURED) {
+ configured_since = timer_read_fast();
+ } else if (current_usb_device_state.configure_state == USB_DEVICE_STATE_INIT) {
+ // reset the keyboard only if it's been stable for at least debounce duration, to avoid issues with some KVMs
+ if (configured_since > 0 && timer_elapsed_fast(configured_since) >= OS_DETECTION_RESET_DEBOUNCE) {
+ reset_pending = true;
+ }
+ configured_since = 0;
+ }
+#endif
}
#if defined(SPLIT_KEYBOARD) && defined(SPLIT_DETECTED_OS_ENABLE)
diff --git a/quantum/painter/qff.h b/quantum/painter/qff.h
index c3b831da17..ed88508d73 100644
--- a/quantum/painter/qff.h
+++ b/quantum/painter/qff.h
@@ -9,6 +9,7 @@
#include <stdint.h>
#include <stdbool.h>
+#include "compiler_support.h"
#include "qp_stream.h"
#include "qp_internal.h"
#include "qgf.h"
@@ -36,7 +37,7 @@ typedef struct QP_PACKED qff_font_descriptor_v1_t {
uint8_t transparency_index; // palette index used for transparent pixels (not yet implemented)
} qff_font_descriptor_v1_t;
-_Static_assert(sizeof(qff_font_descriptor_v1_t) == (sizeof(qgf_block_header_v1_t) + 20), "qff_font_descriptor_v1_t must be 25 bytes in v1 of QFF");
+STATIC_ASSERT(sizeof(qff_font_descriptor_v1_t) == (sizeof(qgf_block_header_v1_t) + 20), "qff_font_descriptor_v1_t must be 25 bytes in v1 of QFF");
#define QFF_MAGIC 0x464651
@@ -54,14 +55,14 @@ typedef struct QP_PACKED qff_ascii_glyph_v1_t {
uint32_t value : 24; // Uses QFF_GLYPH_*_(BITS|MASK) as bitfield ordering is compiler-defined
} qff_ascii_glyph_v1_t;
-_Static_assert(sizeof(qff_ascii_glyph_v1_t) == 3, "qff_ascii_glyph_v1_t must be 3 bytes in v1 of QFF");
+STATIC_ASSERT(sizeof(qff_ascii_glyph_v1_t) == 3, "qff_ascii_glyph_v1_t must be 3 bytes in v1 of QFF");
typedef struct QP_PACKED qff_ascii_glyph_table_v1_t {
qgf_block_header_v1_t header; // = { .type_id = 0x01, .neg_type_id = (~0x01), .length = 285 }
qff_ascii_glyph_v1_t glyph[95]; // 95 glyphs, 0x20..0x7E
} qff_ascii_glyph_table_v1_t;
-_Static_assert(sizeof(qff_ascii_glyph_table_v1_t) == (sizeof(qgf_block_header_v1_t) + (95 * sizeof(qff_ascii_glyph_v1_t))), "qff_ascii_glyph_table_v1_t must be 290 bytes in v1 of QFF");
+STATIC_ASSERT(sizeof(qff_ascii_glyph_table_v1_t) == (sizeof(qgf_block_header_v1_t) + (95 * sizeof(qff_ascii_glyph_v1_t))), "qff_ascii_glyph_table_v1_t must be 290 bytes in v1 of QFF");
/////////////////////////////////////////
// Unicode glyph table descriptor
@@ -73,7 +74,7 @@ typedef struct QP_PACKED qff_unicode_glyph_v1_t {
uint32_t value : 24; // Uses QFF_GLYPH_*_(BITS|MASK) as bitfield ordering is compiler-defined
} qff_unicode_glyph_v1_t;
-_Static_assert(sizeof(qff_unicode_glyph_v1_t) == 6, "qff_unicode_glyph_v1_t must be 6 bytes in v1 of QFF");
+STATIC_ASSERT(sizeof(qff_unicode_glyph_v1_t) == 6, "qff_unicode_glyph_v1_t must be 6 bytes in v1 of QFF");
typedef struct QP_PACKED qff_unicode_glyph_table_v1_t {
qgf_block_header_v1_t header; // = { .type_id = 0x02, .neg_type_id = (~0x02), .length = (N * 6) }
diff --git a/quantum/painter/qgf.h b/quantum/painter/qgf.h
index 33a37709e6..a1e245f15d 100644
--- a/quantum/painter/qgf.h
+++ b/quantum/painter/qgf.h
@@ -9,6 +9,7 @@
#include <stdint.h>
#include <stdbool.h>
+#include "compiler_support.h"
#include "qp_stream.h"
#include "qp_internal.h"
@@ -24,7 +25,7 @@ typedef struct QP_PACKED qgf_block_header_v1_t {
uint32_t length : 24; // 24-bit blob length, allowing for block sizes of a maximum of 16MB.
} qgf_block_header_v1_t;
-_Static_assert(sizeof(qgf_block_header_v1_t) == 5, "qgf_block_header_v1_t must be 5 bytes in v1 of QGF");
+STATIC_ASSERT(sizeof(qgf_block_header_v1_t) == 5, "qgf_block_header_v1_t must be 5 bytes in v1 of QGF");
/////////////////////////////////////////
// Graphics descriptor
@@ -42,7 +43,7 @@ typedef struct QP_PACKED qgf_graphics_descriptor_v1_t {
uint16_t frame_count; // minimum of 1
} qgf_graphics_descriptor_v1_t;
-_Static_assert(sizeof(qgf_graphics_descriptor_v1_t) == (sizeof(qgf_block_header_v1_t) + 18), "qgf_graphics_descriptor_v1_t must be 23 bytes in v1 of QGF");
+STATIC_ASSERT(sizeof(qgf_graphics_descriptor_v1_t) == (sizeof(qgf_block_header_v1_t) + 18), "qgf_graphics_descriptor_v1_t must be 23 bytes in v1 of QGF");
#define QGF_MAGIC 0x464751
@@ -56,7 +57,7 @@ typedef struct QP_PACKED qgf_frame_offsets_v1_t {
uint32_t offset[0]; // '0' signifies that this struct is immediately followed by the frame offsets
} qgf_frame_offsets_v1_t;
-_Static_assert(sizeof(qgf_frame_offsets_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_frame_offsets_v1_t must only contain qgf_block_header_v1_t in v1 of QGF");
+STATIC_ASSERT(sizeof(qgf_frame_offsets_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_frame_offsets_v1_t must only contain qgf_block_header_v1_t in v1 of QGF");
/////////////////////////////////////////
// Frame descriptor
@@ -72,7 +73,7 @@ typedef struct QP_PACKED qgf_frame_v1_t {
uint16_t delay; // frame delay time for animations (in units of milliseconds)
} qgf_frame_v1_t;
-_Static_assert(sizeof(qgf_frame_v1_t) == (sizeof(qgf_block_header_v1_t) + 6), "qgf_frame_v1_t must be 11 bytes in v1 of QGF");
+STATIC_ASSERT(sizeof(qgf_frame_v1_t) == (sizeof(qgf_block_header_v1_t) + 6), "qgf_frame_v1_t must be 11 bytes in v1 of QGF");
#define QGF_FRAME_FLAG_DELTA 0x02
#define QGF_FRAME_FLAG_TRANSPARENT 0x01
@@ -88,14 +89,14 @@ typedef struct QP_PACKED qgf_palette_entry_v1_t {
uint8_t v; // value component: `[0,1]` is mapped to `[0,255]` uint8_t.
} qgf_palette_entry_v1_t;
-_Static_assert(sizeof(qgf_palette_entry_v1_t) == 3, "Palette entry is not 3 bytes in size");
+STATIC_ASSERT(sizeof(qgf_palette_entry_v1_t) == 3, "Palette entry is not 3 bytes in size");
typedef struct QP_PACKED qgf_palette_v1_t {
qgf_block_header_v1_t header; // = { .type_id = 0x03, .neg_type_id = (~0x03), .length = (N * 3 * sizeof(uint8_t)) }
qgf_palette_entry_v1_t hsv[0]; // N * hsv, where N is the number of palette entries depending on the frame format in the descriptor
} qgf_palette_v1_t;
-_Static_assert(sizeof(qgf_palette_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_palette_v1_t must only contain qgf_block_header_v1_t in v1 of QGF");
+STATIC_ASSERT(sizeof(qgf_palette_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_palette_v1_t must only contain qgf_block_header_v1_t in v1 of QGF");
/////////////////////////////////////////
// Frame delta descriptor
@@ -110,7 +111,7 @@ typedef struct QP_PACKED qgf_delta_v1_t {
uint16_t bottom; // The bottom pixel location to to draw the delta image
} qgf_delta_v1_t;
-_Static_assert(sizeof(qgf_delta_v1_t) == (sizeof(qgf_block_header_v1_t) + 8), "qgf_delta_v1_t must be 13 bytes in v1 of QGF");
+STATIC_ASSERT(sizeof(qgf_delta_v1_t) == (sizeof(qgf_block_header_v1_t) + 8), "qgf_delta_v1_t must be 13 bytes in v1 of QGF");
/////////////////////////////////////////
// Frame data descriptor
@@ -122,7 +123,7 @@ typedef struct QP_PACKED qgf_data_v1_t {
uint8_t data[0]; // 0 signifies that this struct is immediately followed by the length of data specified in the header
} qgf_data_v1_t;
-_Static_assert(sizeof(qgf_data_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_data_v1_t must only contain qgf_block_header_v1_t in v1 of QGF");
+STATIC_ASSERT(sizeof(qgf_data_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_data_v1_t must only contain qgf_block_header_v1_t in v1 of QGF");
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// QGF API
diff --git a/quantum/painter/qp_draw_core.c b/quantum/painter/qp_draw_core.c
index aa5fa4aa76..852abb19e8 100644
--- a/quantum/painter/qp_draw_core.c
+++ b/quantum/painter/qp_draw_core.c
@@ -2,12 +2,13 @@
// Copyright 2021 Paul Cotter (@gr1mr3aver)
// SPDX-License-Identifier: GPL-2.0-or-later
+#include "compiler_support.h"
#include "qp_internal.h"
#include "qp_comms.h"
#include "qp_draw.h"
#include "qgf.h"
-_Static_assert((QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE > 0) && (QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE % 16) == 0, "QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE needs to be a non-zero multiple of 16");
+STATIC_ASSERT((QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE > 0) && (QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE % 16) == 0, "QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE needs to be a non-zero multiple of 16");
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Global variables
diff --git a/quantum/painter/qp_internal.c b/quantum/painter/qp_internal.c
index 24b881bd09..fe0c598d78 100644
--- a/quantum/painter/qp_internal.c
+++ b/quantum/painter/qp_internal.c
@@ -3,6 +3,8 @@
#include "qp_internal.h"
+#include "compiler_support.h"
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter Core API: device registration
@@ -67,7 +69,7 @@ static void qp_internal_display_timeout_task(void) {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter Core API: qp_internal_task
-_Static_assert((QUANTUM_PAINTER_TASK_THROTTLE) > 0 && (QUANTUM_PAINTER_TASK_THROTTLE) < 1000, "QUANTUM_PAINTER_TASK_THROTTLE must be between 1 and 999");
+STATIC_ASSERT((QUANTUM_PAINTER_TASK_THROTTLE) > 0 && (QUANTUM_PAINTER_TASK_THROTTLE) < 1000, "QUANTUM_PAINTER_TASK_THROTTLE must be between 1 and 999");
void qp_internal_task(void) {
// Perform throttling of the internal processing of Quantum Painter
diff --git a/quantum/painter/qp_internal_formats.h b/quantum/painter/qp_internal_formats.h
index 1beb604b9e..bd7105cab2 100644
--- a/quantum/painter/qp_internal_formats.h
+++ b/quantum/painter/qp_internal_formats.h
@@ -3,6 +3,7 @@
#pragma once
+#include "compiler_support.h"
#include "qp_internal.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -29,7 +30,7 @@ typedef union QP_PACKED qp_pixel_t {
uint32_t dummy;
} qp_pixel_t;
-_Static_assert(sizeof(qp_pixel_t) == 4, "Invalid size for qp_pixel_t");
+STATIC_ASSERT(sizeof(qp_pixel_t) == 4, "Invalid size for qp_pixel_t");
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter image format
diff --git a/quantum/pointing_device/pointing_device.c b/quantum/pointing_device/pointing_device.c
index cac2875fc8..fe88d5a1af 100644
--- a/quantum/pointing_device/pointing_device.c
+++ b/quantum/pointing_device/pointing_device.c
@@ -25,6 +25,10 @@
# include "mousekey.h"
#endif
+#ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE
+# include "usb_descriptor_common.h"
+#endif
+
#if (defined(POINTING_DEVICE_ROTATION_90) + defined(POINTING_DEVICE_ROTATION_180) + defined(POINTING_DEVICE_ROTATION_270)) > 1
# error More than one rotation selected. This is not supported.
#endif
@@ -76,14 +80,21 @@ uint16_t pointing_device_get_shared_cpi(void) {
#endif // defined(SPLIT_POINTING_ENABLE)
-static report_mouse_t local_mouse_report = {};
-static bool pointing_device_force_send = false;
+static report_mouse_t local_mouse_report = {};
+static bool pointing_device_force_send = false;
+static pointing_device_status_t pointing_device_status = POINTING_DEVICE_STATUS_UNKNOWN;
+
+#ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE
+static uint16_t hires_scroll_resolution;
+#endif
#define POINTING_DEVICE_DRIVER_CONCAT(name) name##_pointing_device_driver
#define POINTING_DEVICE_DRIVER(name) POINTING_DEVICE_DRIVER_CONCAT(name)
#ifdef POINTING_DEVICE_DRIVER_custom
-__attribute__((weak)) void pointing_device_driver_init(void) {}
+__attribute__((weak)) bool pointing_device_driver_init(void) {
+ return false;
+}
__attribute__((weak)) report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report) {
return mouse_report;
}
@@ -102,6 +113,11 @@ const pointing_device_driver_t custom_pointing_device_driver = {
const pointing_device_driver_t *pointing_device_driver = &POINTING_DEVICE_DRIVER(POINTING_DEVICE_DRIVER_NAME);
+__attribute__((weak)) void pointing_device_init_modules(void) {}
+__attribute__((weak)) report_mouse_t pointing_device_task_modules(report_mouse_t mouse_report) {
+ return mouse_report;
+}
+
/**
* @brief Keyboard level code pointing device initialisation
*
@@ -167,7 +183,11 @@ __attribute__((weak)) void pointing_device_init(void) {
if ((POINTING_DEVICE_THIS_SIDE))
#endif
{
- pointing_device_driver->init();
+ if (pointing_device_driver->init()) {
+ pointing_device_status = POINTING_DEVICE_STATUS_SUCCESS;
+ } else {
+ pointing_device_status = POINTING_DEVICE_STATUS_INIT_FAILED;
+ }
#ifdef POINTING_DEVICE_MOTION_PIN
# ifdef POINTING_DEVICE_MOTION_PIN_ACTIVE_LOW
gpio_set_pin_input_high(POINTING_DEVICE_MOTION_PIN);
@@ -176,12 +196,41 @@ __attribute__((weak)) void pointing_device_init(void) {
# endif
#endif
}
+#ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE
+ hires_scroll_resolution = POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER;
+ for (int i = 0; i < POINTING_DEVICE_HIRES_SCROLL_EXPONENT; i++) {
+ hires_scroll_resolution *= 10;
+ }
+#endif
+ pointing_device_init_modules();
pointing_device_init_kb();
pointing_device_init_user();
}
/**
+ * @brief Gets status of pointing device
+ *
+ * Returns current pointing device status
+ * @return pointing_device_status_t
+ */
+__attribute__((weak)) pointing_device_status_t pointing_device_get_status(void) {
+#ifdef SPLIT_POINTING_ENABLE
+ // Assume target side is always good, split transaction checksum should stop additional reports being generated.
+ return POINTING_DEVICE_THIS_SIDE ? pointing_device_status : POINTING_DEVICE_STATUS_SUCCESS;
+#else
+ return pointing_device_status;
+#endif
+}
+
+/**
+ * @brief Sets status of pointing device
+ */
+void pointing_device_set_status(pointing_device_status_t status) {
+ pointing_device_status = status;
+}
+
+/**
* @brief Sends processed mouse report to host
*
* This sends the mouse report generated by pointing_device_task if changed since the last report. Once send zeros mouse report except buttons.
@@ -262,6 +311,10 @@ __attribute__((weak)) bool pointing_device_task(void) {
last_exec = timer_read32();
#endif
+ if (pointing_device_get_status() != POINTING_DEVICE_STATUS_SUCCESS) {
+ return false;
+ }
+
// Gather report info
#ifdef POINTING_DEVICE_MOTION_PIN
# if defined(SPLIT_POINTING_ENABLE)
@@ -306,8 +359,9 @@ __attribute__((weak)) bool pointing_device_task(void) {
local_mouse_report = is_keyboard_left() ? pointing_device_task_combined_kb(local_mouse_report, shared_mouse_report) : pointing_device_task_combined_kb(shared_mouse_report, local_mouse_report);
#else
local_mouse_report = pointing_device_adjust_by_defines(local_mouse_report);
- local_mouse_report = pointing_device_task_kb(local_mouse_report);
#endif
+ local_mouse_report = pointing_device_task_modules(local_mouse_report);
+ local_mouse_report = pointing_device_task_kb(local_mouse_report);
// automatic mouse layer function
#ifdef POINTING_DEVICE_AUTO_MOUSE_ENABLE
pointing_device_task_auto_mouse(local_mouse_report);
@@ -404,10 +458,10 @@ void pointing_device_set_cpi_on_side(bool left, uint16_t cpi) {
* @return mouse_hv_report_t clamped value
*/
static inline mouse_hv_report_t pointing_device_hv_clamp(hv_clamp_range_t value) {
- if (value < HV_REPORT_MIN) {
- return HV_REPORT_MIN;
- } else if (value > HV_REPORT_MAX) {
- return HV_REPORT_MAX;
+ if (value < MOUSE_REPORT_HV_MIN) {
+ return MOUSE_REPORT_HV_MIN;
+ } else if (value > MOUSE_REPORT_HV_MAX) {
+ return MOUSE_REPORT_HV_MAX;
} else {
return value;
}
@@ -420,10 +474,10 @@ static inline mouse_hv_report_t pointing_device_hv_clamp(hv_clamp_range_t value)
* @return mouse_xy_report_t clamped value
*/
static inline mouse_xy_report_t pointing_device_xy_clamp(xy_clamp_range_t value) {
- if (value < XY_REPORT_MIN) {
- return XY_REPORT_MIN;
- } else if (value > XY_REPORT_MAX) {
- return XY_REPORT_MAX;
+ if (value < MOUSE_REPORT_XY_MIN) {
+ return MOUSE_REPORT_XY_MIN;
+ } else if (value > MOUSE_REPORT_XY_MAX) {
+ return MOUSE_REPORT_XY_MAX;
} else {
return value;
}
@@ -523,3 +577,9 @@ __attribute__((weak)) void pointing_device_keycode_handler(uint16_t keycode, boo
pointing_device_send();
}
}
+
+#ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE
+uint16_t pointing_device_get_hires_scroll_resolution(void) {
+ return hires_scroll_resolution;
+}
+#endif \ No newline at end of file
diff --git a/quantum/pointing_device/pointing_device.h b/quantum/pointing_device/pointing_device.h
index 72188c977d..5dfb9ce196 100644
--- a/quantum/pointing_device/pointing_device.h
+++ b/quantum/pointing_device/pointing_device.h
@@ -17,12 +17,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
+#include <stdbool.h>
#include <stdint.h>
#include "host.h"
#include "report.h"
typedef struct {
- void (*init)(void);
+ bool (*init)(void);
report_mouse_t (*get_report)(report_mouse_t mouse_report);
void (*set_cpi)(uint16_t);
uint16_t (*get_cpi)(void);
@@ -74,7 +75,7 @@ typedef struct {
# include "drivers/sensors/pmw33xx_common.h"
# define POINTING_DEVICE_MOTION_PIN_ACTIVE_LOW
#else
-void pointing_device_driver_init(void);
+bool pointing_device_driver_init(void);
report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report);
uint16_t pointing_device_driver_get_cpi(void);
void pointing_device_driver_set_cpi(uint16_t cpi);
@@ -91,36 +92,37 @@ typedef enum {
POINTING_DEVICE_BUTTON8,
} pointing_device_buttons_t;
+typedef enum {
+ POINTING_DEVICE_STATUS_UNKNOWN,
+ POINTING_DEVICE_STATUS_INIT_FAILED,
+ POINTING_DEVICE_STATUS_FAILED,
+ POINTING_DEVICE_STATUS_SUCCESS,
+} pointing_device_status_t;
+
#ifdef MOUSE_EXTENDED_REPORT
-# define XY_REPORT_MIN INT16_MIN
-# define XY_REPORT_MAX INT16_MAX
typedef int32_t xy_clamp_range_t;
#else
-# define XY_REPORT_MIN INT8_MIN
-# define XY_REPORT_MAX INT8_MAX
typedef int16_t xy_clamp_range_t;
#endif
#ifdef WHEEL_EXTENDED_REPORT
-# define HV_REPORT_MIN INT16_MIN
-# define HV_REPORT_MAX INT16_MAX
typedef int32_t hv_clamp_range_t;
#else
-# define HV_REPORT_MIN INT8_MIN
-# define HV_REPORT_MAX INT8_MAX
typedef int16_t hv_clamp_range_t;
#endif
#define CONSTRAIN_HID(amt) ((amt) < INT8_MIN ? INT8_MIN : ((amt) > INT8_MAX ? INT8_MAX : (amt)))
-#define CONSTRAIN_HID_XY(amt) ((amt) < XY_REPORT_MIN ? XY_REPORT_MIN : ((amt) > XY_REPORT_MAX ? XY_REPORT_MAX : (amt)))
+#define CONSTRAIN_HID_XY(amt) ((amt) < MOUSE_REPORT_XY_MIN ? MOUSE_REPORT_XY_MIN : ((amt) > MOUSE_REPORT_XY_MAX ? MOUSE_REPORT_XY_MAX : (amt)))
-void pointing_device_init(void);
-bool pointing_device_task(void);
-bool pointing_device_send(void);
-report_mouse_t pointing_device_get_report(void);
-void pointing_device_set_report(report_mouse_t mouse_report);
-uint16_t pointing_device_get_cpi(void);
-void pointing_device_set_cpi(uint16_t cpi);
+void pointing_device_init(void);
+bool pointing_device_task(void);
+bool pointing_device_send(void);
+report_mouse_t pointing_device_get_report(void);
+void pointing_device_set_report(report_mouse_t mouse_report);
+uint16_t pointing_device_get_cpi(void);
+void pointing_device_set_cpi(uint16_t cpi);
+pointing_device_status_t pointing_device_get_status(void);
+void pointing_device_set_status(pointing_device_status_t status);
void pointing_device_init_kb(void);
void pointing_device_init_user(void);
@@ -130,6 +132,10 @@ uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, poi
report_mouse_t pointing_device_adjust_by_defines(report_mouse_t mouse_report);
void pointing_device_keycode_handler(uint16_t keycode, bool pressed);
+#ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE
+uint16_t pointing_device_get_hires_scroll_resolution(void);
+#endif
+
#if defined(SPLIT_POINTING_ENABLE)
void pointing_device_set_shared_report(report_mouse_t report);
uint16_t pointing_device_get_shared_cpi(void);
diff --git a/quantum/process_keycode/process_caps_word.c b/quantum/process_keycode/process_caps_word.c
index b8fb868c6d..8ab66cc521 100644
--- a/quantum/process_keycode/process_caps_word.c
+++ b/quantum/process_keycode/process_caps_word.c
@@ -160,8 +160,13 @@ bool process_caps_word(uint16_t keycode, keyrecord_t* record) {
case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX:
case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX:
case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX:
+#ifdef TRI_LAYER_ENABLE // Ignore Tri Layer keys.
case QK_TRI_LAYER_LOWER ... QK_TRI_LAYER_UPPER:
- // Ignore AltGr.
+#endif // TRI_LAYER_ENABLE
+#ifdef LAYER_LOCK_ENABLE // Ignore Layer Lock key.
+ case QK_LAYER_LOCK:
+#endif // LAYER_LOCK_ENABLE
+ // Ignore AltGr.
case KC_RALT:
case OSM(MOD_RALT):
return true;
diff --git a/quantum/process_keycode/process_connection.c b/quantum/process_keycode/process_connection.c
index b0e230d680..501529ede7 100644
--- a/quantum/process_keycode/process_connection.c
+++ b/quantum/process_keycode/process_connection.c
@@ -1,24 +1,34 @@
// Copyright 2024 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "outputselect.h"
+#include "connection.h"
#include "process_connection.h"
bool process_connection(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) {
switch (keycode) {
case QK_OUTPUT_NEXT:
- set_output(OUTPUT_AUTO); // This should cycle through the outputs going forward. Ensure `docs/keycodes.md`, `docs/features/bluetooth.md` are updated when it does.
+ connection_next_host();
+ return false;
+ case QK_OUTPUT_PREV:
+ connection_prev_host();
+ return false;
+
+ case QK_OUTPUT_AUTO:
+ connection_set_host(CONNECTION_HOST_AUTO);
+ return false;
+ case QK_OUTPUT_NONE:
+ connection_set_host(CONNECTION_HOST_NONE);
return false;
case QK_OUTPUT_USB:
- set_output(OUTPUT_USB);
+ connection_set_host(CONNECTION_HOST_USB);
return false;
case QK_OUTPUT_BLUETOOTH:
- set_output(OUTPUT_BLUETOOTH);
+ connection_set_host(CONNECTION_HOST_BLUETOOTH);
return false;
-
- case QK_OUTPUT_PREV:
- case QK_OUTPUT_NONE:
case QK_OUTPUT_2P4GHZ:
+ connection_set_host(CONNECTION_HOST_2P4GHZ);
+ return false;
+
case QK_BLUETOOTH_PROFILE_NEXT:
case QK_BLUETOOTH_PROFILE_PREV:
case QK_BLUETOOTH_UNPAIR:
diff --git a/quantum/process_keycode/process_leader.c b/quantum/process_keycode/process_leader.c
index ca017a577d..a5466c513c 100644
--- a/quantum/process_keycode/process_leader.c
+++ b/quantum/process_keycode/process_leader.c
@@ -22,11 +22,7 @@ bool process_leader(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) {
if (leader_sequence_active() && !leader_sequence_timed_out()) {
#ifndef LEADER_KEY_STRICT_KEY_PROCESSING
- if (IS_QK_MOD_TAP(keycode)) {
- keycode = QK_MOD_TAP_GET_TAP_KEYCODE(keycode);
- } else if (IS_QK_LAYER_TAP(keycode)) {
- keycode = QK_LAYER_TAP_GET_TAP_KEYCODE(keycode);
- }
+ keycode = get_tap_keycode(keycode);
#endif
if (!leader_sequence_add(keycode)) {
diff --git a/quantum/process_keycode/process_oneshot.c b/quantum/process_keycode/process_oneshot.c
new file mode 100644
index 0000000000..6c43da1011
--- /dev/null
+++ b/quantum/process_keycode/process_oneshot.c
@@ -0,0 +1,25 @@
+// Copyright 2025 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "process_oneshot.h"
+#include "action_util.h"
+
+bool process_oneshot(uint16_t keycode, keyrecord_t *record) {
+#ifndef NO_ACTION_ONESHOT
+ if (record->event.pressed) {
+ switch (keycode) {
+ case QK_ONE_SHOT_TOGGLE:
+ oneshot_toggle();
+ return false;
+ case QK_ONE_SHOT_ON:
+ oneshot_enable();
+ return false;
+ case QK_ONE_SHOT_OFF:
+ oneshot_disable();
+ return false;
+ }
+ }
+#endif
+
+ return true;
+}
diff --git a/quantum/process_keycode/process_oneshot.h b/quantum/process_keycode/process_oneshot.h
new file mode 100644
index 0000000000..11445b9b38
--- /dev/null
+++ b/quantum/process_keycode/process_oneshot.h
@@ -0,0 +1,10 @@
+// Copyright 2025 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "action.h"
+
+bool process_oneshot(uint16_t keycode, keyrecord_t *record);
diff --git a/quantum/process_keycode/process_quantum.c b/quantum/process_keycode/process_quantum.c
new file mode 100644
index 0000000000..703e00755b
--- /dev/null
+++ b/quantum/process_keycode/process_quantum.c
@@ -0,0 +1,76 @@
+// Copyright 2025 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "process_quantum.h"
+#include "quantum.h"
+
+#ifdef ENABLE_COMPILE_KEYCODE
+/** \brief Compiles the firmware, and adds the flash command based on keyboard bootloader
+ */
+static void send_make_command(void) {
+# ifdef NO_ACTION_ONESHOT
+ const uint8_t temp_mod = mod_config(get_mods());
+# else
+ const uint8_t temp_mod = mod_config(get_mods() | get_oneshot_mods());
+ clear_oneshot_mods();
+# endif
+ clear_mods();
+
+ SEND_STRING_DELAY("qmk", TAP_CODE_DELAY);
+ if (temp_mod & MOD_MASK_SHIFT) { // if shift is held, flash rather than compile
+ SEND_STRING_DELAY(" flash ", TAP_CODE_DELAY);
+ } else {
+ SEND_STRING_DELAY(" compile ", TAP_CODE_DELAY);
+ }
+# if defined(CONVERTER_ENABLED)
+ SEND_STRING_DELAY("-kb " QMK_KEYBOARD " -km " QMK_KEYMAP " -e CONVERT_TO=" CONVERTER_TARGET SS_TAP(X_ENTER), TAP_CODE_DELAY);
+# else
+ SEND_STRING_DELAY("-kb " QMK_KEYBOARD " -km " QMK_KEYMAP SS_TAP(X_ENTER), TAP_CODE_DELAY);
+# endif
+ if (temp_mod & MOD_MASK_SHIFT && temp_mod & MOD_MASK_CTRL) {
+ reset_keyboard();
+ }
+}
+#endif
+
+bool process_quantum(uint16_t keycode, keyrecord_t *record) {
+ if (record->event.pressed) {
+ switch (keycode) {
+#ifndef NO_RESET
+ case QK_BOOTLOADER:
+ reset_keyboard();
+ return false;
+ case QK_REBOOT:
+ soft_reset_keyboard();
+ return false;
+#endif
+#ifndef NO_DEBUG
+ case QK_DEBUG_TOGGLE:
+ debug_enable ^= 1;
+ if (debug_enable) {
+ print("DEBUG: enabled.\n");
+ } else {
+ print("DEBUG: disabled.\n");
+ }
+ return false;
+#endif
+ case QK_CLEAR_EEPROM:
+#ifdef NO_RESET
+ eeconfig_init();
+#else
+ eeconfig_disable();
+ soft_reset_keyboard();
+#endif
+ return false;
+#ifdef ENABLE_COMPILE_KEYCODE
+ case QK_MAKE:
+ send_make_command();
+ return false;
+#endif
+ default:
+ break;
+ }
+ }
+
+ return true;
+}
diff --git a/quantum/process_keycode/process_quantum.h b/quantum/process_keycode/process_quantum.h
new file mode 100644
index 0000000000..5c2462be01
--- /dev/null
+++ b/quantum/process_keycode/process_quantum.h
@@ -0,0 +1,10 @@
+// Copyright 2025 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "action.h"
+
+bool process_quantum(uint16_t keycode, keyrecord_t *record);
diff --git a/quantum/process_keycode/process_repeat_key.c b/quantum/process_keycode/process_repeat_key.c
index 73f4ddedcf..fdeed4f466 100644
--- a/quantum/process_keycode/process_repeat_key.c
+++ b/quantum/process_keycode/process_repeat_key.c
@@ -41,7 +41,10 @@ static bool remember_last_key(uint16_t keycode, keyrecord_t* record, uint8_t* re
#ifdef TRI_LAYER_ENABLE // Ignore Tri Layer keys.
case QK_TRI_LAYER_LOWER:
case QK_TRI_LAYER_UPPER:
-#endif // TRI_LAYER_ENABLE
+#endif // TRI_LAYER_ENABLE
+#ifdef LAYER_LOCK_ENABLE // Ignore Layer Lock key.
+ case QK_LAYER_LOCK:
+#endif // LAYER_LOCK_ENABLE
return false;
// Ignore hold events on tap-hold keys.
diff --git a/quantum/process_keycode/process_underglow.c b/quantum/process_keycode/process_underglow.c
index b8d8989ef3..78006ee099 100644
--- a/quantum/process_keycode/process_underglow.c
+++ b/quantum/process_keycode/process_underglow.c
@@ -200,6 +200,11 @@ bool process_underglow(uint16_t keycode, keyrecord_t *record) {
}
#endif
return false;
+#ifdef VELOCIKEY_ENABLE
+ case QK_VELOCIKEY_TOGGLE:
+ velocikey_toggle();
+ return false;
+#endif
}
}
diff --git a/quantum/quantum.c b/quantum/quantum.c
index adb14d64b6..09e5fe1dac 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -15,12 +15,17 @@
*/
#include "quantum.h"
+#include "process_quantum.h"
+
+#ifdef SLEEP_LED_ENABLE
+# include "sleep_led.h"
+#endif
#ifdef BACKLIGHT_ENABLE
# include "process_backlight.h"
#endif
-#ifdef BLUETOOTH_ENABLE
+#ifdef CONNECTION_ENABLE
# include "process_connection.h"
#endif
@@ -84,6 +89,10 @@
# include "process_layer_lock.h"
#endif
+#ifndef NO_ACTION_ONESHOT
+# include "process_oneshot.h"
+#endif
+
#ifdef AUDIO_ENABLE
# ifndef GOODBYE_SONG
# define GOODBYE_SONG SONG(GOODBYE_SOUND)
@@ -174,10 +183,6 @@ __attribute__((weak)) bool pre_process_record_user(uint16_t keycode, keyrecord_t
return true;
}
-__attribute__((weak)) bool process_action_kb(keyrecord_t *record) {
- return true;
-}
-
__attribute__((weak)) bool process_record_modules(uint16_t keycode, keyrecord_t *record) {
return true;
}
@@ -292,9 +297,10 @@ void post_process_record_quantum(keyrecord_t *record) {
post_process_record_kb(keycode, record);
}
-/* Core keycode function, hands off handling to other functions,
- then processes internal quantum keycodes, and then processes
- ACTIONs. */
+/** \brief Core keycode function
+ *
+ * Hands off handling to other quantum/process_keycode/ functions
+ */
bool process_record_quantum(keyrecord_t *record) {
uint16_t keycode = get_record_keycode(record, true);
@@ -436,88 +442,17 @@ bool process_record_quantum(keyrecord_t *record) {
#ifdef LAYER_LOCK_ENABLE
process_layer_lock(keycode, record) &&
#endif
-#ifdef BLUETOOTH_ENABLE
+#ifdef CONNECTION_ENABLE
process_connection(keycode, record) &&
#endif
- true)) {
- return false;
- }
-
- if (record->event.pressed) {
- switch (keycode) {
-#ifndef NO_RESET
- case QK_BOOTLOADER:
- reset_keyboard();
- return false;
- case QK_REBOOT:
- soft_reset_keyboard();
- return false;
-#endif
-#ifndef NO_DEBUG
- case QK_DEBUG_TOGGLE:
- debug_enable ^= 1;
- if (debug_enable) {
- print("DEBUG: enabled.\n");
- } else {
- print("DEBUG: disabled.\n");
- }
-#endif
- return false;
- case QK_CLEAR_EEPROM:
-#ifdef NO_RESET
- eeconfig_init();
-#else
- eeconfig_disable();
- soft_reset_keyboard();
-#endif
- return false;
-#ifdef VELOCIKEY_ENABLE
- case QK_VELOCIKEY_TOGGLE:
- velocikey_toggle();
- return false;
-#endif
#ifndef NO_ACTION_ONESHOT
- case QK_ONE_SHOT_TOGGLE:
- oneshot_toggle();
- break;
- case QK_ONE_SHOT_ON:
- oneshot_enable();
- break;
- case QK_ONE_SHOT_OFF:
- oneshot_disable();
- break;
-#endif
-#ifdef ENABLE_COMPILE_KEYCODE
- case QK_MAKE: // Compiles the firmware, and adds the flash command based on keyboard bootloader
- {
-# ifdef NO_ACTION_ONESHOT
- const uint8_t temp_mod = mod_config(get_mods());
-# else
- const uint8_t temp_mod = mod_config(get_mods() | get_oneshot_mods());
- clear_oneshot_mods();
-# endif
- clear_mods();
-
- SEND_STRING_DELAY("qmk", TAP_CODE_DELAY);
- if (temp_mod & MOD_MASK_SHIFT) { // if shift is held, flash rather than compile
- SEND_STRING_DELAY(" flash ", TAP_CODE_DELAY);
- } else {
- SEND_STRING_DELAY(" compile ", TAP_CODE_DELAY);
- }
-# if defined(CONVERTER_ENABLED)
- SEND_STRING_DELAY("-kb " QMK_KEYBOARD " -km " QMK_KEYMAP " -e CONVERT_TO=" CONVERTER_TARGET SS_TAP(X_ENTER), TAP_CODE_DELAY);
-# else
- SEND_STRING_DELAY("-kb " QMK_KEYBOARD " -km " QMK_KEYMAP SS_TAP(X_ENTER), TAP_CODE_DELAY);
-# endif
- if (temp_mod & MOD_MASK_SHIFT && temp_mod & MOD_MASK_CTRL) {
- reset_keyboard();
- }
- }
+ process_oneshot(keycode, record) &&
#endif
- }
+ process_quantum(keycode, record))) {
+ return false;
}
- return process_action_kb(record);
+ return true;
}
void set_single_default_layer(uint8_t default_layer) {
@@ -556,6 +491,10 @@ void suspend_power_down_quantum(void) {
backlight_level_noeeprom(0);
# endif
+# ifdef SLEEP_LED_ENABLE
+ sleep_led_enable();
+# endif
+
# ifdef LED_MATRIX_ENABLE
led_matrix_task();
# endif
@@ -602,6 +541,10 @@ __attribute__((weak)) void suspend_wakeup_init_quantum(void) {
backlight_init();
#endif
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_disable();
+#endif
+
// Restore LED indicators
led_wakeup();
diff --git a/quantum/quantum.h b/quantum/quantum.h
index 3a994e9a03..0036cd784b 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -263,7 +263,6 @@ uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache);
bool pre_process_record_quantum(keyrecord_t *record);
bool pre_process_record_kb(uint16_t keycode, keyrecord_t *record);
bool pre_process_record_user(uint16_t keycode, keyrecord_t *record);
-bool process_action_kb(keyrecord_t *record);
bool process_record_kb(uint16_t keycode, keyrecord_t *record);
bool process_record_user(uint16_t keycode, keyrecord_t *record);
void post_process_record_kb(uint16_t keycode, keyrecord_t *record);
diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h
index bcaf94af8b..a2a86e175c 100644
--- a/quantum/quantum_keycodes.h
+++ b/quantum/quantum_keycodes.h
@@ -41,44 +41,59 @@
#define QK_MODS_GET_MODS(kc) (((kc) >> 8) & 0x1F)
#define QK_MODS_GET_BASIC_KEYCODE(kc) ((kc)&0xFF)
-// Keycode modifiers & aliases
+// Modified keycodes
#define LCTL(kc) (QK_LCTL | (kc))
#define LSFT(kc) (QK_LSFT | (kc))
#define LALT(kc) (QK_LALT | (kc))
#define LGUI(kc) (QK_LGUI | (kc))
+
#define LOPT(kc) LALT(kc)
#define LCMD(kc) LGUI(kc)
#define LWIN(kc) LGUI(kc)
+
+#define C(kc) LCTL(kc)
+#define S(kc) LSFT(kc)
+#define A(kc) LALT(kc)
+#define G(kc) LGUI(kc)
+
+#define LCS(kc) (QK_LCTL | QK_LSFT | (kc))
+#define LCA(kc) (QK_LCTL | QK_LALT | (kc))
+#define LCG(kc) (QK_LCTL | QK_LGUI | (kc))
+#define LSA(kc) (QK_LSFT | QK_LALT | (kc))
+#define LSG(kc) (QK_LSFT | QK_LGUI | (kc))
+#define LAG(kc) (QK_LALT | QK_LGUI | (kc))
+#define LCSG(kc) (QK_LCTL | QK_LSFT | QK_LGUI | (kc))
+#define LCAG(kc) (QK_LCTL | QK_LALT | QK_LGUI | (kc))
+#define LSAG(kc) (QK_LSFT | QK_LALT | QK_LGUI | (kc))
+
+#define SGUI(kc) LSG(kc)
+#define SCMD(kc) LSG(kc)
+#define SWIN(kc) LSG(kc)
+
#define RCTL(kc) (QK_RCTL | (kc))
#define RSFT(kc) (QK_RSFT | (kc))
#define RALT(kc) (QK_RALT | (kc))
#define RGUI(kc) (QK_RGUI | (kc))
+
#define ALGR(kc) RALT(kc)
#define ROPT(kc) RALT(kc)
#define RCMD(kc) RGUI(kc)
#define RWIN(kc) RGUI(kc)
-#define HYPR(kc) (QK_LCTL | QK_LSFT | QK_LALT | QK_LGUI | (kc))
-#define MEH(kc) (QK_LCTL | QK_LSFT | QK_LALT | (kc))
-#define LCAG(kc) (QK_LCTL | QK_LALT | QK_LGUI | (kc))
-#define LSG(kc) (QK_LSFT | QK_LGUI | (kc))
-#define SGUI(kc) LSG(kc)
-#define SCMD(kc) LSG(kc)
-#define SWIN(kc) LSG(kc)
-#define LAG(kc) (QK_LALT | QK_LGUI | (kc))
+#define RCA(kc) (QK_RCTL | QK_RALT | (kc))
+#define RCS(kc) (QK_RCTL | QK_RSFT | (kc))
+#define RCG(kc) (QK_RCTL | QK_RGUI | (kc))
+#define RSA(kc) (QK_RSFT | QK_RALT | (kc))
#define RSG(kc) (QK_RSFT | QK_RGUI | (kc))
#define RAG(kc) (QK_RALT | QK_RGUI | (kc))
-#define LCA(kc) (QK_LCTL | QK_LALT | (kc))
-#define LSA(kc) (QK_LSFT | QK_LALT | (kc))
-#define RSA(kc) (QK_RSFT | QK_RALT | (kc))
-#define RCS(kc) (QK_RCTL | QK_RSFT | (kc))
+#define RCSG(kc) (QK_RCTL | QK_RSFT | QK_RGUI | (kc))
+#define RCAG(kc) (QK_RCTL | QK_RALT | QK_RGUI | (kc))
+#define RSAG(kc) (QK_RSFT | QK_RALT | QK_RGUI | (kc))
+
#define SAGR(kc) RSA(kc)
-// Modified keycode aliases
-#define C(kc) LCTL(kc)
-#define S(kc) LSFT(kc)
-#define A(kc) LALT(kc)
-#define G(kc) LGUI(kc)
+#define HYPR(kc) (QK_LCTL | QK_LSFT | QK_LALT | QK_LGUI | (kc))
+#define MEH(kc) (QK_LCTL | QK_LSFT | QK_LALT | (kc))
// GOTO layer - 32 layer max
#define TO(layer) (QK_TO | ((layer)&0x1F))
@@ -127,50 +142,63 @@
#define QK_MOD_TAP_GET_MODS(kc) (((kc) >> 8) & 0x1F)
#define QK_MOD_TAP_GET_TAP_KEYCODE(kc) ((kc)&0xFF)
+// Mod-Tap shortcuts
#define LCTL_T(kc) MT(MOD_LCTL, kc)
-#define RCTL_T(kc) MT(MOD_RCTL, kc)
-#define CTL_T(kc) LCTL_T(kc)
-
#define LSFT_T(kc) MT(MOD_LSFT, kc)
-#define RSFT_T(kc) MT(MOD_RSFT, kc)
-#define SFT_T(kc) LSFT_T(kc)
-
#define LALT_T(kc) MT(MOD_LALT, kc)
-#define RALT_T(kc) MT(MOD_RALT, kc)
-#define LOPT_T(kc) LALT_T(kc)
-#define ROPT_T(kc) RALT_T(kc)
-#define ALGR_T(kc) RALT_T(kc)
+#define LGUI_T(kc) MT(MOD_LGUI, kc)
+
+#define CTL_T(kc) LCTL_T(kc)
+#define SFT_T(kc) LSFT_T(kc)
#define ALT_T(kc) LALT_T(kc)
-#define OPT_T(kc) LOPT_T(kc)
+#define GUI_T(kc) LGUI_T(kc)
-#define LGUI_T(kc) MT(MOD_LGUI, kc)
-#define RGUI_T(kc) MT(MOD_RGUI, kc)
+#define LOPT_T(kc) LALT_T(kc)
#define LCMD_T(kc) LGUI_T(kc)
#define LWIN_T(kc) LGUI_T(kc)
-#define RCMD_T(kc) RGUI_T(kc)
-#define RWIN_T(kc) RGUI_T(kc)
-#define GUI_T(kc) LGUI_T(kc)
+
+#define OPT_T(kc) LOPT_T(kc)
#define CMD_T(kc) LCMD_T(kc)
#define WIN_T(kc) LWIN_T(kc)
-#define C_S_T(kc) MT(MOD_LCTL | MOD_LSFT, kc) // Left Control + Shift e.g. for gnome-terminal
-#define MEH_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT, kc) // Meh is a less hyper version of the Hyper key -- doesn't include GUI, so just Left Control + Shift + Alt
-#define LCAG_T(kc) MT(MOD_LCTL | MOD_LALT | MOD_LGUI, kc) // Left Control + Alt + GUI
-#define RCAG_T(kc) MT(MOD_RCTL | MOD_RALT | MOD_RGUI, kc) // Right Control + Alt + GUI
-#define HYPR_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI, kc) // see http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/
-#define LSG_T(kc) MT(MOD_LSFT | MOD_LGUI, kc) // Left Shift + GUI
+#define LCS_T(kc) MT(MOD_LCTL | MOD_LSFT, kc)
+#define LCA_T(kc) MT(MOD_LCTL | MOD_LALT, kc)
+#define LCG_T(kc) MT(MOD_LCTL | MOD_LGUI, kc)
+#define LSA_T(kc) MT(MOD_LSFT | MOD_LALT, kc)
+#define LSG_T(kc) MT(MOD_LSFT | MOD_LGUI, kc)
+#define LAG_T(kc) MT(MOD_LALT | MOD_LGUI, kc)
+#define LCSG_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LGUI, kc)
+#define LCAG_T(kc) MT(MOD_LCTL | MOD_LALT | MOD_LGUI, kc)
+#define LSAG_T(kc) MT(MOD_LSFT | MOD_LALT | MOD_LGUI, kc)
+
#define SGUI_T(kc) LSG_T(kc)
#define SCMD_T(kc) LSG_T(kc)
#define SWIN_T(kc) LSG_T(kc)
-#define LAG_T(kc) MT(MOD_LALT | MOD_LGUI, kc) // Left Alt + GUI
-#define RSG_T(kc) MT(MOD_RSFT | MOD_RGUI, kc) // Right Shift + GUI
-#define RAG_T(kc) MT(MOD_RALT | MOD_RGUI, kc) // Right Alt + GUI
-#define LCA_T(kc) MT(MOD_LCTL | MOD_LALT, kc) // Left Control + Alt
-#define LSA_T(kc) MT(MOD_LSFT | MOD_LALT, kc) // Left Shift + Alt
-#define RSA_T(kc) MT(MOD_RSFT | MOD_RALT, kc) // Right Shift + Alt
-#define RCS_T(kc) MT(MOD_RCTL | MOD_RSFT, kc) // Right Control + Shift
+
+#define RCTL_T(kc) MT(MOD_RCTL, kc)
+#define RSFT_T(kc) MT(MOD_RSFT, kc)
+#define RALT_T(kc) MT(MOD_RALT, kc)
+#define RGUI_T(kc) MT(MOD_RGUI, kc)
+
+#define ROPT_T(kc) RALT_T(kc)
+#define ALGR_T(kc) RALT_T(kc)
+#define RCMD_T(kc) RGUI_T(kc)
+#define RWIN_T(kc) RGUI_T(kc)
+
+#define RCS_T(kc) MT(MOD_RCTL | MOD_RSFT, kc)
+#define RCA_T(kc) MT(MOD_RCTL | MOD_RALT, kc)
+#define RCG_T(kc) MT(MOD_RCTL | MOD_RGUI, kc)
+#define RSA_T(kc) MT(MOD_RSFT | MOD_RALT, kc)
+#define RSG_T(kc) MT(MOD_RSFT | MOD_RGUI, kc)
+#define RAG_T(kc) MT(MOD_RALT | MOD_RGUI, kc)
+#define RCSG_T(kc) MT(MOD_RCTL | MOD_RSFT | MOD_RGUI, kc)
+#define RCAG_T(kc) MT(MOD_RCTL | MOD_RALT | MOD_RGUI, kc)
+#define RSAG_T(kc) MT(MOD_RSFT | MOD_RALT | MOD_RGUI, kc)
+
#define SAGR_T(kc) RSA_T(kc)
+#define MEH_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT, kc)
+#define HYPR_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI, kc)
#define ALL_T(kc) HYPR_T(kc)
// Dedicated keycode versions for Hyper and Meh, if you want to use them as standalone keys rather than mod-tap
diff --git a/quantum/quantum_keycodes_legacy.h b/quantum/quantum_keycodes_legacy.h
index 21aec90675..55b0fc3596 100644
--- a/quantum/quantum_keycodes_legacy.h
+++ b/quantum/quantum_keycodes_legacy.h
@@ -57,3 +57,5 @@
#define KC_ACL2 QK_MOUSE_ACCELERATION_2
#define QK_OUTPUT_AUTO OU_AUTO
+
+#define C_S_T(kc) LCS_T(kc)
diff --git a/quantum/raw_hid.c b/quantum/raw_hid.c
new file mode 100644
index 0000000000..2c7a75f325
--- /dev/null
+++ b/quantum/raw_hid.c
@@ -0,0 +1,15 @@
+// Copyright 2025 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "raw_hid.h"
+#include "host.h"
+
+void raw_hid_send(uint8_t *data, uint8_t length) {
+ host_raw_hid_send(data, length);
+}
+
+__attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) {
+ // Users should #include "raw_hid.h" in their own code
+ // and implement this function there. Leave this as weak linkage
+ // so users can opt to not handle data coming in.
+}
diff --git a/quantum/rgb_matrix/animations/pixel_flow_anim.h b/quantum/rgb_matrix/animations/pixel_flow_anim.h
index 35170f9588..44b4b5c481 100644
--- a/quantum/rgb_matrix/animations/pixel_flow_anim.h
+++ b/quantum/rgb_matrix/animations/pixel_flow_anim.h
@@ -22,7 +22,7 @@ static bool PIXEL_FLOW(effect_params_t* params) {
// Clear LEDs and fill the state array
rgb_matrix_set_color_all(0, 0, 0);
for (uint8_t j = 0; j < RGB_MATRIX_LED_COUNT; ++j) {
- led[j] = (random8() & 2) ? (rgb_t){0, 0, 0} : hsv_to_rgb((hsv_t){random8(), random8_min_max(127, 255), rgb_matrix_config.hsv.v});
+ led[j] = (random8() & 2) ? (rgb_t){0, 0, 0} : rgb_matrix_hsv_to_rgb((hsv_t){random8(), random8_min_max(127, 255), rgb_matrix_config.hsv.v});
}
}
@@ -39,7 +39,7 @@ static bool PIXEL_FLOW(effect_params_t* params) {
led[j] = led[j + 1];
}
// Fill last LED
- led[led_max - 1] = (random8() & 2) ? (rgb_t){0, 0, 0} : hsv_to_rgb((hsv_t){random8(), random8_min_max(127, 255), rgb_matrix_config.hsv.v});
+ led[led_max - 1] = (random8() & 2) ? (rgb_t){0, 0, 0} : rgb_matrix_hsv_to_rgb((hsv_t){random8(), random8_min_max(127, 255), rgb_matrix_config.hsv.v});
// Set pulse timer
wait_timer = g_rgb_timer + interval();
}
diff --git a/quantum/rgb_matrix/animations/rgb_matrix_effects.inc b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc
index e8b7a2bcde..abc2adf2cc 100644
--- a/quantum/rgb_matrix/animations/rgb_matrix_effects.inc
+++ b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc
@@ -39,6 +39,7 @@
#include "solid_reactive_nexus.h"
#include "splash_anim.h"
#include "solid_splash_anim.h"
+#include "starlight_smooth_anim.h"
#include "starlight_anim.h"
#include "starlight_dual_sat_anim.h"
#include "starlight_dual_hue_anim.h"
diff --git a/quantum/rgb_matrix/animations/starlight_smooth_anim.h b/quantum/rgb_matrix/animations/starlight_smooth_anim.h
new file mode 100644
index 0000000000..a87c06f9df
--- /dev/null
+++ b/quantum/rgb_matrix/animations/starlight_smooth_anim.h
@@ -0,0 +1,26 @@
+// Copyright 2022 @art-was-here
+// SPDX-License-Identifier: GPL-2.0+
+
+#ifdef ENABLE_RGB_MATRIX_STARLIGHT_SMOOTH
+RGB_MATRIX_EFFECT(STARLIGHT_SMOOTH)
+# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+
+static uint8_t phase_offsets[RGB_MATRIX_LED_COUNT];
+
+hsv_t STARLIGHT_SMOOTH_math(hsv_t hsv, uint8_t i, uint8_t time) {
+ if (phase_offsets[i] == 0) {
+ phase_offsets[i] = rand() % 255;
+ }
+ hsv.v = scale8(abs8(sin8((time + phase_offsets[i]) / 2) - 128) * 2, hsv.v);
+ return hsv;
+}
+
+bool STARLIGHT_SMOOTH(effect_params_t* params) {
+ if (params->init) {
+ memset(phase_offsets, 0, sizeof(phase_offsets));
+ }
+ return effect_runner_i(params, &STARLIGHT_SMOOTH_math);
+}
+
+# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+#endif // ENABLE_RGB_MATRIX_STARLIGHT_SMOOTH
diff --git a/quantum/rgb_matrix/rgb_matrix.c b/quantum/rgb_matrix/rgb_matrix.c
index a18105c9b3..ab0aa17512 100644
--- a/quantum/rgb_matrix/rgb_matrix.c
+++ b/quantum/rgb_matrix/rgb_matrix.c
@@ -18,7 +18,6 @@
#include "rgb_matrix.h"
#include "progmem.h"
-#include "eeprom.h"
#include "eeconfig.h"
#include "keyboard.h"
#include "sync_timer.h"
@@ -48,6 +47,9 @@ __attribute__((weak)) rgb_t rgb_matrix_hsv_to_rgb(hsv_t hsv) {
#define RGB_MATRIX_CUSTOM_EFFECT_IMPLS
#include "rgb_matrix_effects.inc"
+#ifdef COMMUNITY_MODULES_ENABLE
+# include "rgb_matrix_community_modules.inc"
+#endif
#ifdef RGB_MATRIX_CUSTOM_KB
# include "rgb_matrix_kb.inc"
#endif
@@ -107,7 +109,11 @@ void eeconfig_update_rgb_matrix_default(void) {
void eeconfig_debug_rgb_matrix(void) {
dprintf("rgb_matrix_config EEPROM\n");
dprintf("rgb_matrix_config.enable = %d\n", rgb_matrix_config.enable);
+#ifdef RGB_MATRIX_MODE_NAME_ENABLE
+ dprintf("rgb_matrix_config.mode = %d (%s)\n", rgb_matrix_config.mode, rgb_matrix_get_mode_name(rgb_matrix_config.mode));
+#else
dprintf("rgb_matrix_config.mode = %d\n", rgb_matrix_config.mode);
+#endif // RGB_MATRIX_MODE_NAME_ENABLE
dprintf("rgb_matrix_config.hsv.h = %d\n", rgb_matrix_config.hsv.h);
dprintf("rgb_matrix_config.hsv.s = %d\n", rgb_matrix_config.hsv.s);
dprintf("rgb_matrix_config.hsv.v = %d\n", rgb_matrix_config.hsv.v);
@@ -311,6 +317,15 @@ static void rgb_task_render(uint8_t effect) {
#include "rgb_matrix_effects.inc"
#undef RGB_MATRIX_EFFECT
+#ifdef COMMUNITY_MODULES_ENABLE
+# define RGB_MATRIX_EFFECT(name, ...) \
+ case RGB_MATRIX_COMMUNITY_MODULE_##name: \
+ rendering = name(&rgb_effect_params); \
+ break;
+# include "rgb_matrix_community_modules.inc"
+# undef RGB_MATRIX_EFFECT
+#endif
+
#if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER)
# define RGB_MATRIX_EFFECT(name, ...) \
case RGB_MATRIX_CUSTOM_##name: \
@@ -394,7 +409,12 @@ void rgb_matrix_task(void) {
}
}
+__attribute__((weak)) bool rgb_matrix_indicators_modules(void) {
+ return true;
+}
+
void rgb_matrix_indicators(void) {
+ rgb_matrix_indicators_modules();
rgb_matrix_indicators_kb();
}
@@ -434,6 +454,10 @@ struct rgb_matrix_limits_t rgb_matrix_get_limits(uint8_t iter) {
return limits;
}
+__attribute__((weak)) bool rgb_matrix_indicators_advanced_modules(uint8_t led_min, uint8_t led_max) {
+ return true;
+}
+
void rgb_matrix_indicators_advanced(effect_params_t *params) {
/* special handling is needed for "params->iter", since it's already been incremented.
* Could move the invocations to rgb_task_render, but then it's missing a few checks
@@ -441,6 +465,7 @@ void rgb_matrix_indicators_advanced(effect_params_t *params) {
* rgb_task_render, right before the iter++ line.
*/
RGB_MATRIX_USE_LIMITS_ITER(min, max, params->iter - 1);
+ rgb_matrix_indicators_advanced_modules(min, max);
rgb_matrix_indicators_advanced_kb(min, max);
}
@@ -539,7 +564,11 @@ void rgb_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
}
rgb_task_state = STARTING;
eeconfig_flag_rgb_matrix(write_to_eeprom);
- dprintf("rgb matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.mode);
+#ifdef RGB_MATRIX_MODE_NAME_ENABLE
+ dprintf("rgb matrix mode [%s]: %u (%s)\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", (unsigned)rgb_matrix_config.mode, rgb_matrix_get_mode_name(rgb_matrix_config.mode));
+#else
+ dprintf("rgb matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", (unsigned)rgb_matrix_config.mode);
+#endif // RGB_MATRIX_MODE_NAME_ENABLE
}
void rgb_matrix_mode_noeeprom(uint8_t mode) {
rgb_matrix_mode_eeprom_helper(mode, false);
@@ -717,3 +746,49 @@ void rgb_matrix_set_flags(led_flags_t flags) {
void rgb_matrix_set_flags_noeeprom(led_flags_t flags) {
rgb_matrix_set_flags_eeprom_helper(flags, false);
}
+
+//----------------------------------------------------------
+// RGB Matrix naming
+#undef RGB_MATRIX_EFFECT
+#ifdef RGB_MATRIX_MODE_NAME_ENABLE
+const char *rgb_matrix_get_mode_name(uint8_t mode) {
+ switch (mode) {
+ case RGB_MATRIX_NONE:
+ return "NONE";
+
+# define RGB_MATRIX_EFFECT(name, ...) \
+ case RGB_MATRIX_##name: \
+ return #name;
+# include "rgb_matrix_effects.inc"
+# undef RGB_MATRIX_EFFECT
+
+# ifdef COMMUNITY_MODULES_ENABLE
+# define RGB_MATRIX_EFFECT(name, ...) \
+ case RGB_MATRIX_COMMUNITY_MODULE_##name: \
+ return #name;
+# include "rgb_matrix_community_modules.inc"
+# undef RGB_MATRIX_EFFECT
+# endif // COMMUNITY_MODULES_ENABLE
+
+# if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER)
+# define RGB_MATRIX_EFFECT(name, ...) \
+ case RGB_MATRIX_CUSTOM_##name: \
+ return #name;
+
+# ifdef RGB_MATRIX_CUSTOM_KB
+# include "rgb_matrix_kb.inc"
+# endif // RGB_MATRIX_CUSTOM_KB
+
+# ifdef RGB_MATRIX_CUSTOM_USER
+# include "rgb_matrix_user.inc"
+# endif // RGB_MATRIX_CUSTOM_USER
+
+# undef RGB_MATRIX_EFFECT
+# endif // RGB_MATRIX_CUSTOM_KB || RGB_MATRIX_CUSTOM_USER
+
+ default:
+ return "UNKNOWN";
+ }
+}
+# undef RGB_MATRIX_EFFECT
+#endif // RGB_MATRIX_MODE_NAME_ENABLE
diff --git a/quantum/rgb_matrix/rgb_matrix.h b/quantum/rgb_matrix/rgb_matrix.h
index e00e3927c7..a91dded4a8 100644
--- a/quantum/rgb_matrix/rgb_matrix.h
+++ b/quantum/rgb_matrix/rgb_matrix.h
@@ -123,6 +123,12 @@ enum rgb_matrix_effects {
#include "rgb_matrix_effects.inc"
#undef RGB_MATRIX_EFFECT
+#ifdef COMMUNITY_MODULES_ENABLE
+# define RGB_MATRIX_EFFECT(name, ...) RGB_MATRIX_COMMUNITY_MODULE_##name,
+# include "rgb_matrix_community_modules.inc"
+# undef RGB_MATRIX_EFFECT
+#endif
+
#if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER)
# define RGB_MATRIX_EFFECT(name, ...) RGB_MATRIX_CUSTOM_##name,
# ifdef RGB_MATRIX_CUSTOM_KB
@@ -214,6 +220,10 @@ void rgb_matrix_set_flags(led_flags_t flags);
void rgb_matrix_set_flags_noeeprom(led_flags_t flags);
void rgb_matrix_update_pwm_buffers(void);
+#ifdef RGB_MATRIX_MODE_NAME_ENABLE
+const char *rgb_matrix_get_mode_name(uint8_t mode);
+#endif // RGB_MATRIX_MODE_NAME_ENABLE
+
#ifndef RGBLIGHT_ENABLE
# define eeconfig_update_rgblight_current eeconfig_force_flush_rgb_matrix
# define rgblight_reload_from_eeprom rgb_matrix_reload_from_eeprom
diff --git a/quantum/rgb_matrix/rgb_matrix_types.h b/quantum/rgb_matrix/rgb_matrix_types.h
index 62005ebea9..0115edee6a 100644
--- a/quantum/rgb_matrix/rgb_matrix_types.h
+++ b/quantum/rgb_matrix/rgb_matrix_types.h
@@ -18,6 +18,8 @@
#include <stdint.h>
#include <stdbool.h>
+
+#include "compiler_support.h"
#include "color.h"
#include "util.h"
@@ -84,4 +86,4 @@ typedef union rgb_config_t {
};
} rgb_config_t;
-_Static_assert(sizeof(rgb_config_t) == sizeof(uint64_t), "RGB Matrix EECONFIG out of spec.");
+STATIC_ASSERT(sizeof(rgb_config_t) == sizeof(uint64_t), "RGB Matrix EECONFIG out of spec.");
diff --git a/quantum/rgblight/rgblight.c b/quantum/rgblight/rgblight.c
index 83f97c8114..bfccb472b5 100644
--- a/quantum/rgblight/rgblight.c
+++ b/quantum/rgblight/rgblight.c
@@ -496,7 +496,7 @@ void rgblight_decrease_speed_noeeprom(void) {
void rgblight_sethsv_noeeprom_old(uint8_t hue, uint8_t sat, uint8_t val) {
if (rgblight_config.enable) {
- rgb_t rgb = hsv_to_rgb((hsv_t){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val});
+ rgb_t rgb = rgblight_hsv_to_rgb((hsv_t){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val});
rgblight_setrgb(rgb.r, rgb.g, rgb.b);
}
}
@@ -515,7 +515,7 @@ void rgblight_sethsv_eeprom_helper(uint8_t hue, uint8_t sat, uint8_t val, bool w
// needed for rgblight_layers_write() to get the new val, since it reads rgblight_config.val
rgblight_config.val = val;
#endif
- rgb_t rgb = hsv_to_rgb((hsv_t){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val});
+ rgb_t rgb = rgblight_hsv_to_rgb((hsv_t){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val});
rgblight_setrgb(rgb.r, rgb.g, rgb.b);
} else {
// all LEDs in same color
@@ -647,7 +647,7 @@ void rgblight_sethsv_at(uint8_t hue, uint8_t sat, uint8_t val, uint8_t index) {
return;
}
- rgb_t rgb = hsv_to_rgb((hsv_t){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val});
+ rgb_t rgb = rgblight_hsv_to_rgb((hsv_t){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val});
rgblight_setrgb_at(rgb.r, rgb.g, rgb.b, index);
}
@@ -679,7 +679,7 @@ void rgblight_sethsv_range(uint8_t hue, uint8_t sat, uint8_t val, uint8_t start,
return;
}
- rgb_t rgb = hsv_to_rgb((hsv_t){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val});
+ rgb_t rgb = rgblight_hsv_to_rgb((hsv_t){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val});
rgblight_setrgb_range(rgb.r, rgb.g, rgb.b, start, end);
}
diff --git a/quantum/rgblight/rgblight.h b/quantum/rgblight/rgblight.h
index f5fd450d4c..c061e71895 100644
--- a/quantum/rgblight/rgblight.h
+++ b/quantum/rgblight/rgblight.h
@@ -16,6 +16,8 @@
#pragma once
+#include "compiler_support.h"
+
// DEPRECATED DEFINES - DO NOT USE
#if defined(RGBLED_NUM)
# define RGBLIGHT_LED_COUNT RGBLED_NUM
@@ -260,7 +262,7 @@ typedef union rgblight_config_t {
};
} rgblight_config_t;
-_Static_assert(sizeof(rgblight_config_t) == sizeof(uint64_t), "RGB Light EECONFIG out of spec.");
+STATIC_ASSERT(sizeof(rgblight_config_t) == sizeof(uint64_t), "RGB Light EECONFIG out of spec.");
typedef struct _rgblight_status_t {
uint8_t base_mode;
diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c
index 9af3c29d75..59b6009ec4 100644
--- a/quantum/split_common/split_util.c
+++ b/quantum/split_common/split_util.c
@@ -13,6 +13,8 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
+#include "compiler_support.h"
#include "split_util.h"
#include "matrix.h"
#include "keyboard.h"
@@ -62,7 +64,7 @@ static struct {
} split_config;
#if defined(SPLIT_USB_DETECT)
-_Static_assert((SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL) <= UINT16_MAX, "Please lower SPLIT_USB_TIMEOUT and/or increase SPLIT_USB_TIMEOUT_POLL.");
+STATIC_ASSERT((SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL) <= UINT16_MAX, "Please lower SPLIT_USB_TIMEOUT and/or increase SPLIT_USB_TIMEOUT_POLL.");
static bool usb_bus_detected(void) {
for (uint16_t i = 0; i < (SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL); i++) {
// This will return true if a USB connection has been established
@@ -88,9 +90,9 @@ static inline bool usb_bus_detected(void) {
# endif
# endif
# if defined(SPLIT_USB_DETECT)
-_Static_assert(SPLIT_USB_TIMEOUT < SPLIT_WATCHDOG_TIMEOUT, "SPLIT_WATCHDOG_TIMEOUT should not be below SPLIT_USB_TIMEOUT.");
+STATIC_ASSERT(SPLIT_USB_TIMEOUT < SPLIT_WATCHDOG_TIMEOUT, "SPLIT_WATCHDOG_TIMEOUT should not be below SPLIT_USB_TIMEOUT.");
# endif
-_Static_assert(SPLIT_MAX_CONNECTION_ERRORS > 0, "SPLIT_WATCHDOG_ENABLE requires SPLIT_MAX_CONNECTION_ERRORS be above 0 for a functioning disconnection check.");
+STATIC_ASSERT(SPLIT_MAX_CONNECTION_ERRORS > 0, "SPLIT_WATCHDOG_ENABLE requires SPLIT_MAX_CONNECTION_ERRORS be above 0 for a functioning disconnection check.");
static uint32_t split_watchdog_started = 0;
static bool split_watchdog_done = false;
diff --git a/quantum/split_common/transaction_id_define.h b/quantum/split_common/transaction_id_define.h
index 5bfbe2aec7..694737868a 100644
--- a/quantum/split_common/transaction_id_define.h
+++ b/quantum/split_common/transaction_id_define.h
@@ -16,6 +16,8 @@
#pragma once
+#include "compiler_support.h"
+
enum serial_transaction_id {
#ifdef USE_I2C
I2C_EXECUTE_CALLBACK,
@@ -122,4 +124,4 @@ enum serial_transaction_id {
};
// Ensure we only use 5 bits for transaction
-_Static_assert(NUM_TOTAL_TRANSACTIONS <= (1 << 5), "Max number of usable transactions exceeded");
+STATIC_ASSERT(NUM_TOTAL_TRANSACTIONS <= (1 << 5), "Max number of usable transactions exceeded");
diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c
index 83edc34859..ea687af1c2 100644
--- a/quantum/split_common/transport.c
+++ b/quantum/split_common/transport.c
@@ -17,6 +17,7 @@
#include <string.h>
#include <debug.h>
+#include "compiler_support.h"
#include "transactions.h"
#include "transport.h"
#include "transaction_id_define.h"
@@ -36,7 +37,7 @@
# include "i2c_slave.h"
// Ensure the I2C buffer has enough space
-_Static_assert(sizeof(split_shared_memory_t) <= I2C_SLAVE_REG_COUNT, "split_shared_memory_t too large for I2C_SLAVE_REG_COUNT");
+STATIC_ASSERT(sizeof(split_shared_memory_t) <= I2C_SLAVE_REG_COUNT, "split_shared_memory_t too large for I2C_SLAVE_REG_COUNT");
split_shared_memory_t *const split_shmem = (split_shared_memory_t *)i2c_slave_reg;
diff --git a/quantum/unicode/unicode.c b/quantum/unicode/unicode.c
index b0729335f0..dff1d43fb4 100644
--- a/quantum/unicode/unicode.c
+++ b/quantum/unicode/unicode.c
@@ -16,7 +16,6 @@
#include "unicode.h"
-#include "eeprom.h"
#include "eeconfig.h"
#include "action.h"
#include "action_util.h"
diff --git a/quantum/unicode/unicode.h b/quantum/unicode/unicode.h
index f19d803335..7cddc78b7a 100644
--- a/quantum/unicode/unicode.h
+++ b/quantum/unicode/unicode.h
@@ -17,6 +17,8 @@
#pragma once
#include <stdint.h>
+
+#include "compiler_support.h"
#include "unicode_keycodes.h"
/**
@@ -33,7 +35,7 @@ typedef union unicode_config_t {
};
} unicode_config_t;
-_Static_assert(sizeof(unicode_config_t) == sizeof(uint8_t), "Unicode EECONFIG out of spec.");
+STATIC_ASSERT(sizeof(unicode_config_t) == sizeof(uint8_t), "Unicode EECONFIG out of spec.");
extern unicode_config_t unicode_config;
diff --git a/quantum/via.c b/quantum/via.c
index c746d9a608..3682b4ab2b 100644
--- a/quantum/via.c
+++ b/quantum/via.c
@@ -26,7 +26,6 @@
#include "raw_hid.h"
#include "dynamic_keymap.h"
-#include "eeprom.h"
#include "eeconfig.h"
#include "matrix.h"
#include "timer.h"
diff --git a/quantum/wear_leveling/wear_leveling.c b/quantum/wear_leveling/wear_leveling.c
index 429df45df5..258f074a5c 100644
--- a/quantum/wear_leveling/wear_leveling.c
+++ b/quantum/wear_leveling/wear_leveling.c
@@ -3,6 +3,7 @@
#include <stdbool.h>
#include "fnv.h"
#include "wear_leveling.h"
+#include "wear_leveling_drivers.h"
#include "wear_leveling_internal.h"
/*
diff --git a/quantum/wear_leveling/wear_leveling_drivers.h b/quantum/wear_leveling/wear_leveling_drivers.h
new file mode 100644
index 0000000000..e81f833fd1
--- /dev/null
+++ b/quantum/wear_leveling/wear_leveling_drivers.h
@@ -0,0 +1,13 @@
+// Copyright 2025 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+#if defined(WEAR_LEVELING_EMBEDDED_FLASH)
+# include "wear_leveling/wear_leveling_efl_config.h"
+#elif defined(WEAR_LEVELING_SPI_FLASH)
+# include "wear_leveling/wear_leveling_flash_spi_config.h"
+#elif defined(WEAR_LEVELING_RP2040_FLASH)
+# include "wear_leveling/wear_leveling_rp2040_flash_config.h"
+#elif defined(WEAR_LEVELING_LEGACY)
+# include "wear_leveling/wear_leveling_legacy_config.h"
+#endif
diff --git a/quantum/wear_leveling/wear_leveling_internal.h b/quantum/wear_leveling/wear_leveling_internal.h
index e83f9b22ea..c590f42235 100644
--- a/quantum/wear_leveling/wear_leveling_internal.h
+++ b/quantum/wear_leveling/wear_leveling_internal.h
@@ -2,9 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
-#ifdef __cplusplus
-# define _Static_assert static_assert
-#endif
+#include "compiler_support.h"
#include <stdint.h>
#include <string.h>
@@ -62,9 +60,9 @@ typedef uint64_t backing_store_int_t;
#endif // WEAR_LEVELING_ASSERTS
// Compile-time validation of configurable options
-_Static_assert(WEAR_LEVELING_BACKING_SIZE >= (WEAR_LEVELING_LOGICAL_SIZE * 2), "Total backing size must be at least twice the size of the logical size");
-_Static_assert(WEAR_LEVELING_LOGICAL_SIZE % BACKING_STORE_WRITE_SIZE == 0, "Logical size must be a multiple of write size");
-_Static_assert(WEAR_LEVELING_BACKING_SIZE % WEAR_LEVELING_LOGICAL_SIZE == 0, "Backing size must be a multiple of logical size");
+STATIC_ASSERT(WEAR_LEVELING_BACKING_SIZE >= (WEAR_LEVELING_LOGICAL_SIZE * 2), "Total backing size must be at least twice the size of the logical size");
+STATIC_ASSERT(WEAR_LEVELING_LOGICAL_SIZE % BACKING_STORE_WRITE_SIZE == 0, "Logical size must be a multiple of write size");
+STATIC_ASSERT(WEAR_LEVELING_BACKING_SIZE % WEAR_LEVELING_LOGICAL_SIZE == 0, "Backing size must be a multiple of logical size");
// Backing Store API, to be implemented elsewhere by flash driver etc.
bool backing_store_init(void);
@@ -86,7 +84,7 @@ typedef union write_log_entry_t {
uint8_t raw8[8];
} write_log_entry_t;
-_Static_assert(sizeof(write_log_entry_t) == 8, "Wear leveling write log entry size was not 8");
+STATIC_ASSERT(sizeof(write_log_entry_t) == 8, "Wear leveling write log entry size was not 8");
/**
* Log entry type discriminator.
@@ -104,7 +102,7 @@ enum {
LOG_ENTRY_TYPES
};
-_Static_assert(LOG_ENTRY_TYPES <= (1 << 2), "Too many log entry types to fit into 2 bits of storage");
+STATIC_ASSERT(LOG_ENTRY_TYPES <= (1 << 2), "Too many log entry types to fit into 2 bits of storage");
#define BITMASK_FOR_BITCOUNT(n) ((1 << (n)) - 1)