diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index efa34905..ee3acbe5 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -91,5 +91,6 @@ target_sources(app PRIVATE src/workqueue.c) target_sources(app PRIVATE src/main.c) add_subdirectory(src/display/) +add_subdirectory(src/shell/) zephyr_cc_option(-Wfatal-errors) diff --git a/app/Kconfig b/app/Kconfig index 89a128b5..da1dd579 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -380,6 +380,8 @@ endmenu menu "Advanced" +rsource "src/shell/Kconfig" + menu "Initialization Priorities" if USB_DEVICE_STACK diff --git a/app/src/shell/CMakeLists.txt b/app/src/shell/CMakeLists.txt new file mode 100644 index 00000000..76ead89b --- /dev/null +++ b/app/src/shell/CMakeLists.txt @@ -0,0 +1 @@ +target_sources_ifdef(CONFIG_ZMK_SHELL_KEY_POSITIONS app PRIVATE key_positions.c) \ No newline at end of file diff --git a/app/src/shell/Kconfig b/app/src/shell/Kconfig new file mode 100644 index 00000000..6d242235 --- /dev/null +++ b/app/src/shell/Kconfig @@ -0,0 +1,8 @@ +menu "Shell" + +config ZMK_SHELL_KEY_POSITIONS + bool "Key Position commands" + default y if !ZMK_SPLIT || ZMK_SPLIT_ROLE_CENTRAL + depends on SHELL + +endmenu diff --git a/app/src/shell/key_positions.c b/app/src/shell/key_positions.c new file mode 100644 index 00000000..12277fa4 --- /dev/null +++ b/app/src/shell/key_positions.c @@ -0,0 +1,80 @@ + +#include +#include +#include +#include +#include + +#define HELP_NONE "[key_position]" + +static int parse_key_position(const struct shell *shell, char *pos_str) { + int position; + char *endptr; + + position = strtoul(pos_str, &endptr, 10); + + if (endptr == pos_str) { + shell_error(shell, "Enter an integer key position"); + return -EINVAL; + } + + return position; +} + +static int parse_and_raise(const struct shell *shell, char *pos_str, bool pressed) { + int position = parse_key_position(shell, pos_str); + + if (position < 0) { + return position; + } + + ZMK_EVENT_RAISE(new_zmk_position_state_changed( + (struct zmk_position_state_changed){.source = ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL, + .state = pressed, + .position = position, + .timestamp = k_uptime_get()})); + + return position; +} + +static int cmd_key_tap(const struct shell *shell, size_t argc, char **argv) { + if (argc != 2) { + return -EINVAL; + } + + parse_and_raise(shell, argv[1], true); + + k_sleep(K_MSEC(50)); + + parse_and_raise(shell, argv[1], false); + + return 0; +}; + +static int cmd_key_press(const struct shell *shell, size_t argc, char **argv) { + if (argc != 2) { + return -EINVAL; + } + + parse_and_raise(shell, argv[1], true); + + return 0; +}; + +static int cmd_key_release(const struct shell *shell, size_t argc, char **argv) { + if (argc != 2) { + return -EINVAL; + } + + parse_and_raise(shell, argv[1], false); + + return 0; +}; + +SHELL_STATIC_SUBCMD_SET_CREATE(sub_key, SHELL_CMD(tap, NULL, HELP_NONE, cmd_key_tap), + SHELL_CMD(press, NULL, HELP_NONE, cmd_key_press), + SHELL_CMD(release, NULL, HELP_NONE, cmd_key_release), + SHELL_SUBCMD_SET_END /* Array terminated. */ +); + +SHELL_CMD_REGISTER(key, &sub_key, "Key commands", NULL); \ No newline at end of file