From 3c817f0b1bf3f326a1b470f53608934d993c6cc8 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 6 Jan 2017 09:05:00 +0100 Subject: [PATCH] deserialize: Initial layer deserialization So far, the code is able to deserialize and apply a single layer, as saved by the Agent in binary format. It does not support macros and keymap switching yet (it parses the latter, but will choke on the former), but the rest should be handled fine. Signed-off-by: Gergely Nagy --- right/src/deserialize.c | 241 ++++++++++++++++++++++++++++++++++++++++ right/src/deserialize.h | 8 ++ right/src/main.c | 13 +++ 3 files changed, 262 insertions(+) create mode 100644 right/src/deserialize.c create mode 100644 right/src/deserialize.h diff --git a/right/src/deserialize.c b/right/src/deserialize.c new file mode 100644 index 0000000..cc2f258 --- /dev/null +++ b/right/src/deserialize.c @@ -0,0 +1,241 @@ +#include "deserialize.h" +#include "action.h" +#define longCompactLengthPrefix 0xff + +#define HAS_SCANCODE (1 << 0) +#define HAS_MODS (1 << 1) +#define HAS_LONGPRESS (1 << 2) + +typedef struct { + const uint8_t *buffer; + uint16_t offset; +} serialized_buffer_t; + +enum { + NoneAction = 0, + KeyStrokeAction = 1, + LastKeyStrokeAction = 7, + SwitchLayerAction, + SwitchKeymapAction, + MouseAction, + PlayMacroAction +}; + +// ---------------- + +static uint8_t readUInt8(serialized_buffer_t *buffer) { + return buffer->buffer[buffer->offset++]; +} + +static bool readBool(serialized_buffer_t *buffer) { + return buffer->buffer[buffer->offset++] == 1; +} + +static uint16_t readCompactLength(serialized_buffer_t *buffer) { + uint16_t length = readUInt8(buffer); + if (length == longCompactLengthPrefix) { + length += readUInt8(buffer) << 8; + } + return length; +} + +static const char *readString(serialized_buffer_t *buffer, uint16_t *len) { + const char *str = (const char *)&(buffer->buffer[buffer->offset]); + + *len = readCompactLength(buffer); + buffer->offset += *len; + + return str; +} + +// ---------------- + +static uint8_t findIndex(uint8_t moduleID, uint8_t idx) { + switch (moduleID) { + case 0: + switch (idx) { + case 0 ... 6: + return idx; + case 7: + return 14; + case 8 ... 14: + return idx - 1; + case 15: + return 21; + case 16 ... 21: + return idx - 1; + case 22 ... 27: + return idx; + case 28: + return idx + 1; + case 29 ... 32: + return idx + 2; + case 33: + return 30; + } + break; + + case 1: + switch (idx) { + case 0 ... 11: + return idx; + case 12 ... 17: + return idx + 1; + case 18 ... 19: + return idx + 2; + case 20 ... 28: + return idx + 3; + case 29: + return 33; + case 30: + return 32; + } + break; + } + return idx; +} + +static void processNoneAction(key_action_t *action, serialized_buffer_t *buffer) { + action->type = KEY_ACTION_NONE; +} + +static void processKeyStrokeAction(key_action_t *action, uint8_t actionType, serialized_buffer_t *buffer) { + uint8_t flags = actionType - 1; + + action->type = KEY_ACTION_KEYSTROKE; + + if (flags & HAS_SCANCODE) { + action->keystroke.key = readUInt8(buffer); + } + if (flags & HAS_MODS) { + action->keystroke.mods = readUInt8(buffer); + } + if (flags & HAS_LONGPRESS) { + action->keystroke.longPress = readUInt8(buffer); + } +} + +static void processSwitchLayerAction(key_action_t *action, serialized_buffer_t *buffer) { + uint8_t layer = readUInt8(buffer) + 1; + bool isToggle = readBool(buffer); + + action->type = KEY_ACTION_SWITCH_LAYER; + action->switchLayer.layer = layer; + action->switchLayer.isToggle = isToggle; +} + +static void processSwitchKeymapAction(key_action_t *action, serialized_buffer_t *buffer) { + uint16_t len; + const char *keymap = readString(buffer, &len); + + action->type = KEY_ACTION_SWITCH_KEYMAP; + + // TODO: Implement this +} + +static void processMouseAction(key_action_t *action, serialized_buffer_t *buffer) { + uint8_t mouseAction = readUInt8(buffer); + + action->type = KEY_ACTION_MOUSE; + switch (mouseAction) { + case 0: // leftClick + action->mouse.buttonActions |= MOUSE_BUTTON_LEFT; + break; + case 1: // middleClick + action->mouse.buttonActions |= MOUSE_BUTTON_MIDDLE; + break; + case 2: // rightClick + action->mouse.buttonActions |= MOUSE_BUTTON_RIGHT; + break; + case 3: // moveUp + action->mouse.moveActions |= MOUSE_MOVE_UP; + break; + case 4: // moveDown + action->mouse.moveActions |= MOUSE_MOVE_DOWN; + break; + case 5: // moveLeft + action->mouse.moveActions |= MOUSE_MOVE_LEFT; + break; + case 6: // moveRight + action->mouse.moveActions |= MOUSE_MOVE_RIGHT; + break; + case 7: // scrollUp + action->mouse.scrollActions |= MOUSE_SCROLL_UP; + break; + case 8: // scrollDown + action->mouse.scrollActions |= MOUSE_SCROLL_DOWN; + break; + case 9: // scrollLeft + action->mouse.scrollActions |= MOUSE_SCROLL_LEFT; + break; + case 10: // scrollRight + action->mouse.scrollActions |= MOUSE_SCROLL_RIGHT; + break; + case 11: // accelerate + action->mouse.moveActions |= MOUSE_ACCELERATE; + break; + case 12: // decelerate + action->mouse.moveActions |= MOUSE_DECELERATE; + break; + } +} + +static void processKeyAction(key_action_t *action, serialized_buffer_t *buffer) { + uint8_t actionType = readUInt8(buffer); + + switch (actionType) { + case NoneAction: + return processNoneAction(action, buffer); + case KeyStrokeAction ... LastKeyStrokeAction: + return processKeyStrokeAction(action, actionType, buffer); + case SwitchLayerAction: + return processSwitchLayerAction(action, buffer); + case SwitchKeymapAction: + return processSwitchKeymapAction(action, buffer); + case MouseAction: + return processMouseAction(action, buffer); + default: + // TODO: Handle the case where the actionType is unknown + break; + } +} + +static void processKeyActions(uint8_t targetLayer, serialized_buffer_t *buffer, uint8_t moduleID, uint8_t pointerRole) { + uint8_t actionCount = readCompactLength(buffer); + + for (uint8_t actionIdx = 0; actionIdx < actionCount; actionIdx++) { + uint8_t pos = findIndex(moduleID, actionIdx); + key_action_t *action = &(CurrentKeymap[targetLayer][moduleID][pos]); + + processKeyAction(action, buffer); + } +} + +static void processModule(serialized_buffer_t *buffer, uint8_t targetLayer) { + uint8_t moduleID, pointerRole; + + moduleID = readUInt8(buffer); + pointerRole = readUInt8(buffer); + + processKeyActions(targetLayer, buffer, moduleID, pointerRole); +} + +static void clearModule(uint8_t targetLayer, uint8_t moduleID) { + memset(&CurrentKeymap[targetLayer][moduleID], 0, MAX_KEY_COUNT_PER_MODULE * sizeof(key_action_t)); +} + +// ---------- + +void deserialize_Layer (const uint8_t *data, uint8_t targetLayer) { + serialized_buffer_t buffer; + + buffer.buffer = data; + buffer.offset = 0; + + uint8_t moduleCount = readCompactLength(&buffer); + + for (uint8_t modIdx = 0; modIdx < moduleCount; modIdx++) { + clearModule(targetLayer, modIdx); + processModule(&buffer, targetLayer); + } +} diff --git a/right/src/deserialize.h b/right/src/deserialize.h new file mode 100644 index 0000000..4989836 --- /dev/null +++ b/right/src/deserialize.h @@ -0,0 +1,8 @@ +#ifndef __DESERIALIZE_H__ +#define __DESERIALIZE_H__ 1 + +#include + +void deserialize_Layer(const uint8_t *data, uint8_t targetLayer); + +#endif diff --git a/right/src/main.c b/right/src/main.c index e45e9af..7c3f11d 100644 --- a/right/src/main.c +++ b/right/src/main.c @@ -3,6 +3,7 @@ #include "init_peripherials.h" #include "usb_composite_device.h" #include "led_driver.h" +#include "deserialize.h" key_matrix_t KeyMatrix = { .colNum = KEYBOARD_MATRIX_COLS_NUM, @@ -47,6 +48,16 @@ key_matrix_t KeyMatrix = { uint8_t PreviousKeyStates[SLOT_COUNT][MAX_KEY_COUNT_PER_MODULE]; uint8_t CurrentKeyStates[SLOT_COUNT][MAX_KEY_COUNT_PER_MODULE]; +static const uint8_t testData[] = + {0x03, 0x00, 0x01, 0x22, 0x02, 0x24, 0x02, 0x25, 0x02, 0x26, 0x02, 0x27, 0x02, 0x2d, 0x02, 0x2e, 0x02, 0x2a, 0x02, + 0x1c, 0x02, 0x18, 0x02, 0x0c, 0x02, 0x12, 0x04, 0x13, 0x22, 0x02, 0x2f, 0x02, 0x30, 0x02, 0x31, 0x02, 0x0b, 0x02, + 0x0d, 0x02, 0x0e, 0x02, 0x0f, 0x02, 0x33, 0x02, 0x34, 0x02, 0x28, 0x02, 0x11, 0x02, 0x10, 0x02, 0x36, 0x02, 0x37, + 0x02, 0x38, 0x0a, 0x03, 0x02, 0x2c, 0x02, 0x1c, 0x02, 0x1b, 0x02, 0x1a, 0x02, 0x14, 0x02, 0x1d, 0x01, 0x01, 0x1f, + 0x02, 0x35, 0x02, 0x1e, 0x02, 0x1f, 0x02, 0x20, 0x02, 0x21, 0x02, 0x22, 0x02, 0x23, 0x06, 0x29, 0x09, 0x02, 0x14, + 0x02, 0x1a, 0x02, 0x08, 0x02, 0x15, 0x02, 0x17, 0x02, 0x2b, 0x02, 0x04, 0x02, 0x16, 0x02, 0x07, 0x02, 0x09, 0x02, + 0x0a, 0x02, 0x2d, 0x02, 0x1d, 0x02, 0x1b, 0x02, 0x06, 0x02, 0x19, 0x02, 0x05, 0x02, 0x04, 0x02, 0x05, 0x02, 0x06, + 0x02, 0x07, 0x02, 0x08, 0x02, 0x09, 0x02, 0x02, 0x00 }; + void main() { InitPeripherials(); InitClock(); @@ -55,6 +66,8 @@ void main() { UsbKeyboadTask(); InitUsb(); + // deserialize_Layer(testData, 0); + while (1) { UsbKeyboadTask(); asm("wfi");