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]; | 
