From 1d369ffa73ae63af821d012b1c2ab4a07a5dc9c7 Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Sun, 11 Oct 2020 17:03:21 -0500 Subject: 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/src/endpoints.c | 140 +++++++++++++++++++++++++------- app/src/events/usb_conn_state_changed.c | 10 +++ app/src/power.c | 9 +- app/src/usb.c | 29 ++++++- 4 files changed, 151 insertions(+), 37 deletions(-) create mode 100644 app/src/events/usb_conn_state_changed.c (limited to 'app/src') diff --git a/app/src/endpoints.c b/app/src/endpoints.c index 79d294e..4f56aa5 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 0000000..d845f6d --- /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 73b3f12..bad54d2 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 434b3d4..d4bc2e4 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; -- cgit v1.2.3 From 8f666cecc9717b3fbbe2f5f34375b6a45b8965fd Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Sun, 11 Oct 2020 18:38:39 -0500 Subject: 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/src/endpoints.c | 12 +++++++++++- app/src/hid.c | 4 ++++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'app/src') diff --git a/app/src/endpoints.c b/app/src/endpoints.c index 4f56aa5..3acaba6 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 f80906c..8f6c388 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; } -- cgit v1.2.3 From b538e605321791568aa25f0bd534ebcb30da92c2 Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Sat, 24 Oct 2020 13:39:02 -0500 Subject: 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/src/ble.c | 26 +++++++++++++++++++++++--- app/src/endpoints.c | 24 ++++++++++++++++++------ 2 files changed, 41 insertions(+), 9 deletions(-) (limited to 'app/src') diff --git a/app/src/ble.c b/app/src/ble.c index 9090582..a79f723 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 3acaba6..56204a4 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 -- cgit v1.2.3 From 600bba25f049b1fa161b2372b2a47762164c7fcd Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Sat, 24 Oct 2020 16:28:58 -0500 Subject: 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/src/behaviors/behavior_endpoints.c | 44 +++++++++++++ app/src/endpoints.c | 112 +++++++++++++++++++++++++++------ 2 files changed, 137 insertions(+), 19 deletions(-) create mode 100644 app/src/behaviors/behavior_endpoints.c (limited to 'app/src') 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 +#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 56204a4..0c79589 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); -- cgit v1.2.3 From 2fe1fbb526d9190e478999f36adbcfcf4a8847b2 Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Tue, 27 Oct 2020 13:49:28 -0500 Subject: feat(endpoints): rename behavior to outputs "Outputs" is probably easier for most people to understand than "endpoints". --- app/src/behaviors/behavior_endpoints.c | 44 ---------------------------------- app/src/behaviors/behavior_outputs.c | 44 ++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 44 deletions(-) delete mode 100644 app/src/behaviors/behavior_endpoints.c create mode 100644 app/src/behaviors/behavior_outputs.c (limited to 'app/src') diff --git a/app/src/behaviors/behavior_endpoints.c b/app/src/behaviors/behavior_endpoints.c deleted file mode 100644 index dd56fc1..0000000 --- a/app/src/behaviors/behavior_endpoints.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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/behaviors/behavior_outputs.c b/app/src/behaviors/behavior_outputs.c new file mode 100644 index 0000000..0e7ac49 --- /dev/null +++ b/app/src/behaviors/behavior_outputs.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#define DT_DRV_COMPAT zmk_behavior_outputs + +#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 OUTPUT_TOGGLE_CMD: + return zmk_endpoints_toggle(); + case OUTPUT_USB_CMD: + return zmk_endpoints_select(ZMK_ENDPOINT_USB); + case OUTPUT_BLE_CMD: + return zmk_endpoints_select(ZMK_ENDPOINT_BLE); + default: + LOG_ERR("Unknown output command: %d", binding->param1); + } + + return -ENOTSUP; +} + +static int behavior_out_init(struct device *dev) { return 0; } + +static const struct behavior_driver_api behavior_outputs_driver_api = { + .binding_pressed = on_keymap_binding_pressed, +}; + +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); -- cgit v1.2.3 From 440d09fd45fa59de481837825d27635819ad1c37 Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Wed, 28 Oct 2020 18:10:47 -0500 Subject: feat(endpoints): simplify behavior constants --- app/src/behaviors/behavior_outputs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app/src') diff --git a/app/src/behaviors/behavior_outputs.c b/app/src/behaviors/behavior_outputs.c index 0e7ac49..e5182bd 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); -- cgit v1.2.3 From 821f0540711158985eb38b360b1f1b422408ca31 Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Wed, 28 Oct 2020 18:11:34 -0500 Subject: feat(endpoints): remove redundant connection check --- app/src/ble.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/src') diff --git a/app/src/ble.c b/app/src/ble.c index a79f723..f3962ae 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; -- cgit v1.2.3