Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(pointing): Release pressed keys on disconnect #2721

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/include/zmk/pointing/input_split.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
bool sync);
int zmk_input_split_peripheral_disconnected(uint8_t reg);
5 changes: 5 additions & 0 deletions app/src/pointing/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
60 changes: 60 additions & 0 deletions app/src/pointing/input_split.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,78 @@ 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);
}
}

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);
Expand Down
2 changes: 1 addition & 1 deletion app/src/split/bluetooth/central.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
Expand Down
Loading