esphome_ducky/src/main.cpp

442 lines
13 KiB
C++

#define HID_CUSTOM_LAYOUT
#define LAYOUT_GERMAN
#define BAUD_RATE 115200
#define OUTER_LED 13
#define INNER_LED 8
#define ESP_RECEIVE_BUFFER_SIZE 255
#define USB_RECEIVE_BUFFER_SIZE 8
#define EspSerial Serial1
#define UsbSerial Serial
#define WRITE_CHAR_DELAY 10
//-----------------------------
#include <Arduino.h>
#include <HID-Project.h>
//#include <SPI.h>
//#include <SD.h>
//-----------------------------
const char ESP_START_MARKER = 0x02; // START OF TEXT
const char ESP_END_MARKER = 0x03; // END OF TEXT
enum State : byte { NONE, ON, OFF, SLEEP };
char espReceivedChars[ESP_RECEIVE_BUFFER_SIZE];
boolean espRecvInProgress = false;
uint16_t espReceiveIndex = 0;
boolean espNewData = false;
char usbReceivedChars[USB_RECEIVE_BUFFER_SIZE];
uint16_t usbReceiveIndex = 0;
boolean usbNewData = false;
uint16_t defaultDelay = 0;
const boolean DEBUG = false;
uint16_t startRam = 0;
State lastPusblishedState = NONE;
uint16_t getFreeRam() {
uint16_t size = 2560;
byte *buf;
while ((buf = (byte *)malloc(--size)) == NULL)
;
free(buf);
return size;
}
void setup() {
if (DEBUG) {
startRam = getFreeRam();
}
pinMode(OUTER_LED, OUTPUT);
digitalWrite(OUTER_LED, HIGH);
pinMode(INNER_LED, OUTPUT);
digitalWrite(INNER_LED, HIGH);
// disable arduino pro micro leds
pinMode(LED_BUILTIN_RX, INPUT);
pinMode(LED_BUILTIN_TX, INPUT);
UsbSerial.begin(BAUD_RATE);
EspSerial.begin(BAUD_RATE);
Keyboard.begin();
Mouse.begin();
Consumer.begin();
System.begin();
digitalWrite(INNER_LED, LOW);
digitalWrite(OUTER_LED, LOW);
// processSD();
EspSerial.println("setup done");
}
// https://forum.arduino.cc/index.php?topic=396450
void receiveFromEspSerial() {
while (EspSerial.available() > 0 && espNewData == false) {
char rc = EspSerial.read();
if (espRecvInProgress == true) {
if (rc != ESP_END_MARKER) {
espReceivedChars[espReceiveIndex] = rc;
espReceiveIndex++;
if (espReceiveIndex >= ESP_RECEIVE_BUFFER_SIZE) {
espReceiveIndex = ESP_RECEIVE_BUFFER_SIZE - 1;
}
} else {
espReceivedChars[espReceiveIndex] = '\0'; // terminate the string
espRecvInProgress = false;
espReceiveIndex = 0;
espNewData = true;
}
}
else if (rc == ESP_START_MARKER) {
espRecvInProgress = true;
}
}
}
void receiveFromUsbSerial() {
while (UsbSerial.available() > 0 && usbNewData == false) {
char rc = UsbSerial.read();
if (rc != '\n') {
usbReceivedChars[usbReceiveIndex] = rc;
usbReceiveIndex++;
if (usbReceiveIndex >= USB_RECEIVE_BUFFER_SIZE) {
usbReceiveIndex = USB_RECEIVE_BUFFER_SIZE - 1;
}
} else {
usbReceivedChars[usbReceiveIndex] = '\0'; // terminate the string
usbReceiveIndex = 0;
usbNewData = true;
}
}
}
void Press(String b) {
if (b.length() == 1)
Keyboard.press(tolower(b[0]));
else if (b.equals("ENTER"))
Keyboard.press(KEY_RETURN);
else if (b.equals("CTRL") || b.equals("CONTROL"))
Keyboard.press(KEY_LEFT_CTRL);
else if (b.equals("SHIFT"))
Keyboard.press(KEY_LEFT_SHIFT);
else if (b.equals("ALT"))
Keyboard.press(KEY_LEFT_ALT);
else if (b.equals("ALTGR"))
Keyboard.press(KEY_RIGHT_ALT);
else if (b.equals("GUI") || b.equals("WIN") || b.equals("CMD"))
Keyboard.press(KEY_LEFT_GUI);
else if (b.equals("UP") || b.equals("UPARROW"))
Keyboard.press(KEY_UP_ARROW);
else if (b.equals("DOWN") || b.equals("DOWNARROW"))
Keyboard.press(KEY_DOWN_ARROW);
else if (b.equals("LEFT") || b.equals("LEFTARROW"))
Keyboard.press(KEY_LEFT_ARROW);
else if (b.equals("RIGHT") || b.equals("RIGHTARROW"))
Keyboard.press(KEY_RIGHT_ARROW);
else if (b.equals("DELETE") || b.equals("DEL"))
Keyboard.press(KEY_DELETE);
else if (b.equals("PAGEUP"))
Keyboard.press(KEY_PAGE_UP);
else if (b.equals("PAGEDOWN"))
Keyboard.press(KEY_PAGE_DOWN);
else if (b.equals("HOME"))
Keyboard.press(KEY_HOME);
else if (b.equals("ESC") || b.equals("ESCAPE"))
Keyboard.press(KEY_ESC);
else if (b.equals("BACKSPACE"))
Keyboard.press(KEY_BACKSPACE);
else if (b.equals("INSERT"))
Keyboard.press(KEY_INSERT);
else if (b.equals("TAB"))
Keyboard.press(KEY_TAB);
else if (b.equals("END"))
Keyboard.press(KEY_END);
else if (b.equals("CAPSLOCK"))
Keyboard.press(KEY_CAPS_LOCK);
else if (b.equals("F1"))
Keyboard.press(KEY_F1);
else if (b.equals("F2"))
Keyboard.press(KEY_F2);
else if (b.equals("F3"))
Keyboard.press(KEY_F3);
else if (b.equals("F4"))
Keyboard.press(KEY_F4);
else if (b.equals("F5"))
Keyboard.press(KEY_F5);
else if (b.equals("F6"))
Keyboard.press(KEY_F6);
else if (b.equals("F7"))
Keyboard.press(KEY_F7);
else if (b.equals("F8"))
Keyboard.press(KEY_F8);
else if (b.equals("F9"))
Keyboard.press(KEY_F9);
else if (b.equals("F10"))
Keyboard.press(KEY_F10);
else if (b.equals("F11"))
Keyboard.press(KEY_F11);
else if (b.equals("F12"))
Keyboard.press(KEY_F12);
else if (b.equals("SPACE"))
Keyboard.press(KEY_SPACE);
else if (b.equals("APP") || b.equals("MENU"))
Keyboard.press(KEY_MENU);
else if (b.equals("PRINTSCREEN"))
Keyboard.press(KEY_PRINT);
else if (b.equals("SCROLLOCK"))
Keyboard.press(KEY_SCROLL_LOCK);
else if (b.equals("BREAK"))
Keyboard.press(KEY_PAUSE);
else if (b.equals("NUMLOCK"))
Keyboard.press(KEY_NUM_LOCK);
//---------------------------------------------------------
else if (b.equals("VOLUP"))
Consumer.write(MEDIA_VOL_UP);
else if (b.equals("VOLDWN"))
Consumer.write(MEDIA_VOL_DOWN);
else if (b.equals("VOLMUT") || b.equals("MUTE"))
Consumer.write(MEDIA_VOL_MUTE);
else if (b.equals("PLAY_PAUSE"))
Consumer.write(MEDIA_PLAY_PAUSE);
else if (b.equals("PLAY"))
Consumer.write(HID_CONSUMER_PLAY);
else if (b.equals("PAUSE"))
Consumer.write(HID_CONSUMER_PAUSE);
else if (b.equals("STOP"))
Consumer.write(MEDIA_STOP);
else if (b.equals("NEXT"))
Consumer.write(MEDIA_NEXT);
else if (b.equals("PREV"))
Consumer.write(MEDIA_PREVIOUS);
//---------------------------------------------------------
else if (b.equals("WAKE"))
System.write(SYSTEM_WAKE_UP);
else if (b.equals("SLEEP"))
System.write(SYSTEM_SLEEP);
else if (b.equals("POWER_DOWN"))
System.write(SYSTEM_POWER_DOWN);
//---------------------------------------------------------
else if (b.equals("MOUSE_LEFT") || b.equals("CLICK"))
Mouse.click();
else if (b.equals("MOUSE_RIGHT"))
Mouse.click(MOUSE_RIGHT);
else if (b.equals("MOUSE_MIDDLE"))
Mouse.click(MOUSE_MIDDLE);
else if (b.equals("MOUSE_PREV"))
Mouse.click(MOUSE_PREV);
else if (b.equals("MOUSE_NEXT"))
Mouse.click(MOUSE_NEXT);
else if (b.equals("MOUSE_LEFT_DOWN")) {
if (!Mouse.isPressed(MOUSE_LEFT)) {
Mouse.press(MOUSE_LEFT);
}
} else if (b.equals("MOUSE_LEFT_UP")) {
if (Mouse.isPressed(MOUSE_LEFT)) {
Mouse.release(MOUSE_LEFT);
}
} else if (b.equals("MOUSE_RIGHT_DOWN")) {
if (!Mouse.isPressed(MOUSE_RIGHT)) {
Mouse.press(MOUSE_RIGHT);
}
} else if (b.equals("MOUSE_RIGHT_UP")) {
if (Mouse.isPressed(MOUSE_RIGHT)) {
Mouse.release(MOUSE_RIGHT);
}
} else if (b.equals("MOUSE_MIDDLE_DOWN")) {
if (!Mouse.isPressed(MOUSE_MIDDLE)) {
Mouse.press(MOUSE_MIDDLE);
}
} else if (b.equals("MOUSE_MIDDLE_UP")) {
if (Mouse.isPressed(MOUSE_MIDDLE)) {
Mouse.release(MOUSE_MIDDLE);
}
}
}
void Line(String _line, String last) {
int16_t firstSpace = _line.indexOf(" ");
if (firstSpace == -1) {
Press(_line);
} else {
String subString = _line.substring(0, firstSpace);
if (subString.equals("STRING")) {
if (DEBUG) {
UsbSerial.print("Going to type ");
UsbSerial.print(
_line.substring(firstSpace + 1, _line.length()).length());
UsbSerial.println(" chars...");
}
for (uint16_t i = firstSpace + 1; i < _line.length(); i++) {
Keyboard.write(_line[i]);
delay(WRITE_CHAR_DELAY);
}
if (DEBUG) UsbSerial.println("typing done");
} else if (subString.equals("SERIAL") && UsbSerial) {
for (uint16_t i = firstSpace + 1; i < _line.length(); i++) {
UsbSerial.print(_line[i]);
}
UsbSerial.println();
} else if (subString.equals("DELAY")) {
uint16_t delaytime = _line.substring(firstSpace + 1).toInt();
delay(delaytime);
} else if (subString.equals("DEFAULTDELAY"))
defaultDelay = _line.substring(firstSpace + 1).toInt();
else if (subString.equals("REM")) {
// nothing :/
} else if (subString.equals("MOUSE_MOVE")) {
uint16_t comma = _line.indexOf(",");
int point_x = _line.substring(firstSpace + 1, comma).toInt();
int point_y = _line.substring(comma + 1).toInt();
if (DEBUG) {
UsbSerial.print("Move to x=");
UsbSerial.print(point_x);
UsbSerial.print(", y=");
UsbSerial.println(point_y);
}
Mouse.move(point_x, point_y);
} else if (subString.equals("MOUSE_SCROLL") ||
subString.equals("MOUSE_WHEEL") || subString.equals("SCROLL")) {
int steps = _line.substring(firstSpace + 1).toInt();
Mouse.move(0, 0, steps);
}
//---------------------------------------------------------
else if (subString.equals("REPLAY") || subString.equals("REPEAT")) {
uint16_t replaynum = _line.substring(firstSpace + 1).toInt();
while (replaynum) {
Line(last, "");
--replaynum;
}
} else {
String remain = String(_line);
while (remain.length() > 0) {
int16_t latest_space = remain.indexOf(" ");
if (latest_space == -1) {
Press(remain);
remain = "";
} else {
Press(remain.substring(0, latest_space));
remain = remain.substring(latest_space + 1);
}
delay(WRITE_CHAR_DELAY);
}
}
}
Keyboard.releaseAll();
Consumer.releaseAll();
// Mouse.releaseAll();
System.releaseAll();
delay(defaultDelay);
}
void handleDuckyCommand() {
String bufferStr = String(espReceivedChars);
String last = "";
bufferStr.replace("\r", "\n");
bufferStr.replace("\n\n", "\n");
if (bufferStr.length() > 0) {
EspSerial.println("busy");
digitalWrite(INNER_LED, HIGH);
while (bufferStr.length() > 0) {
int16_t latest_return = bufferStr.indexOf("\n");
if (latest_return == -1) {
if (DEBUG) {
UsbSerial.print("run1: '");
UsbSerial.print(bufferStr);
UsbSerial.println("'");
}
Line(bufferStr, last);
bufferStr = "";
} else {
String temp = bufferStr.substring(0, latest_return);
if (temp.length() > 0) {
if (DEBUG) {
UsbSerial.print("run2: '");
UsbSerial.print(temp);
UsbSerial.println("'");
}
Line(temp, last);
last = temp;
}
if (DEBUG) {
UsbSerial.println("bufferStr length: " + String(bufferStr.length()));
UsbSerial.println("Select next substring from: " +
String(latest_return + 1));
}
bufferStr = bufferStr.substring(latest_return + 1);
if (DEBUG) {
UsbSerial.println("resulting bufferStr length: " +
String(bufferStr.length()));
}
}
}
UsbSerial.println("done");
EspSerial.println("ready");
defaultDelay = 0;
last = "";
digitalWrite(INNER_LED, LOW);
if (DEBUG) {
UsbSerial.println("done");
UsbSerial.println("Free ram start: " + String(startRam) + " Bytes.");
UsbSerial.println("Free ram now: " + String(getFreeRam()) + " Bytes.");
}
}
}
void handleNewData() {
if (espNewData == true) {
handleDuckyCommand();
if (DEBUG) {
EspSerial.print("ESP_INPUT=");
EspSerial.println(espReceivedChars);
}
espNewData = false;
}
if (usbNewData == true) {
EspSerial.print("USB_INPUT=");
EspSerial.println(usbReceivedChars);
usbNewData = false;
}
}
String getStateText(State state) {
switch (state) {
case ON:
return "STATE=ON";
case OFF:
return "STATE=OFF";
case SLEEP:
return "STATE=SLEEP";
default:
return "STATE=NONE";
}
}
void publishUsbDeviceState() {
State state = NONE;
if (USBDevice.configured()) {
if (USBDevice.isSuspended()) {
state = SLEEP;
} else {
state = ON;
}
} else {
state = OFF;
}
if (lastPusblishedState != state) {
lastPusblishedState = state;
EspSerial.println(getStateText(state));
EspSerial.println("ready");
}
}
void loop() {
receiveFromEspSerial();
receiveFromUsbSerial();
handleNewData();
publishUsbDeviceState();
}