summaryrefslogtreecommitdiff
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.c120
1 files changed, 78 insertions, 42 deletions
diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c
index 575bdc0fdc..35f0a9d181 100644
--- a/quantum/split_common/split_util.c
+++ b/quantum/split_common/split_util.c
@@ -1,3 +1,18 @@
+/* Copyright 2021 QMK
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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 "split_util.h"
#include "matrix.h"
#include "keyboard.h"
@@ -6,14 +21,7 @@
#include "transport.h"
#include "quantum.h"
#include "wait.h"
-
-#ifdef PROTOCOL_LUFA
-# include <LUFA/Drivers/USB/USB.h>
-#endif
-
-#ifdef PROTOCOL_VUSB
-# include <usbdrv/usbdrv.h>
-#endif
+#include "usb_util.h"
#ifdef EE_HANDS
# include "eeconfig.h"
@@ -31,53 +39,36 @@
# define SPLIT_USB_TIMEOUT_POLL 10
#endif
-#ifdef PROTOCOL_CHIBIOS
-# define SPLIT_USB_DETECT // Force this on for now
-#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)
-# if defined(PROTOCOL_LUFA)
-static inline bool usbHasActiveConnection(void) { return USB_Device_IsAddressSet(); }
-static inline void usbDisable(void) { USB_Disable(); }
-# elif defined(PROTOCOL_CHIBIOS)
-static inline bool usbHasActiveConnection(void) { return usbGetDriverStateI(&USBD1) == USB_ACTIVE; }
-static inline void usbDisable(void) { usbStop(&USBD1); }
-# elif defined(PROTOCOL_VUSB)
-static inline bool usbHasActiveConnection(void) {
- usbPoll();
- return usbConfiguration;
-}
-static inline void usbDisable(void) { usbDeviceDisconnect(); }
-# else
-static inline bool usbHasActiveConnection(void) { return true; }
-static inline void usbDisable(void) {}
-# endif
-
-bool usbIsActive(void) {
+static bool usbIsActive(void) {
for (uint8_t i = 0; i < (SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL); i++) {
// This will return true if a USB connection has been established
- if (usbHasActiveConnection()) {
+ if (usb_connected_state()) {
return true;
}
wait_ms(SPLIT_USB_TIMEOUT_POLL);
}
-
- // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow
- usbDisable();
-
return false;
}
-#elif defined(PROTOCOL_LUFA) && defined(OTGPADE)
-static inline bool usbIsActive(void) {
- USB_OTGPAD_On(); // enables VBUS pad
- wait_us(5);
-
- return USB_VBUS_GetStatus(); // checks state of VBUS
-}
#else
-static inline bool usbIsActive(void) { return true; }
+static inline bool usbIsActive(void) { return usb_vbus_state(); }
#endif
#ifdef SPLIT_HAND_MATRIX_GRID
@@ -101,7 +92,11 @@ __attribute__((weak)) bool is_keyboard_left(void) {
#if defined(SPLIT_HAND_PIN)
// Test pin SPLIT_HAND_PIN for High/Low, if low it's right hand
setPinInput(SPLIT_HAND_PIN);
+# ifdef SPLIT_HAND_PIN_LOW_IS_LEFT
+ return !readPin(SPLIT_HAND_PIN);
+# else
return readPin(SPLIT_HAND_PIN);
+# endif
#elif defined(SPLIT_HAND_MATRIX_GRID)
# ifdef SPLIT_HAND_MATRIX_GRID_LOW_IS_RIGHT
return peek_matrix_intersection(SPLIT_HAND_MATRIX_GRID);
@@ -123,6 +118,11 @@ __attribute__((weak)) bool is_keyboard_master(void) {
// only check once, as this is called often
if (usbstate == UNKNOWN) {
usbstate = usbIsActive() ? MASTER : SLAVE;
+
+ // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow
+ if (usbstate == SLAVE) {
+ usb_disconnect();
+ }
}
return (usbstate == MASTER);
@@ -157,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;
+}