diff options
author | Joel Spadin <joelspadin@gmail.com> | 2020-10-24 16:28:58 -0500 |
---|---|---|
committer | Joel Spadin <joelspadin@gmail.com> | 2020-10-28 18:15:05 -0500 |
commit | 600bba25f049b1fa161b2372b2a47762164c7fcd (patch) | |
tree | facbda4a77b0c454233047f8a8d5c264f3a0e3fb /app | |
parent | b538e605321791568aa25f0bd534ebcb30da92c2 (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.txt | 1 | ||||
-rw-r--r-- | app/dts/behaviors.dtsi | 1 | ||||
-rw-r--r-- | app/dts/behaviors/endpoints.dtsi | 9 | ||||
-rw-r--r-- | app/dts/bindings/behaviors/zmk,behavior-endpoints.yaml | 10 | ||||
-rw-r--r-- | app/include/dt-bindings/zmk/endpoints.h | 13 | ||||
-rw-r--r-- | app/include/zmk/endpoints.h | 8 | ||||
-rw-r--r-- | app/src/behaviors/behavior_endpoints.c | 44 | ||||
-rw-r--r-- | app/src/endpoints.c | 112 |
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); |