aboutsummaryrefslogtreecommitdiff
path: root/quantum/connection
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/connection')
-rw-r--r--quantum/connection/connection.c141
-rw-r--r--quantum/connection/connection.h110
2 files changed, 251 insertions, 0 deletions
diff --git a/quantum/connection/connection.c b/quantum/connection/connection.c
new file mode 100644
index 0000000000..1ff8876876
--- /dev/null
+++ b/quantum/connection/connection.c
@@ -0,0 +1,141 @@
+// Copyright 2025 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include "connection.h"
+#include "eeconfig.h"
+#include "usb_util.h"
+#include "util.h"
+
+#ifdef BLUETOOTH_ENABLE
+# include "bluetooth.h"
+#endif
+
+// ======== DEPRECATED DEFINES - DO NOT USE ========
+#ifdef OUTPUT_DEFAULT
+# undef CONNECTION_HOST_DEFAULT
+# define CONNECTION_HOST_DEFAULT OUTPUT_DEFAULT
+#endif
+
+__attribute__((weak)) void set_output_user(uint8_t output) {}
+// ========
+
+#define CONNECTION_HOST_INVALID 0xFF
+
+#ifndef CONNECTION_HOST_DEFAULT
+# define CONNECTION_HOST_DEFAULT CONNECTION_HOST_AUTO
+#endif
+
+static const connection_host_t host_candidates[] = {
+ CONNECTION_HOST_AUTO,
+ CONNECTION_HOST_USB,
+#ifdef BLUETOOTH_ENABLE
+ CONNECTION_HOST_BLUETOOTH,
+#endif
+#if 0
+ CONNECTION_HOST_2P4GHZ,
+#endif
+};
+
+#define HOST_CANDIDATES_COUNT ARRAY_SIZE(host_candidates)
+
+static connection_config_t config = {.desired_host = CONNECTION_HOST_INVALID};
+
+void eeconfig_update_connection_default(void) {
+ config.desired_host = CONNECTION_HOST_DEFAULT;
+
+ eeconfig_update_connection(&config);
+}
+
+void connection_init(void) {
+ eeconfig_read_connection(&config);
+ if (config.desired_host == CONNECTION_HOST_INVALID) {
+ eeconfig_update_connection_default();
+ }
+}
+
+__attribute__((weak)) void connection_host_changed_user(connection_host_t host) {}
+__attribute__((weak)) void connection_host_changed_kb(connection_host_t host) {}
+
+static void handle_host_changed(void) {
+ connection_host_changed_user(config.desired_host);
+ connection_host_changed_kb(config.desired_host);
+
+ // TODO: Remove deprecated callback
+ set_output_user(config.desired_host);
+}
+
+void connection_set_host_noeeprom(connection_host_t host) {
+ if (config.desired_host == host) {
+ return;
+ }
+
+ config.desired_host = host;
+
+ handle_host_changed();
+}
+
+void connection_set_host(connection_host_t host) {
+ connection_set_host_noeeprom(host);
+
+ eeconfig_update_connection(&config);
+}
+
+void connection_next_host_noeeprom(void) {
+ uint8_t next = 0;
+ for (uint8_t i = 0; i < HOST_CANDIDATES_COUNT; i++) {
+ if (host_candidates[i] == config.desired_host) {
+ next = i == HOST_CANDIDATES_COUNT - 1 ? 0 : i + 1;
+ break;
+ }
+ }
+
+ connection_set_host_noeeprom(host_candidates[next]);
+}
+
+void connection_next_host(void) {
+ connection_next_host_noeeprom();
+
+ eeconfig_update_connection(&config);
+}
+
+void connection_prev_host_noeeprom(void) {
+ uint8_t next = 0;
+ for (uint8_t i = 0; i < HOST_CANDIDATES_COUNT; i++) {
+ if (host_candidates[i] == config.desired_host) {
+ next = i == 0 ? HOST_CANDIDATES_COUNT - 1 : i - 1;
+ break;
+ }
+ }
+
+ connection_set_host_noeeprom(host_candidates[next]);
+}
+
+void connection_prev_host(void) {
+ connection_prev_host_noeeprom();
+
+ eeconfig_update_connection(&config);
+}
+
+connection_host_t connection_get_host_raw(void) {
+ return config.desired_host;
+}
+
+connection_host_t connection_auto_detect_host(void) {
+ if (usb_connected_state()) {
+ return CONNECTION_HOST_USB;
+ }
+
+#ifdef BLUETOOTH_ENABLE
+ if (bluetooth_is_connected()) {
+ return CONNECTION_HOST_BLUETOOTH;
+ }
+#endif
+
+ return CONNECTION_HOST_NONE;
+}
+
+connection_host_t connection_get_host(void) {
+ if (config.desired_host == CONNECTION_HOST_AUTO) {
+ return connection_auto_detect_host();
+ }
+ return config.desired_host;
+}
diff --git a/quantum/connection/connection.h b/quantum/connection/connection.h
new file mode 100644
index 0000000000..e403141fae
--- /dev/null
+++ b/quantum/connection/connection.h
@@ -0,0 +1,110 @@
+// Copyright 2025 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+#include <stdint.h>
+#include "util.h"
+
+/**
+ * \enum connection_host_t
+ *
+ * An enumeration of the possible hosts.
+ */
+typedef enum connection_host_t {
+ CONNECTION_HOST_AUTO,
+
+ CONNECTION_HOST_NONE,
+ CONNECTION_HOST_USB,
+ CONNECTION_HOST_BLUETOOTH,
+ CONNECTION_HOST_2P4GHZ
+} connection_host_t;
+
+/**
+ * \union connection_config_t
+ *
+ * Configuration structure for the connection subsystem.
+ */
+typedef union connection_config_t {
+ uint8_t raw;
+ connection_host_t desired_host : 8;
+} PACKED connection_config_t;
+
+_Static_assert(sizeof(connection_config_t) == sizeof(uint8_t), "Connection EECONFIG out of spec.");
+
+/**
+ * \brief Initialize the subsystem.
+ *
+ * This function must be called only once, before any of the below functions can be called.
+ */
+void connection_init(void);
+
+/**
+ * \brief Get currently configured host. Does not resolve 'CONNECTION_HOST_AUTO'.
+ *
+ * \return 'connection_host_t' of the configured host.
+ */
+connection_host_t connection_get_host_raw(void);
+
+/**
+ * \brief Get current active host.
+ *
+ * \return 'connection_host_t' of the configured host.
+ */
+connection_host_t connection_auto_detect_host(void);
+
+/**
+ * \brief Get currently configured host. Resolves 'CONNECTION_HOST_AUTO' using 'connection_auto_detect_host()'.
+ *
+ * \return 'connection_host_t' of the configured host.
+ */
+connection_host_t connection_get_host(void);
+
+/**
+ * \brief Get current host. New state is not written to EEPROM.
+ *
+ * \param host The host to configure.
+ */
+void connection_set_host_noeeprom(connection_host_t host);
+
+/**
+ * \brief Get current host.
+ *
+ * \param host The host to configure.
+ */
+void connection_set_host(connection_host_t host);
+
+/**
+ * \brief Move to the next potential host. New state is not written to EEPROM.
+ *
+ */
+void connection_next_host_noeeprom(void);
+
+/**
+ * \brief Move to the next potential host.
+ *
+ */
+void connection_next_host(void);
+
+/**
+ * \brief Move to the previous potential host. New state is not written to EEPROM.
+ *
+ */
+void connection_prev_host_noeeprom(void);
+
+/**
+ * \brief Move to the previous potential host.
+ *
+ */
+void connection_prev_host(void);
+
+/**
+ * \brief user hook called when changing configured host
+ *
+ */
+void connection_host_changed_user(connection_host_t host);
+
+/**
+ * \brief keyboard hook called when changing configured host
+ *
+ */
+void connection_host_changed_kb(connection_host_t host);