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 /quantum/oryx.c | |
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)
Diffstat (limited to 'quantum/oryx.c')
-rw-r--r-- | quantum/oryx.c | 379 |
1 files changed, 153 insertions, 226 deletions
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 } |