From 1d369ffa73ae63af821d012b1c2ab4a07a5dc9c7 Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Sun, 11 Oct 2020 17:03:21 -0500 Subject: [PATCH 1/7] feat: only send HID reports to one endpoint Added some utility functions and an event for tracking the state of the USB connection. Updated endpoints.c to select a single endpoint to send HID reports to based on the status of the USB and BLE connections. Partially fixes #206. Future commits will add a user setting to control which endpoint is used if both USB and BLE are ready. --- app/CMakeLists.txt | 1 + .../zmk/events/usb-conn-state-changed.h | 20 +++ app/include/zmk/usb.h | 12 +- app/src/endpoints.c | 140 ++++++++++++++---- app/src/events/usb_conn_state_changed.c | 10 ++ app/src/power.c | 9 +- app/src/usb.c | 29 +++- 7 files changed, 183 insertions(+), 38 deletions(-) create mode 100644 app/include/zmk/events/usb-conn-state-changed.h create mode 100644 app/src/events/usb_conn_state_changed.c diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 8a3971e8..bce21700 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -37,6 +37,7 @@ target_sources(app PRIVATE src/events/keycode_state_changed.c) target_sources(app PRIVATE src/events/modifiers_state_changed.c) 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_key_press.c) target_sources(app PRIVATE src/behaviors/behavior_reset.c) diff --git a/app/include/zmk/events/usb-conn-state-changed.h b/app/include/zmk/events/usb-conn-state-changed.h new file mode 100644 index 00000000..d6cc6985 --- /dev/null +++ b/app/include/zmk/events/usb-conn-state-changed.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#pragma once + +#include +#include + +#include +#include + +struct usb_conn_state_changed { + struct zmk_event_header header; + enum zmk_usb_conn_state conn_state; +}; + +ZMK_EVENT_DECLARE(usb_conn_state_changed); \ No newline at end of file diff --git a/app/include/zmk/usb.h b/app/include/zmk/usb.h index 452fd54d..30461de2 100644 --- a/app/include/zmk/usb.h +++ b/app/include/zmk/usb.h @@ -12,8 +12,18 @@ #include #include +enum zmk_usb_conn_state { + ZMK_USB_CONN_NONE, + ZMK_USB_CONN_POWERED, + ZMK_USB_CONN_HID, +}; + enum usb_dc_status_code zmk_usb_get_status(); +enum zmk_usb_conn_state zmk_usb_get_conn_state(); + +static inline bool zmk_usb_is_powered() { return zmk_usb_get_conn_state() != ZMK_USB_CONN_NONE; } +static inline bool zmk_usb_is_hid_ready() { return zmk_usb_get_conn_state() == ZMK_USB_CONN_HID; } #ifdef CONFIG_ZMK_USB -int zmk_usb_hid_send_report(u8_t *report, size_t len); +int zmk_usb_hid_send_report(const u8_t *report, size_t len); #endif /* CONFIG_ZMK_USB */ \ No newline at end of file diff --git a/app/src/endpoints.c b/app/src/endpoints.c index 79d294ef..4f56aa5c 100644 --- a/app/src/endpoints.c +++ b/app/src/endpoints.c @@ -8,54 +8,138 @@ #include #include #include +#include +#include #include LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); -int zmk_endpoints_send_report(u8_t usage_page) { - int err; - struct zmk_hid_keypad_report *keypad_report; - struct zmk_hid_consumer_report *consumer_report; - LOG_DBG("usage page 0x%02X", usage_page); - switch (usage_page) { - case USAGE_KEYPAD: - keypad_report = zmk_hid_get_keypad_report(); -#ifdef CONFIG_ZMK_USB - if (zmk_usb_hid_send_report((u8_t *)keypad_report, sizeof(struct zmk_hid_keypad_report)) != - 0) { - LOG_DBG("USB Send Failed"); +enum endpoint { + ENDPOINT_USB, + ENDPOINT_BLE, +}; + +static enum endpoint current_endpoint = + COND_CODE_1(IS_ENABLED(CONFIG_ZMK_BLE), (ENDPOINT_BLE), (ENDPOINT_USB)); + +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: { + 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); } -#endif /* CONFIG_ZMK_USB */ + return err; + } +#endif /* IS_ENABLED(CONFIG_ZMK_USB) */ -#ifdef CONFIG_ZMK_BLE - err = zmk_hog_send_keypad_report(&keypad_report->body); +#if IS_ENABLED(CONFIG_ZMK_BLE) + case ENDPOINT_BLE: { + int err = zmk_hog_send_keypad_report(&keypad_report->body); if (err) { LOG_ERR("FAILED TO SEND OVER HOG: %d", err); } -#endif /* CONFIG_ZMK_BLE */ + return err; + } +#endif /* IS_ENABLED(CONFIG_ZMK_BLE) */ - break; - case USAGE_CONSUMER: - consumer_report = zmk_hid_get_consumer_report(); -#ifdef CONFIG_ZMK_USB - if (zmk_usb_hid_send_report((u8_t *)consumer_report, - sizeof(struct zmk_hid_consumer_report)) != 0) { - LOG_DBG("USB Send Failed"); + default: + LOG_ERR("Unsupported endpoint %d", current_endpoint); + return -ENOTSUP; + } +} + +static int send_consumer_report() { + struct zmk_hid_consumer_report *consumer_report = zmk_hid_get_consumer_report(); + + switch (current_endpoint) { +#if IS_ENABLED(CONFIG_ZMK_USB) + case 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); } -#endif /* CONFIG_ZMK_USB */ + return err; + } +#endif /* IS_ENABLED(CONFIG_ZMK_USB) */ -#ifdef CONFIG_ZMK_BLE - err = zmk_hog_send_consumer_report(&consumer_report->body); +#if IS_ENABLED(CONFIG_ZMK_BLE) + case ENDPOINT_BLE: { + int err = zmk_hog_send_consumer_report(&consumer_report->body); if (err) { LOG_ERR("FAILED TO SEND OVER HOG: %d", err); } -#endif /* CONFIG_ZMK_BLE */ + return err; + } +#endif /* IS_ENABLED(CONFIG_ZMK_BLE) */ + + default: + LOG_ERR("Unsupported endpoint %d", current_endpoint); + return -ENOTSUP; + } +} + +int zmk_endpoints_send_report(u8_t usage_page) { - break; + LOG_DBG("usage page 0x%02X", usage_page); + switch (usage_page) { + case USAGE_KEYPAD: + return send_keypad_report(); + case USAGE_CONSUMER: + return send_consumer_report(); default: LOG_ERR("Unsupported usage page %d", usage_page); return -ENOTSUP; } +} + +static bool is_usb_ready() { +#if IS_ENABLED(CONFIG_ZMK_USB) + return zmk_usb_is_hid_ready(); +#else + return false; +#endif +} + +static bool is_ble_ready() { +#if IS_ENABLED(CONFIG_ZMK_BLE) + return zmk_ble_active_profile_is_connected(); +#else + return false; +#endif +} + +static enum endpoint get_selected_endpoint() { + if (is_ble_ready()) { + if (is_usb_ready()) { + LOG_DBG("Both endpoints ready. Selecting USB"); + // TODO: add user setting to control this + return ENDPOINT_USB; + } + + return ENDPOINT_BLE; + } + + return ENDPOINT_USB; +} + +static int endpoint_listener(const struct zmk_event_header *eh) { + enum endpoint new_endpoint = get_selected_endpoint(); + + if (new_endpoint != current_endpoint) { + // TODO: send null report on previous endpoint + current_endpoint = new_endpoint; + LOG_INF("Endpoint changed: %d", current_endpoint); + } return 0; } + +ZMK_LISTENER(endpoint_listener, endpoint_listener); +#if IS_ENABLED(CONFIG_USB) +ZMK_SUBSCRIPTION(endpoint_listener, usb_conn_state_changed); +#endif +// TODO: add BLE state subscription \ No newline at end of file diff --git a/app/src/events/usb_conn_state_changed.c b/app/src/events/usb_conn_state_changed.c new file mode 100644 index 00000000..d845f6d7 --- /dev/null +++ b/app/src/events/usb_conn_state_changed.c @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include + +ZMK_EVENT_IMPL(usb_conn_state_changed); \ No newline at end of file diff --git a/app/src/power.c b/app/src/power.c index 73b3f123..bad54d28 100644 --- a/app/src/power.c +++ b/app/src/power.c @@ -23,14 +23,7 @@ static u32_t power_last_uptime; bool is_usb_power_present() { #ifdef CONFIG_USB - enum usb_dc_status_code usb_status = zmk_usb_get_status(); - switch (usb_status) { - case USB_DC_DISCONNECTED: - case USB_DC_UNKNOWN: - return false; - default: - return true; - } + return zmk_usb_is_powered(); #else return false; #endif /* CONFIG_USB */ diff --git a/app/src/usb.c b/app/src/usb.c index 434b3d4d..d4bc2e41 100644 --- a/app/src/usb.c +++ b/app/src/usb.c @@ -13,6 +13,8 @@ #include #include +#include +#include LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); @@ -53,9 +55,34 @@ int zmk_usb_hid_send_report(const u8_t *report, size_t len) { #endif /* CONFIG_ZMK_USB */ +static void raise_usb_status_changed_event() { + struct usb_conn_state_changed *ev = new_usb_conn_state_changed(); + ev->conn_state = zmk_usb_get_conn_state(); + + ZMK_EVENT_RAISE(ev); +} + enum usb_dc_status_code zmk_usb_get_status() { return usb_status; } -void usb_status_cb(enum usb_dc_status_code status, const u8_t *params) { usb_status = status; }; +enum zmk_usb_conn_state zmk_usb_get_conn_state() { + switch (usb_status) { + case USB_DC_DISCONNECTED: + case USB_DC_UNKNOWN: + return ZMK_USB_CONN_NONE; + + case USB_DC_ERROR: + case USB_DC_RESET: + return ZMK_USB_CONN_POWERED; + + default: + return ZMK_USB_CONN_HID; + } +} + +void usb_status_cb(enum usb_dc_status_code status, const u8_t *params) { + usb_status = status; + raise_usb_status_changed_event(); +}; static int zmk_usb_init(struct device *_arg) { int usb_enable_ret; From 8f666cecc9717b3fbbe2f5f34375b6a45b8965fd Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Sun, 11 Oct 2020 18:38:39 -0500 Subject: [PATCH 2/7] feat(endpoints): clear HID report on endpoint change This prevents stuck keys when switching endpoints by clearing everything in the HID report and sending one last report before switching to the new endpoint. --- app/include/zmk/hid.h | 2 ++ app/src/endpoints.c | 12 +++++++++++- app/src/hid.c | 4 ++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/app/include/zmk/hid.h b/app/include/zmk/hid.h index 744de98e..04b12e15 100644 --- a/app/include/zmk/hid.h +++ b/app/include/zmk/hid.h @@ -165,9 +165,11 @@ int zmk_hid_register_mods(zmk_mod_flags modifiers); int zmk_hid_unregister_mods(zmk_mod_flags modifiers); int zmk_hid_keypad_press(zmk_key key); int zmk_hid_keypad_release(zmk_key key); +void zmk_hid_keypad_clear(); int zmk_hid_consumer_press(zmk_key key); int zmk_hid_consumer_release(zmk_key key); +void zmk_hid_consumer_clear(); struct zmk_hid_keypad_report *zmk_hid_get_keypad_report(); struct zmk_hid_consumer_report *zmk_hid_get_consumer_report(); diff --git a/app/src/endpoints.c b/app/src/endpoints.c index 4f56aa5c..3acaba64 100644 --- a/app/src/endpoints.c +++ b/app/src/endpoints.c @@ -126,11 +126,21 @@ static enum endpoint get_selected_endpoint() { return ENDPOINT_USB; } +static void disconnect_current_endpoint() { + zmk_hid_keypad_clear(); + zmk_hid_consumer_clear(); + + zmk_endpoints_send_report(USAGE_KEYPAD); + zmk_endpoints_send_report(USAGE_CONSUMER); +} + static int endpoint_listener(const struct zmk_event_header *eh) { enum endpoint new_endpoint = get_selected_endpoint(); if (new_endpoint != current_endpoint) { - // TODO: send null report on previous endpoint + /* Cancel all current keypresses so keys don't stay held on the old endpoint. */ + disconnect_current_endpoint(); + current_endpoint = new_endpoint; LOG_INF("Endpoint changed: %d", current_endpoint); } diff --git a/app/src/hid.c b/app/src/hid.c index f80906cc..8f6c388d 100644 --- a/app/src/hid.c +++ b/app/src/hid.c @@ -94,6 +94,8 @@ int zmk_hid_keypad_release(zmk_key code) { return 0; }; +void zmk_hid_keypad_clear() { memset(&kp_report.body, 0, sizeof(kp_report.body)); } + int zmk_hid_consumer_press(zmk_key code) { TOGGLE_CONSUMER(0U, code); return 0; @@ -104,6 +106,8 @@ int zmk_hid_consumer_release(zmk_key code) { return 0; }; +void zmk_hid_consumer_clear() { memset(&consumer_report.body, 0, sizeof(consumer_report.body)); } + struct zmk_hid_keypad_report *zmk_hid_get_keypad_report() { return &kp_report; } From b538e605321791568aa25f0bd534ebcb30da92c2 Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Sat, 24 Oct 2020 13:39:02 -0500 Subject: [PATCH 3/7] feat(endpoints): update on BLE profile change Added zmk_ble_active_profile_is_connected() to allow code outside ble.c to check the status of the active profile, and changed the ble_active_profile_changed event to also notify when the active profile connects or disconnects. Changed endpoint selection to to also update when the active profile changes, connects, or disconnects. --- app/include/zmk/ble.h | 1 + app/src/ble.c | 26 +++++++++++++++++++++++--- app/src/endpoints.c | 24 ++++++++++++++++++------ 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/app/include/zmk/ble.h b/app/include/zmk/ble.h index 1cf71a77..56980c69 100644 --- a/app/include/zmk/ble.h +++ b/app/include/zmk/ble.h @@ -15,6 +15,7 @@ int zmk_ble_prof_prev(); int zmk_ble_prof_select(u8_t index); bt_addr_le_t *zmk_ble_active_profile_addr(); +bool zmk_ble_active_profile_is_connected(); char *zmk_ble_active_profile_name(); int zmk_ble_unpair_all(); diff --git a/app/src/ble.c b/app/src/ble.c index 9090582c..a79f7237 100644 --- a/app/src/ble.c +++ b/app/src/ble.c @@ -94,6 +94,12 @@ static void raise_profile_changed_event() { ZMK_EVENT_RAISE(ev); } +static void raise_profile_changed_event_callback(struct k_work *work) { + raise_profile_changed_event(); +} + +K_WORK_DEFINE(raise_profile_changed_event_work, raise_profile_changed_event_callback); + static bool active_profile_is_open() { return !bt_addr_le_cmp(&profiles[active_profile].peer, BT_ADDR_LE_ANY); } @@ -111,7 +117,7 @@ void set_profile_address(u8_t index, const bt_addr_le_t *addr) { raise_profile_changed_event(); } -bool active_profile_is_connected() { +bool zmk_ble_active_profile_is_connected() { struct bt_conn *conn; bt_addr_le_t *addr = zmk_ble_active_profile_addr(); if (!bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) { @@ -163,9 +169,9 @@ int update_advertising() { struct bt_conn *conn; enum advertising_type desired_adv = ZMK_ADV_NONE; - if (active_profile_is_open() || !active_profile_is_connected()) { + if (active_profile_is_open() || !zmk_ble_active_profile_is_connected()) { desired_adv = ZMK_ADV_CONN; - } else if (!active_profile_is_connected()) { + } else if (!zmk_ble_active_profile_is_connected()) { desired_adv = ZMK_ADV_CONN; // Need to fix directed advertising for privacy centrals. See // https://github.com/zephyrproject-rtos/zephyr/pull/14984 char @@ -327,6 +333,10 @@ static int ble_profiles_handle_set(const char *name, size_t len, settings_read_c struct settings_handler profiles_handler = {.name = "ble", .h_set = ble_profiles_handle_set}; #endif /* IS_ENABLED(CONFIG_SETTINGS) */ +static bool is_conn_active_profile(const struct bt_conn *conn) { + return bt_addr_le_cmp(bt_conn_get_dst(conn), &profiles[active_profile].peer) == 0; +} + static void connected(struct bt_conn *conn, u8_t err) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); @@ -352,6 +362,11 @@ static void connected(struct bt_conn *conn, u8_t err) { } update_advertising(); + + if (is_conn_active_profile(conn)) { + LOG_DBG("Active profile connected"); + raise_profile_changed_event(); + } } static void disconnected(struct bt_conn *conn, u8_t reason) { @@ -364,6 +379,11 @@ static void disconnected(struct bt_conn *conn, u8_t reason) { // We need to do this in a work callback, otherwise the advertising update will still see the // connection for a profile as active, and not start advertising yet. k_work_submit(&update_advertising_work); + + if (is_conn_active_profile(conn)) { + LOG_DBG("Active profile disconnected"); + k_work_submit(&raise_profile_changed_event_work); + } } static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) { diff --git a/app/src/endpoints.c b/app/src/endpoints.c index 3acaba64..56204a47 100644 --- a/app/src/endpoints.c +++ b/app/src/endpoints.c @@ -4,11 +4,13 @@ * SPDX-License-Identifier: MIT */ +#include #include #include #include #include #include +#include #include #include @@ -19,8 +21,9 @@ enum endpoint { ENDPOINT_BLE, }; -static enum endpoint current_endpoint = - COND_CODE_1(IS_ENABLED(CONFIG_ZMK_BLE), (ENDPOINT_BLE), (ENDPOINT_USB)); +#define DEFAULT_ENDPOINT COND_CODE_1(IS_ENABLED(CONFIG_ZMK_BLE), (ENDPOINT_BLE), (ENDPOINT_USB)) + +static enum endpoint current_endpoint = DEFAULT_ENDPOINT; static int send_keypad_report() { struct zmk_hid_keypad_report *keypad_report = zmk_hid_get_keypad_report(); @@ -115,15 +118,22 @@ static bool is_ble_ready() { static enum endpoint get_selected_endpoint() { if (is_ble_ready()) { if (is_usb_ready()) { - LOG_DBG("Both endpoints ready. Selecting USB"); + LOG_DBG("Both endpoints are ready."); // TODO: add user setting to control this return ENDPOINT_USB; } + LOG_DBG("Only BLE is ready."); return ENDPOINT_BLE; } - return ENDPOINT_USB; + if (is_usb_ready()) { + LOG_DBG("Only USB is ready."); + return ENDPOINT_USB; + } + + LOG_DBG("No endpoints are ready."); + return DEFAULT_ENDPOINT; } static void disconnect_current_endpoint() { @@ -149,7 +159,9 @@ static int endpoint_listener(const struct zmk_event_header *eh) { } ZMK_LISTENER(endpoint_listener, endpoint_listener); -#if IS_ENABLED(CONFIG_USB) +#if IS_ENABLED(CONFIG_ZMK_USB) ZMK_SUBSCRIPTION(endpoint_listener, usb_conn_state_changed); #endif -// TODO: add BLE state subscription \ No newline at end of file +#if IS_ENABLED(CONFIG_ZMK_BLE) +ZMK_SUBSCRIPTION(endpoint_listener, ble_active_profile_changed); +#endif \ No newline at end of file From 600bba25f049b1fa161b2372b2a47762164c7fcd Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Sat, 24 Oct 2020 16:28:58 -0500 Subject: [PATCH 4/7] 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 --- app/CMakeLists.txt | 1 + app/dts/behaviors.dtsi | 1 + app/dts/behaviors/endpoints.dtsi | 9 ++ .../behaviors/zmk,behavior-endpoints.yaml | 10 ++ app/include/dt-bindings/zmk/endpoints.h | 13 ++ app/include/zmk/endpoints.h | 8 ++ app/src/behaviors/behavior_endpoints.c | 44 +++++++ app/src/endpoints.c | 112 +++++++++++++++--- docs/docs/behavior/endpoints.md | 59 +++++++++ docs/sidebars.js | 1 + 10 files changed, 239 insertions(+), 19 deletions(-) create mode 100644 app/dts/behaviors/endpoints.dtsi create mode 100644 app/dts/bindings/behaviors/zmk,behavior-endpoints.yaml create mode 100644 app/include/dt-bindings/zmk/endpoints.h create mode 100644 app/src/behaviors/behavior_endpoints.c create mode 100644 docs/docs/behavior/endpoints.md diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index bce21700..0c43b913 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 36c918cf..4a507619 100644 --- a/app/dts/behaviors.dtsi +++ b/app/dts/behaviors.dtsi @@ -10,3 +10,4 @@ #include #include #include +#include diff --git a/app/dts/behaviors/endpoints.dtsi b/app/dts/behaviors/endpoints.dtsi new file mode 100644 index 00000000..f6cb64c1 --- /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 00000000..fdd76bbd --- /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 00000000..3bba972a --- /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 aad6265b..aad688e7 100644 --- a/app/include/zmk/endpoints.h +++ b/app/include/zmk/endpoints.h @@ -9,4 +9,12 @@ #include #include +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 00000000..dd56fc11 --- /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 +#include +#include + +#include + +#include +#include + +#include +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 56204a47..0c795890 100644 --- a/app/src/endpoints.c +++ b/app/src/endpoints.c @@ -4,6 +4,9 @@ * SPDX-License-Identifier: MIT */ +#include +#include + #include #include #include @@ -16,21 +19,45 @@ #include 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); diff --git a/docs/docs/behavior/endpoints.md b/docs/docs/behavior/endpoints.md new file mode 100644 index 00000000..caedf3a6 --- /dev/null +++ b/docs/docs/behavior/endpoints.md @@ -0,0 +1,59 @@ +--- +title: Endpoint Behavior +sidebar_label: Endpoints +--- + +## Summary + +The endpoint behavior allows selecting whether keyboard input is sent to the +USB or bluetooth connection when both are connected. This allows connecting a +keyboard to USB for power but sending input to a different device over bluetooth. + +By default, keyboard input is sent to USB when both endpoints are connected. +Once you select a different endpoint, it will be remembered until you change it again. + +## Endpoints Command Defines + +Endpoints command defines are provided through the [`dt-bindings/zmk/endpoints.h`](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/endpoints.h) +header, which is added at the top of the keymap file: + +``` +#include +``` + +This allows you to reference the actions defined in this header: + +| Define | Action | Alias | +| --------------------- | ---------------------------------------------------- | --------- | +| `ENDPOINT_USB_CMD` | Send keyboard input to USB | `END_USB` | +| `ENDPOINT_BLE_CMD` | Send keyboard input to the current bluetooth profile | `END_BLE` | +| `ENDPOINT_TOGGLE_CMD` | Toggle between USB and BLE | `END_TOG` | + +## Endpoints Behavior + +The endpoints behavior changes the preferred endpoint on press. + +### Behavior Binding + +- Reference: `&end` +- Parameter #1: Command, e.g. `END_BLE` + +### Example: + +1. Behavior binding to prefer sending keyboard input to USB + + ``` + &end END_USB + ``` + +1. Behavior binding to prefer sending keyboard input to the current bluetooth profile + + ``` + &end END_BLE + ``` + +1. Behavior binding to toggle between preferring USB and BLE + + ``` + &end END_TOG + ``` diff --git a/docs/sidebars.js b/docs/sidebars.js index 54f6576b..334a35df 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -22,6 +22,7 @@ module.exports = { "behavior/mod-tap", "behavior/reset", "behavior/bluetooth", + "behavior/endpoints", "behavior/lighting", "behavior/power", ], From 2fe1fbb526d9190e478999f36adbcfcf4a8847b2 Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Tue, 27 Oct 2020 13:49:28 -0500 Subject: [PATCH 5/7] feat(endpoints): rename behavior to outputs "Outputs" is probably easier for most people to understand than "endpoints". --- app/CMakeLists.txt | 2 +- app/dts/behaviors.dtsi | 2 +- app/dts/behaviors/endpoints.dtsi | 9 --- app/dts/behaviors/outputs.dtsi | 9 +++ ...dpoints.yaml => zmk,behavior-outputs.yaml} | 4 +- app/include/dt-bindings/zmk/endpoints.h | 13 ---- app/include/dt-bindings/zmk/outputs.h | 13 ++++ ...ehavior_endpoints.c => behavior_outputs.c} | 20 +++---- docs/docs/behavior/endpoints.md | 59 ------------------- docs/docs/behavior/outputs.md | 59 +++++++++++++++++++ docs/sidebars.js | 2 +- 11 files changed, 96 insertions(+), 96 deletions(-) delete mode 100644 app/dts/behaviors/endpoints.dtsi create mode 100644 app/dts/behaviors/outputs.dtsi rename app/dts/bindings/behaviors/{zmk,behavior-endpoints.yaml => zmk,behavior-outputs.yaml} (58%) delete mode 100644 app/include/dt-bindings/zmk/endpoints.h create mode 100644 app/include/dt-bindings/zmk/outputs.h rename app/src/behaviors/{behavior_endpoints.c => behavior_outputs.c} (61%) delete mode 100644 docs/docs/behavior/endpoints.md create mode 100644 docs/docs/behavior/outputs.md diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 0c43b913..f76effc0 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -39,11 +39,11 @@ 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) target_sources(app PRIVATE src/behaviors/behavior_momentary_layer.c) + target_sources(app PRIVATE src/behaviors/behavior_outputs.c) target_sources(app PRIVATE src/behaviors/behavior_toggle_layer.c) target_sources(app PRIVATE src/behaviors/behavior_transparent.c) target_sources(app PRIVATE src/behaviors/behavior_none.c) diff --git a/app/dts/behaviors.dtsi b/app/dts/behaviors.dtsi index 4a507619..a120b84b 100644 --- a/app/dts/behaviors.dtsi +++ b/app/dts/behaviors.dtsi @@ -10,4 +10,4 @@ #include #include #include -#include +#include diff --git a/app/dts/behaviors/endpoints.dtsi b/app/dts/behaviors/endpoints.dtsi deleted file mode 100644 index f6cb64c1..00000000 --- a/app/dts/behaviors/endpoints.dtsi +++ /dev/null @@ -1,9 +0,0 @@ -/ { - behaviors { - end: behavior_endpoints { - compatible = "zmk,behavior-endpoints"; - label = "ENDPOINTS"; - #binding-cells = <1>; - }; - }; -}; diff --git a/app/dts/behaviors/outputs.dtsi b/app/dts/behaviors/outputs.dtsi new file mode 100644 index 00000000..a534cbf9 --- /dev/null +++ b/app/dts/behaviors/outputs.dtsi @@ -0,0 +1,9 @@ +/ { + behaviors { + out: behavior_outputs { + compatible = "zmk,behavior-outputs"; + label = "OUTPUTS"; + #binding-cells = <1>; + }; + }; +}; diff --git a/app/dts/bindings/behaviors/zmk,behavior-endpoints.yaml b/app/dts/bindings/behaviors/zmk,behavior-outputs.yaml similarity index 58% rename from app/dts/bindings/behaviors/zmk,behavior-endpoints.yaml rename to app/dts/bindings/behaviors/zmk,behavior-outputs.yaml index fdd76bbd..8bcefd94 100644 --- a/app/dts/bindings/behaviors/zmk,behavior-endpoints.yaml +++ b/app/dts/bindings/behaviors/zmk,behavior-outputs.yaml @@ -3,8 +3,8 @@ # SPDX-License-Identifier: MIT # -description: Endpoints Behavior +description: Output Selection Behavior -compatible: "zmk,behavior-endpoints" +compatible: "zmk,behavior-outputs" include: one_param.yaml diff --git a/app/include/dt-bindings/zmk/endpoints.h b/app/include/dt-bindings/zmk/endpoints.h deleted file mode 100644 index 3bba972a..00000000 --- a/app/include/dt-bindings/zmk/endpoints.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * 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/dt-bindings/zmk/outputs.h b/app/include/dt-bindings/zmk/outputs.h new file mode 100644 index 00000000..c9a34ae0 --- /dev/null +++ b/app/include/dt-bindings/zmk/outputs.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#define OUTPUT_TOGGLE_CMD 0 +#define OUTPUT_USB_CMD 1 +#define OUTPUT_BLE_CMD 2 + +#define OUT_TOG OUTPUT_TOGGLE_CMD +#define OUT_USB OUTPUT_USB_CMD +#define OUT_BLE OUTPUT_BLE_CMD \ No newline at end of file diff --git a/app/src/behaviors/behavior_endpoints.c b/app/src/behaviors/behavior_outputs.c similarity index 61% rename from app/src/behaviors/behavior_endpoints.c rename to app/src/behaviors/behavior_outputs.c index dd56fc11..0e7ac490 100644 --- a/app/src/behaviors/behavior_endpoints.c +++ b/app/src/behaviors/behavior_outputs.c @@ -4,13 +4,13 @@ * SPDX-License-Identifier: MIT */ -#define DT_DRV_COMPAT zmk_behavior_endpoints +#define DT_DRV_COMPAT zmk_behavior_outputs #include #include #include -#include +#include #include #include @@ -21,24 +21,24 @@ 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: + case OUTPUT_TOGGLE_CMD: return zmk_endpoints_toggle(); - case ENDPOINT_USB_CMD: + case OUTPUT_USB_CMD: return zmk_endpoints_select(ZMK_ENDPOINT_USB); - case ENDPOINT_BLE_CMD: + case OUTPUT_BLE_CMD: return zmk_endpoints_select(ZMK_ENDPOINT_BLE); default: - LOG_ERR("Unknown endpoints command: %d", binding->param1); + LOG_ERR("Unknown output command: %d", binding->param1); } return -ENOTSUP; } -static int behavior_ep_init(struct device *dev) { return 0; } +static int behavior_out_init(struct device *dev) { return 0; } -static const struct behavior_driver_api behavior_endpoints_driver_api = { +static const struct behavior_driver_api behavior_outputs_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); +DEVICE_AND_API_INIT(behavior_out, DT_INST_LABEL(0), behavior_out_init, NULL, NULL, APPLICATION, + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_outputs_driver_api); diff --git a/docs/docs/behavior/endpoints.md b/docs/docs/behavior/endpoints.md deleted file mode 100644 index caedf3a6..00000000 --- a/docs/docs/behavior/endpoints.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Endpoint Behavior -sidebar_label: Endpoints ---- - -## Summary - -The endpoint behavior allows selecting whether keyboard input is sent to the -USB or bluetooth connection when both are connected. This allows connecting a -keyboard to USB for power but sending input to a different device over bluetooth. - -By default, keyboard input is sent to USB when both endpoints are connected. -Once you select a different endpoint, it will be remembered until you change it again. - -## Endpoints Command Defines - -Endpoints command defines are provided through the [`dt-bindings/zmk/endpoints.h`](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/endpoints.h) -header, which is added at the top of the keymap file: - -``` -#include -``` - -This allows you to reference the actions defined in this header: - -| Define | Action | Alias | -| --------------------- | ---------------------------------------------------- | --------- | -| `ENDPOINT_USB_CMD` | Send keyboard input to USB | `END_USB` | -| `ENDPOINT_BLE_CMD` | Send keyboard input to the current bluetooth profile | `END_BLE` | -| `ENDPOINT_TOGGLE_CMD` | Toggle between USB and BLE | `END_TOG` | - -## Endpoints Behavior - -The endpoints behavior changes the preferred endpoint on press. - -### Behavior Binding - -- Reference: `&end` -- Parameter #1: Command, e.g. `END_BLE` - -### Example: - -1. Behavior binding to prefer sending keyboard input to USB - - ``` - &end END_USB - ``` - -1. Behavior binding to prefer sending keyboard input to the current bluetooth profile - - ``` - &end END_BLE - ``` - -1. Behavior binding to toggle between preferring USB and BLE - - ``` - &end END_TOG - ``` diff --git a/docs/docs/behavior/outputs.md b/docs/docs/behavior/outputs.md new file mode 100644 index 00000000..50afac9c --- /dev/null +++ b/docs/docs/behavior/outputs.md @@ -0,0 +1,59 @@ +--- +title: Output Selection Behavior +sidebar_label: Output Selection +--- + +## Summary + +The output behavior allows selecting whether keyboard output is sent to the +USB or bluetooth connection when both are connected. This allows connecting a +keyboard to USB for power but outputting to a different device over bluetooth. + +By default, output is sent to USB when both USB and BLE are connected. +Once you select a different output, it will be remembered until you change it again. + +## Output Command Defines + +Output command defines are provided through the [`dt-bindings/zmk/outputs.h`](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/outputs.h) +header, which is added at the top of the keymap file: + +``` +#include +``` + +This allows you to reference the actions defined in this header: + +| Define | Action | Alias | +| ------------------- | ----------------------------------------------- | --------- | +| `OUTPUT_USB_CMD` | Prefer sending to USB | `OUT_USB` | +| `OUTPUT_BLE_CMD` | Prefer sending to the current bluetooth profile | `OUT_BLE` | +| `OUTPUT_TOGGLE_CMD` | Toggle between USB and BLE | `OUT_TOG` | + +## Output Selection Behavior + +The output selection behavior changes the preferred output on press. + +### Behavior Binding + +- Reference: `&out` +- Parameter #1: Command, e.g. `OUT_BLE` + +### Example: + +1. Behavior binding to prefer sending keyboard output to USB + + ``` + &out OUT_USB + ``` + +1. Behavior binding to prefer sending keyboard output to the current bluetooth profile + + ``` + &out OUT_BLE + ``` + +1. Behavior binding to toggle between preferring USB and BLE + + ``` + &out OUT_TOG + ``` diff --git a/docs/sidebars.js b/docs/sidebars.js index 334a35df..c8dc79fc 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -22,7 +22,7 @@ module.exports = { "behavior/mod-tap", "behavior/reset", "behavior/bluetooth", - "behavior/endpoints", + "behavior/outputs", "behavior/lighting", "behavior/power", ], From 440d09fd45fa59de481837825d27635819ad1c37 Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Wed, 28 Oct 2020 18:10:47 -0500 Subject: [PATCH 6/7] feat(endpoints): simplify behavior constants --- app/include/dt-bindings/zmk/outputs.h | 10 +++------- app/src/behaviors/behavior_outputs.c | 6 +++--- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/app/include/dt-bindings/zmk/outputs.h b/app/include/dt-bindings/zmk/outputs.h index c9a34ae0..f24380f7 100644 --- a/app/include/dt-bindings/zmk/outputs.h +++ b/app/include/dt-bindings/zmk/outputs.h @@ -4,10 +4,6 @@ * SPDX-License-Identifier: MIT */ -#define OUTPUT_TOGGLE_CMD 0 -#define OUTPUT_USB_CMD 1 -#define OUTPUT_BLE_CMD 2 - -#define OUT_TOG OUTPUT_TOGGLE_CMD -#define OUT_USB OUTPUT_USB_CMD -#define OUT_BLE OUTPUT_BLE_CMD \ No newline at end of file +#define OUT_TOG 0 +#define OUT_USB 1 +#define OUT_BLE 2 \ No newline at end of file diff --git a/app/src/behaviors/behavior_outputs.c b/app/src/behaviors/behavior_outputs.c index 0e7ac490..e5182bd4 100644 --- a/app/src/behaviors/behavior_outputs.c +++ b/app/src/behaviors/behavior_outputs.c @@ -21,11 +21,11 @@ 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 OUTPUT_TOGGLE_CMD: + case OUT_TOG: return zmk_endpoints_toggle(); - case OUTPUT_USB_CMD: + case OUT_USB: return zmk_endpoints_select(ZMK_ENDPOINT_USB); - case OUTPUT_BLE_CMD: + case OUT_BLE: return zmk_endpoints_select(ZMK_ENDPOINT_BLE); default: LOG_ERR("Unknown output command: %d", binding->param1); From 821f0540711158985eb38b360b1f1b422408ca31 Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Wed, 28 Oct 2020 18:11:34 -0500 Subject: [PATCH 7/7] feat(endpoints): remove redundant connection check --- app/src/ble.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/ble.c b/app/src/ble.c index a79f7237..f3962ae0 100644 --- a/app/src/ble.c +++ b/app/src/ble.c @@ -169,7 +169,7 @@ int update_advertising() { struct bt_conn *conn; enum advertising_type desired_adv = ZMK_ADV_NONE; - if (active_profile_is_open() || !zmk_ble_active_profile_is_connected()) { + if (active_profile_is_open()) { desired_adv = ZMK_ADV_CONN; } else if (!zmk_ble_active_profile_is_connected()) { desired_adv = ZMK_ADV_CONN;