diff --git a/USBNova.ino b/USBNova.ino index b551b14..d8ee399 100644 --- a/USBNova.ino +++ b/USBNova.ino @@ -1,12 +1,8 @@ -/* - * Note2: If your flash is not formatted as FAT12 previously, you could format it using - * follow sketch https://github.com/adafruit/Adafruit_SPIFlash/tree/master/examples/SdFat_format - */ - #include "config.h" #include "debug.h" -#include "src/keyboard/keyboard.h" +#include "src/hid/hid.h" +#include "src/hid/keyboard.h" #include "src/led/led.h" #include "src/msc/msc.h" #include "src/selector/selector.h" @@ -14,6 +10,7 @@ #include "src/preferences/preferences.h" #include "src/duckparser/duckparser.h" #include "src/format/format.h" +#include "src/tasks/tasks.h" enum Mode { SETUP, ATTACK @@ -26,6 +23,7 @@ void setup() { debug_init(); selector::init(); led::init(); + tasks::setCallback(loop); // Initialize memory and ceck for problems if (!msc::init()) { @@ -49,12 +47,12 @@ void setup() { preferences::load(); led::setEnable(preferences::ledEnabled()); keyboard::setLocale(locale::get(preferences::getDefaultLayout().c_str())); - keyboard::setID(preferences::getHidVid(), preferences::getHidPid(), preferences::getHidRev()); + hid::setID(preferences::getHidVid(), preferences::getHidPid(), preferences::getHidRev()); msc::setID(preferences::getMscVid().c_str(), preferences::getMscPid().c_str(), preferences::getMscRev().c_str()); duckparser::setDefaultDelay(preferences::getDefaultDelay()); // Start Keyboard - keyboard::init(); + hid::init(); // Start USB Drive if (preferences::mscEnabled() || (mode == SETUP)) msc::enableDrive(); @@ -66,7 +64,7 @@ void setup() { if (preferences::getDisableCapslock()) { keyboard::disableCapslock(); delay(10); - keyboard::indicatorChanged(); + hid::indicatorChanged(); } // Format Flash @@ -106,7 +104,7 @@ void setup() { else if (mode == ATTACK) { // Run on capslock if (preferences::getRunOnIndicator()) { - while (!keyboard::indicatorChanged()) { + while (!hid::indicatorChanged()) { delay(100); } keyboard::disableCapslock(); @@ -135,4 +133,6 @@ void setup() { debugln("[Finished]"); } -void loop() {} \ No newline at end of file +void loop() { + led::update(); +} \ No newline at end of file diff --git a/src/duckparser/duckparser.cpp b/src/duckparser/duckparser.cpp index 430eb04..cf6b841 100644 --- a/src/duckparser/duckparser.cpp +++ b/src/duckparser/duckparser.cpp @@ -4,7 +4,7 @@ #include "../../config.h" #include "../../debug.h" -#include "../keyboard/keyboard.h" +#include "../hid/keyboard.h" #include "../led/led.h" #include // millis(), delay() diff --git a/src/hid/hid.cpp b/src/hid/hid.cpp new file mode 100644 index 0000000..29d6b4a --- /dev/null +++ b/src/hid/hid.cpp @@ -0,0 +1,107 @@ +/* This software is licensed under the MIT License: https://github.com/spacehuhntech/usbnova */ + +#include "hid.h" + +#include +#include // delay() + +#include "../tasks/tasks.h" + +namespace hid { + // ====== PRIVATE ====== // + uint8_t indicator = 0; // Indicator LED state + bool indicator_changed = false; // Whether or not any indicator changed since last time + bool indicator_read = false; // If initial indicator was read + + // HID report descriptor using TinyUSB's template + // Single Report (no ID) descriptor + uint8_t const desc_hid_report[] = { + // TUD_HID_REPORT_DESC_KEYBOARD() + TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(RID::KEYBOARD)), + TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(RID::MOUSE)), + TUD_HID_REPORT_DESC_CONSUMER(HID_REPORT_ID(RID::CONSUMER_CONTROL)) + }; + + // USB HID object. For ESP32 these values cannot be changed after this declaration + // desc report, desc len, protocol, interval, use out endpoint + Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_KEYBOARD, 2, false); + + // Output report callback for LED indicator such as Caplocks + void hid_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { + (void)report_id; + (void)bufsize; + + // LED indicator is output report with only 1 byte length + if (report_type != HID_REPORT_TYPE_OUTPUT) + return; + + // The LED bit map is as follows: (also defined by KEYBOARD_LED_* ) + // Kana (4) | Compose (3) | ScrollLock (2) | CapsLock (1) | Numlock (0) + uint8_t tmp = buffer[0]; + + // Save caps lock state + if (tmp != indicator) { + indicator = tmp; + indicator_changed = true; + } + + // Making sure that indicator_changed isn't set to true because of an initial read + if (!indicator_read) { + indicator_read = true; + indicator_changed = false; + } + + // turn on LED if capslock is set + // digitalWrite(LED_BUILTIN, ledIndicator & KEYBOARD_LED_CAPSLOCK); + } + + // ====== PUBLIC ====== // + void init() { + // Notes: following commented-out functions has no affect on ESP32 + // usb_hid.setBootProtocol(HID_ITF_PROTOCOL_KEYBOARD); + // usb_hid.setPollInterval(2); + // usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report)); + // usb_hid.setStringDescriptor("TinyUSB Keyboard"); + + // Set up output report (on control endpoint) for Capslock indicator + usb_hid.setReportCallback(NULL, hid_report_callback); + + usb_hid.begin(); + } + + void setID(uint16_t vid, uint16_t pid, uint16_t version) { + TinyUSBDevice.setID(vid, pid); + TinyUSBDevice.setDeviceVersion(version); + } + + bool mounted() { + return TinyUSBDevice.mounted(); + } + + void sendKeyboardReport(uint8_t modifier, uint8_t* keys) { + if (TinyUSBDevice.suspended()) { + // Wake up host if we are in suspend mode + // and REMOTE_WAKEUP feature is enabled by host + TinyUSBDevice.remoteWakeup(); + } + + // Wait until ready to send next report + while (!usb_hid.ready()) { + delay(1); + tasks::update(); + } + + usb_hid.keyboardReport(RID::KEYBOARD, modifier, keys); + } + + uint8_t getIndicator() { + return indicator; + } + + bool indicatorChanged() { + bool res = indicator_changed; + + indicator_changed = false; + return res; + } +} \ No newline at end of file diff --git a/src/hid/hid.h b/src/hid/hid.h new file mode 100644 index 0000000..eb39ed9 --- /dev/null +++ b/src/hid/hid.h @@ -0,0 +1,23 @@ +/* This software is licensed under the MIT License: https://github.com/spacehuhntech/usbnova */ + +#pragma once + +#include // uint8_t + +namespace hid { + // Report ID + enum RID { + KEYBOARD = 1, + MOUSE = 2, + CONSUMER_CONTROL = 3, // Media, volume etc .. + }; + + void init(); + void setID(uint16_t vid, uint16_t pid, uint16_t version); + bool mounted(); + + void sendKeyboardReport(uint8_t modifier, uint8_t* keys); + + uint8_t getIndicator(); + bool indicatorChanged(); +} \ No newline at end of file diff --git a/src/keyboard/keyboard.cpp b/src/hid/keyboard.cpp similarity index 58% rename from src/keyboard/keyboard.cpp rename to src/hid/keyboard.cpp index 1cd457a..c25b60d 100644 --- a/src/keyboard/keyboard.cpp +++ b/src/hid/keyboard.cpp @@ -2,33 +2,14 @@ #include "keyboard.h" -#include -#include // millis(), delay() - -#include "../led/led.h" +#include "hid.h" +#include // pgm_read_byte namespace keyboard { // ====== PRIVATE ====== // hid_locale_t* locale { locale::get_default() }; - report_t prev_report = report_t{ KEY_NONE, { KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE } }; - uint8_t const report_id = 0; - - bool caps_lock = false; // State of capslock - - uint8_t indicator = 0; // Indicator LED state - bool indicator_changed = false; // Whether or not any indicator changed since last time - bool indicator_read = false; // If initial indicator was read - - // HID report descriptor using TinyUSB's template - // Single Report (no ID) descriptor - uint8_t const desc_hid_report[] = { - TUD_HID_REPORT_DESC_KEYBOARD() - }; - - // USB HID object. For ESP32 these values cannot be changed after this declaration - // desc report, desc len, protocol, interval, use out endpoint - Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_KEYBOARD, 2, false); + report_t prev_report = report_t{ KEY_NONE, { KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE } }; report_t makeReport(uint8_t modifiers = 0, uint8_t key1 = 0, uint8_t key2 = 0, uint8_t key3 = 0, uint8_t key4 = 0, uint8_t key5 = 0, uint8_t key6 = 0); @@ -47,78 +28,14 @@ namespace keyboard { return k; } - // Output report callback for LED indicator such as Caplocks - void hid_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { - (void)report_id; - (void)bufsize; - - // LED indicator is output report with only 1 byte length - if (report_type != HID_REPORT_TYPE_OUTPUT) - return; - - // The LED bit map is as follows: (also defined by KEYBOARD_LED_* ) - // Kana (4) | Compose (3) | ScrollLock (2) | CapsLock (1) | Numlock (0) - uint8_t tmp = buffer[0]; - - // Save caps lock state - if (tmp != indicator) { - indicator = tmp; - caps_lock = indicator & KEYBOARD_LED_CAPSLOCK; - indicator_changed = true; - } - - // Making sure that indicator_changed isn't set to true because of an initial read - if (!indicator_read) { - indicator_read = true; - indicator_changed = false; - } - - // turn on LED if capslock is set - // digitalWrite(LED_BUILTIN, ledIndicator & KEYBOARD_LED_CAPSLOCK); - } - // ====== PUBLIC ====== // - void init() { - // Notes: following commented-out functions has no affect on ESP32 - // usb_hid.setBootProtocol(HID_ITF_PROTOCOL_KEYBOARD); - // usb_hid.setPollInterval(2); - // usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report)); - // usb_hid.setStringDescriptor("TinyUSB Keyboard"); - - // Set up output report (on control endpoint) for Capslock indicator - usb_hid.setReportCallback(NULL, hid_report_callback); - - usb_hid.begin(); - } - - void setID(uint16_t vid, uint16_t pid, uint16_t version) { - TinyUSBDevice.setID(vid, pid); - TinyUSBDevice.setDeviceVersion(version); - } - - bool mounted() { - return TinyUSBDevice.mounted(); - } - void setLocale(hid_locale_t* locale) { if (locale == nullptr) return; keyboard::locale = locale; } void send(report_t* k) { - if (TinyUSBDevice.suspended()) { - // Wake up host if we are in suspend mode - // and REMOTE_WAKEUP feature is enabled by host - TinyUSBDevice.remoteWakeup(); - } - - // Wait until ready to send next report - while (!usb_hid.ready()) { - delay(1); - led::update(); - } - - usb_hid.keyboardReport(report_id, k->modifiers, k->keys); + hid::sendKeyboardReport(k->modifiers, k->keys); } void release() { @@ -251,16 +168,9 @@ namespace keyboard { } void disableCapslock() { - if (caps_lock) { + if (hid::getIndicator() & 2) { /*KEYBOARD_LED_CAPSLOCK*/ pressKey(KEY_CAPSLOCK); release(); } } - - bool indicatorChanged() { - bool res = indicator_changed; - - indicator_changed = false; - return res; - } } \ No newline at end of file diff --git a/src/keyboard/keyboard.h b/src/hid/keyboard.h similarity index 90% rename from src/keyboard/keyboard.h rename to src/hid/keyboard.h index 723311d..e2a4561 100644 --- a/src/keyboard/keyboard.h +++ b/src/hid/keyboard.h @@ -12,9 +12,6 @@ namespace keyboard { uint8_t keys[6]; } report_t; - void init(); - void setID(uint16_t vid, uint16_t pid, uint16_t version); - void setLocale(hid_locale_t* locale); void send(report_t* k); diff --git a/src/hid/mouse.cpp b/src/hid/mouse.cpp new file mode 100644 index 0000000..df18474 --- /dev/null +++ b/src/hid/mouse.cpp @@ -0,0 +1,11 @@ +/* This software is licensed under the MIT License: https://github.com/spacehuhntech/usbnova */ + +#include "mouse.h" + +namespace mouse { + // ====== PRIVATE ====== // + + + // ====== PUBLIC ====== // + +} \ No newline at end of file diff --git a/src/hid/mouse.h b/src/hid/mouse.h new file mode 100644 index 0000000..81dcc5b --- /dev/null +++ b/src/hid/mouse.h @@ -0,0 +1,7 @@ +/* This software is licensed under the MIT License: https://github.com/spacehuhntech/usbnova */ + +#pragma once + +namespace mouse { + +} \ No newline at end of file diff --git a/src/tasks/tasks.cpp b/src/tasks/tasks.cpp new file mode 100644 index 0000000..ad985f8 --- /dev/null +++ b/src/tasks/tasks.cpp @@ -0,0 +1,21 @@ +/* This software is licensed under the MIT License: https://github.com/spacehuhntech/usbnova */ + +#include "tasks.h" + +#include // NULL + +namespace tasks { + // ====== PRIVATE ====== // + void (*callback)(void) = NULL; + + // ====== PUBLIC ====== // + void setCallback(void (*_callback)(void)) { + callback = _callback; + } + + void update() { + if (callback != NULL) { + callback(); + } + } +} \ No newline at end of file diff --git a/src/tasks/tasks.h b/src/tasks/tasks.h new file mode 100644 index 0000000..4fc24a0 --- /dev/null +++ b/src/tasks/tasks.h @@ -0,0 +1,8 @@ +/* This software is licensed under the MIT License: https://github.com/spacehuhntech/usbnova */ + +#pragma once + +namespace tasks { + void setCallback(void (*callback)(void)); + void update(); +} \ No newline at end of file