From 79a564b206e079aa6b6ddedaaae53c7a259d706c Mon Sep 17 00:00:00 2001 From: Edward Hesketh Date: Tue, 20 Aug 2024 16:52:06 +0100 Subject: [PATCH] feat: switch from stdarg to void**, add tests for squirrel_key --- CMakeLists.txt | 4 ++ include/squirrel_key.h | 12 ++-- include/squirrel_quantum.h | 22 +++--- src/squirrel_quantum.c | 67 ++++++----------- tests/consumer_press_release.c | 14 ++-- tests/key.c | 88 +++++++++++++++++++++++ tests/keyboard_modifier_press_release.c | 36 ++++++---- tests/keyboard_press_release.c | 26 +++++-- tests/quantum_passthrough_press_release.c | 6 +- 9 files changed, 184 insertions(+), 91 deletions(-) create mode 100644 tests/key.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 78385be..4d867cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,10 @@ elseif(CMAKE_BUILD_TYPE STREQUAL "Testing") add_executable(consumer_press_release tests/consumer_press_release.c) target_link_libraries(consumer_press_release squirrel) add_test(NAME consumer_press_release COMMAND consumer_press_release) + + add_executable(key tests/key.c) + target_link_libraries(key squirrel) + add_test(NAME key COMMAND key) else() add_compile_options(-Os) # Enable size optimizations endif() diff --git a/include/squirrel_key.h b/include/squirrel_key.h index 0fa4ab8..974afb0 100644 --- a/include/squirrel_key.h +++ b/include/squirrel_key.h @@ -6,13 +6,13 @@ struct key { enum squirrel_error (*pressed)(struct key *, uint8_t layer, uint8_t key_index, int arg_count, - ...); // called when the key is pressed - void *pressed_arguments; // arguments to pass to pressed + void **args); // called when the key is pressed + void **pressed_arguments; // arguments to pass to pressed int pressed_argument_count; // the amount of arguments in pressed_arguments - enum squirrel_error (*released)(struct key *, uint8_t layer, - uint8_t key_index, int arg_count, - ...); // called when the key is released - void *released_arguments; // arguments to pass to released + enum squirrel_error (*released)( + struct key *, uint8_t layer, uint8_t key_index, int arg_count, + void **args); // called when the key is released + void **released_arguments; // arguments to pass to released int released_argument_count; // the amount of arguments in released_arguments bool is_pressed; // true if the key is currently pressed }; diff --git a/include/squirrel_quantum.h b/include/squirrel_quantum.h index 538ba97..6f86074 100644 --- a/include/squirrel_quantum.h +++ b/include/squirrel_quantum.h @@ -17,46 +17,50 @@ extern struct layer layers[17]; // key_nop does nothing (no operation) enum squirrel_error key_nop(struct key *key, uint8_t layer, uint8_t key_index, - int arg_count, ...); + int arg_count, void **args); // keyboard_press expects a single uint8 keycode enum squirrel_error keyboard_press(struct key *key, uint8_t layer, - uint8_t key_index, int arg_count, ...); + uint8_t key_index, int arg_count, + void **args); // keyboard_release expects a single uint8 keycode enum squirrel_error keyboard_release(struct key *key, uint8_t layer, - uint8_t key_index, int arg_count, ...); + uint8_t key_index, int arg_count, + void **args); // keyboard_modifier_press expects a single uint8 modifier enum squirrel_error keyboard_modifier_press(struct key *key, uint8_t layer, uint8_t key_index, int arg_count, - ...); + void **args); // keyboard_modifier_release expects a single uint8 modifier enum squirrel_error keyboard_modifier_release(struct key *key, uint8_t layer, uint8_t key_index, int arg_count, - ...); + void **args); // consumer_press expects a single uint16 consumer code. See // https://www.freebsddiary.org/APC/usb_hid_usages for all defined codes. enum squirrel_error consumer_press(struct key *key, uint8_t layer, - uint8_t key_index, int arg_count, ...); + uint8_t key_index, int arg_count, + void **args); // consumer_release expects a single uint16 consumer code. See // https://www.freebsddiary.org/APC/usb_hid_usages for all defined codes. enum squirrel_error consumer_release(struct key *key, uint8_t layer, - uint8_t key_index, int arg_count, ...); + uint8_t key_index, int arg_count, + void **args); // quantum_passthrough passes the press action to the highest active layer below // the current one. It expectes no extra args. enum squirrel_error quantum_passthrough_press(struct key *key, uint8_t layer, uint8_t key_index, int arg_count, - ...); + void **args); // quantum_passthrough_release passes the release action to the highest active // layer below the current one. It expectes no extra args. enum squirrel_error quantum_passthrough_release(struct key *key, uint8_t layer, uint8_t key_index, - int arg_count, ...); + int arg_count, void **args); #endif diff --git a/src/squirrel_quantum.c b/src/squirrel_quantum.c index 9b2e718..50bb604 100644 --- a/src/squirrel_quantum.c +++ b/src/squirrel_quantum.c @@ -3,120 +3,95 @@ #include "squirrel_consumer.h" #include "squirrel_key.h" #include "squirrel_keyboard.h" -#include #include struct layer layers[17]; enum squirrel_error key_nop(struct key *key, uint8_t layer, uint8_t key_index, - int arg_count, ...) { + int arg_count, void **args) { (void)key; (void)arg_count; + (void)args; return ERR_NONE; } enum squirrel_error keyboard_press(struct key *key, uint8_t layer, - uint8_t key_index, int arg_count, ...) { + uint8_t key_index, int arg_count, + void **args) { (void)layer; (void)key_index; - - va_list args; - va_start(args, arg_count); if (arg_count != 1) { return ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT; }; - uint8_t keycode = va_arg(args, int); - keyboard_activate_keycode(keycode); // squirrel_keyboard - va_end(args); + + keyboard_activate_keycode(*(uint8_t *)args[0]); // squirrel_keyboard return ERR_NONE; }; enum squirrel_error keyboard_release(struct key *key, uint8_t layer, - uint8_t key_index, int arg_count, ...) { + uint8_t key_index, int arg_count, + void **args) { (void)layer; (void)key_index; - - va_list args; - va_start(args, arg_count); if (arg_count != 1) { return ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT; }; - uint8_t keycode = va_arg(args, int); - keyboard_deactivate_keycode(keycode); // squirrel_keyboard - va_end(args); + keyboard_deactivate_keycode(*(uint8_t *)args[0]); // squirrel_keyboard return ERR_NONE; } enum squirrel_error keyboard_modifier_press(struct key *key, uint8_t layer, uint8_t key_index, int arg_count, - ...) { + void **args) { (void)layer; (void)key_index; - - va_list args; - va_start(args, arg_count); if (arg_count != 1) { return ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT; }; - uint8_t modifier = va_arg(args, int); - keyboard_activate_modifier(modifier); // squirrel_keyboard - va_end(args); + keyboard_activate_modifier(*(uint8_t *)args[0]); // squirrel_keyboard return ERR_NONE; } enum squirrel_error keyboard_modifier_release(struct key *key, uint8_t layer, uint8_t key_index, int arg_count, - ...) { + void **args) { (void)layer; (void)key_index; - - va_list args; - va_start(args, arg_count); if (arg_count != 1) { return ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT; }; - uint8_t modifier = va_arg(args, int); - keyboard_deactivate_modifier(modifier); // squirrel_keyboard - va_end(args); + keyboard_deactivate_modifier(*(uint8_t *)args[0]); // squirrel_keyboard return ERR_NONE; } enum squirrel_error consumer_press(struct key *key, uint8_t layer, - uint8_t key_index, int arg_count, ...) { + uint8_t key_index, int arg_count, + void **args) { (void)layer; (void)key_index; - - va_list args; - va_start(args, arg_count); if (arg_count != 1) { return ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT; }; - uint16_t consumer_code = va_arg(args, int); - consumer_activate_consumer_code(consumer_code); // squirrel_consumer - va_end(args); + consumer_activate_consumer_code(*(uint16_t *)args[0]); // squirrel_consumer return ERR_NONE; } enum squirrel_error consumer_release(struct key *key, uint8_t layer, - uint8_t key_index, int arg_count, ...) { + uint8_t key_index, int arg_count, + void **args) { (void)layer; (void)key_index; - - va_list args; - va_start(args, arg_count); if (arg_count != 1) { return ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT; }; - uint16_t consumer_code = va_arg(args, int); - consumer_deactivate_consumer_code(consumer_code); // squirrel_consumer - va_end(args); + consumer_deactivate_consumer_code(*(uint16_t *)args[0]); // squirrel_consumer return ERR_NONE; } // quantum_passthrough_press does not take extra arguments. enum squirrel_error quantum_passthrough_press(struct key *key, uint8_t layer, uint8_t key_index, int arg_count, - ...) { + void **args) { if (arg_count != 0) { return ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT; }; @@ -145,7 +120,7 @@ enum squirrel_error quantum_passthrough_press(struct key *key, uint8_t layer, // quantum_passthrough_release does not take extra arguments. enum squirrel_error quantum_passthrough_release(struct key *key, uint8_t layer, uint8_t key_index, - int arg_count, ...) { + int arg_count, void **args) { if (arg_count != 0) { return ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT; }; diff --git a/tests/consumer_press_release.c b/tests/consumer_press_release.c index d80416e..90ef875 100644 --- a/tests/consumer_press_release.c +++ b/tests/consumer_press_release.c @@ -2,17 +2,21 @@ #include "squirrel_consumer.h" #include "squirrel_key.h" #include "squirrel_quantum.h" +#include +#include // test: consumer_press + consumer_release - in squirrel_quantum.c int main() { struct key test_key; // values unused enum squirrel_error err; + void **args = malloc(sizeof(void *)); for (uint16_t test_consumer_code = 0; test_consumer_code <= 65534; test_consumer_code++) { + args[0] = &test_consumer_code; // consumer_press // no code becomes a code consumer_code = 0; - err = consumer_press(&test_key, 0, 0, 1, test_consumer_code); + err = consumer_press(&test_key, 0, 0, 1, args); if (err != ERR_NONE) { return 1; } @@ -20,7 +24,7 @@ int main() { return 2; } // a code stays a code - err = consumer_press(&test_key, 0, 0, 1, test_consumer_code); + err = consumer_press(&test_key, 0, 0, 1, args); if (err != ERR_NONE) { return 3; } @@ -29,7 +33,7 @@ int main() { } // another code becomes a code consumer_code = 0xFFFF; - err = consumer_press(&test_key, 0, 0, 1, test_consumer_code); + err = consumer_press(&test_key, 0, 0, 1, args); if (err != ERR_NONE) { return 5; } @@ -40,7 +44,7 @@ int main() { // consumer_release // a code becomes no code consumer_code = test_consumer_code; - err = consumer_release(&test_key, 0, 0, 1, test_consumer_code); + err = consumer_release(&test_key, 0, 0, 1, args); if (err != ERR_NONE) { return 7; } @@ -49,7 +53,7 @@ int main() { } // another code stays another code consumer_code = 0xFFFF; - err = consumer_release(&test_key, 0, 0, 1, test_consumer_code); + err = consumer_release(&test_key, 0, 0, 1, args); if (err != ERR_NONE) { return 9; } diff --git a/tests/key.c b/tests/key.c new file mode 100644 index 0000000..f053093 --- /dev/null +++ b/tests/key.c @@ -0,0 +1,88 @@ +#include "squirrel.h" +#include "squirrel_init.h" +#include "squirrel_key.h" +#include "squirrel_quantum.h" +#include +#include + +uint8_t test_result = 1; + +enum squirrel_error test_press(struct key *key, uint8_t layer, + uint8_t key_index, int arg_count, void **args) { + (void)layer; + (void)key_index; + + if (arg_count != 2) { + return ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT; + }; + uint8_t code1 = *(uint8_t *)args[0]; + uint8_t code2 = *(uint8_t *)args[1]; + if (code1 == 0x0F && code2 == 0xF0) { + test_result = 0; + } + return ERR_NONE; +} + +enum squirrel_error test_release(struct key *key, uint8_t layer, + uint8_t key_index, int arg_count, + void **args) { + (void)layer; + (void)key_index; + + if (arg_count != 2) { + return ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT; + }; + uint8_t code1 = *(uint8_t *)args[0]; + uint8_t code2 = *(uint8_t *)args[1]; + if (code1 == 0xF0 && code2 == 0x0F) { + test_result = 0; + } + return ERR_NONE; +} + +// test: press_key, release_key + check_key - in squirrel_key.c +int main() { + init_keyboard(1); + + // press_key + release_key + + uint8_t code1 = 0x0F; + uint8_t code2 = 0xF0; + + struct key testkey; + testkey.pressed = test_press; + testkey.pressed_argument_count = 2; + testkey.pressed_arguments = malloc(2 * sizeof(void *)); + testkey.pressed_arguments[0] = &code1; + testkey.pressed_arguments[1] = &code2; + + testkey.released = test_release; + testkey.released_argument_count = 2; + testkey.released_arguments = malloc(2 * sizeof(void *)); + testkey.released_arguments[0] = &code2; + testkey.released_arguments[1] = &code1; + + layers[0].keys[0] = testkey; + layers[0].active = true; + + enum squirrel_error err = press_key(0); + if (err != ERR_NONE) { + return 2; + } + if (test_result != 0) { + return 3; + } + + test_result = 1; + err = release_key(0); + if (err != ERR_NONE) { + return 4; + } + + free(testkey.pressed_arguments); + free(testkey.released_arguments); + + // TODO: check_key + + return test_result; +} diff --git a/tests/keyboard_modifier_press_release.c b/tests/keyboard_modifier_press_release.c index 6536621..389775c 100644 --- a/tests/keyboard_modifier_press_release.c +++ b/tests/keyboard_modifier_press_release.c @@ -1,19 +1,21 @@ #include "squirrel.h" #include "squirrel_key.h" #include "squirrel_quantum.h" +#include +#include // test: keyboard_modifier_press + keyboard_modifier_release test - in // squirrel_quantum.c int main() { struct key test_key; // values unused - + void **args = malloc(sizeof(void *)); // keyboard_modifier_press // no modifiers adding no modifiers is no modifiers uint8_t current_modifier = 0b00000000; keyboard_modifiers = 0; - enum squirrel_error err = - keyboard_modifier_press(&test_key, 0, 0, 1, current_modifier); + args[0] = ¤t_modifier; + enum squirrel_error err = keyboard_modifier_press(&test_key, 0, 0, 1, args); if (err != ERR_NONE) { return 255; } @@ -25,8 +27,8 @@ int main() { current_modifier = 0b00000001; for (uint8_t i = 0; i < 8; i++) { keyboard_modifiers = 0; - enum squirrel_error err = - keyboard_modifier_press(&test_key, 0, 0, 1, current_modifier); + args[0] = ¤t_modifier; + enum squirrel_error err = keyboard_modifier_press(&test_key, 0, 0, 1, args); if (err != ERR_NONE) { return 255; } @@ -41,8 +43,8 @@ int main() { for (uint8_t i = 0; i < 8; i++) { // modifiers stack, ORd to become the same number uint8_t old_modifiers = keyboard_modifiers; - enum squirrel_error err = - keyboard_modifier_press(&test_key, 0, 0, 1, current_modifier); + args[0] = ¤t_modifier; + enum squirrel_error err = keyboard_modifier_press(&test_key, 0, 0, 1, args); if (err != ERR_NONE) { return 255; } @@ -54,11 +56,11 @@ int main() { // checking expected errors: // incorrect arguments error. - err = keyboard_modifier_press(&test_key, 0, 0, 2, 0, 0); // too many arguments + err = keyboard_modifier_press(&test_key, 0, 0, 2, 0); // too many arguments if (err != ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT) { return 254; } - err = keyboard_modifier_press(&test_key, 0, 0, 0); // too few arguments + err = keyboard_modifier_press(&test_key, 0, 0, 0, 0); // too few arguments if (err != ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT) { return 254; } @@ -68,7 +70,8 @@ int main() { // no modifiers removing no modifiers is no modifiers current_modifier = 0b00000000; keyboard_modifiers = 0; - err = keyboard_modifier_release(&test_key, 0, 0, 1, current_modifier); + args[0] = ¤t_modifier; + err = keyboard_modifier_release(&test_key, 0, 0, 1, args); if (err != ERR_NONE) { return 255; } @@ -80,8 +83,9 @@ int main() { current_modifier = 0b00000001; for (uint8_t i = 0; i < 8; i++) { keyboard_modifiers = current_modifier; + args[0] = ¤t_modifier; enum squirrel_error err = - keyboard_modifier_release(&test_key, 0, 0, 1, current_modifier); + keyboard_modifier_release(&test_key, 0, 0, 1, args); if (err != ERR_NONE) { return 255; } @@ -97,8 +101,9 @@ int main() { for (uint8_t i = 0; i < 8; i++) { // modifiers stack, ORd to become the same number uint8_t old_modifiers = keyboard_modifiers; + args[0] = ¤t_modifier; enum squirrel_error err = - keyboard_modifier_release(&test_key, 0, 0, 1, current_modifier); + keyboard_modifier_release(&test_key, 0, 0, 1, args); if (err != ERR_NONE) { return 255; } @@ -108,14 +113,15 @@ int main() { current_modifier = current_modifier << 1; } + free(args); + // checking expected errors: // incorrect arguments error. - err = - keyboard_modifier_release(&test_key, 0, 0, 2, 0, 0); // too many arguments + err = keyboard_modifier_release(&test_key, 0, 0, 2, 0); // too many arguments if (err != ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT) { return 254; } - err = keyboard_modifier_release(&test_key, 0, 0, 0); // too few arguments + err = keyboard_modifier_release(&test_key, 0, 0, 0, 0); // too few arguments if (err != ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT) { return 254; } diff --git a/tests/keyboard_press_release.c b/tests/keyboard_press_release.c index 55bee57..236a279 100644 --- a/tests/keyboard_press_release.c +++ b/tests/keyboard_press_release.c @@ -1,16 +1,20 @@ #include "squirrel.h" #include "squirrel_key.h" #include "squirrel_quantum.h" +#include +#include // test: keyboard_press + keyboard_release - in squirrel_quantum.c int main() { struct key test_key; // values unused enum squirrel_error err; + void **args = malloc(sizeof(void *)); for (uint8_t keycode = 0; keycode != 255; keycode++) { + args[0] = &keycode; // keyboard_press // Off becomes on keyboard_keycodes[keycode] = false; - err = keyboard_press(&test_key, 0, 0, 1, keycode); + err = keyboard_press(&test_key, 0, 0, 1, args); if (err != ERR_NONE) { return 1; } @@ -18,7 +22,7 @@ int main() { return 2; } // On stays on - err = keyboard_press(&test_key, 0, 0, 1, keycode); + err = keyboard_press(&test_key, 0, 0, 1, args); if (err != ERR_NONE) { return 3; } @@ -29,7 +33,7 @@ int main() { // keyboard_release // On becomes off keyboard_keycodes[keycode] = true; - err = keyboard_release(&test_key, 0, 0, 1, keycode); + err = keyboard_release(&test_key, 0, 0, 1, args); if (err != ERR_NONE) { return 5; } @@ -37,7 +41,7 @@ int main() { return 6; } // Off stays off - err = keyboard_release(&test_key, 0, 0, 1, keycode); + err = keyboard_release(&test_key, 0, 0, 1, args); if (err != ERR_NONE) { return 7; } @@ -45,16 +49,24 @@ int main() { return 8; } } + free(args); // Test expected errors - err = consumer_press(&test_key, 0, 0, 0, 0); + err = consumer_press(&test_key, 0, 0, 0, 0); // too few if (err != ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT) { return 9; } - err = consumer_release(&test_key, 0, 0, 0, 0); + err = consumer_press(&test_key, 0, 0, 2, 0); // too many + if (err != ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT) { + return 10; + } + err = consumer_release(&test_key, 0, 0, 0, 0); // too few + if (err != ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT) { + return 10; + } + err = consumer_release(&test_key, 0, 0, 2, 0); // too many if (err != ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT) { return 10; } - return 0; }; diff --git a/tests/quantum_passthrough_press_release.c b/tests/quantum_passthrough_press_release.c index ab5b2e8..e536342 100644 --- a/tests/quantum_passthrough_press_release.c +++ b/tests/quantum_passthrough_press_release.c @@ -42,17 +42,17 @@ int main() { enum squirrel_error err = press_key(0); if (err != ERR_NONE) { - return 1; + return 2; } if (test_result != 0) { - return 2; + return 3; } test_result = 1; err = release_key(0); if (err != ERR_NONE) { - return 3; + return 4; } return test_result;