From 9b67c18b5f3b9502f39546b87fecce04937d7760 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Tue, 17 Dec 2024 18:24:28 -0700 Subject: [PATCH] feat(pointing): Release pressed keys on disconnect Match the behavior for key press release on split peripheral disconnect, and track pressed input keys to release them as needed on disconnect. --- app/include/zmk/pointing/input_split.h | 3 +- app/src/pointing/Kconfig | 5 +++ app/src/pointing/input_split.c | 60 ++++++++++++++++++++++++++ app/src/split/bluetooth/central.c | 2 +- 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/app/include/zmk/pointing/input_split.h b/app/include/zmk/pointing/input_split.h index 812035477e2..235ea4954b1 100644 --- a/app/include/zmk/pointing/input_split.h +++ b/app/include/zmk/pointing/input_split.h @@ -7,4 +7,5 @@ #pragma once int zmk_input_split_report_peripheral_event(uint8_t reg, uint8_t type, uint16_t code, int32_t value, - bool sync); \ No newline at end of file + bool sync); +int zmk_input_split_peripheral_disconnected(uint8_t reg); \ No newline at end of file diff --git a/app/src/pointing/Kconfig b/app/src/pointing/Kconfig index b4051e1fcef..9331fd5e7bb 100644 --- a/app/src/pointing/Kconfig +++ b/app/src/pointing/Kconfig @@ -73,6 +73,11 @@ config ZMK_INPUT_SPLIT_INIT_PRIORITY int "Input Split initialization priority" default INPUT_INIT_PRIORITY + +config ZMK_INPUT_SPLIT_MAX_TRACKED_KEYS + int "Input Split max tracked keys to release on peripheral disconnect" + default 5 + endif # ZMK_INPUT_SPLIT endif # ZMK_POINTING diff --git a/app/src/pointing/input_split.c b/app/src/pointing/input_split.c index 55a84ea4624..f4106c8f5d0 100644 --- a/app/src/pointing/input_split.c +++ b/app/src/pointing/input_split.c @@ -26,11 +26,40 @@ struct zis_entry { static const struct zis_entry proxy_inputs[] = {DT_INST_FOREACH_STATUS_OKAY(ZIS_ENTRY)}; +#define PLUS_ONE(n) +1 + +static uint16_t proxy_active_keys[(0 DT_INST_FOREACH_STATUS_OKAY(PLUS_ONE))] + [CONFIG_ZMK_INPUT_SPLIT_MAX_TRACKED_KEYS]; + +static int replace_active_key(size_t input, uint16_t find, uint16_t replace) { + for (size_t k = 0; k < CONFIG_ZMK_INPUT_SPLIT_MAX_TRACKED_KEYS; k++) { + if (proxy_active_keys[input][k] == find) { + proxy_active_keys[input][k] = replace; + return 0; + } + } + + return -ENODEV; +} + int zmk_input_split_report_peripheral_event(uint8_t reg, uint8_t type, uint16_t code, int32_t value, bool sync) { LOG_DBG("Got peripheral event for %d!", reg); for (size_t i = 0; i < ARRAY_SIZE(proxy_inputs); i++) { if (reg == proxy_inputs[i].reg) { + if (type == INPUT_EV_KEY) { + if (value) { + int ret = replace_active_key(i, 0, code); + if (ret < 0) { + LOG_WRN("Failed to track pressed key %d", ret); + } + } else { + int ret = replace_active_key(i, code, 0); + if (ret < 0) { + LOG_WRN("Failed to untrack released key %d", ret); + } + } + } return input_report(proxy_inputs[i].dev, type, code, value, sync, K_NO_WAIT); } } @@ -38,6 +67,37 @@ int zmk_input_split_report_peripheral_event(uint8_t reg, uint8_t type, uint16_t return -ENODEV; } +int zmk_input_split_peripheral_disconnected(uint8_t reg) { + for (size_t i = 0; i < ARRAY_SIZE(proxy_inputs); i++) { + if (reg == proxy_inputs[i].reg) { + uint16_t prev = 0; + for (size_t k = 0; k < CONFIG_ZMK_INPUT_SPLIT_MAX_TRACKED_KEYS; k++) { + if (proxy_active_keys[i][k] != 0) { + if (prev != 0) { + int ret = input_report(proxy_inputs[i].dev, INPUT_EV_KEY, prev, 0, false, + K_NO_WAIT); + if (ret < 0) { + LOG_WRN("Failed to report release event on disconnect (%d)", ret); + } + } + + prev = proxy_active_keys[i][k]; + proxy_active_keys[i][k] = 0; + } + } + + if (prev != 0) { + int ret = input_report(proxy_inputs[i].dev, INPUT_EV_KEY, prev, 0, true, K_NO_WAIT); + if (ret < 0) { + LOG_WRN("Failed to report release event on disconnect (%d)", ret); + } + } + } + } + + return -ENODEV; +} + #define ZIS_INST(n) \ DEVICE_DT_INST_DEFINE(n, NULL, NULL, NULL, NULL, POST_KERNEL, \ CONFIG_ZMK_INPUT_SPLIT_INIT_PRIORITY, NULL); diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index 4c354b36b16..f16884bbe0e 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -121,7 +121,7 @@ void release_peripheral_input_subs(struct bt_conn *conn) { for (size_t i = 0; i < ARRAY_SIZE(peripheral_input_slots); i++) { if (peripheral_input_slots[i].conn == conn) { peripheral_input_slots[i].conn = NULL; - // memset(&peripheral_input_slots[i], 0, sizeof(struct peripheral_input_slot)); + zmk_input_split_peripheral_disconnected(peripheral_input_slots[i].reg); } } }