Skip to content

Commit 24487bd

Browse files
authored
feat(pointing): Release pressed keys on disconnect (zmkfirmware#3204)
Match the behavior for key press release on split peripheral disconnect, and track pressed input keys to release them as needed on disconnect.
1 parent 88db5f3 commit 24487bd

7 files changed

Lines changed: 82 additions & 3 deletions

File tree

app/include/zmk/pointing/input_split.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@
77
#pragma once
88

99
int zmk_input_split_report_peripheral_event(uint8_t reg, uint8_t type, uint16_t code, int32_t value,
10-
bool sync);
10+
bool sync);
11+
int zmk_input_split_peripheral_disconnected(uint8_t reg);

app/src/pointing/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ config ZMK_INPUT_SPLIT_INIT_PRIORITY
7878
int "Input Split initialization priority"
7979
default INPUT_INIT_PRIORITY
8080

81+
82+
config ZMK_INPUT_SPLIT_MAX_TRACKED_KEYS
83+
int "Input Split max tracked keys to release on peripheral disconnect"
84+
default 5
85+
8186
endif # ZMK_INPUT_SPLIT
8287

8388
endif # ZMK_POINTING

app/src/pointing/input_split.c

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,80 @@ struct zis_entry {
2626

2727
static const struct zis_entry proxy_inputs[] = {DT_INST_FOREACH_STATUS_OKAY(ZIS_ENTRY)};
2828

29+
static uint16_t proxy_active_keys[DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT)]
30+
[CONFIG_ZMK_INPUT_SPLIT_MAX_TRACKED_KEYS];
31+
32+
static int replace_active_key(size_t input, uint16_t find, uint16_t replace) {
33+
for (size_t k = 0; k < CONFIG_ZMK_INPUT_SPLIT_MAX_TRACKED_KEYS; k++) {
34+
if (proxy_active_keys[input][k] == find) {
35+
proxy_active_keys[input][k] = replace;
36+
return 0;
37+
}
38+
}
39+
40+
return -ENODEV;
41+
}
42+
2943
int zmk_input_split_report_peripheral_event(uint8_t reg, uint8_t type, uint16_t code, int32_t value,
3044
bool sync) {
3145
LOG_DBG("Got peripheral event for %d!", reg);
3246
for (size_t i = 0; i < ARRAY_SIZE(proxy_inputs); i++) {
3347
if (reg == proxy_inputs[i].reg) {
48+
if (type == INPUT_EV_KEY) {
49+
uint16_t find, replace;
50+
51+
if (value) {
52+
find = 0;
53+
replace = code;
54+
} else {
55+
find = code;
56+
replace = 0;
57+
}
58+
59+
int ret = replace_active_key(i, find, replace);
60+
if (ret < 0) {
61+
LOG_WRN("Failed to %s key %d", value ? "track pressed" : "untrack released",
62+
ret);
63+
}
64+
}
3465
return input_report(proxy_inputs[i].dev, type, code, value, sync, K_NO_WAIT);
3566
}
3667
}
3768

3869
return -ENODEV;
3970
}
4071

72+
int zmk_input_split_peripheral_disconnected(uint8_t reg) {
73+
for (size_t i = 0; i < ARRAY_SIZE(proxy_inputs); i++) {
74+
if (reg == proxy_inputs[i].reg) {
75+
uint16_t prev = 0;
76+
for (size_t k = 0; k < CONFIG_ZMK_INPUT_SPLIT_MAX_TRACKED_KEYS; k++) {
77+
if (proxy_active_keys[i][k] != 0) {
78+
if (prev != 0) {
79+
int ret = input_report(proxy_inputs[i].dev, INPUT_EV_KEY, prev, 0, false,
80+
K_NO_WAIT);
81+
if (ret < 0) {
82+
LOG_WRN("Failed to report release event on disconnect (%d)", ret);
83+
}
84+
}
85+
86+
prev = proxy_active_keys[i][k];
87+
proxy_active_keys[i][k] = 0;
88+
}
89+
}
90+
91+
if (prev != 0) {
92+
int ret = input_report(proxy_inputs[i].dev, INPUT_EV_KEY, prev, 0, true, K_NO_WAIT);
93+
if (ret < 0) {
94+
LOG_WRN("Failed to report release event on disconnect (%d)", ret);
95+
}
96+
}
97+
}
98+
}
99+
100+
return -ENODEV;
101+
}
102+
41103
#define ZIS_INST(n) \
42104
DEVICE_DT_INST_DEFINE(n, NULL, NULL, NULL, NULL, POST_KERNEL, \
43105
CONFIG_ZMK_INPUT_SPLIT_INIT_PRIORITY, NULL);
@@ -78,4 +140,4 @@ int zmk_input_split_report_peripheral_event(uint8_t reg, uint8_t type, uint16_t
78140

79141
#endif
80142

81-
DT_INST_FOREACH_STATUS_OKAY(ZIS_INST)
143+
DT_INST_FOREACH_STATUS_OKAY(ZIS_INST)

app/src/split/bluetooth/central.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ void release_peripheral_input_subs(struct bt_conn *conn) {
122122
for (size_t i = 0; i < ARRAY_SIZE(peripheral_input_slots); i++) {
123123
if (peripheral_input_slots[i].conn == conn) {
124124
peripheral_input_slots[i].conn = NULL;
125-
// memset(&peripheral_input_slots[i], 0, sizeof(struct peripheral_input_slot));
125+
zmk_input_split_peripheral_disconnected(peripheral_input_slots[i].reg);
126126
}
127127
}
128128
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
s/^d_02: @[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9][0-9][0-9][0-9] .{19}/profile 0 /p
2+
s/^d_00: @[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9][0-9][0-9][0-9] .{19}.*zmk_hid_mouse_button_/mouse button /p

app/tests/ble/split/peripheral-input/peripheral.overlay

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
, <INPUT_EV_REL INPUT_REL_Y 100 1>
2222
, <INPUT_EV_REL INPUT_REL_X 40 0>
2323
, <INPUT_EV_REL INPUT_REL_Y 50 1>
24+
, <INPUT_EV_KEY INPUT_BTN_1 1 1>
2425
;
2526
exit-after;
2627
};

app/tests/ble/split/peripheral-input/snapshot.log

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,12 @@ profile 0 <dbg> ble_central: notify_func: payload
2424
profile 0 00 64 00 64 00 00 00 00 00 |.d.d.... .
2525
profile 0 <dbg> ble_central: notify_func: payload
2626
profile 0 00 28 00 32 00 00 00 00 00 |.(.2.... .
27+
mouse button press: Button 1 count 1
28+
mouse button press: Mouse buttons set to 0x02
29+
profile 0 <dbg> ble_central: notify_func: payload
30+
profile 0 02 00 00 00 00 00 00 00 00 |........ .
31+
mouse button release: Button 1 count: 0
32+
mouse button release: Button 1 released
33+
mouse button release: Mouse buttons set to 0x00
34+
profile 0 <dbg> ble_central: notify_func: payload
35+
profile 0 00 00 00 00 00 00 00 00 00 |........ .

0 commit comments

Comments
 (0)