summary refs log tree commit diff
path: root/quantum/split_common/split_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/split_common/split_util.c')
-rw-r--r--quantum/split_common/split_util.c51
1 files changed, 51 insertions, 0 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;
+}