summaryrefslogtreecommitdiff
path: root/quantum/oryx.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/oryx.c')
-rw-r--r--quantum/oryx.c379
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, &param[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, &param[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, &param[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, &param[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
}