Skip to content

Commit

Permalink
feat(pointing): Release pressed keys on disconnect
Browse files Browse the repository at this point in the history
Match the behavior for key press release on split peripheral disconnect,
and track pressed input keys to release them as needed on disconnect.
  • Loading branch information
petejohanson committed Dec 18, 2024
1 parent cb867f9 commit 9b67c18
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 2 deletions.
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

0 comments on commit 9b67c18

Please sign in to comment.