Skip to content

Commit ecac94d

Browse files
committed
fix: Cleanups of sideband and direct kscan from review.
* Add dedicated init priority for the sideband kscan. * Refactor sideband code for clarity. * Tweaks to direct kscan for clarity. * Make sideband behavior row optional for brevity. * Allow overriding ZMK Uno sideband behaviors.
1 parent 62cc467 commit ecac94d

File tree

7 files changed

+79
-62
lines changed

7 files changed

+79
-62
lines changed

app/Kconfig

+9
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,15 @@ config ZMK_KSCAN_SIDEBAND_BEHAVIORS
500500
depends on DT_HAS_ZMK_KSCAN_SIDEBAND_BEHAVIORS_ENABLED
501501
select KSCAN
502502

503+
if ZMK_KSCAN_SIDEBAND_BEHAVIORS
504+
505+
config ZMK_KSCAN_SIDEBAND_BEHAVIORS_INIT_PRIORITY
506+
int "Keyboard scan sideband behaviors driver init priority"
507+
# The default kscan init priority is 90, so be sure we are lower.
508+
default 95
509+
510+
endif # ZMK_KSCAN_SIDEBAND_BEHAVIORS
511+
503512
menu "Logging"
504513

505514
config ZMK_LOGGING_MINIMAL

app/boards/shields/zmk_uno/zmk_uno.keymap

+9-13
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,17 @@
1111
#include <dt-bindings/zmk/ext_power.h>
1212
#include <dt-bindings/zmk/rgb.h>
1313

14-
// Uncomment the following block if using the "Direct Wire" jumper to switch the matrix to a direct wire.
14+
// Uncomment the following lines if using the "Direct Wire" jumper to switch the matrix to a direct wire.
1515

16-
/* :REMOVE ME
16+
// &kscan_direct { status = "okay"; };
17+
// &kscan_matrix { status = "disabled"; };
1718

18-
&kscan_direct { status = "okay"; };
19-
&kscan_matrix { status = "disabled"; };
20-
21-
/ {
22-
chosen {
23-
zmk,matrix-transform = &direct_matrix_transform;
24-
zmk,kscan = &kscan_direct;
25-
};
26-
};
27-
28-
REMOVE ME: */
19+
// / {
20+
// chosen {
21+
// zmk,matrix-transform = &direct_matrix_transform;
22+
// zmk,kscan = &kscan_direct;
23+
// };
24+
// };
2925

