diff options
Diffstat (limited to 'quantum/split_common')
-rw-r--r-- | quantum/split_common/split_util.c | 57 | ||||
-rw-r--r-- | quantum/split_common/split_util.h | 4 | ||||
-rw-r--r-- | quantum/split_common/transaction_id_define.h | 4 | ||||
-rw-r--r-- | quantum/split_common/transactions.c | 152 | ||||
-rw-r--r-- | quantum/split_common/transport.h | 4 |
5 files changed, 189 insertions, 32 deletions
diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index 4892b7f8d8..9f57c7b9fc 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -74,6 +74,46 @@ static inline bool usbIsActive(void) { } #endif +#if defined(SPLIT_WATCHDOG_ENABLE) +# if !defined(SPLIT_WATCHDOG_TIMEOUT) +# if defined(SPLIT_USB_TIMEOUT) +# define SPLIT_WATCHDOG_TIMEOUT (SPLIT_USB_TIMEOUT + 100) +# else +# define SPLIT_WATCHDOG_TIMEOUT 3000 +# 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."); +# 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 uint32_t split_watchdog_started = 0; +static bool split_watchdog_done = false; + +void split_watchdog_init(void) { + split_watchdog_started = timer_read32(); +} + +void split_watchdog_update(bool done) { + split_watchdog_done = done; +} + +bool split_watchdog_check(void) { + if (!is_transport_connected()) { + split_watchdog_done = false; + } + return split_watchdog_done; +} + +void split_watchdog_task(void) { + if (!split_watchdog_done && !is_keyboard_master()) { + if (timer_elapsed32(split_watchdog_started) > SPLIT_WATCHDOG_TIMEOUT) { + mcu_reset(); + } + } +} +#endif // defined(SPLIT_WATCHDOG_ENABLE) + #ifdef SPLIT_HAND_MATRIX_GRID void matrix_io_delay(void); @@ -139,6 +179,20 @@ void split_pre_init(void) { if (!eeconfig_is_enabled()) { eeconfig_init(); } + // TODO: Remove once ARM has a way to configure EECONFIG_HANDEDNESS within the emulated eeprom via dfu-util or another tool +# if defined(INIT_EE_HANDS_LEFT) || defined(INIT_EE_HANDS_RIGHT) +# if defined(INIT_EE_HANDS_LEFT) +# pragma message "Faking EE_HANDS for left hand" + const bool should_be_left = true; +# else +# pragma message "Faking EE_HANDS for right hand" + const bool should_be_left = false; +# endif + bool is_left = eeconfig_read_handedness(); + if (is_left != should_be_left) { + eeconfig_update_handedness(should_be_left); + } +# endif // defined(INIT_EE_HANDS_LEFT) || defined(INIT_EE_HANDS_RIGHT) #endif isLeftHand = is_keyboard_left(); @@ -165,6 +219,9 @@ void split_pre_init(void) { void split_post_init(void) { if (!is_keyboard_master()) { transport_slave_init(); +#if defined(SPLIT_WATCHDOG_ENABLE) + split_watchdog_init(); +#endif } } diff --git a/quantum/split_common/split_util.h b/quantum/split_common/split_util.h index c7eabea233..5c9a260a14 100644 --- a/quantum/split_common/split_util.h +++ b/quantum/split_common/split_util.h @@ -14,3 +14,7 @@ void split_post_init(void); bool transport_master_if_connected(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); bool is_transport_connected(void); + +void split_watchdog_update(bool done); +void split_watchdog_task(void); +bool split_watchdog_check(void);
\ No newline at end of file diff --git a/quantum/split_common/transaction_id_define.h b/quantum/split_common/transaction_id_define.h index 761a8884f4..8c19948107 100644 --- a/quantum/split_common/transaction_id_define.h +++ b/quantum/split_common/transaction_id_define.h @@ -84,6 +84,10 @@ enum serial_transaction_id { PUT_POINTING_CPI, #endif // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE) +#if defined(SPLIT_WATCHDOG_ENABLE) + PUT_WATCHDOG, +#endif // defined(SPLIT_WATCHDOG_ENABLE) + #if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) PUT_RPC_INFO, PUT_RPC_REQ_DATA, diff --git a/quantum/split_common/transactions.c b/quantum/split_common/transactions.c index 719068908f..527b2f4caf 100644 --- a/quantum/split_common/transactions.c +++ b/quantum/split_common/transactions.c @@ -76,8 +76,27 @@ static bool transaction_handler_master(matrix_row_t master_matrix[], matrix_row_ if (!transaction_handler_master(master_matrix, slave_matrix, #prefix, &prefix##_handlers_master)) return false; \ } while (0) +/** + * @brief Constructs a transaction handler that doesn't acquire a lock to the + * split shared memory. Therefore the locking and unlocking has to be done + * manually inside the handler. Use this macro only if the handler is + * non-deterministic in runtime and thus needs a manual lock unlock + * implementation to hold the lock for the shortest possible time. + */ #define TRANSACTION_HANDLER_SLAVE(prefix) \ do { \ + prefix##_handlers_slave(master_matrix, slave_matrix); \ + } while (0) + +/** + * @brief Constructs a transaction handler that automatically acquires a lock to + * safely access the split shared memory and releases the lock again after + * processing the handler. Use this macro if the handler is fast and + * deterministic in runtime and thus holds the lock only for a very short time. + * If not fallback to manually locking and unlocking inside the handler. + */ +#define TRANSACTION_HANDLER_SLAVE_AUTOLOCK(prefix) \ + do { \ split_shared_memory_lock(); \ prefix##_handlers_slave(master_matrix, slave_matrix); \ split_shared_memory_unlock(); \ @@ -139,7 +158,7 @@ static void slave_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row // clang-format off #define TRANSACTIONS_SLAVE_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(slave_matrix) -#define TRANSACTIONS_SLAVE_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(slave_matrix) +#define TRANSACTIONS_SLAVE_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE_AUTOLOCK(slave_matrix) #define TRANSACTIONS_SLAVE_MATRIX_REGISTRATIONS \ [GET_SLAVE_MATRIX_CHECKSUM] = trans_target2initiator_initializer(smatrix.checksum), \ [GET_SLAVE_MATRIX_DATA] = trans_target2initiator_initializer(smatrix.matrix), @@ -161,7 +180,7 @@ static void master_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_ro } # define TRANSACTIONS_MASTER_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(master_matrix) -# define TRANSACTIONS_MASTER_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(master_matrix) +# define TRANSACTIONS_MASTER_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE_AUTOLOCK(master_matrix) # define TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS [PUT_MASTER_MATRIX] = trans_initiator2target_initializer(mmatrix.matrix), #else // SPLIT_TRANSPORT_MIRROR @@ -197,7 +216,7 @@ static void encoder_handlers_slave(matrix_row_t master_matrix[], matrix_row_t sl // clang-format off # define TRANSACTIONS_ENCODERS_MASTER() TRANSACTION_HANDLER_MASTER(encoder) -# define TRANSACTIONS_ENCODERS_SLAVE() TRANSACTION_HANDLER_SLAVE(encoder) +# define TRANSACTIONS_ENCODERS_SLAVE() TRANSACTION_HANDLER_SLAVE_AUTOLOCK(encoder) # define TRANSACTIONS_ENCODERS_REGISTRATIONS \ [GET_ENCODERS_CHECKSUM] = trans_target2initiator_initializer(encoders.checksum), \ [GET_ENCODERS_DATA] = trans_target2initiator_initializer(encoders.state), @@ -239,7 +258,7 @@ static void sync_timer_handlers_slave(matrix_row_t master_matrix[], matrix_row_t } # define TRANSACTIONS_SYNC_TIMER_MASTER() TRANSACTION_HANDLER_MASTER(sync_timer) -# define TRANSACTIONS_SYNC_TIMER_SLAVE() TRANSACTION_HANDLER_SLAVE(sync_timer) +# define TRANSACTIONS_SYNC_TIMER_SLAVE() TRANSACTION_HANDLER_SLAVE_AUTOLOCK(sync_timer) # define TRANSACTIONS_SYNC_TIMER_REGISTRATIONS [PUT_SYNC_TIMER] = trans_initiator2target_initializer(sync_timer), #else // DISABLE_SYNC_TIMER @@ -273,7 +292,7 @@ static void layer_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_ // clang-format off # define TRANSACTIONS_LAYER_STATE_MASTER() TRANSACTION_HANDLER_MASTER(layer_state) -# define TRANSACTIONS_LAYER_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(layer_state) +# define TRANSACTIONS_LAYER_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE_AUTOLOCK(layer_state) # define TRANSACTIONS_LAYER_STATE_REGISTRATIONS \ [PUT_LAYER_STATE] = trans_initiator2target_initializer(layers.layer_state), \ [PUT_DEFAULT_LAYER_STATE] = trans_initiator2target_initializer(layers.default_layer_state), @@ -304,7 +323,7 @@ static void led_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_t } # define TRANSACTIONS_LED_STATE_MASTER() TRANSACTION_HANDLER_MASTER(led_state) -# define TRANSACTIONS_LED_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(led_state) +# define TRANSACTIONS_LED_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE_AUTOLOCK(led_state) # define TRANSACTIONS_LED_STATE_REGISTRATIONS [PUT_LED_STATE] = trans_initiator2target_initializer(led_state), #else // SPLIT_LED_STATE_ENABLE @@ -353,10 +372,15 @@ static bool mods_handlers_master(matrix_row_t master_matrix[], matrix_row_t slav } static void mods_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { - set_mods(split_shmem->mods.real_mods); - set_weak_mods(split_shmem->mods.weak_mods); + split_shared_memory_lock(); + split_mods_sync_t mods; + memcpy(&mods, &split_shmem->mods, sizeof(split_mods_sync_t)); + split_shared_memory_unlock(); + + set_mods(mods.real_mods); + set_weak_mods(mods.weak_mods); # ifndef NO_ACTION_ONESHOT - set_oneshot_mods(split_shmem->mods.oneshot_mods); + set_oneshot_mods(mods.oneshot_mods); # endif } @@ -384,7 +408,11 @@ static bool backlight_handlers_master(matrix_row_t master_matrix[], matrix_row_t } static void backlight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { - backlight_set(split_shmem->backlight_level); + split_shared_memory_lock(); + uint8_t backlight_level = split_shmem->backlight_level; + split_shared_memory_unlock(); + + backlight_set(backlight_level); } # define TRANSACTIONS_BACKLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(backlight) @@ -417,10 +445,15 @@ static bool rgblight_handlers_master(matrix_row_t master_matrix[], matrix_row_t } static void rgblight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + split_shared_memory_lock(); // Update the RGB with the new data - if (split_shmem->rgblight_sync.status.change_flags != 0) { - rgblight_update_sync(&split_shmem->rgblight_sync, false); - split_shmem->rgblight_sync.status.change_flags = 0; + rgblight_syncinfo_t rgblight_sync; + memcpy(&rgblight_sync, &split_shmem->rgblight_sync, sizeof(rgblight_syncinfo_t)); + split_shmem->rgblight_sync.status.change_flags = 0; + split_shared_memory_unlock(); + + if (rgblight_sync.status.change_flags != 0) { + rgblight_update_sync(&rgblight_sync, false); } } @@ -450,8 +483,12 @@ static bool led_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_ } static void led_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + split_shared_memory_lock(); memcpy(&led_matrix_eeconfig, &split_shmem->led_matrix_sync.led_matrix, sizeof(led_eeconfig_t)); - led_matrix_set_suspend_state(split_shmem->led_matrix_sync.led_suspend_state); + bool led_suspend_state = split_shmem->led_matrix_sync.led_suspend_state; + split_shared_memory_unlock(); + + led_matrix_set_suspend_state(led_suspend_state); } # define TRANSACTIONS_LED_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(led_matrix) @@ -480,8 +517,12 @@ static bool rgb_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_ } static void rgb_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + split_shared_memory_lock(); memcpy(&rgb_matrix_config, &split_shmem->rgb_matrix_sync.rgb_matrix, sizeof(rgb_config_t)); - rgb_matrix_set_suspend_state(split_shmem->rgb_matrix_sync.rgb_suspend_state); + bool rgb_suspend_state = split_shmem->rgb_matrix_sync.rgb_suspend_state; + split_shared_memory_unlock(); + + rgb_matrix_set_suspend_state(rgb_suspend_state); } # define TRANSACTIONS_RGB_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(rgb_matrix) @@ -512,7 +553,7 @@ static void wpm_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_ } # define TRANSACTIONS_WPM_MASTER() TRANSACTION_HANDLER_MASTER(wpm) -# define TRANSACTIONS_WPM_SLAVE() TRANSACTION_HANDLER_SLAVE(wpm) +# define TRANSACTIONS_WPM_SLAVE() TRANSACTION_HANDLER_SLAVE_AUTOLOCK(wpm) # define TRANSACTIONS_WPM_REGISTRATIONS [PUT_WPM] = trans_initiator2target_initializer(current_wpm), #else // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) @@ -535,7 +576,11 @@ static bool oled_handlers_master(matrix_row_t master_matrix[], matrix_row_t slav } static void oled_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { - if (split_shmem->current_oled_state) { + split_shared_memory_lock(); + uint8_t current_oled_state = split_shmem->current_oled_state; + split_shared_memory_unlock(); + + if (current_oled_state) { oled_on(); } else { oled_off(); @@ -566,7 +611,11 @@ static bool st7565_handlers_master(matrix_row_t master_matrix[], matrix_row_t sl } static void st7565_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { - if (split_shmem->current_st7565_state) { + split_shared_memory_lock(); + uint8_t current_st7565_state = split_shmem->current_st7565_state; + split_shared_memory_unlock(); + + if (current_st7565_state) { st7565_on(); } else { st7565_off(); @@ -607,9 +656,9 @@ static bool pointing_handlers_master(matrix_row_t master_matrix[], matrix_row_t bool okay = read_if_checksum_mismatch(GET_POINTING_CHECKSUM, GET_POINTING_DATA, &last_update, &temp_state, &split_shmem->pointing.report, sizeof(temp_state)); if (okay) pointing_device_set_shared_report(temp_state); temp_cpi = pointing_device_get_shared_cpi(); - if (temp_cpi && memcmp(&last_cpi, &temp_cpi, sizeof(temp_cpi)) != 0) { - memcpy(&split_shmem->pointing.cpi, &temp_cpi, sizeof(temp_cpi)); - okay = transport_write(PUT_POINTING_CPI, &split_shmem->pointing.cpi, sizeof(split_shmem->pointing.cpi)); + if (temp_cpi && last_cpi != temp_cpi) { + split_shmem->pointing.cpi = temp_cpi; + okay = transport_write(PUT_POINTING_CPI, &split_shmem->pointing.cpi, sizeof(split_shmem->pointing.cpi)); if (okay) { last_cpi = temp_cpi; } @@ -629,8 +678,6 @@ static void pointing_handlers_slave(matrix_row_t master_matrix[], matrix_row_t s return; } # endif - report_mouse_t temp_report; - uint16_t temp_cpi; # if (POINTING_DEVICE_TASK_THROTTLE_MS > 0) static uint32_t last_exec = 0; if (timer_elapsed32(last_exec) < POINTING_DEVICE_TASK_THROTTLE_MS) { @@ -638,17 +685,25 @@ static void pointing_handlers_slave(matrix_row_t master_matrix[], matrix_row_t s } last_exec = timer_read32(); # endif - temp_cpi = !pointing_device_driver.get_cpi ? 0 : pointing_device_driver.get_cpi(); // check for NULL - if (split_shmem->pointing.cpi && memcmp(&split_shmem->pointing.cpi, &temp_cpi, sizeof(temp_cpi)) != 0) { - if (pointing_device_driver.set_cpi) { - pointing_device_driver.set_cpi(split_shmem->pointing.cpi); - } + + uint16_t temp_cpi = !pointing_device_driver.get_cpi ? 0 : pointing_device_driver.get_cpi(); // check for NULL + + split_shared_memory_lock(); + split_slave_pointing_sync_t pointing; + memcpy(&pointing, &split_shmem->pointing, sizeof(split_slave_pointing_sync_t)); + split_shared_memory_unlock(); + + if (pointing.cpi && pointing.cpi != temp_cpi && pointing_device_driver.set_cpi) { + pointing_device_driver.set_cpi(pointing.cpi); } - memset(&temp_report, 0, sizeof(temp_report)); - temp_report = pointing_device_driver.get_report(temp_report); - memcpy(&split_shmem->pointing.report, &temp_report, sizeof(temp_report)); + + pointing.report = pointing_device_driver.get_report((report_mouse_t){0}); // Now update the checksum given that the pointing has been written to - split_shmem->pointing.checksum = crc8(&temp_report, sizeof(temp_report)); + pointing.checksum = crc8(&pointing.report, sizeof(report_mouse_t)); + + split_shared_memory_lock(); + memcpy(&split_shmem->pointing, &pointing, sizeof(split_slave_pointing_sync_t)); + split_shared_memory_unlock(); } # define TRANSACTIONS_POINTING_MASTER() TRANSACTION_HANDLER_MASTER(pointing) @@ -664,6 +719,36 @@ static void pointing_handlers_slave(matrix_row_t master_matrix[], matrix_row_t s #endif // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE) //////////////////////////////////////////////////// +// WATCHDOG + +#if defined(SPLIT_WATCHDOG_ENABLE) + +static bool watchdog_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + bool okay = true; + if (!split_watchdog_check()) { + okay = transport_write(PUT_WATCHDOG, &okay, sizeof(okay)); + split_watchdog_update(okay); + } + return okay; +} + +static void watchdog_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + split_watchdog_update(split_shmem->watchdog_pinged); +} + +# define TRANSACTIONS_WATCHDOG_MASTER() TRANSACTION_HANDLER_MASTER(watchdog) +# define TRANSACTIONS_WATCHDOG_SLAVE() TRANSACTION_HANDLER_SLAVE_AUTOLOCK(watchdog) +# define TRANSACTIONS_WATCHDOG_REGISTRATIONS [PUT_WATCHDOG] = trans_initiator2target_initializer(watchdog_pinged), + +#else // defined(SPLIT_WATCHDOG_ENABLE) + +# define TRANSACTIONS_WATCHDOG_MASTER() +# define TRANSACTIONS_WATCHDOG_SLAVE() +# define TRANSACTIONS_WATCHDOG_REGISTRATIONS + +#endif // defined(SPLIT_WATCHDOG_ENABLE) + +//////////////////////////////////////////////////// split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = { // Set defaults @@ -689,6 +774,7 @@ split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = { TRANSACTIONS_OLED_REGISTRATIONS TRANSACTIONS_ST7565_REGISTRATIONS TRANSACTIONS_POINTING_REGISTRATIONS + TRANSACTIONS_WATCHDOG_REGISTRATIONS // clang-format on #if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) @@ -715,6 +801,7 @@ bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix TRANSACTIONS_OLED_MASTER(); TRANSACTIONS_ST7565_MASTER(); TRANSACTIONS_POINTING_MASTER(); + TRANSACTIONS_WATCHDOG_MASTER(); return true; } @@ -734,6 +821,7 @@ void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[ TRANSACTIONS_OLED_SLAVE(); TRANSACTIONS_ST7565_SLAVE(); TRANSACTIONS_POINTING_SLAVE(); + TRANSACTIONS_WATCHDOG_SLAVE(); } #if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) diff --git a/quantum/split_common/transport.h b/quantum/split_common/transport.h index 06778ad14a..833633edc2 100644 --- a/quantum/split_common/transport.h +++ b/quantum/split_common/transport.h @@ -188,6 +188,10 @@ typedef struct _split_shared_memory_t { split_slave_pointing_sync_t pointing; #endif // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE) +#if defined(SPLIT_WATCHDOG_ENABLE) + bool watchdog_pinged; +#endif // defined(SPLIT_WATCHDOG_ENABLE) + #if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) rpc_sync_info_t rpc_info; uint8_t rpc_m2s_buffer[RPC_M2S_BUFFER_SIZE]; |