diff --git a/CMakeLists.txt b/CMakeLists.txt index 0cd069f..78385be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,14 @@ elseif(CMAKE_BUILD_TYPE STREQUAL "Testing") add_executable(quantum_passthrough_press_release tests/quantum_passthrough_press_release.c) target_link_libraries(quantum_passthrough_press_release squirrel) add_test(NAME quantum_passthrough_press_release COMMAND quantum_passthrough_press_release) + + add_executable(keyboard_get_keycodes tests/keyboard_get_keycodes.c) + target_link_libraries(keyboard_get_keycodes squirrel) + add_test(NAME keyboard_get_keycodes COMMAND keyboard_get_keycodes) + + 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) else() add_compile_options(-Os) # Enable size optimizations endif() diff --git a/include/squirrel_consumer.h b/include/squirrel_consumer.h index e404387..1f576ef 100644 --- a/include/squirrel_consumer.h +++ b/include/squirrel_consumer.h @@ -9,15 +9,13 @@ // time. extern uint16_t consumer_code; -// activate_consumer_code sets the provided consumer code as the active consumer -// code. -void activate_consumer_code(uint16_t consumer_code); - -// deactivate_consumer_code sets the active consumer code to 0 if it is the -// provided consumer code. -void deactivate_consumer_code(uint16_t consumer_code); - -// get_consumer_code returns the currently active consumer code. -uint16_t get_consumer_code(); +// consumer_activate_consumer_code sets the provided consumer code as the active +// consumer code. +void consumer_activate_consumer_code(uint16_t consumer_code); +// consumer_deactivate_consumer_code sets the active consumer code to 0 if it is +// the provided consumer code. +void consumer_deactivate_consumer_code(uint16_t consumer_code); +// consumer_get_consumer_code returns the currently active consumer code. +uint16_t consumer_get_consumer_code(); #endif diff --git a/include/squirrel_keyboard.h b/include/squirrel_keyboard.h index 2525534..c5365d6 100644 --- a/include/squirrel_keyboard.h +++ b/include/squirrel_keyboard.h @@ -5,22 +5,23 @@ #include #include -extern bool keycodes[256]; -extern uint8_t modifiers; +extern bool keyboard_keycodes[256]; +extern uint8_t keyboard_modifiers; // keyboard_activate_keycode marks the provided keycode as active. void keyboard_activate_keycode(uint8_t keycode); // keyboard_deactivate_keycode marks the provided keycode as inactive. void keyboard_deactivate_keycode(uint8_t keycode); -// get_active_keycodes populates the provided array with the active keycodes, -// and returns the number of active keycodes. -void keyboard_get_keycodes(uint8_t *active_keycodes); +// keyboard_get_keycodes populates the provided array with the first 6 active +// keycodes. 6 is the maximum number of keycodes that +// can be sent over USB HID. +void keyboard_get_keycodes(uint8_t (*active_keycodes)[6]); // keyboard_activate_modifier marks the provided modifier as active. void keyboard_activate_modifier(uint8_t modifier); // keyboard_deactivate_modifier marks the provided modifier as inactive. void keyboard_deactivate_modifier(uint8_t modifier); -// get_active_modifiers returns the active modifiers. +// keyboard_get_modifiers returns a bitfield of active modifiers. uint8_t keyboard_get_modifiers(); #endif diff --git a/include/squirrel_quantum.h b/include/squirrel_quantum.h index 764ae27..538ba97 100644 --- a/include/squirrel_quantum.h +++ b/include/squirrel_quantum.h @@ -37,6 +37,16 @@ enum squirrel_error keyboard_modifier_release(struct key *key, uint8_t layer, uint8_t key_index, int arg_count, ...); +// 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, ...); + +// 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, ...); + // 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, diff --git a/src/squirrel_consumer.c b/src/squirrel_consumer.c index f9a740f..cdc9bf4 100644 --- a/src/squirrel_consumer.c +++ b/src/squirrel_consumer.c @@ -3,12 +3,10 @@ uint16_t consumer_code = 0; -void activate_consumer_code(uint16_t code) { consumer_code = code; } - -void deactivate_consumer_code(uint16_t code) { +void consumer_activate_consumer_code(uint16_t code) { consumer_code = code; } +void consumer_deactivate_consumer_code(uint16_t code) { if (consumer_code == code) { consumer_code = 0; } } - -uint16_t get_consumer_code() { return consumer_code; } +uint16_t consumer_get_consumer_code() { return consumer_code; } diff --git a/src/squirrel_keyboard.c b/src/squirrel_keyboard.c index 7723bd5..a5f0249 100644 --- a/src/squirrel_keyboard.c +++ b/src/squirrel_keyboard.c @@ -2,22 +2,30 @@ #include #include -bool keycodes[256] = {false}; -uint8_t modifiers = 0; +bool keyboard_keycodes[256] = {false}; +uint8_t keyboard_modifiers = 0; -void keyboard_activate_keycode(uint8_t keycode) { keycodes[keycode] = true; } -void keyboard_deactivate_keycode(uint8_t keycode) { keycodes[keycode] = false; } -void keyboard_get_keycodes(uint8_t *active_keycodes) { +void keyboard_activate_keycode(uint8_t keycode) { + keyboard_keycodes[keycode] = true; +} +void keyboard_deactivate_keycode(uint8_t keycode) { + keyboard_keycodes[keycode] = false; +} +void keyboard_get_keycodes(uint8_t (*active_keycodes)[6]) { uint8_t active_keycodes_index = 0; - for (uint8_t i = 0; i != 255; i++) { - if (!keycodes[i]) { + for (int i = 0; (i <= 0xFF) && active_keycodes_index < 6; i++) { + if (!keyboard_keycodes[i]) { continue; } - active_keycodes[active_keycodes_index] = i; + (*active_keycodes)[active_keycodes_index] = i; active_keycodes_index++; } } -void keyboard_activate_modifier(uint8_t modifier) { modifiers |= modifier; } -void keyboard_deactivate_modifier(uint8_t modifier) { modifiers &= ~modifier; } -uint8_t keyboard_get_modifiers() { return modifiers; } +void keyboard_activate_modifier(uint8_t modifier) { + keyboard_modifiers |= modifier; +} +void keyboard_deactivate_modifier(uint8_t modifier) { + keyboard_modifiers &= ~modifier; +} +uint8_t keyboard_get_modifiers() { return keyboard_modifiers; } diff --git a/src/squirrel_quantum.c b/src/squirrel_quantum.c index eca1a1f..9b2e718 100644 --- a/src/squirrel_quantum.c +++ b/src/squirrel_quantum.c @@ -1,5 +1,6 @@ #include "squirrel_quantum.h" #include "squirrel.h" +#include "squirrel_consumer.h" #include "squirrel_key.h" #include "squirrel_keyboard.h" #include @@ -80,6 +81,38 @@ enum squirrel_error keyboard_modifier_release(struct key *key, uint8_t layer, return ERR_NONE; } +enum squirrel_error consumer_press(struct key *key, uint8_t layer, + uint8_t key_index, int arg_count, ...) { + (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); + return ERR_NONE; +} + +enum squirrel_error consumer_release(struct key *key, uint8_t layer, + uint8_t key_index, int arg_count, ...) { + (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); + 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, diff --git a/tests/consumer_press_release.c b/tests/consumer_press_release.c new file mode 100644 index 0000000..d80416e --- /dev/null +++ b/tests/consumer_press_release.c @@ -0,0 +1,72 @@ +#include "squirrel.h" +#include "squirrel_consumer.h" +#include "squirrel_key.h" +#include "squirrel_quantum.h" + +// test: consumer_press + consumer_release - in squirrel_quantum.c +int main() { + struct key test_key; // values unused + enum squirrel_error err; + for (uint16_t test_consumer_code = 0; test_consumer_code <= 65534; + test_consumer_code++) { + // consumer_press + // no code becomes a code + consumer_code = 0; + err = consumer_press(&test_key, 0, 0, 1, test_consumer_code); + if (err != ERR_NONE) { + return 1; + } + if (consumer_code != test_consumer_code) { + return 2; + } + // a code stays a code + err = consumer_press(&test_key, 0, 0, 1, test_consumer_code); + if (err != ERR_NONE) { + return 3; + } + if (consumer_code != test_consumer_code) { + return 4; + } + // another code becomes a code + consumer_code = 0xFFFF; + err = consumer_press(&test_key, 0, 0, 1, test_consumer_code); + if (err != ERR_NONE) { + return 5; + } + if (consumer_code != test_consumer_code) { + return 6; + } + + // consumer_release + // a code becomes no code + consumer_code = test_consumer_code; + err = consumer_release(&test_key, 0, 0, 1, test_consumer_code); + if (err != ERR_NONE) { + return 7; + } + if (consumer_code != 0) { + return 8; + } + // another code stays another code + consumer_code = 0xFFFF; + err = consumer_release(&test_key, 0, 0, 1, test_consumer_code); + if (err != ERR_NONE) { + return 9; + } + if (consumer_code != 0xFFFF) { + return 10; + } + } + + // Test expected errors + err = consumer_press(&test_key, 0, 0, 0, 0); + if (err != ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT) { + return 11; + } + err = consumer_release(&test_key, 0, 0, 0, 0); + if (err != ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT) { + return 12; + } + + return 0; +}; diff --git a/tests/keyboard_get_keycodes.c b/tests/keyboard_get_keycodes.c new file mode 100644 index 0000000..b8b1231 --- /dev/null +++ b/tests/keyboard_get_keycodes.c @@ -0,0 +1,32 @@ +#include "squirrel.h" +#include "squirrel_key.h" +#include "squirrel_keyboard.h" +#include "squirrel_quantum.h" + +// test: keyboard_get_keycodes - in squirrel_keyboard.c +int main() { + uint8_t active_keycodes[6] = {0, 0, 0, 0, 0, 0}; + keyboard_get_keycodes(&active_keycodes); + for (uint8_t i = 0; i < 6; i++) { + if (active_keycodes[i] != 0) { + return 1; + } + } + for (int i = 0; i < 6; i++) { + keyboard_keycodes[i] = true; + } + keyboard_get_keycodes(&active_keycodes); + for (uint8_t i = 0; i < 6; i++) { + if (active_keycodes[i] != i) { + return 2; + } + } + keyboard_keycodes[7] = true; + keyboard_get_keycodes(&active_keycodes); + for (uint8_t i = 0; i < 6; i++) { + if (active_keycodes[i] != i) { + return 3; + } + } + return 0; +}; diff --git a/tests/keyboard_modifier_press_release.c b/tests/keyboard_modifier_press_release.c index 0c79191..6536621 100644 --- a/tests/keyboard_modifier_press_release.c +++ b/tests/keyboard_modifier_press_release.c @@ -11,26 +11,26 @@ int main() { // no modifiers adding no modifiers is no modifiers uint8_t current_modifier = 0b00000000; - modifiers = 0; + keyboard_modifiers = 0; enum squirrel_error err = keyboard_modifier_press(&test_key, 0, 0, 1, current_modifier); if (err != ERR_NONE) { return 255; } - if (modifiers != 0b00000000) { + if (keyboard_modifiers != 0b00000000) { return 1; } // no modifiers adding a modifier is a modifier current_modifier = 0b00000001; for (uint8_t i = 0; i < 8; i++) { - modifiers = 0; + keyboard_modifiers = 0; enum squirrel_error err = keyboard_modifier_press(&test_key, 0, 0, 1, current_modifier); if (err != ERR_NONE) { return 255; } - if (modifiers != current_modifier) { + if (keyboard_modifiers != current_modifier) { return 2; } current_modifier = current_modifier << 1; @@ -40,13 +40,13 @@ int main() { current_modifier = 0b00000001; for (uint8_t i = 0; i < 8; i++) { // modifiers stack, ORd to become the same number - uint8_t old_modifiers = modifiers; + uint8_t old_modifiers = keyboard_modifiers; enum squirrel_error err = keyboard_modifier_press(&test_key, 0, 0, 1, current_modifier); if (err != ERR_NONE) { return 255; } - if (modifiers != (old_modifiers | current_modifier)) { + if (keyboard_modifiers != (old_modifiers | current_modifier)) { return 3; } current_modifier = current_modifier << 1; @@ -67,25 +67,25 @@ int main() { // no modifiers removing no modifiers is no modifiers current_modifier = 0b00000000; - modifiers = 0; + keyboard_modifiers = 0; err = keyboard_modifier_release(&test_key, 0, 0, 1, current_modifier); if (err != ERR_NONE) { return 255; } - if (modifiers != 0b00000000) { + if (keyboard_modifiers != 0b00000000) { return 4; } // a modifier removing a modifier is no modifiers current_modifier = 0b00000001; for (uint8_t i = 0; i < 8; i++) { - modifiers = current_modifier; + keyboard_modifiers = current_modifier; enum squirrel_error err = keyboard_modifier_release(&test_key, 0, 0, 1, current_modifier); if (err != ERR_NONE) { return 255; } - if (modifiers != 0b000000000) { + if (keyboard_modifiers != 0b000000000) { return 5; } current_modifier = current_modifier << 1; @@ -93,16 +93,16 @@ int main() { // more than one modifier removing a modifier is less modifiers. current_modifier = 0b00000001; - modifiers = 0b11111111; + keyboard_modifiers = 0b11111111; for (uint8_t i = 0; i < 8; i++) { // modifiers stack, ORd to become the same number - uint8_t old_modifiers = modifiers; + uint8_t old_modifiers = keyboard_modifiers; enum squirrel_error err = keyboard_modifier_release(&test_key, 0, 0, 1, current_modifier); if (err != ERR_NONE) { return 255; } - if (modifiers != (old_modifiers & ~current_modifier)) { + if (keyboard_modifiers != (old_modifiers & ~current_modifier)) { return 6; } current_modifier = current_modifier << 1; diff --git a/tests/keyboard_press_release.c b/tests/keyboard_press_release.c index 1652261..55bee57 100644 --- a/tests/keyboard_press_release.c +++ b/tests/keyboard_press_release.c @@ -2,34 +2,59 @@ #include "squirrel_key.h" #include "squirrel_quantum.h" -// test: keyboard_press + keyboard_release test - in squirrel_quantum.c +// test: keyboard_press + keyboard_release - in squirrel_quantum.c int main() { - // keyboard_press struct key test_key; // values unused - for (uint8_t keycode; keycode <= 127; keycode++) { + enum squirrel_error err; + for (uint8_t keycode = 0; keycode != 255; keycode++) { + // keyboard_press // Off becomes on - keycodes[keycode] = false; - keyboard_press(&test_key, 0, 0, 1, keycode); - if (keycodes[keycode] != true) { + keyboard_keycodes[keycode] = false; + err = keyboard_press(&test_key, 0, 0, 1, keycode); + if (err != ERR_NONE) { return 1; } - // On stays on - keyboard_press(&test_key, 0, 0, 1, keycode); - if (keycodes[keycode] != true) { + if (keyboard_keycodes[keycode] != true) { return 2; } + // On stays on + err = keyboard_press(&test_key, 0, 0, 1, keycode); + if (err != ERR_NONE) { + return 3; + } + if (keyboard_keycodes[keycode] != true) { + return 4; + } + // keyboard_release // On becomes off - keycodes[keycode] = true; - keyboard_release(&test_key, 0, 0, 1, keycode); - if (keycodes[keycode] != false) { - return 3; + keyboard_keycodes[keycode] = true; + err = keyboard_release(&test_key, 0, 0, 1, keycode); + if (err != ERR_NONE) { + return 5; + } + if (keyboard_keycodes[keycode] != false) { + return 6; } // Off stays off - keyboard_release(&test_key, 0, 0, 1, keycode); - if (keycodes[keycode] != false) { - return 4; + err = keyboard_release(&test_key, 0, 0, 1, keycode); + if (err != ERR_NONE) { + return 7; + } + if (keyboard_keycodes[keycode] != false) { + return 8; } } + + // Test expected errors + err = consumer_press(&test_key, 0, 0, 0, 0); + if (err != ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT) { + return 9; + } + err = consumer_release(&test_key, 0, 0, 0, 0); + if (err != ERR_KEY_FUNC_WRONG_ARGUMENT_COUNT) { + return 10; + } + return 0; };