3026
/ {
3127
keymap {

app/boards/shields/zmk_uno/zmk_uno.overlay

+3-6
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,17 @@
4040
compatible = "zmk,kscan-sideband-behaviors";
4141
kscan = <&kscan_sp3t_toggle>;
4242

43-
usb {
44-
row = <0>;
43+
first_toggle_sideband: first_toggle_sideband {
4544
column = <0>;
4645
bindings = <&out OUT_USB>;
4746
};
4847

49-
ble_zero {
50-
row = <0>;
48+
second_toggle_sideband: second_toggle_sideband {
5149
column = <1>;
5250
bindings = <&ble_zero>;
5351
};
5452

55-
ble_one {
56-
row = <0>;
53+
third_toggle_sideband: third_toggle_sideband {
5754
column = <2>;
5855
bindings = <&ble_one>;
5956
};

app/boards/shields/zmk_uno/zmk_uno_split.keymap

+9-12
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,18 @@
1212
#include <dt-bindings/zmk/outputs.h>
1313
#include <dt-bindings/zmk/rgb.h>
1414

15-
// Uncomment the following block if using the "Direct Wire" jumper to switch the matrix to a direct wire.
15+
// Uncomment the following lines if using the "Direct Wire" jumper to switch the matrix to a direct wire.
1616

17-
/* :REMOVE ME
1817

19-
&kscan_direct { status = "okay"; };
20-
&kscan_matrix { status = "disabled"; };
18+
// &kscan_direct { status = "okay"; };
19+
// &kscan_matrix { status = "disabled"; };
2120

22-
/ {
23-
chosen {
24-
zmk,matrix-transform = &split_direct_matrix_transform;
25-
zmk,kscan = &kscan_direct_comp;
26-
};
27-
};
28-
29-
REMOVE ME: */
21+
// / {
22+
// chosen {
23+
// zmk,matrix-transform = &split_direct_matrix_transform;
24+
// zmk,kscan = &kscan_direct_comp;
25+
// };
26+
// };
3027

3128
/ {
3229

app/dts/bindings/kscan/zmk,kscan-sideband-behaviors.yaml

+4-3
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
# SPDX-License-Identifier: MIT
33

44
description: |
5-
kscan sideband behavior runner. Only basic system behavior should be used,
6-
since no keymap processing occurs when using them.
5+
kscan sideband behavior runner. Only basic system behaviors should be used,
6+
since no keymap processing occurs when using them. Primarily, that means avoiding
7+
using tap-holds, sticky keys, etc. as sideband behaviors.
78
89
compatible: "zmk,kscan-sideband-behaviors"
910

@@ -20,7 +21,7 @@ child-binding:
2021
properties:
2122
row:
2223
type: int
23-
required: true
24+
default: 0
2425
column:
2526
type: int
2627
required: true

app/module/drivers/kscan/kscan_gpio_direct.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
4646
COND_CODE_1(DT_INST_NODE_HAS_PROP(n, input_gpios), (DT_INST_PROP_LEN(n, input_gpios)), \
4747
(DT_INST_PROP_LEN(n, input_keys)))
4848

49-
#define KSCAN_DIRECT_INPUT_CFG_INIT(idx, inst_idx) \
49+
#define KSCAN_GPIO_DIRECT_INPUT_CFG_INIT(idx, inst_idx) \
5050
KSCAN_GPIO_GET_BY_IDX(DT_DRV_INST(inst_idx), input_gpios, idx)
5151
#define KSCAN_KEY_DIRECT_INPUT_CFG_INIT(idx, inst_idx) \
5252
KSCAN_GPIO_GET_BY_IDX(DT_INST_PROP_BY_IDX(inst_idx, input_keys, idx), gpios, 0)
@@ -353,7 +353,7 @@ static const struct kscan_driver_api kscan_direct_api = {
353353
\
354354
static struct kscan_gpio kscan_direct_inputs_##n[] = { \
355355
COND_CODE_1(DT_INST_NODE_HAS_PROP(n, input_gpios), \
356-
(LISTIFY(INST_INPUTS_LEN(n), KSCAN_DIRECT_INPUT_CFG_INIT, (, ), n)), \
356+
(LISTIFY(INST_INPUTS_LEN(n), KSCAN_GPIO_DIRECT_INPUT_CFG_INIT, (, ), n)), \
357357
(LISTIFY(INST_INPUTS_LEN(n), KSCAN_KEY_DIRECT_INPUT_CFG_INIT, (, ), n)))}; \
358358
\
359359
static struct zmk_debounce_state kscan_direct_state_##n[INST_INPUTS_LEN(n)]; \

app/src/kscan_sideband_behaviors.c

+43-26
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
2020

2121
struct ksbb_entry {
22+
struct zmk_behavior_binding binding;
2223
uint8_t row;
2324
uint8_t column;
24-
struct zmk_behavior_binding binding;
2525
};
2626

2727
struct ksbb_config {
@@ -39,32 +39,53 @@ struct ksbb_data {
3939

4040
// The kscan callback has no context with it, so we keep a static array of all possible
4141
// KSBBs to check when a kscan callback from the "wrapped" inner kscan fires.
42-
static const struct device *ksbbs[DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT)] = {
43-
DT_INST_FOREACH_STATUS_OKAY(GET_KSBB_DEV)};
42+
static const struct device *ksbbs[] = {DT_INST_FOREACH_STATUS_OKAY(GET_KSBB_DEV)};
4443

45-
void ksbb_inner_kscan_callback(const struct device *dev, uint32_t row, uint32_t column,
46-
bool pressed) {
44+
int find_ksbb_for_inner(const struct device *inner_dev, const struct device **ksbb_dev) {
4745
for (int i = 0; i < ARRAY_SIZE(ksbbs); i++) {
4846
const struct device *ksbb = ksbbs[i];
4947
const struct ksbb_config *cfg = ksbb->config;
50-
struct ksbb_data *data = ksbb->data;
5148

52-
if (cfg->kscan != dev) {
53-
continue;
49+
if (cfg->kscan == inner_dev) {
50+
*ksbb_dev = ksbb;
51+
return 0;
52+
}
53+
}
54+
55+
return -ENODEV;
56+
}
57+
58+
int find_sideband_behavior(const struct device *dev, uint32_t row, uint32_t column,
59+
struct ksbb_entry **entry) {
60+
const struct ksbb_config *cfg = dev->config;
61+
62+
for (int e = 0; e < cfg->entries_len; e++) {
63+
struct ksbb_entry *candidate = &cfg->entries[e];
64+
65+
if (candidate->row == row && candidate->column == column) {
66+
*entry = candidate;
67+
return 0;
5468
}
69+
}
5570

56-
for (int e = 0; e < cfg->entries_len; e++) {
57-
struct ksbb_entry *entry = &cfg->entries[e];
58-
if (entry->row == row && entry->column == column) {
59-
struct zmk_behavior_binding_event event = {.position = INT32_MAX,
60-
.timestamp = k_uptime_get()};
61-
62-
if (pressed) {
63-
behavior_keymap_binding_pressed(&entry->binding, event);
64-
} else {
65-
behavior_keymap_binding_released(&entry->binding, event);
66-
}
67-
return;
71+
return -ENODEV;
72+
}
73+
74+
void ksbb_inner_kscan_callback(const struct device *dev, uint32_t row, uint32_t column,
75+
bool pressed) {
76+
struct ksbb_entry *entry = NULL;
77+
const struct device *ksbb = NULL;
78+
79+
if (find_ksbb_for_inner(dev, &ksbb) >= 0) {
80+
struct ksbb_data *data = ksbb->data;
81+
if (find_sideband_behavior(ksbb, row, column, &entry) >= 0) {
82+
struct zmk_behavior_binding_event event = {.position = INT32_MAX,
83+
.timestamp = k_uptime_get()};
84+
85+
if (pressed) {
86+
behavior_keymap_binding_pressed(&entry->binding, event);
87+
} else {
88+
behavior_keymap_binding_released(&entry->binding, event);
6889
}
6990
}
7091

@@ -78,10 +99,6 @@ static int ksbb_configure(const struct device *dev, kscan_callback_t callback) {
7899
const struct ksbb_config *cfg = dev->config;
79100
struct ksbb_data *data = dev->data;
80101

81-
if (!callback) {
82-
return -EINVAL;
83-
}
84-
85102
data->callback = callback;
86103

87104
#if IS_ENABLED(CONFIG_PM_DEVICE)
@@ -161,7 +178,7 @@ static int ksbb_pm_action(const struct device *dev, enum pm_device_action action
161178
struct ksbb_data ksbb_data_##n = {}; \
162179
PM_DEVICE_DT_INST_DEFINE(n, ksbb_pm_action); \
163180
DEVICE_DT_INST_DEFINE(n, ksbb_init, PM_DEVICE_DT_INST_GET(n), &ksbb_data_##n, \
164-
&ksbb_config_##n, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
165-
&ksbb_api);
181+
&ksbb_config_##n, POST_KERNEL, \
182+
CONFIG_ZMK_KSCAN_SIDEBAND_BEHAVIORS_INIT_PRIORITY, &ksbb_api);
166183

167184
DT_INST_FOREACH_STATUS_OKAY(KSBB_INST)

0 commit comments

Comments
 (0)