429 lines
12 KiB
C
429 lines
12 KiB
C
#include "macros.h"
|
|
#include "config_parser/parse_macro.h"
|
|
#include "config_parser/config_globals.h"
|
|
#include "timer.h"
|
|
|
|
macro_reference_t AllMacros[MAX_MACRO_NUM];
|
|
uint8_t AllMacrosCount;
|
|
bool MacroPlaying = false;
|
|
usb_mouse_report_t MacroMouseReport;
|
|
usb_basic_keyboard_report_t MacroBasicKeyboardReport;
|
|
usb_media_keyboard_report_t MacroMediaKeyboardReport;
|
|
usb_system_keyboard_report_t MacroSystemKeyboardReport;
|
|
|
|
static uint8_t currentMacroIndex;
|
|
static uint16_t currentMacroActionIndex;
|
|
static macro_action_t currentMacroAction;
|
|
|
|
uint8_t characterToScancode(char character)
|
|
{
|
|
switch (character) {
|
|
case 'A' ... 'Z':
|
|
case 'a' ... 'z':
|
|
return HID_KEYBOARD_SC_A - 1 + (character & 0x1F);
|
|
case '1' ... '9':
|
|
return HID_KEYBOARD_SC_1_AND_EXCLAMATION - 1 + (character & 0x0F);
|
|
case ')':
|
|
case '0':
|
|
return HID_KEYBOARD_SC_0_AND_CLOSING_PARENTHESIS;
|
|
case '!':
|
|
return HID_KEYBOARD_SC_1_AND_EXCLAMATION;
|
|
case '@':
|
|
return HID_KEYBOARD_SC_2_AND_AT;
|
|
case '#':
|
|
return HID_KEYBOARD_SC_3_AND_HASHMARK;
|
|
case '$':
|
|
return HID_KEYBOARD_SC_4_AND_DOLLAR;
|
|
case '%':
|
|
return HID_KEYBOARD_SC_5_AND_PERCENTAGE;
|
|
case '^':
|
|
return HID_KEYBOARD_SC_6_AND_CARET;
|
|
case '&':
|
|
return HID_KEYBOARD_SC_7_AND_AMPERSAND;
|
|
case '*':
|
|
return HID_KEYBOARD_SC_8_AND_ASTERISK;
|
|
case '(':
|
|
return HID_KEYBOARD_SC_9_AND_OPENING_PARENTHESIS;
|
|
case '`':
|
|
case '~':
|
|
return HID_KEYBOARD_SC_GRAVE_ACCENT_AND_TILDE;
|
|
case '[':
|
|
case '{':
|
|
return HID_KEYBOARD_SC_OPENING_BRACKET_AND_OPENING_BRACE;
|
|
case ']':
|
|
case '}':
|
|
return HID_KEYBOARD_SC_CLOSING_BRACKET_AND_CLOSING_BRACE;
|
|
case ';':
|
|
case ':':
|
|
return HID_KEYBOARD_SC_SEMICOLON_AND_COLON;
|
|
case '\'':
|
|
case '\"':
|
|
return HID_KEYBOARD_SC_APOSTROPHE_AND_QUOTE;
|
|
case '+':
|
|
case '=':
|
|
return HID_KEYBOARD_SC_EQUAL_AND_PLUS;
|
|
case '\\':
|
|
case '|':
|
|
return HID_KEYBOARD_SC_BACKSLASH_AND_PIPE;
|
|
case '.':
|
|
case '>':
|
|
return HID_KEYBOARD_SC_DOT_AND_GREATER_THAN_SIGN;
|
|
case ',':
|
|
case '<':
|
|
return HID_KEYBOARD_SC_COMMA_AND_LESS_THAN_SIGN;
|
|
case '/':
|
|
case '\?':
|
|
return HID_KEYBOARD_SC_SLASH_AND_QUESTION_MARK;
|
|
case '-':
|
|
case '_':
|
|
return HID_KEYBOARD_SC_MINUS_AND_UNDERSCORE;
|
|
case '\n':
|
|
return HID_KEYBOARD_SC_ENTER;
|
|
case ' ':
|
|
return HID_KEYBOARD_SC_SPACE;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool characterToShift(char character)
|
|
{
|
|
switch (character) {
|
|
case 'A' ... 'Z':
|
|
case ')':
|
|
case '!':
|
|
case '@':
|
|
case '#':
|
|
case '$':
|
|
case '%':
|
|
case '^':
|
|
case '&':
|
|
case '*':
|
|
case '(':
|
|
case '~':
|
|
case '{':
|
|
case '}':
|
|
case ':':
|
|
case '\"':
|
|
case '+':
|
|
case '|':
|
|
case '>':
|
|
case '<':
|
|
case '\?':
|
|
case '_':
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void addBasicScancode(uint8_t scancode)
|
|
{
|
|
if (!scancode) {
|
|
return;
|
|
}
|
|
for (uint8_t i = 0; i < USB_BASIC_KEYBOARD_MAX_KEYS; i++) {
|
|
if (MacroBasicKeyboardReport.scancodes[i] == scancode) {
|
|
return;
|
|
}
|
|
}
|
|
for (uint8_t i = 0; i < USB_BASIC_KEYBOARD_MAX_KEYS; i++) {
|
|
if (!MacroBasicKeyboardReport.scancodes[i]) {
|
|
MacroBasicKeyboardReport.scancodes[i] = scancode;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void deleteBasicScancode(uint8_t scancode)
|
|
{
|
|
if (!scancode) {
|
|
return;
|
|
}
|
|
for (uint8_t i = 0; i < USB_BASIC_KEYBOARD_MAX_KEYS; i++) {
|
|
if (MacroBasicKeyboardReport.scancodes[i] == scancode) {
|
|
MacroBasicKeyboardReport.scancodes[i] = 0;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void addModifiers(uint8_t modifiers)
|
|
{
|
|
MacroBasicKeyboardReport.modifiers |= modifiers;
|
|
}
|
|
|
|
void deleteModifiers(uint8_t modifiers)
|
|
{
|
|
MacroBasicKeyboardReport.modifiers &= ~modifiers;
|
|
}
|
|
|
|
void addMediaScancode(uint16_t scancode)
|
|
{
|
|
if (!scancode) {
|
|
return;
|
|
}
|
|
for (uint8_t i = 0; i < USB_MEDIA_KEYBOARD_MAX_KEYS; i++) {
|
|
if (MacroMediaKeyboardReport.scancodes[i] == scancode) {
|
|
return;
|
|
}
|
|
}
|
|
for (uint8_t i = 0; i < USB_MEDIA_KEYBOARD_MAX_KEYS; i++) {
|
|
if (!MacroMediaKeyboardReport.scancodes[i]) {
|
|
MacroMediaKeyboardReport.scancodes[i] = scancode;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void deleteMediaScancode(uint16_t scancode)
|
|
{
|
|
if (!scancode) {
|
|
return;
|
|
}
|
|
for (uint8_t i = 0; i < USB_MEDIA_KEYBOARD_MAX_KEYS; i++) {
|
|
if (MacroMediaKeyboardReport.scancodes[i] == scancode) {
|
|
MacroMediaKeyboardReport.scancodes[i] = 0;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void addSystemScancode(uint8_t scancode)
|
|
{
|
|
if (!scancode) {
|
|
return;
|
|
}
|
|
for (uint8_t i = 0; i < USB_SYSTEM_KEYBOARD_MAX_KEYS; i++) {
|
|
if (MacroSystemKeyboardReport.scancodes[i] == scancode) {
|
|
return;
|
|
}
|
|
}
|
|
for (uint8_t i = 0; i < USB_SYSTEM_KEYBOARD_MAX_KEYS; i++) {
|
|
if (!MacroSystemKeyboardReport.scancodes[i]) {
|
|
MacroSystemKeyboardReport.scancodes[i] = scancode;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void deleteSystemScancode(uint8_t scancode)
|
|
{
|
|
if (!scancode) {
|
|
return;
|
|
}
|
|
for (uint8_t i = 0; i < USB_SYSTEM_KEYBOARD_MAX_KEYS; i++) {
|
|
if (MacroSystemKeyboardReport.scancodes[i] == scancode) {
|
|
MacroSystemKeyboardReport.scancodes[i] = 0;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void addScancode(uint16_t scancode, keystroke_type_t type)
|
|
{
|
|
switch (type) {
|
|
case KeystrokeType_Basic:
|
|
addBasicScancode(scancode);
|
|
break;
|
|
case KeystrokeType_Media:
|
|
addMediaScancode(scancode);
|
|
break;
|
|
case KeystrokeType_System:
|
|
addSystemScancode(scancode);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void deleteScancode(uint16_t scancode, keystroke_type_t type)
|
|
{
|
|
switch (type) {
|
|
case KeystrokeType_Basic:
|
|
deleteBasicScancode(scancode);
|
|
break;
|
|
case KeystrokeType_Media:
|
|
deleteMediaScancode(scancode);
|
|
break;
|
|
case KeystrokeType_System:
|
|
deleteSystemScancode(scancode);
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool processKeyAction(void)
|
|
{
|
|
static bool pressStarted;
|
|
|
|
switch (currentMacroAction.key.action) {
|
|
case MacroSubAction_Tap:
|
|
if (!pressStarted) {
|
|
pressStarted = true;
|
|
addModifiers(currentMacroAction.key.modifierMask);
|
|
addScancode(currentMacroAction.key.scancode, currentMacroAction.key.type);
|
|
return true;
|
|
}
|
|
pressStarted = false;
|
|
deleteModifiers(currentMacroAction.key.modifierMask);
|
|
deleteScancode(currentMacroAction.key.scancode, currentMacroAction.key.type);
|
|
break;
|
|
case MacroSubAction_Release:
|
|
deleteModifiers(currentMacroAction.key.modifierMask);
|
|
deleteScancode(currentMacroAction.key.scancode, currentMacroAction.key.type);
|
|
break;
|
|
case MacroSubAction_Press:
|
|
addModifiers(currentMacroAction.key.modifierMask);
|
|
addScancode(currentMacroAction.key.scancode, currentMacroAction.key.type);
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool processDelayAction(void)
|
|
{
|
|
static bool inDelay;
|
|
static uint32_t delayStart;
|
|
|
|
if (inDelay) {
|
|
if (Timer_GetElapsedTime(&delayStart) >= currentMacroAction.delay.delay) {
|
|
inDelay = false;
|
|
}
|
|
} else {
|
|
delayStart = CurrentTime;
|
|
inDelay = true;
|
|
}
|
|
return inDelay;
|
|
}
|
|
|
|
bool processMouseButtonAction(void)
|
|
{
|
|
static bool pressStarted;
|
|
|
|
switch (currentMacroAction.mouseButton.action) {
|
|
case MacroSubAction_Tap:
|
|
if (!pressStarted) {
|
|
pressStarted = true;
|
|
MacroMouseReport.buttons |= currentMacroAction.mouseButton.mouseButtonsMask;
|
|
return true;
|
|
}
|
|
pressStarted = false;
|
|
MacroMouseReport.buttons &= ~currentMacroAction.mouseButton.mouseButtonsMask;
|
|
break;
|
|
case MacroSubAction_Release:
|
|
MacroMouseReport.buttons &= ~currentMacroAction.mouseButton.mouseButtonsMask;
|
|
break;
|
|
case MacroSubAction_Press:
|
|
MacroMouseReport.buttons |= currentMacroAction.mouseButton.mouseButtonsMask;
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool processMoveMouseAction(void)
|
|
{
|
|
static bool inMotion;
|
|
|
|
if (inMotion) {
|
|
MacroMouseReport.x = 0;
|
|
MacroMouseReport.y = 0;
|
|
inMotion = false;
|
|
} else {
|
|
MacroMouseReport.x = currentMacroAction.moveMouse.x;
|
|
MacroMouseReport.y = currentMacroAction.moveMouse.y;
|
|
inMotion = true;
|
|
}
|
|
return inMotion;
|
|
}
|
|
|
|
bool processScrollMouseAction(void)
|
|
{
|
|
static bool inMotion;
|
|
|
|
if (inMotion) {
|
|
MacroMouseReport.wheelX = 0;
|
|
MacroMouseReport.wheelY = 0;
|
|
inMotion = false;
|
|
} else {
|
|
MacroMouseReport.wheelX = currentMacroAction.scrollMouse.x;
|
|
MacroMouseReport.wheelY = currentMacroAction.scrollMouse.y;
|
|
inMotion = true;
|
|
}
|
|
return inMotion;
|
|
}
|
|
|
|
bool processTextAction(void)
|
|
{
|
|
static uint16_t textIndex;
|
|
static uint8_t reportIndex = USB_BASIC_KEYBOARD_MAX_KEYS;
|
|
char character;
|
|
uint8_t scancode;
|
|
|
|
if (textIndex == currentMacroAction.text.textLen) {
|
|
textIndex = 0;
|
|
reportIndex = USB_BASIC_KEYBOARD_MAX_KEYS;
|
|
memset(&MacroBasicKeyboardReport, 0, sizeof MacroBasicKeyboardReport);
|
|
return false;
|
|
}
|
|
if (reportIndex == USB_BASIC_KEYBOARD_MAX_KEYS) {
|
|
reportIndex = 0;
|
|
memset(&MacroBasicKeyboardReport, 0, sizeof MacroBasicKeyboardReport);
|
|
return true;
|
|
}
|
|
character = currentMacroAction.text.text[textIndex];
|
|
scancode = characterToScancode(character);
|
|
for (uint8_t i = 0; i < reportIndex; i++) {
|
|
if (MacroBasicKeyboardReport.scancodes[i] == scancode) {
|
|
reportIndex = USB_BASIC_KEYBOARD_MAX_KEYS;
|
|
return true;
|
|
}
|
|
}
|
|
MacroBasicKeyboardReport.scancodes[reportIndex++] = scancode;
|
|
MacroBasicKeyboardReport.modifiers = characterToShift(character) ? HID_KEYBOARD_MODIFIER_LEFTSHIFT : 0;
|
|
++textIndex;
|
|
return true;
|
|
}
|
|
|
|
bool processCurrentMacroAction(void)
|
|
{
|
|
switch (currentMacroAction.type) {
|
|
case MacroActionType_Delay:
|
|
return processDelayAction();
|
|
case MacroActionType_Key:
|
|
return processKeyAction();
|
|
case MacroActionType_MouseButton:
|
|
return processMouseButtonAction();
|
|
case MacroActionType_MoveMouse:
|
|
return processMoveMouseAction();
|
|
case MacroActionType_ScrollMouse:
|
|
return processScrollMouseAction();
|
|
case MacroActionType_Text:
|
|
return processTextAction();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void Macros_StartMacro(uint8_t index)
|
|
{
|
|
if(AllMacros[index].macroActionsCount == 0) {
|
|
return;
|
|
}
|
|
MacroPlaying = true;
|
|
currentMacroIndex = index;
|
|
currentMacroActionIndex = 0;
|
|
ValidatedUserConfigBuffer.offset = AllMacros[index].firstMacroActionOffset;
|
|
ParseMacroAction(&ValidatedUserConfigBuffer, ¤tMacroAction);
|
|
memset(&MacroMouseReport, 0, sizeof MacroMouseReport);
|
|
memset(&MacroBasicKeyboardReport, 0, sizeof MacroBasicKeyboardReport);
|
|
memset(&MacroMediaKeyboardReport, 0, sizeof MacroMediaKeyboardReport);
|
|
memset(&MacroSystemKeyboardReport, 0, sizeof MacroSystemKeyboardReport);
|
|
}
|
|
|
|
void Macros_ContinueMacro(void)
|
|
{
|
|
if (processCurrentMacroAction()) {
|
|
return;
|
|
}
|
|
if (++currentMacroActionIndex == AllMacros[currentMacroIndex].macroActionsCount) {
|
|
MacroPlaying = false;
|
|
return;
|
|
}
|
|
ParseMacroAction(&ValidatedUserConfigBuffer, ¤tMacroAction);
|
|
}
|