summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorJoel Spadin <joelspadin@gmail.com>2020-10-24 16:28:58 -0500
committerJoel Spadin <joelspadin@gmail.com>2020-10-28 18:15:05 -0500
commit600bba25f049b1fa161b2372b2a47762164c7fcd (patch)
treefacbda4a77b0c454233047f8a8d5c264f3a0e3fb /app
parentb538e605321791568aa25f0bd534ebcb30da92c2 (diff)
feat(endpoints): add preferred endpoint setting
Added a new setting to remember the user's preferred endpoint. When both USB and BLE are connected, the preferred endpoint will be used. Added a new behavior to control this setting. It supports commands: &end END_USB - Prefer USB output &end END_BLE - Prefer BLE output &end END_TOG - Toggle between USB and BLE
Diffstat (limited to 'app')
-rw-r--r--app/CMakeLists.txt1
-rw-r--r--app/dts/behaviors.dtsi1
-rw-r--r--app/dts/behaviors/endpoints.dtsi9
-rw-r--r--app/dts/bindings/behaviors/zmk,behavior-endpoints.yaml10
-rw-r--r--app/include/dt-bindings/zmk/endpoints.h13
-rw-r--r--app/include/zmk/endpoints.h8
-rw-r--r--app/src/behaviors/behavior_endpoints.c44
-rw-r--r--app/src/endpoints.c112
8 files changed, 179 insertions, 19 deletions
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index bce2170..0c43b91 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -39,6 +39,7 @@ target_sources(app PRIVATE src/events/sensor_event.c)
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/ble_active_profile_changed.c)
target_sources_ifdef(CONFIG_USB app PRIVATE src/events/usb_conn_state_changed.c)
if (NOT CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
+ target_sources(app PRIVATE src/behaviors/behavior_endpoints.c)
target_sources(app PRIVATE src/behaviors/behavior_key_press.c)
target_sources(app PRIVATE src/behaviors/behavior_reset.c)
target_sources(app PRIVATE src/behaviors/behavior_hold_tap.c)
diff --git a/app/dts/behaviors.dtsi b/app/dts/behaviors.dtsi
index 36c918c..4a50761 100644
--- a/app/dts/behaviors.dtsi
+++ b/app/dts/behaviors.dtsi
@@ -10,3 +10,4 @@
#include <behaviors/rgb_underglow.dtsi>
#include <behaviors/bluetooth.dtsi>
#include <behaviors/ext_power.dtsi>
+#include <behaviors/endpoints.dtsi>
diff --git a/app/dts/behaviors/endpoints.dtsi b/app/dts/behaviors/endpoints.dtsi
new file mode 100644
index 0000000..f6cb64c
--- /dev/null
+++ b/app/dts/behaviors/endpoints.dtsi
@@ -0,0 +1,9 @@
+/ {
+ behaviors {
+ end: behavior_endpoints {
+ compatible = "zmk,behavior-endpoints";
+ label = "ENDPOINTS";
+ #binding-cells = <1>;
+ };
+ };
+};
diff --git a/app/dts/bindings/behaviors/zmk,behavior-endpoints.yaml b/app/dts/bindings/behaviors/zmk,behavior-endpoints.yaml
new file mode 100644
index 0000000..fdd76bb
--- /dev/null
+++ b/app/dts/bindings/behaviors/zmk,behavior-endpoints.yaml
@@ -0,0 +1,10 @@
+#
+# Copyright (c) 2020, The ZMK Contributors
+# SPDX-License-Identifier: MIT
+#
+
+description: Endpoints Behavior
+
+compatible: "zmk,behavior-endpoints"
+
+include: one_param.yaml
diff --git a/app/include/dt-bindings/zmk/endpoints.h b/app/include/dt-bindings/zmk/endpoints.h
new file mode 100644
index 0000000..3bba972
--- /dev/null
+++ b/app/include/dt-bindings/zmk/endpoints.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define ENDPOINT_TOGGLE_CMD 0
+#define ENDPOINT_USB_CMD 1
+#define ENDPOINT_BLE_CMD 2
+
+#define END_TOG ENDPOINT_TOGGLE_CMD
+#define END_USB ENDPOINT_USB_CMD
+#define END_BLE ENDPOINT_BLE_CMD \ No newline at end of file
diff --git a/app/include/zmk/endpoints.h b/app/include/zmk/endpoints.h
index aad6265..aad688e 100644
--- a/app/include/zmk/endpoints.h
+++ b/app/include/zmk/endpoints.h
@@ -9,4 +9,12 @@
#include <zmk/keys.h>
#include <zmk/hid.h>
+enum zmk_endpoint {
+ ZMK_ENDPOINT_USB,
+ ZMK_ENDPOINT_BLE,
+};
+
+int zmk_endpoints_select(enum zmk_endpoint endpoint);
+int zmk_endpoints_toggle();
+
int zmk_endpoints_send_report(u8_t usage_report);
diff --git a/app/src/behaviors/behavior_endpoints.c b/app/src/behaviors/behavior_endpoints.c
new file mode 100644
index 0000000..dd56fc1
--- /dev/null
+++ b/app/src/behaviors/behavior_endpoints.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define DT_DRV_COMPAT zmk_behavior_endpoints
+
+#include <device.h>
+#include <devicetree.h>
+#include <drivers/behavior.h>
+
+#include <dt-bindings/zmk/endpoints.h>
+
+#include <zmk/behavior.h>
+#include <zmk/endpoints.h>
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
+static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
+ switch (binding->param1) {
+ case ENDPOINT_TOGGLE_CMD:
+ return zmk_endpoints_toggle();
+ case ENDPOINT_USB_CMD:
+ return zmk_endpoints_select(ZMK_ENDPOINT_USB);
+ case ENDPOINT_BLE_CMD:
+ return zmk_endpoints_select(ZMK_ENDPOINT_BLE);
+ default:
+ LOG_ERR("Unknown endpoints command: %d", binding->param1);
+ }
+
+ return -ENOTSUP;
+}
+
+static int behavior_ep_init(struct device *dev) { return 0; }
+
+static const struct behavior_driver_api behavior_endpoints_driver_api = {
+ .binding_pressed = on_keymap_binding_pressed,
+};
+
+DEVICE_AND_API_INIT(behavior_end, DT_INST_LABEL(0), behavior_ep_init, NULL, NULL, APPLICATION,
+ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_endpoints_driver_api);
diff --git a/app/src/endpoints.c b/app/src/endpoints.c
index 56204a4..0c79589 100644
--- a/app/src/endpoints.c
+++ b/app/src/endpoints.c
@@ -4,6 +4,9 @@
* SPDX-License-Identifier: MIT
*/
+#include <init.h>
+#include <settings/settings.h>
+
#include <zmk/ble.h>
#include <zmk/endpoints.h>
#include <zmk/hid.h>
@@ -16,21 +19,45 @@
#include <logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
-enum endpoint {
- ENDPOINT_USB,
- ENDPOINT_BLE,
-};
+#define DEFAULT_ENDPOINT \
+ COND_CODE_1(IS_ENABLED(CONFIG_ZMK_BLE), (ZMK_ENDPOINT_BLE), (ZMK_ENDPOINT_USB))
+
+static enum zmk_endpoint current_endpoint = DEFAULT_ENDPOINT;
+static enum zmk_endpoint preferred_endpoint =
+ ZMK_ENDPOINT_USB; /* Used if multiple endpoints are ready */
+
+static void update_current_endpoint();
+
+int zmk_endpoints_select(enum zmk_endpoint endpoint) {
+ LOG_DBG("Selected endpoint %d", endpoint);
+
+ if (preferred_endpoint == endpoint) {
+ return 0;
+ }
+
+ preferred_endpoint = endpoint;
+
+#if IS_ENABLED(CONFIG_SETTINGS)
+ settings_save_one("endpoints/preferred", &preferred_endpoint, sizeof(preferred_endpoint));
+#endif
+
+ update_current_endpoint();
-#define DEFAULT_ENDPOINT COND_CODE_1(IS_ENABLED(CONFIG_ZMK_BLE), (ENDPOINT_BLE), (ENDPOINT_USB))
+ return 0;
+}
-static enum endpoint current_endpoint = DEFAULT_ENDPOINT;
+int zmk_endpoints_toggle() {
+ enum zmk_endpoint new_endpoint =
+ (preferred_endpoint == ZMK_ENDPOINT_USB) ? ZMK_ENDPOINT_BLE : ZMK_ENDPOINT_USB;
+ return zmk_endpoints_select(new_endpoint);
+}
static int send_keypad_report() {
struct zmk_hid_keypad_report *keypad_report = zmk_hid_get_keypad_report();
switch (current_endpoint) {
#if IS_ENABLED(CONFIG_ZMK_USB)
- case ENDPOINT_USB: {
+ case ZMK_ENDPOINT_USB: {
int err = zmk_usb_hid_send_report((u8_t *)keypad_report, sizeof(*keypad_report));
if (err) {
LOG_ERR("FAILED TO SEND OVER USB: %d", err);
@@ -40,7 +67,7 @@ static int send_keypad_report() {
#endif /* IS_ENABLED(CONFIG_ZMK_USB) */
#if IS_ENABLED(CONFIG_ZMK_BLE)
- case ENDPOINT_BLE: {
+ case ZMK_ENDPOINT_BLE: {
int err = zmk_hog_send_keypad_report(&keypad_report->body);
if (err) {
LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
@@ -60,7 +87,7 @@ static int send_consumer_report() {
switch (current_endpoint) {
#if IS_ENABLED(CONFIG_ZMK_USB)
- case ENDPOINT_USB: {
+ case ZMK_ENDPOINT_USB: {
int err = zmk_usb_hid_send_report((u8_t *)consumer_report, sizeof(*consumer_report));
if (err) {
LOG_ERR("FAILED TO SEND OVER USB: %d", err);
@@ -70,7 +97,7 @@ static int send_consumer_report() {
#endif /* IS_ENABLED(CONFIG_ZMK_USB) */
#if IS_ENABLED(CONFIG_ZMK_BLE)
- case ENDPOINT_BLE: {
+ case ZMK_ENDPOINT_BLE: {
int err = zmk_hog_send_consumer_report(&consumer_report->body);
if (err) {
LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
@@ -99,6 +126,49 @@ int zmk_endpoints_send_report(u8_t usage_page) {
}
}
+#if IS_ENABLED(CONFIG_SETTINGS)
+
+static int endpoints_handle_set(const char *name, size_t len, settings_read_cb read_cb,
+ void *cb_arg) {
+ LOG_DBG("Setting endpoint value %s", log_strdup(name));
+
+ if (settings_name_steq(name, "preferred", NULL)) {
+ if (len != sizeof(enum zmk_endpoint)) {
+ LOG_ERR("Invalid endpoint size (got %d expected %d)", len, sizeof(enum zmk_endpoint));
+ return -EINVAL;
+ }
+
+ int err = read_cb(cb_arg, &preferred_endpoint, sizeof(enum zmk_endpoint));
+ if (err <= 0) {
+ LOG_ERR("Failed to read preferred endpoint from settings (err %d)", err);
+ return err;
+ }
+
+ update_current_endpoint();
+ }
+
+ return 0;
+}
+
+struct settings_handler endpoints_handler = {.name = "endpoints", .h_set = endpoints_handle_set};
+#endif /* IS_ENABLED(CONFIG_SETTINGS) */
+
+static int zmk_endpoints_init(struct device *_arg) {
+#if IS_ENABLED(CONFIG_SETTINGS)
+ settings_subsys_init();
+
+ int err = settings_register(&endpoints_handler);
+ if (err) {
+ LOG_ERR("Failed to register the endpoints settings handler (err %d)", err);
+ return err;
+ }
+
+ settings_load();
+#endif
+
+ return 0;
+}
+
static bool is_usb_ready() {
#if IS_ENABLED(CONFIG_ZMK_USB)
return zmk_usb_is_hid_ready();
@@ -115,21 +185,20 @@ static bool is_ble_ready() {
#endif
}
-static enum endpoint get_selected_endpoint() {
+static enum zmk_endpoint get_selected_endpoint() {
if (is_ble_ready()) {
if (is_usb_ready()) {
- LOG_DBG("Both endpoints are ready.");
- // TODO: add user setting to control this
- return ENDPOINT_USB;
+ LOG_DBG("Both endpoints are ready. Using %d", preferred_endpoint);
+ return preferred_endpoint;
}
LOG_DBG("Only BLE is ready.");
- return ENDPOINT_BLE;
+ return ZMK_ENDPOINT_BLE;
}
if (is_usb_ready()) {
LOG_DBG("Only USB is ready.");
- return ENDPOINT_USB;
+ return ZMK_ENDPOINT_USB;
}
LOG_DBG("No endpoints are ready.");
@@ -144,8 +213,8 @@ static void disconnect_current_endpoint() {
zmk_endpoints_send_report(USAGE_CONSUMER);
}
-static int endpoint_listener(const struct zmk_event_header *eh) {
- enum endpoint new_endpoint = get_selected_endpoint();
+static void update_current_endpoint() {
+ enum zmk_endpoint new_endpoint = get_selected_endpoint();
if (new_endpoint != current_endpoint) {
/* Cancel all current keypresses so keys don't stay held on the old endpoint. */
@@ -154,7 +223,10 @@ static int endpoint_listener(const struct zmk_event_header *eh) {
current_endpoint = new_endpoint;
LOG_INF("Endpoint changed: %d", current_endpoint);
}
+}
+static int endpoint_listener(const struct zmk_event_header *eh) {
+ update_current_endpoint();
return 0;
}
@@ -164,4 +236,6 @@ ZMK_SUBSCRIPTION(endpoint_listener, usb_conn_state_changed);
#endif
#if IS_ENABLED(CONFIG_ZMK_BLE)
ZMK_SUBSCRIPTION(endpoint_listener, ble_active_profile_changed);
-#endif \ No newline at end of file
+#endif
+
+SYS_INIT(zmk_endpoints_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);