diff options
Diffstat (limited to 'quantum/split_common')
| -rw-r--r-- | quantum/split_common/split_util.c | 51 | ||||
| -rw-r--r-- | quantum/split_common/split_util.h | 5 | ||||
| -rw-r--r-- | quantum/split_common/transactions.c | 102 | ||||
| -rw-r--r-- | quantum/split_common/transport.c | 2 | 
4 files changed, 108 insertions, 52 deletions
diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index 8d414f6fe6..35f0a9d181 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -39,6 +39,21 @@  #    define SPLIT_USB_TIMEOUT_POLL 10  #endif +// Max number of consecutive failed communications (one per scan cycle) before the communication is seen as disconnected. +// Set to 0 to disable the disconnection check altogether. +#ifndef SPLIT_MAX_CONNECTION_ERRORS +#    define SPLIT_MAX_CONNECTION_ERRORS 10 +#endif  // SPLIT_MAX_CONNECTION_ERRORS + +// How long (in milliseconds) to block all connection attempts after the communication has been flagged as disconnected. +// One communication attempt will be allowed everytime this amount of time has passed since the last attempt. If that attempt succeeds, the communication is seen as working again. +// Set to 0 to disable communication throttling while disconnected +#ifndef SPLIT_CONNECTION_CHECK_TIMEOUT +#    define SPLIT_CONNECTION_CHECK_TIMEOUT 500 +#endif  // SPLIT_CONNECTION_CHECK_TIMEOUT + +static uint8_t connection_errors = 0; +  volatile bool isLeftHand = true;  #if defined(SPLIT_USB_DETECT) @@ -142,3 +157,39 @@ void split_post_init(void) {          transport_slave_init();      }  } + +bool is_transport_connected(void) { return connection_errors < SPLIT_MAX_CONNECTION_ERRORS; } + +bool transport_master_if_connected(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +#if SPLIT_MAX_CONNECTION_ERRORS > 0 && SPLIT_CONNECTION_CHECK_TIMEOUT > 0 +    // Throttle transaction attempts if target doesn't seem to be connected +    // Without this, a solo half becomes unusable due to constant read timeouts +    static uint16_t connection_check_timer = 0; +    const bool      is_disconnected        = !is_transport_connected(); +    if (is_disconnected && timer_elapsed(connection_check_timer) < SPLIT_CONNECTION_CHECK_TIMEOUT) { +        return false; +    } +#endif  // SPLIT_MAX_CONNECTION_ERRORS > 0 && SPLIT_CONNECTION_CHECK_TIMEOUT > 0 + +    __attribute__((unused)) bool okay = transport_master(master_matrix, slave_matrix); +#if SPLIT_MAX_CONNECTION_ERRORS > 0 +    if (!okay) { +        if (connection_errors < UINT8_MAX) { +            connection_errors++; +        } +#    if SPLIT_CONNECTION_CHECK_TIMEOUT > 0 +        bool connected = is_transport_connected(); +        if (!connected) { +            connection_check_timer = timer_read(); +            dprintln("Target disconnected, throttling connection attempts"); +        } +        return connected; +    } else if (is_disconnected) { +        dprintln("Target connected"); +#    endif  // SPLIT_CONNECTION_CHECK_TIMEOUT > 0 +    } + +    connection_errors = 0; +#endif  // SPLIT_MAX_CONNECTION_ERRORS > 0 +    return true; +} diff --git a/quantum/split_common/split_util.h b/quantum/split_common/split_util.h index a4c12519e0..ef72043bb7 100644 --- a/quantum/split_common/split_util.h +++ b/quantum/split_common/split_util.h @@ -5,8 +5,13 @@  #include <stdio.h>  #include <stdlib.h> +#include "matrix.h" +  extern volatile bool isLeftHand;  void matrix_master_OLED_init(void);  void split_pre_init(void);  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); diff --git a/quantum/split_common/transactions.c b/quantum/split_common/transactions.c index 7eb3eca3e7..28ea4ef6d8 100644 --- a/quantum/split_common/transactions.c +++ b/quantum/split_common/transactions.c @@ -23,6 +23,7 @@  #include "quantum.h"  #include "transactions.h"  #include "transport.h" +#include "split_util.h"  #include "transaction_id_define.h"  #define SYNC_TIMER_OFFSET 2 @@ -53,34 +54,30 @@ void slave_rpc_exec_callback(uint8_t initiator2target_buffer_size, const void *i  ////////////////////////////////////////////////////  // Helpers -bool transaction_handler_master(bool okay, matrix_row_t master_matrix[], matrix_row_t slave_matrix[], const char *prefix, bool (*handler)(matrix_row_t master_matrix[], matrix_row_t slave_matrix[])) { -    if (okay) { -        bool this_okay = true; -        for (int iter = 1; iter <= 10; ++iter) { -            if (!this_okay) { -                for (int i = 0; i < iter * iter; ++i) { -                    wait_us(10); -                } +static bool transaction_handler_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[], const char *prefix, bool (*handler)(matrix_row_t master_matrix[], matrix_row_t slave_matrix[])) { +    int num_retries = is_transport_connected() ? 10 : 1; +    for (int iter = 1; iter <= num_retries; ++iter) { +        if (iter > 1) { +            for (int i = 0; i < iter * iter; ++i) { +                wait_us(10);              } -            ATOMIC_BLOCK_FORCEON { this_okay = handler(master_matrix, slave_matrix); }; -            if (this_okay) break; -        } -        okay &= this_okay; -        if (!okay) { -            dprintf("Failed to execute %s\n", prefix);          } +        bool this_okay = true; +        ATOMIC_BLOCK_FORCEON { this_okay = handler(master_matrix, slave_matrix); }; +        if (this_okay) return true;      } -    return okay; +    dprintf("Failed to execute %s\n", prefix); +    return false;  } -#define TRANSACTION_HANDLER_MASTER(prefix)                                                                \ -    do {                                                                                                  \ -        okay &= transaction_handler_master(okay, master_matrix, slave_matrix, #prefix, &prefix##_master); \ +#define TRANSACTION_HANDLER_MASTER(prefix)                                                                              \ +    do {                                                                                                                \ +        if (!transaction_handler_master(master_matrix, slave_matrix, #prefix, &prefix##_handlers_master)) return false; \      } while (0) -#define TRANSACTION_HANDLER_SLAVE(prefix)                                      \ -    do {                                                                       \ -        ATOMIC_BLOCK_FORCEON { prefix##_slave(master_matrix, slave_matrix); }; \ +#define TRANSACTION_HANDLER_SLAVE(prefix)                                               \ +    do {                                                                                \ +        ATOMIC_BLOCK_FORCEON { prefix##_handlers_slave(master_matrix, slave_matrix); }; \      } while (0)  inline static bool read_if_checksum_mismatch(int8_t trans_id_checksum, int8_t trans_id_retrieve, uint32_t *last_update, void *destination, const void *equiv_shmem, size_t length) { @@ -138,8 +135,8 @@ 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_handlers) -#define TRANSACTIONS_SLAVE_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(slave_matrix_handlers) +#define TRANSACTIONS_SLAVE_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(slave_matrix) +#define TRANSACTIONS_SLAVE_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(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), @@ -160,8 +157,8 @@ static void master_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_ro      memcpy(master_matrix, split_shmem->mmatrix.matrix, sizeof(split_shmem->mmatrix.matrix));  } -#    define TRANSACTIONS_MASTER_MATRIX_MASTER()      TRANSACTION_HANDLER_MASTER(master_matrix_handlers) -#    define TRANSACTIONS_MASTER_MATRIX_SLAVE()       TRANSACTION_HANDLER_SLAVE(master_matrix_handlers) +#    define TRANSACTIONS_MASTER_MATRIX_MASTER()      TRANSACTION_HANDLER_MASTER(master_matrix) +#    define TRANSACTIONS_MASTER_MATRIX_SLAVE()       TRANSACTION_HANDLER_SLAVE(master_matrix)  #    define TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS [PUT_MASTER_MATRIX] = trans_initiator2target_initializer(mmatrix.matrix),  #else  // SPLIT_TRANSPORT_MIRROR @@ -196,8 +193,8 @@ 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_handlers) -#    define TRANSACTIONS_ENCODERS_SLAVE() TRANSACTION_HANDLER_SLAVE(encoder_handlers) +#    define TRANSACTIONS_ENCODERS_MASTER() TRANSACTION_HANDLER_MASTER(encoder) +#    define TRANSACTIONS_ENCODERS_SLAVE() TRANSACTION_HANDLER_SLAVE(encoder)  #    define TRANSACTIONS_ENCODERS_REGISTRATIONS \      [GET_ENCODERS_CHECKSUM] = trans_target2initiator_initializer(encoders.checksum), \      [GET_ENCODERS_DATA]     = trans_target2initiator_initializer(encoders.state), @@ -238,8 +235,8 @@ static void sync_timer_handlers_slave(matrix_row_t master_matrix[], matrix_row_t      }  } -#    define TRANSACTIONS_SYNC_TIMER_MASTER()      TRANSACTION_HANDLER_MASTER(sync_timer_handlers) -#    define TRANSACTIONS_SYNC_TIMER_SLAVE()       TRANSACTION_HANDLER_SLAVE(sync_timer_handlers) +#    define TRANSACTIONS_SYNC_TIMER_MASTER()      TRANSACTION_HANDLER_MASTER(sync_timer) +#    define TRANSACTIONS_SYNC_TIMER_SLAVE()       TRANSACTION_HANDLER_SLAVE(sync_timer)  #    define TRANSACTIONS_SYNC_TIMER_REGISTRATIONS [PUT_SYNC_TIMER] = trans_initiator2target_initializer(sync_timer),  #else  // DISABLE_SYNC_TIMER @@ -272,8 +269,8 @@ 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_handlers) -#    define TRANSACTIONS_LAYER_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(layer_state_handlers) +#    define TRANSACTIONS_LAYER_STATE_MASTER() TRANSACTION_HANDLER_MASTER(layer_state) +#    define TRANSACTIONS_LAYER_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(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), @@ -303,8 +300,8 @@ static void led_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_t      set_split_host_keyboard_leds(split_shmem->led_state);  } -#    define TRANSACTIONS_LED_STATE_MASTER()      TRANSACTION_HANDLER_MASTER(led_state_handlers) -#    define TRANSACTIONS_LED_STATE_SLAVE()       TRANSACTION_HANDLER_SLAVE(led_state_handlers) +#    define TRANSACTIONS_LED_STATE_MASTER()      TRANSACTION_HANDLER_MASTER(led_state) +#    define TRANSACTIONS_LED_STATE_SLAVE()       TRANSACTION_HANDLER_SLAVE(led_state)  #    define TRANSACTIONS_LED_STATE_REGISTRATIONS [PUT_LED_STATE] = trans_initiator2target_initializer(led_state),  #else  // SPLIT_LED_STATE_ENABLE @@ -360,8 +357,8 @@ static void mods_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave  #    endif  } -#    define TRANSACTIONS_MODS_MASTER()      TRANSACTION_HANDLER_MASTER(mods_handlers) -#    define TRANSACTIONS_MODS_SLAVE()       TRANSACTION_HANDLER_SLAVE(mods_handlers) +#    define TRANSACTIONS_MODS_MASTER()      TRANSACTION_HANDLER_MASTER(mods) +#    define TRANSACTIONS_MODS_SLAVE()       TRANSACTION_HANDLER_SLAVE(mods)  #    define TRANSACTIONS_MODS_REGISTRATIONS [PUT_MODS] = trans_initiator2target_initializer(mods),  #else  // SPLIT_MODS_ENABLE @@ -385,8 +382,8 @@ 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); } -#    define TRANSACTIONS_BACKLIGHT_MASTER()      TRANSACTION_HANDLER_MASTER(backlight_handlers) -#    define TRANSACTIONS_BACKLIGHT_SLAVE()       TRANSACTION_HANDLER_SLAVE(backlight_handlers) +#    define TRANSACTIONS_BACKLIGHT_MASTER()      TRANSACTION_HANDLER_MASTER(backlight) +#    define TRANSACTIONS_BACKLIGHT_SLAVE()       TRANSACTION_HANDLER_SLAVE(backlight)  #    define TRANSACTIONS_BACKLIGHT_REGISTRATIONS [PUT_BACKLIGHT] = trans_initiator2target_initializer(backlight_level),  #else  // BACKLIGHT_ENABLE @@ -422,8 +419,8 @@ static void rgblight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t s      }  } -#    define TRANSACTIONS_RGBLIGHT_MASTER()      TRANSACTION_HANDLER_MASTER(rgblight_handlers) -#    define TRANSACTIONS_RGBLIGHT_SLAVE()       TRANSACTION_HANDLER_SLAVE(rgblight_handlers) +#    define TRANSACTIONS_RGBLIGHT_MASTER()      TRANSACTION_HANDLER_MASTER(rgblight) +#    define TRANSACTIONS_RGBLIGHT_SLAVE()       TRANSACTION_HANDLER_SLAVE(rgblight)  #    define TRANSACTIONS_RGBLIGHT_REGISTRATIONS [PUT_RGBLIGHT] = trans_initiator2target_initializer(rgblight_sync),  #else  // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) @@ -452,8 +449,8 @@ static void led_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t      led_matrix_set_suspend_state(split_shmem->led_matrix_sync.led_suspend_state);  } -#    define TRANSACTIONS_LED_MATRIX_MASTER()      TRANSACTION_HANDLER_MASTER(led_matrix_handlers) -#    define TRANSACTIONS_LED_MATRIX_SLAVE()       TRANSACTION_HANDLER_SLAVE(led_matrix_handlers) +#    define TRANSACTIONS_LED_MATRIX_MASTER()      TRANSACTION_HANDLER_MASTER(led_matrix) +#    define TRANSACTIONS_LED_MATRIX_SLAVE()       TRANSACTION_HANDLER_SLAVE(led_matrix)  #    define TRANSACTIONS_LED_MATRIX_REGISTRATIONS [PUT_LED_MATRIX] = trans_initiator2target_initializer(led_matrix_sync),  #else  // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) @@ -482,8 +479,8 @@ static void rgb_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t      rgb_matrix_set_suspend_state(split_shmem->rgb_matrix_sync.rgb_suspend_state);  } -#    define TRANSACTIONS_RGB_MATRIX_MASTER()      TRANSACTION_HANDLER_MASTER(rgb_matrix_handlers) -#    define TRANSACTIONS_RGB_MATRIX_SLAVE()       TRANSACTION_HANDLER_SLAVE(rgb_matrix_handlers) +#    define TRANSACTIONS_RGB_MATRIX_MASTER()      TRANSACTION_HANDLER_MASTER(rgb_matrix) +#    define TRANSACTIONS_RGB_MATRIX_SLAVE()       TRANSACTION_HANDLER_SLAVE(rgb_matrix)  #    define TRANSACTIONS_RGB_MATRIX_REGISTRATIONS [PUT_RGB_MATRIX] = trans_initiator2target_initializer(rgb_matrix_sync),  #else  // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) @@ -507,8 +504,8 @@ static bool wpm_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave  static void wpm_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { set_current_wpm(split_shmem->current_wpm); } -#    define TRANSACTIONS_WPM_MASTER()      TRANSACTION_HANDLER_MASTER(wpm_handlers) -#    define TRANSACTIONS_WPM_SLAVE()       TRANSACTION_HANDLER_SLAVE(wpm_handlers) +#    define TRANSACTIONS_WPM_MASTER()      TRANSACTION_HANDLER_MASTER(wpm) +#    define TRANSACTIONS_WPM_SLAVE()       TRANSACTION_HANDLER_SLAVE(wpm)  #    define TRANSACTIONS_WPM_REGISTRATIONS [PUT_WPM] = trans_initiator2target_initializer(current_wpm),  #else  // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) @@ -538,8 +535,8 @@ static void oled_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave      }  } -#    define TRANSACTIONS_OLED_MASTER()      TRANSACTION_HANDLER_MASTER(oled_handlers) -#    define TRANSACTIONS_OLED_SLAVE()       TRANSACTION_HANDLER_SLAVE(oled_handlers) +#    define TRANSACTIONS_OLED_MASTER()      TRANSACTION_HANDLER_MASTER(oled) +#    define TRANSACTIONS_OLED_SLAVE()       TRANSACTION_HANDLER_SLAVE(oled)  #    define TRANSACTIONS_OLED_REGISTRATIONS [PUT_OLED] = trans_initiator2target_initializer(current_oled_state),  #else  // defined(OLED_DRIVER_ENABLE) && defined(SPLIT_OLED_ENABLE) @@ -569,8 +566,8 @@ static void st7565_handlers_slave(matrix_row_t master_matrix[], matrix_row_t sla      }  } -#    define TRANSACTIONS_ST7565_MASTER()      TRANSACTION_HANDLER_MASTER(st7565_handlers) -#    define TRANSACTIONS_ST7565_SLAVE()       TRANSACTION_HANDLER_SLAVE(st7565_handlers) +#    define TRANSACTIONS_ST7565_MASTER()      TRANSACTION_HANDLER_MASTER(st7565) +#    define TRANSACTIONS_ST7565_SLAVE()       TRANSACTION_HANDLER_SLAVE(st7565)  #    define TRANSACTIONS_ST7565_REGISTRATIONS [PUT_ST7565] = trans_initiator2target_initializer(current_st7565_state),  #else  // defined(ST7565_ENABLE) && defined(SPLIT_ST7565_ENABLE) @@ -618,7 +615,6 @@ split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = {  };  bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { -    bool okay = true;      TRANSACTIONS_SLAVE_MATRIX_MASTER();      TRANSACTIONS_MASTER_MATRIX_MASTER();      TRANSACTIONS_ENCODERS_MASTER(); @@ -633,7 +629,7 @@ bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix      TRANSACTIONS_WPM_MASTER();      TRANSACTIONS_OLED_MASTER();      TRANSACTIONS_ST7565_MASTER(); -    return okay; +    return true;  }  void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { @@ -666,6 +662,10 @@ void transaction_register_rpc(int8_t transaction_id, slave_callback_t callback)  }  bool transaction_rpc_exec(int8_t transaction_id, uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) { +    // Prevent transaction attempts while transport is disconnected +    if (!is_transport_connected()) { +        return false; +    }      // Prevent invoking RPC on QMK core sync data      if (transaction_id <= GET_RPC_RESP_DATA) return false;      // Prevent sizing issues diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c index a711ef85f0..bcc0261417 100644 --- a/quantum/split_common/transport.c +++ b/quantum/split_common/transport.c @@ -115,4 +115,4 @@ bool transport_execute_transaction(int8_t id, const void *initiator2target_buf,  bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { return transactions_master(master_matrix, slave_matrix); } -void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { transactions_slave(master_matrix, slave_matrix); }
\ No newline at end of file +void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { transactions_slave(master_matrix, slave_matrix); }  | 
