aboutsummaryrefslogtreecommitdiffhomepage
path: root/app/src/physical_layouts.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/physical_layouts.c')
-rw-r--r--app/src/physical_layouts.c37
1 files changed, 28 insertions, 9 deletions
diff --git a/app/src/physical_layouts.c b/app/src/physical_layouts.c
index 16b13e710c..00cfa29e78 100644
--- a/app/src/physical_layouts.c
+++ b/app/src/physical_layouts.c
@@ -72,9 +72,17 @@ struct position_map_entry {
const uint32_t positions[ZMK_POS_MAP_LEN];
};
+#define ZMK_POS_MAP_LEN_CHECK(node_id) \
+ BUILD_ASSERT(ZMK_POS_MAP_LEN == DT_PROP_LEN(node_id, positions), \
+ "Position maps must all have the same number of entries")
+
+DT_FOREACH_CHILD_SEP(DT_INST(0, POS_MAP_COMPAT), ZMK_POS_MAP_LEN_CHECK, (;));
+
#define ZMK_POS_MAP_ENTRY(node_id) \
{ \
- .layout = &_CONCAT(_zmk_physical_layout_, DT_PHANDLE(node_id, physical_layout)), \
+ .layout = COND_CODE_1( \
+ DT_HAS_COMPAT_STATUS_OKAY(DT_PHANDLE(node_id, physical_layout)), \
+ (&_CONCAT(_zmk_physical_layout_, DT_PHANDLE(node_id, physical_layout))), (NULL)), \
.positions = DT_PROP(node_id, positions), \
}
@@ -275,13 +283,15 @@ int zmk_physical_layouts_save_selected(void) {
int zmk_physical_layouts_revert_selected(void) { return zmk_physical_layouts_select_initial(); }
-int zmk_physical_layouts_get_position_map(uint8_t source, uint8_t dest, uint32_t *map) {
+int zmk_physical_layouts_get_position_map(uint8_t source, uint8_t dest, size_t map_size,
+ uint32_t map[map_size]) {
if (source >= ARRAY_SIZE(layouts) || dest >= ARRAY_SIZE(layouts)) {
return -EINVAL;
}
const struct zmk_physical_layout *src_layout = layouts[source];
const struct zmk_physical_layout *dest_layout = layouts[dest];
+ int max_kp = dest_layout->keys_len;
#if HAVE_POS_MAP
const struct position_map_entry *src_pos_map = NULL;
@@ -296,11 +306,24 @@ int zmk_physical_layouts_get_position_map(uint8_t source, uint8_t dest, uint32_t
dest_pos_map = &positions_maps[pm];
}
}
+
+ // Maps can place items "off the end" of other layouts so they are
+ // preserved but not visible, so adjust our max here if that is being used.
+ if (src_pos_map && dest_pos_map) {
+ for (int mp = 0; mp < ZMK_POS_MAP_LEN; mp++) {
+ max_kp =
+ MAX(max_kp, MAX(src_pos_map->positions[mp] + 1, dest_pos_map->positions[mp] + 1));
+ }
+ }
#endif
- memset(map, UINT32_MAX, dest_layout->keys_len);
+ if (map_size < max_kp) {
+ return -EINVAL;
+ }
+
+ memset(map, UINT32_MAX, map_size);
- for (int b = 0; b < dest_layout->keys_len; b++) {
+ for (int b = 0; b < max_kp; b++) {
bool found = false;
#if HAVE_POS_MAP
@@ -329,13 +352,9 @@ int zmk_physical_layouts_get_position_map(uint8_t source, uint8_t dest, uint32_t
}
}
#endif
-
- if (!found || map[b] >= src_layout->keys_len) {
- map[b] = UINT32_MAX;
- }
}
- return dest_layout->keys_len;
+ return max_kp;
}
#if IS_ENABLED(CONFIG_SETTINGS)