diff options
author | Florian Didron <fdidron@users.noreply.github.com> | 2022-05-31 19:03:21 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-31 19:03:21 +0900 |
commit | fc773ff0cf9c528773fa81be0fc8880ca5153d81 (patch) | |
tree | e917ed871290cc78cff818ee896b838d12ccc654 | |
parent | 1fbd91aa106a4beb6ab84614dde14165a43f009a (diff) |
Reimplements Oryx's live training over raw hid (#345)
* feat: initial commit, random pairing sequence generation, host - board pairing handshakes
* feat: reimplements ory's live training over raw hid
* feat: adds planck / ergodox support
* chore: some code styling fixes
* fix: build smoke tests
* fix: code lint
* fix: disable console / command on moonlander, fixes build ci test
* fix: code lint
* fix: remove unused define(MATRIX_SIZE)
-rw-r--r-- | builddefs/common_features.mk | 2 | ||||
-rw-r--r-- | keyboards/ergodox_ez/ergodox_ez.c | 8 | ||||
-rw-r--r-- | keyboards/ergodox_ez/keymaps/oryx/config.h | 3 | ||||
-rw-r--r-- | keyboards/moonlander/keymaps/oryx/config.h | 3 | ||||
-rw-r--r-- | keyboards/moonlander/keymaps/oryx/rules.mk | 2 | ||||
-rw-r--r-- | keyboards/moonlander/moonlander.c | 43 | ||||
-rw-r--r-- | keyboards/moonlander/rules.mk | 4 | ||||
-rw-r--r-- | keyboards/planck/ez/ez.c | 8 | ||||
-rw-r--r-- | quantum/eeconfig.c | 7 | ||||
-rw-r--r-- | quantum/oryx.c | 379 | ||||
-rw-r--r-- | quantum/oryx.h | 103 | ||||
-rw-r--r-- | quantum/quantum.c | 18 | ||||
-rw-r--r-- | tmk_core/protocol/chibios/usb_main.c | 41 | ||||
-rw-r--r-- | tmk_core/protocol/lufa/lufa.c | 67 |
14 files changed, 302 insertions, 386 deletions
diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk index 686b443421..f7ad32c28e 100644 --- a/builddefs/common_features.mk +++ b/builddefs/common_features.mk @@ -549,7 +549,7 @@ ifeq ($(strip $(TERMINAL_ENABLE)), yes) endif ifeq ($(strip $(ORYX_ENABLE)), yes) - WEBUSB_ENABLE := yes + RAW_ENABLE := yes SRC += $(QUANTUM_DIR)/oryx.c OPT_DEFS += -DORYX_ENABLE endif diff --git a/keyboards/ergodox_ez/ergodox_ez.c b/keyboards/ergodox_ez/ergodox_ez.c index f415fa0255..8fa038cdda 100644 --- a/keyboards/ergodox_ez/ergodox_ez.c +++ b/keyboards/ergodox_ez/ergodox_ez.c @@ -424,13 +424,13 @@ void dynamic_macro_record_end_user(int8_t direction) { void matrix_scan_kb(void) { #ifdef ORYX_ENABLE - if(webusb_state.pairing == true) { + if(rawhid_state.pairing == true) { if(loops == 0) { ergodox_right_led_1_off(); ergodox_right_led_2_off(); ergodox_right_led_3_off(); } - if(loops % WEBUSB_BLINK_STEPS == 0) { + if(loops % PAIRING_BLINK_STEPS == 0) { if(is_on) { ergodox_right_led_2_off(); } else { @@ -438,8 +438,8 @@ void matrix_scan_kb(void) { } is_on ^= 1; } - if(loops > WEBUSB_BLINK_END) { - webusb_state.pairing = false; + if(loops > PAIRING_BLINK_END) { + rawhid_state.pairing = false; layer_state_set_user(layer_state); loops = 0; } diff --git a/keyboards/ergodox_ez/keymaps/oryx/config.h b/keyboards/ergodox_ez/keymaps/oryx/config.h index bad98d2c0e..1c7897be6c 100644 --- a/keyboards/ergodox_ez/keymaps/oryx/config.h +++ b/keyboards/ergodox_ez/keymaps/oryx/config.h @@ -1,3 +1,6 @@ #pragma once #define LAYER_STATE_8BIT +#define FIRMWARE_VERSION u8"default/latest" +#define RAW_USAGE_PAGE 0xFF60 +#define RAW_USAGE_ID 0x61 diff --git a/keyboards/moonlander/keymaps/oryx/config.h b/keyboards/moonlander/keymaps/oryx/config.h index be3110d3b0..1ea6cba6b9 100644 --- a/keyboards/moonlander/keymaps/oryx/config.h +++ b/keyboards/moonlander/keymaps/oryx/config.h @@ -1,3 +1,6 @@ #pragma once #include "../default/config.h" +#define FIRMWARE_VERSION u8"default/latest" +#define RAW_USAGE_PAGE 0xFF60 +#define RAW_USAGE_ID 0x61 diff --git a/keyboards/moonlander/keymaps/oryx/rules.mk b/keyboards/moonlander/keymaps/oryx/rules.mk index cc72fbad13..d269d04c82 100644 --- a/keyboards/moonlander/keymaps/oryx/rules.mk +++ b/keyboards/moonlander/keymaps/oryx/rules.mk @@ -1,6 +1,4 @@ SRC += ../default/keymap.c -include ../default/rules.mk -WEBUSB_ENABLE = yes ORYX_ENABLE = yes -DYNAMIC_KEYMAP_ENABLE = yes diff --git a/keyboards/moonlander/moonlander.c b/keyboards/moonlander/moonlander.c index cb8a5abca0..3c8f5b4184 100644 --- a/keyboards/moonlander/moonlander.c +++ b/keyboards/moonlander/moonlander.c @@ -14,11 +14,10 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - - + */ #include "moonlander.h" +#include "raw_hid.h" keyboard_config_t keyboard_config; @@ -28,7 +27,9 @@ bool is_launching = false; #ifdef DYNAMIC_MACRO_ENABLE static bool is_dynamic_recording = false; -void dynamic_macro_record_start_user(void) { is_dynamic_recording = true; } +void dynamic_macro_record_start_user(void) { + is_dynamic_recording = true; +} void dynamic_macro_record_end_user(int8_t direction) { is_dynamic_recording = false; @@ -96,7 +97,6 @@ static THD_FUNCTION(LEDThread, arg) { } } - void keyboard_pre_init_kb(void) { setPinOutput(B5); setPinOutput(B4); @@ -125,9 +125,9 @@ layer_state_t layer_state_set_kb(layer_state_t state) { bool LED_3 = false; bool LED_4 = false; bool LED_5 = false; -#if !defined(CAPS_LOCK_STATUS) +# if !defined(CAPS_LOCK_STATUS) bool LED_6 = false; -#endif +# endif uint8_t layer = get_highest_layer(state); switch (layer) { @@ -141,9 +141,9 @@ layer_state_t layer_state_set_kb(layer_state_t state) { break; case 3: LED_3 = true; -#if !defined(CAPS_LOCK_STATUS) +# if !defined(CAPS_LOCK_STATUS) LED_6 = true; -#endif +# endif break; case 4: LED_4 = true; @@ -152,9 +152,9 @@ layer_state_t layer_state_set_kb(layer_state_t state) { LED_5 = true; break; case 6: -#if !defined(CAPS_LOCK_STATUS) +# if !defined(CAPS_LOCK_STATUS) LED_6 = true; -#endif +# endif break; default: break; @@ -165,10 +165,9 @@ layer_state_t layer_state_set_kb(layer_state_t state) { ML_LED_3(LED_3); ML_LED_4(LED_4); ML_LED_5(LED_5); -#if !defined(CAPS_LOCK_STATUS) +# if !defined(CAPS_LOCK_STATUS) ML_LED_6(LED_6); -#endif - +# endif return state; } #endif @@ -373,7 +372,7 @@ const uint8_t music_map[MATRIX_ROWS][MATRIX_COLS] = LAYOUT_moonlander( #ifdef CAPS_LOCK_STATUS bool led_update_kb(led_t led_state) { bool res = led_update_user(led_state); - if(res) { + if (res) { ML_LED_6(led_state.caps_lock); } return res; @@ -381,7 +380,9 @@ bool led_update_kb(led_t led_state) { #endif bool process_record_kb(uint16_t keycode, keyrecord_t *record) { - if (!process_record_user(keycode, record)) { return false; } + if (!process_record_user(keycode, record)) { + return false; + } switch (keycode) { #if !defined(MOONLANDER_USER_LEDS) case LED_LEVEL: @@ -434,7 +435,7 @@ void matrix_init_kb(void) { keyboard_config.raw = eeconfig_read_kb(); if (!keyboard_config.led_level && !keyboard_config.led_level_res) { - keyboard_config.led_level = true; + keyboard_config.led_level = true; keyboard_config.led_level_res = 0b11; eeconfig_update_kb(keyboard_config.raw); } @@ -448,11 +449,11 @@ void matrix_init_kb(void) { matrix_init_user(); } -void eeconfig_init_kb(void) { // EEPROM is getting reset! - keyboard_config.raw = 0; +void eeconfig_init_kb(void) { // EEPROM is getting reset! + keyboard_config.raw = 0; keyboard_config.rgb_matrix_enable = true; - keyboard_config.led_level = true; - keyboard_config.led_level_res = 0b11; + keyboard_config.led_level = true; + keyboard_config.led_level_res = 0b11; eeconfig_update_kb(keyboard_config.raw); eeconfig_init_user(); } diff --git a/keyboards/moonlander/rules.mk b/keyboards/moonlander/rules.mk index 1dd280db16..24ffb3caca 100644 --- a/keyboards/moonlander/rules.mk +++ b/keyboards/moonlander/rules.mk @@ -10,8 +10,8 @@ BOOTLOADER = stm32-dfu BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite MOUSEKEY_ENABLE = yes # Mouse keys EXTRAKEY_ENABLE = yes # Audio control and System control -CONSOLE_ENABLE = yes # Console for debug -COMMAND_ENABLE = yes # Commands for debug and configuration +CONSOLE_ENABLE = no # Console for debug +COMMAND_ENABLE = no # Commands for debug and configuration NKRO_ENABLE = yes # Enable N-Key Rollover BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow diff --git a/keyboards/planck/ez/ez.c b/keyboards/planck/ez/ez.c index c29f3cfa00..2e74ff860a 100644 --- a/keyboards/planck/ez/ez.c +++ b/keyboards/planck/ez/ez.c @@ -335,11 +335,11 @@ void dynamic_macro_record_end_user(int8_t direction) { void matrix_scan_kb(void) { #ifdef ORYX_ENABLE - if(webusb_state.pairing == true) { + if(rawhid_state.pairing == true) { if(loops == 0) { //lights off } - if(loops % WEBUSB_BLINK_STEPS == 0) { + if(loops % PAIRING_BLINK_STEPS == 0) { if(is_on) { planck_ez_left_led_on(); planck_ez_right_led_off(); @@ -350,8 +350,8 @@ void matrix_scan_kb(void) { } is_on ^= 1; } - if(loops > WEBUSB_BLINK_END * 2) { - webusb_state.pairing = false; + if(loops > PAIRING_BLINK_END * 2) { + rawhid_state.pairing = false; loops = 0; planck_ez_left_led_off(); planck_ez_right_led_off(); diff --git a/quantum/eeconfig.c b/quantum/eeconfig.c index 01895bae2a..0ff9996ca4 100644 --- a/quantum/eeconfig.c +++ b/quantum/eeconfig.c @@ -3,9 +3,6 @@ #include "eeprom.h" #include "eeconfig.h" #include "action_layer.h" -#ifdef ORYX_ENABLE -# include "oryx.h" -#endif #if defined(EEPROM_DRIVER) # include "eeprom_driver.h" @@ -60,10 +57,6 @@ void eeconfig_init_quantum(void) { eeprom_update_dword(EECONFIG_RGB_MATRIX, 0); eeprom_update_word(EECONFIG_RGB_MATRIX_EXTENDED, 0); -#ifdef ORYX_ENABLE - eeconfig_init_oryx(); -#endif - // TODO: Remove once ARM has a way to configure EECONFIG_HANDEDNESS // within the emulated eeprom via dfu-util or another tool #if defined INIT_EE_HANDS_LEFT diff --git a/quantum/oryx.c b/quantum/oryx.c index c1e5dfba31..706a43c42b 100644 --- a/quantum/oryx.c +++ b/quantum/oryx.c @@ -1,253 +1,180 @@ #include "oryx.h" #include "eeprom.h" -#include <string.h> -bool oryx_state_live_training_enabled; +rawhid_state_t rawhid_state = {.pairing = false, .paired = false}; -bool webusb_receive_oryx(uint8_t *data, uint8_t length) { - uint8_t command = data[0]; - uint8_t *param = &(data[1]); +keypos_t keyboard_pairing_sequence[PAIRING_SEQUENCE_SIZE]; +keypos_t host_pairing_sequence[PAIRING_SEQUENCE_SIZE]; +uint8_t pairing_input_index = 0; + +void raw_hid_receive(uint8_t *data, uint8_t length) { + uint8_t command = data[0]; + uint8_t *param = &data[1]; + uint8_t cmd_index = 0; switch (command) { - case ORYX_GET_LAYER: - oryx_layer_event(); - return true; - case ORYX_CMD_LIVE_TRAINING: { - uint8_t event[4]; - switch (param[0]) { // 0 for querying, 1 for off, 2 for on - case 0: - break; - case 1: - oryx_state_live_training_enabled = false; - break; - case 2: - oryx_state_live_training_enabled = true; - break; - default: - webusb_error(WEBUSB_STATUS_UNKNOWN_COMMAND); - return true; - } - event[0] = WEBUSB_STATUS_OK; - event[1] = ORYX_EVT_LIVE_TRAINING; - event[2] = oryx_state_live_training_enabled; - event[3] = WEBUSB_STOP_BIT; - webusb_send(event, sizeof(event)); - return true; - } -#ifdef DYNAMIC_KEYMAP_ENABLE - case ORYX_CMD_LIVE_UPDATE_GET_KEYCODE: { - uint8_t event[5]; - // layer, row, col - uint16_t keycode = dynamic_keymap_get_keycode(param[0], param[1], param[2]); - event[0] = WEBUSB_STATUS_OK; - event[1] = ORYX_EVT_LIVE_UPDATE_GET_KEYCODE; - event[2] = keycode >> 8; - event[3] = keycode & 0xFF; - event[4] = WEBUSB_STOP_BIT; - webusb_send(event, sizeof(event)); - return true; - } - case ORYX_CMD_LIVE_UPDATE_SET_KEYCODE: { - uint8_t event[5]; - dynamic_keymap_set_keycode(param[0], param[1], param[2], (param[3] << 8) | param[4]); - event[0] = WEBUSB_STATUS_OK; - event[1] = ORYX_EVT_LIVE_UPDATE_SET_KEYCODE; - event[2] = param[3]; - event[3] = param[4]; - event[4] = WEBUSB_STOP_BIT; - webusb_send(event, sizeof(event)); - return true; - } - case ORYX_CMD_LIVE_UPDATE_KEYMAP_RESET: { - uint8_t event[3]; - dynamic_keymap_reset(); - event[0] = WEBUSB_STATUS_OK; - event[1] = ORYX_EVT_LIVE_UPDATE_KEYMAP_RESET; - event[2] = WEBUSB_STOP_BIT; - webusb_send(event, sizeof(event)); - return true; - } - case ORYX_CMD_LIVE_UPDATE_GET_BUFFER: { - uint16_t offset = (param[0] << 8) | param[1]; - uint16_t size = param[2]; // size <= 28 - uint8_t event[size+3]; - uint8_t i; - dynamic_keymap_get_buffer(offset, size, ¶m[3]); - event[0] = WEBUSB_STATUS_OK; - event[1] = ORYX_EVT_LIVE_UPDATE_GET_BUFFER; - for (i = 0; i < size; i++) { - event[i+2] = param[i]; - } - event[i+2] = WEBUSB_STOP_BIT; - webusb_send(event, sizeof(event)); - return true; - } - case ORYX_CMD_LIVE_UPDATE_SET_BUFFER: { - uint16_t offset = (param[0] << 8) | param[1]; - uint16_t size = param[2]; // size <= 28 - uint8_t event[3]; - dynamic_keymap_set_buffer(offset, size, ¶m[3]); - event[0] = WEBUSB_STATUS_OK; - event[1] = ORYX_EVT_LIVE_UPDATE_SET_BUFFER; - event[2] = WEBUSB_STOP_BIT; - webusb_send(event, sizeof(event)); - return true; - } - case ORYX_CMD_LIVE_UPDATE_GET_LAYER_COUNT: { - uint8_t event[4]; - event[0] = WEBUSB_STATUS_OK; - event[1] = ORYX_EVT_LIVE_UPDATE_GET_LAYER_COUNT; - event[2] = dynamic_keymap_get_layer_count(); - event[3] = WEBUSB_STOP_BIT; - webusb_send(event, sizeof(event)); - return true; - } - case ORYX_CMD_LIVE_UPDATE_GET_MACRO_COUNT: { - uint8_t event[4]; - event[0] = WEBUSB_STATUS_OK; - event[1] = ORYX_EVT_LIVE_UPDATE_GET_MACRO_COUNT; - event[2] = dynamic_keymap_macro_get_count(); - event[3] = WEBUSB_STOP_BIT; - webusb_send(event, sizeof(event)); - return true; - } - case ORYX_CMD_LIVE_UPDATE_GET_MACRO_BUFFER_SIZE: { - uint16_t size = dynamic_keymap_macro_get_buffer_size(); - uint8_t event[5]; - event[0] = WEBUSB_STATUS_OK; - event[1] = ORYX_EVT_LIVE_UPDATE_GET_MACRO_BUFFER_SIZE; - event[2] = size >> 8; - event[3] = size & 0xFF; - event[4] = WEBUSB_STOP_BIT; - webusb_send(event, sizeof(event)); - return true; + case ORYX_CMD_GET_FW_VERSION: { + uint8_t event[RAW_EPSIZE]; + uint8_t fw_version_size = sizeof(FIRMWARE_VERSION); + uint8_t stop[1]; + + event[0] = ORYX_EVT_GET_FW_VERSION; + stop[0] = ORYX_STOP_BIT; + + memcpy(event + 1, FIRMWARE_VERSION, fw_version_size); + memcpy(event + fw_version_size, stop, 1); + + raw_hid_send(event, RAW_EPSIZE); + break; } - case ORYX_CMD_LIVE_UPDATE_GET_MACRO_BUFFER: { - uint16_t offset = (param[0] << 8) | param[1]; - uint16_t size = param[2]; // size <= 28 - uint8_t event[size+3]; - uint8_t i; - dynamic_keymap_macro_get_buffer(offset, size, ¶m[3]); - event[0] = WEBUSB_STATUS_OK; - event[1] = ORYX_EVT_LIVE_UPDATE_GET_MACRO_BUFFER; - for (i = 0; i < size; i++) { - event[i+2] = param[i]; + + case ORYX_CMD_PAIRING_INIT: + pairing_init_handler(); + store_pairing_sequence(&keyboard_pairing_sequence[0]); + break; + + case ORYX_CMD_PAIRING_VALIDATE: + for (uint8_t i = 0; i < PAIRING_SEQUENCE_SIZE; i++) { + keypos_t pos; + pos.col = param[cmd_index++]; + pos.row = param[cmd_index++]; + host_pairing_sequence[i] = pos; } - event[i+2] = WEBUSB_STOP_BIT; - webusb_send(event, sizeof(event)); - return true; - } - case ORYX_CMD_LIVE_UPDATE_SET_MACRO_BUFFER: { - uint16_t offset = (param[0] << 8) | param[1]; - uint16_t size = param[2]; // size <= 28 - dynamic_keymap_macro_set_buffer(offset, size, ¶m[3]); - uint8_t event[3]; - event[0] = WEBUSB_STATUS_OK; - event[1] = ORYX_EVT_LIVE_UPDATE_SET_MACRO_BUFFER; - event[2] = WEBUSB_STOP_BIT; - webusb_send(event, sizeof(event)); - return true; - } - case ORYX_CMD_LIVE_UPDATE_MACRO_RESET: { - uint8_t event[3]; - event[0] = WEBUSB_STATUS_OK; - event[1] = ORYX_EVT_LIVE_UPDATE_MACRO_RESET; - event[2] = WEBUSB_STOP_BIT; - dynamic_keymap_macro_reset(); - webusb_send(event, sizeof(event)); - return true; - } - case ORYX_CMD_LIVE_UPDATE_EEPROM_RESET: { - uint8_t event[3]; - event[0] = WEBUSB_STATUS_OK; - event[1] = ORYX_EVT_LIVE_UPDATE_EEPROM_RESET; - event[2] = WEBUSB_STOP_BIT; - webusb_send(event, sizeof(event)); - eeconfig_init(); - return true; - } - case ORYX_CMD_LIVE_UPDATE_KEYBOARD_RESET: { - uint8_t event[3]; - event[0] = WEBUSB_STATUS_OK; - event[1] = ORYX_EVT_LIVE_UPDATE_KEYBOARD_RESET; - event[2] = WEBUSB_STOP_BIT; - webusb_send(event, sizeof(event)); - reset_keyboard(); - return true; - } -#endif - default: - return webusb_receive_kb(data, length); + pairing_validate_handler(); + break; } } -void oryx_layer_event(void) { - uint8_t layer; - uint8_t event[4]; - layer = get_highest_layer(layer_state); -#ifdef WEBUSB_ENABLE - event[0] = WEBUSB_STATUS_OK; - event[1] = ORYX_EVT_LAYER; - event[2] = layer; - event[3] = WEBUSB_STOP_BIT; - webusb_send(event, sizeof(event)); -#endif +bool store_pairing_sequence(keypos_t *pairing_sequence) { + uint8_t stored_sequences[sizeof(uint16_t) * PAIRING_SEQUENCE_SIZE * PAIRING_SEQUENCE_NUM_STORED]; + + eeprom_read_block(&stored_sequences, (uint8_t *)EECONFIG_SIZE, PAIRING_STORAGE_SIZE); + + uint8_t shiftLen = sizeof(&pairing_sequence); + + for (int8_t i = PAIRING_STORAGE_SIZE; i >= 0; i--) { + if (i > shiftLen) { + stored_sequences[i] = stored_sequences[i - 1]; + } else { + stored_sequences[i] = 0; + } + } + eeprom_update_block(stored_sequences, (uint8_t *)EECONFIG_SIZE, PAIRING_STORAGE_SIZE); + return true; } -bool is_oryx_live_training_enabled(void) { return (oryx_state_live_training_enabled && webusb_state.paired); } +void pairing_init_handler(void) { + create_pairing_code(); + uint8_t event[RAW_EPSIZE]; + uint8_t event_index = 0; + event[event_index++] = ORYX_EVT_PAIRING_INPUT; + for (uint8_t i = 0; i < PAIRING_SEQUENCE_SIZE; i++) { + event[event_index++] = keyboard_pairing_sequence[i].col; + event[event_index++] = keyboard_pairing_sequence[i].row; + } + event[event_index++] = ORYX_STOP_BIT; + rawhid_state.pairing = true; + raw_hid_send(event, RAW_EPSIZE); +} -bool process_record_oryx(uint16_t keycode, keyrecord_t *record) { - if(is_oryx_live_training_enabled()) { - uint8_t event[5]; - event[0] = WEBUSB_STATUS_OK; - event[1] = record->event.pressed ? ORYX_EVT_KEYDOWN : ORYX_EVT_KEYUP; - event[2] = record->event.key.col; - event[3] = record->event.key.row; - event[4] = WEBUSB_STOP_BIT; - webusb_send(event, sizeof(event)); +void pairing_validate_handler() { + bool valid = true; + uint8_t event[RAW_EPSIZE]; + for (uint8_t i = 0; i < PAIRING_SEQUENCE_SIZE; i++) { + if (keyboard_pairing_sequence[i].row != host_pairing_sequence[i].row) { + valid = false; + break; + } + if (keyboard_pairing_sequence[i].col != host_pairing_sequence[i].col) { + valid = false; + break; + } } - if (keycode == WEBUSB_PAIR && record->event.pressed) { - webusb_state.pairing ^= true; - return true; + if (valid == true) { + event[0] = ORYX_EVT_PAIRING_SUCCESS; + rawhid_state.paired = true; + + } else { + event[0] = ORYX_EVT_PAIRING_FAILED; + rawhid_state.paired = false; } + event[1] = ORYX_STOP_BIT; + rawhid_state.pairing = false; + raw_hid_send(event, sizeof(event)); +} -#ifdef DYNAMIC_KEYMAP_ENABLE - switch (keycode) { - case MACRO00 ... MACRO15: - if (record->event.pressed) { - dynamic_keymap_macro_send(keycode - MACRO00); - } - return false; +keypos_t get_random_keypos(void) { + uint8_t col = rand() % MATRIX_COLS; + uint8_t row = rand() % MATRIX_ROWS; + keypos_t pos = {.col = col, .row = row}; + + if (keymap_key_to_keycode(0, pos) != KC_NO) { + return pos; + } else { + return get_random_keypos(); } -#endif - return true; } -void layer_state_set_oryx(layer_state_t state) { - if(is_oryx_live_training_enabled()) { - uint8_t event[4]; - event[0] = WEBUSB_STATUS_OK; - event[1] = ORYX_EVT_LAYER; - event[2] = get_highest_layer(state); - event[3] = WEBUSB_STOP_BIT; - webusb_send(event, sizeof(event)); +void create_pairing_code(void) { + for (uint8_t i = 0; i < PAIRING_SEQUENCE_SIZE; i++) { + keypos_t pos = get_random_keypos(); + keyboard_pairing_sequence[i] = pos; } } -void eeconfig_init_oryx(void) { -#ifdef DYNAMIC_KEYMAP_ENABLE - // reread settings from flash into eeprom - dynamic_keymap_reset(); - dynamic_keymap_macro_reset(); - eeprom_update_block(FIRMWARE_VERSION, (uint8_t *)EECONFIG_SIZE, sizeof(uint8_t)*FIRMWARE_VERSION_SIZE); +void pairing_key_input_event(void) { + uint8_t event[RAW_EPSIZE]; + event[0] = ORYX_EVT_PAIRING_KEY_INPUT; + raw_hid_send(event, sizeof(event)); } -void matrix_init_oryx(void) { - uint8_t temp[FIRMWARE_VERSION_SIZE]; - uint8_t firmware[FIRMWARE_VERSION_SIZE] = FIRMWARE_VERSION; - eeprom_read_block(&temp, (uint8_t *)EECONFIG_SIZE, sizeof(uint8_t)*FIRMWARE_VERSION_SIZE); - if (!memcmp(&temp, &firmware, sizeof(uint8_t)*FIRMWARE_VERSION_SIZE)) { - eeconfig_init_oryx(); +void oryx_layer_event(void) { + uint8_t layer; + uint8_t event[RAW_EPSIZE]; + layer = get_highest_layer(layer_state); + event[0] = ORYX_EVT_LAYER; + event[1] = layer; + event[2] = ORYX_STOP_BIT; + raw_hid_send(event, sizeof(event)); +} + +bool process_record_oryx(uint16_t keycode, keyrecord_t *record) { + // In pairing mode, key events are absorbed, and the host pairing sequence is filled. + // Once filled, the keyboard and host sequence are compaired, pairing state set to false + // and the proper pairing validation event is sent to the host + if (rawhid_state.pairing == true) { + // The host pairing sequence is filled on key up only + if (!record->event.pressed) { + if (pairing_input_index < PAIRING_SEQUENCE_SIZE) { + host_pairing_sequence[pairing_input_index++] = record->event.key; + pairing_key_input_event(); + } + if (pairing_input_index == PAIRING_SEQUENCE_SIZE) { + rawhid_state.pairing = false; + pairing_input_index = 0; + pairing_validate_handler(); + } + } + return false; + } + // While paired, the keyboard sends keystrokes positions to the host + if (rawhid_state.paired == true) { + uint8_t event[RAW_EPSIZE]; + event[0] = record->event.pressed ? ORYX_EVT_KEYDOWN : ORYX_EVT_KEYUP; + event[1] = record->event.key.col; + event[2] = record->event.key.row; + event[3] = ORYX_STOP_BIT; + raw_hid_send(event, sizeof(event)); + } + return true; +} + +void layer_state_set_oryx(layer_state_t state) { + if (rawhid_state.paired) { + uint8_t event[RAW_EPSIZE]; + event[0] = ORYX_EVT_LAYER; + event[1] = get_highest_layer(state); + event[2] = ORYX_STOP_BIT; + raw_hid_send(event, sizeof(event)); } -#endif } diff --git a/quantum/oryx.h b/quantum/oryx.h index b1fe78a061..5f6581235c 100644 --- a/quantum/oryx.h +++ b/quantum/oryx.h @@ -1,82 +1,61 @@ #pragma once #include "quantum.h" -#include "webusb.h" +#include "raw_hid.h" -#ifndef WEBUSB_ENABLE -# error "WebUSB needs to be enabled, please enable it!" +#ifndef RAW_ENABLE +# error "Raw hid needs to be enabled, please enable it!" +#endif +#ifndef RAW_EPSIZE +# define RAW_EPSIZE 32 #endif -// enum Oryx_Status_code { -// PLACEHOLDER = WEBUSB_STATUS_SAFE_RANGE, -// } +#define ORYX_STOP_BIT -2 +#define PAIRING_BLINK_STEPS 512 +#define PAIRING_BLINK_END PAIRING_BLINK_STEPS * 60 +#define PAIRING_SEQUENCE_SIZE 3 +#define PAIRING_SEQUENCE_NUM_STORED 5 +#define PAIRING_STORAGE_SIZE PAIRING_SEQUENCE_SIZE* PAIRING_SEQUENCE_NUM_STORED * sizeof(uint16_t) enum Oryx_Command_Code { - ORYX_GET_LAYER = WEBUSB_CMD_SAFE_RANGE, - ORYX_CMD_LIVE_TRAINING, - ORYX_CMD_LIVE_UPDATE_GET_KEYCODE, - ORYX_CMD_LIVE_UPDATE_SET_KEYCODE, - ORYX_CMD_LIVE_UPDATE_KEYMAP_RESET, - ORYX_CMD_LIVE_UPDATE_GET_BUFFER, - ORYX_CMD_LIVE_UPDATE_SET_BUFFER, - ORYX_CMD_LIVE_UPDATE_GET_LAYER_COUNT, - ORYX_CMD_LIVE_UPDATE_GET_MACRO_COUNT, - ORYX_CMD_LIVE_UPDATE_GET_MACRO_BUFFER_SIZE, - ORYX_CMD_LIVE_UPDATE_GET_MACRO_BUFFER, - ORYX_CMD_LIVE_UPDATE_SET_MACRO_BUFFER, - ORYX_CMD_LIVE_UPDATE_MACRO_RESET, - ORYX_CMD_LIVE_UPDATE_EEPROM_RESET, - ORYX_CMD_LIVE_UPDATE_KEYBOARD_RESET, - + ORYX_CMD_GET_FW_VERSION, + ORYX_CMD_PAIRING_INIT, + ORYX_CMD_PAIRING_VALIDATE, + ORYX_CMD_DISCONNECT, + ORYX_GET_LAYER, }; enum Oryx_Event_Code { - ORYX_EVT_LAYER = WEBUSB_EVT_SAFE_RANGE, - ORYX_EVT_LIVE_TRAINING, - ORYX_EVT_LIVE_UPDATE_GET_KEYCODE, - ORYX_EVT_LIVE_UPDATE_SET_KEYCODE, - ORYX_EVT_LIVE_UPDATE_KEYMAP_RESET, - ORYX_EVT_LIVE_UPDATE_GET_BUFFER, - ORYX_EVT_LIVE_UPDATE_SET_BUFFER, - ORYX_EVT_LIVE_UPDATE_GET_LAYER_COUNT, - ORYX_EVT_LIVE_UPDATE_GET_MACRO_COUNT, - ORYX_EVT_LIVE_UPDATE_GET_MACRO_BUFFER_SIZE, - ORYX_EVT_LIVE_UPDATE_GET_MACRO_BUFFER, - ORYX_EVT_LIVE_UPDATE_SET_MACRO_BUFFER, - ORYX_EVT_LIVE_UPDATE_MACRO_RESET, - ORYX_EVT_LIVE_UPDATE_EEPROM_RESET, - ORYX_EVT_LIVE_UPDATE_KEYBOARD_RESET, + ORYX_EVT_GET_FW_VERSION, + ORYX_EVT_PAIRING_INPUT, + ORYX_EVT_PAIRING_KEY_INPUT, + ORYX_EVT_PAIRING_FAILED, + ORYX_EVT_PAIRING_SUCCESS, + ORYX_EVT_LAYER, ORYX_EVT_KEYDOWN, ORYX_EVT_KEYUP, }; -#ifdef DYNAMIC_KEYMAP_ENABLE -enum dynamic_macros_keycodes { - MACRO00 = 0x5F12, - MACRO01, - MACRO02, - MACRO03, - MACRO04, - MACRO05, - MACRO06, - MACRO07, - MACRO08, - MACRO09, - MACRO10, - MACRO11, - MACRO12, - MACRO13, - MACRO14, - MACRO15, -}; -#endif - extern bool oryx_state_live_training_enabled; -bool webusb_receive_oryx(uint8_t *data, uint8_t length); +typedef struct { + bool pairing; + bool paired; +} rawhid_state_t; + +extern rawhid_state_t rawhid_state; + +void create_pairing_code(void); +bool store_pairing_sequence(keypos_t* pairing_sequence); +keypos_t get_random_keypos(void); +void pairing_init_handler(void); +void pairing_validate_handler(void); +void pairing_init_event(void); +void pairing_key_input_event(void); +void pairing_failed_event(void); +void pairing_succesful_event(void); + void oryx_layer_event(void); bool is_oryx_live_training_enabled(void); -bool process_record_oryx(uint16_t keycode, keyrecord_t *record); +bool process_record_oryx(uint16_t keycode, keyrecord_t* record); void layer_state_set_oryx(layer_state_t state); -void eeconfig_init_oryx(void); -void matrix_init_oryx(void); diff --git a/quantum/quantum.c b/quantum/quantum.c index 077e7d9d8f..7efe97ae52 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -258,7 +258,7 @@ bool process_record_quantum(keyrecord_t *record) { #endif #ifdef HAPTIC_ENABLE process_haptic(keycode, record) && -#endif // HAPTIC_ENABLE +#endif // HAPTIC_ENABLE #ifdef ORYX_ENABLE process_record_oryx(keycode, record) && #endif @@ -412,7 +412,6 @@ bool process_record_quantum(keyrecord_t *record) { } } - return process_action_kb(record); } @@ -442,21 +441,19 @@ void matrix_scan_quantum() { matrix_scan_kb(); } - #ifdef WEBUSB_ENABLE -__attribute__((weak)) bool webusb_receive_user(uint8_t *data, uint8_t length) { return false; } -__attribute__((weak)) bool webusb_receive_kb(uint8_t *data, uint8_t length) { return webusb_receive_user(data, length); } +__attribute__((weak)) bool webusb_receive_user(uint8_t *data, uint8_t length) { + return false; +} +__attribute__((weak)) bool webusb_receive_kb(uint8_t *data, uint8_t length) { + return webusb_receive_user(data, length); +} bool webusb_receive_quantum(uint8_t *data, uint8_t length) { -# ifdef ORYX_ENABLE - return webusb_receive_oryx(data, length); -# else return webusb_receive_kb(data, length); -# endif } #endif - //------------------------------------------------------------------------------ // Override these functions in your keymap file to play different tunes on // different events such as startup and bootloader jump @@ -465,7 +462,6 @@ __attribute__((weak)) void startup_user() {} __attribute__((weak)) void shutdown_user() {} - void suspend_power_down_quantum(void) { suspend_power_down_kb(); #ifndef NO_SUSPEND_POWER_DOWN diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index 66cef7838a..04ae3d7f4d 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -49,6 +49,14 @@ extern keymap_config_t keymap_config; #endif +#ifdef RAW_ENABLE +# include "raw_hid.h" +#endif + +#ifdef ORYX_ENABLE +# include "oryx.h" +#endif + #ifdef WEBUSB_ENABLE # include "webusb.h" #endif @@ -176,7 +184,6 @@ static const USBEndpointConfig shared_ep_config = { }; #endif - #ifdef WEBUSB_ENABLE /** Microsoft OS 2.0 Descriptor. This is used by Windows to select the USB driver for the device. * @@ -391,10 +398,10 @@ static usb_driver_configs_t drivers = { #endif #ifdef WEBUSB_ENABLE -# define WEBUSB_IN_CAPACITY 4 -# define WEBUSB_OUT_CAPACITY 4 -# define WEBUSB_IN_MODE USB_EP_MODE_TYPE_INTR -# define WEBUSB_OUT_MODE USB_EP_MODE_TYPE_INTR +# define WEBUSB_IN_CAPACITY 4 +# define WEBUSB_OUT_CAPACITY 4 +# define WEBUSB_IN_MODE USB_EP_MODE_TYPE_INTR +# define WEBUSB_OUT_MODE USB_EP_MODE_TYPE_INTR .webusb_driver = QMK_USB_DRIVER_CONFIG(WEBUSB, 0, false), #endif #ifdef JOYSTICK_ENABLE @@ -463,9 +470,9 @@ static inline void usb_event_wakeup_handler(void) { suspend_wakeup_init(); usb_device_state_set_resume(USB_DRIVER.configuration != 0, USB_DRIVER.configuration); #ifdef SLEEP_LED_ENABLE - sleep_led_disable(); - // NOTE: converters may not accept this - led_set(host_keyboard_leds()); + sleep_led_disable(); + // NOTE: converters may not accept this + led_set(host_keyboard_leds()); #endif /* SLEEP_LED_ENABLE */ } @@ -1145,7 +1152,15 @@ void raw_hid_send(uint8_t *data, uint8_t length) { if (length != RAW_EPSIZE) { return; } + +# ifdef ORYX_ENABLE + if (chnWriteTimeout(&drivers.raw_driver.driver, data, length, TIME_IMMEDIATE) != length) { + rawhid_state.pairing = false; + rawhid_state.paired = false; + } +# else chnWrite(&drivers.raw_driver.driver, data, length); +# endif } __attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) { @@ -1169,15 +1184,15 @@ void raw_hid_task(void) { #ifdef WEBUSB_ENABLE void webusb_send(uint8_t *data, uint8_t length) { - if(chnWriteTimeout(&drivers.webusb_driver.driver, data, length, TIME_IMMEDIATE) != length){ - webusb_state.paired = false; + if (chnWriteTimeout(&drivers.webusb_driver.driver, data, length, TIME_IMMEDIATE) != length) { + webusb_state.paired = false; webusb_state.pairing = false; } } - // Users should #include "raw_hid.h" in their own code - // and implement this function there. Leave this as weak linkage - // so users can opt to not handle data coming in. +// Users should #include "raw_hid.h" in their own code +// and implement this function there. Leave this as weak linkage +// so users can opt to not handle data coming in. void webusb_task(void) { uint8_t buffer[WEBUSB_EPSIZE]; diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index bf005d519f..1084f67659 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -161,7 +161,10 @@ void raw_hid_send(uint8_t *data, uint8_t length) { // Check to see if the host is ready to accept another packet if (Endpoint_IsINReady()) { // Write data - Endpoint_Write_Stream_LE(data, RAW_EPSIZE, NULL); + if (Endpoint_Write_Stream_LE(data, RAW_EPSIZE, NULL)) { + rawhid_state.pairing = false; + rawhid_state.paired = false; + } // Finalize the stream transfer to send the last packet Endpoint_ClearIN(); } @@ -279,9 +282,9 @@ void webusb_send(uint8_t *data, uint8_t length) { Endpoint_SelectEndpoint(WEBUSB_IN_EPNUM); - if(Endpoint_Write_Stream_LE(data, length, NULL)) { + if (Endpoint_Write_Stream_LE(data, length, NULL)) { // Stream failed to complete, resetting WEBUSB's state - webusb_state.paired = false; + webusb_state.paired = false; webusb_state.pairing = false; } Endpoint_ClearIN(); @@ -292,7 +295,6 @@ static void webusb_task(void) { uint8_t data[WEBUSB_EPSIZE]; bool data_read = false; - // Device must be connected and configured for the task to run if (USB_DeviceState != DEVICE_STATE_Configured) return; @@ -543,9 +545,9 @@ void EVENT_USB_Device_ConfigurationChanged(void) { #endif #ifdef WEBUSB_ENABLE - /* Setup Webusb Endpoints */ - ConfigSuccess &= Endpoint_ConfigureEndpoint(WEBUSB_IN_EPADDR, EP_TYPE_INTERRUPT, WEBUSB_EPSIZE, 1); - ConfigSuccess &= Endpoint_ConfigureEndpoint(WEBUSB_OUT_EPADDR, EP_TYPE_INTERRUPT, WEBUSB_EPSIZE, 1); + /* Setup Webusb Endpoints */ + ConfigSuccess &= Endpoint_ConfigureEndpoint(WEBUSB_IN_EPADDR, EP_TYPE_INTERRUPT, WEBUSB_EPSIZE, 1); + ConfigSuccess &= Endpoint_ConfigureEndpoint(WEBUSB_OUT_EPADDR, EP_TYPE_INTERRUPT, WEBUSB_EPSIZE, 1); #endif #ifdef MIDI_ENABLE @@ -697,23 +699,23 @@ void EVENT_USB_Device_ControlRequest(void) { case WEBUSB_VENDOR_CODE: if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR | REQREC_DEVICE)) { switch (USB_ControlRequest.wIndex) { - case WebUSB_RTYPE_GetURL: - switch (USB_ControlRequest.wValue) { - case WEBUSB_LANDING_PAGE_INDEX: - Endpoint_ClearSETUP(); - /* Write the descriptor data to the control endpoint */ - Endpoint_Write_Control_PStream_LE(&WebUSB_LandingPage, WebUSB_LandingPage.Header.Size); - /* Release the endpoint after transaction. */ - Endpoint_ClearStatusStage(); + case WebUSB_RTYPE_GetURL: + switch (USB_ControlRequest.wValue) { + case WEBUSB_LANDING_PAGE_INDEX: + Endpoint_ClearSETUP(); + /* Write the descriptor data to the control endpoint */ + Endpoint_Write_Control_PStream_LE(&WebUSB_LandingPage, WebUSB_LandingPage.Header.Size); + /* Release the endpoint after transaction. */ + Endpoint_ClearStatusStage(); + break; + default: /* Stall transfer on invalid index. */ + Endpoint_StallTransaction(); + break; + } break; - default: /* Stall transfer on invalid index. */ + default: /* Stall on unknown WebUSB request */ Endpoint_StallTransaction(); break; - } - break; - default: /* Stall on unknown WebUSB request */ - Endpoint_StallTransaction(); - break; } } @@ -721,16 +723,16 @@ void EVENT_USB_Device_ControlRequest(void) { case MS_OS_20_VENDOR_CODE: if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR | REQREC_DEVICE)) { switch (USB_ControlRequest.wIndex) { - case MS_OS_20_DESCRIPTOR_INDEX: - Endpoint_ClearSETUP(); - /* Write the descriptor data to the control endpoint */ - Endpoint_Write_Control_PStream_LE(&MS_OS_20_Descriptor, MS_OS_20_Descriptor.Header.TotalLength); - /* Release the endpoint after transaction. */ - Endpoint_ClearStatusStage(); - break; - default: /* Stall on unknown MS OS 2.0 request */ - Endpoint_StallTransaction(); - break; + case MS_OS_20_DESCRIPTOR_INDEX: + Endpoint_ClearSETUP(); + /* Write the descriptor data to the control endpoint */ + Endpoint_Write_Control_PStream_LE(&MS_OS_20_Descriptor, MS_OS_20_Descriptor.Header.TotalLength); + /* Release the endpoint after transaction. */ + Endpoint_ClearStatusStage(); + break; + default: /* Stall on unknown MS OS 2.0 request */ + Endpoint_StallTransaction(); + break; } } break; @@ -896,7 +898,6 @@ static void send_consumer(uint16_t data) { #endif } - static void send_programmable_button(uint32_t data) { #ifdef PROGRAMMABLE_BUTTON_ENABLE static report_programmable_button_t r; @@ -1209,7 +1210,7 @@ void protocol_post_task(void) { #endif #ifdef WEBUSB_ENABLE - webusb_task(); + webusb_task(); #endif #if !defined(INTERRUPT_CONTROL_ENDPOINT) |