From 8db0a6e8816f4f9fb46a773f92f15b6cdec290e7 Mon Sep 17 00:00:00 2001 From: Spacehuhn Date: Tue, 27 Jun 2023 16:37:04 +0200 Subject: [PATCH] RP2040 Support --- README.md | 3 ++- USBNova.ino | 35 +++++++++++++++-------------- config.h | 14 ++++++++++-- debug.h | 1 + src/cli/cli.cpp | 55 +++++++++++++++++++++++----------------------- src/hid/hid.h | 8 ++++--- src/msc/format.cpp | 9 ++++++++ src/msc/msc.cpp | 39 ++++++++++++++++++++------------ 8 files changed, 100 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 33acf69..a430193 100644 --- a/README.md +++ b/README.md @@ -25,4 +25,5 @@ Compile and export: `arduino-cli compile --fqbn adafruit:samd:adafruit_qtpy_m0_nova:usbstack=tinyusb,debug=off --output-dir build/` Convert to uf2: -`uf2conv build/USBNova.ino.bin -o build/USBNova.ino.uf2` \ No newline at end of file +`uf2conv build/USBNova.ino.bin -o build/USBNova.ino.uf2` +(To install uf2conv, install rust, then `cargo install uf2conv`) \ No newline at end of file diff --git a/USBNova.ino b/USBNova.ino index fe734bf..4b9333a 100644 --- a/USBNova.ino +++ b/USBNova.ino @@ -18,7 +18,7 @@ void update() { } void setup() { - // Start Serial (for debug) + // Start Serial (for debug) or disable it debug_init(); // Initialize memory and check for problems @@ -35,14 +35,14 @@ void setup() { // Read mode from selector switch selector::init(); - + // Start Keyboard - if (selector::mode() == ATTACK || preferences::hidEnabled()) { + if ((selector::mode() == ATTACK) || preferences::hidEnabled()) { hid::init(); - } + } // Start USB Drive - if (preferences::mscEnabled() || (selector::mode() == SETUP)){ + if (preferences::mscEnabled() || (selector::mode() == SETUP)) { msc::enableDrive(); } @@ -70,7 +70,7 @@ void setup() { if (!msc::exists(PREFERENCES_PATH)) { preferences::save(); } - + // Create main_script.txt if it doesn't exist yet if (!msc::exists(preferences::getMainScript().c_str())) { char message[21]; @@ -85,42 +85,43 @@ void setup() { selector::changed(); // Start attack - if (selector::mode() == ATTACK && !preferences::getRunOnIndicator()) { - delay(preferences::getInitialDelay()); // Wait to give computer time to init keyboard - attack::start(); // Start keystroke injection attack + if ((selector::mode() == ATTACK) && !preferences::getRunOnIndicator()) { + delay(preferences::getInitialDelay()); // Wait to give computer time to init keyboard + attack::start(); // Start keystroke injection attack led::setColor(preferences::getIdleColor()); // Set LED to green } // Setup CLI +#ifdef ENABLE_DEBUG cli::init(); +#endif // ifdef ENABLE_DEBUG debugln("[Started]"); } void loop() { - taks:update(); + tasks::update(); cli::update(); - if(selector::read() != ATTACK) return; + if (selector::read() != ATTACK) return; // Only start the attack if run-on-indicator is disabled, or indicator actually changed - if(preferences::getRunOnIndicator() && hid::indicatorChanged()) { + if (preferences::getRunOnIndicator() && hid::indicatorChanged()) { delay(100); attack::start(); // Run script led::setColor(preferences::getIdleColor()); // Set LED to green } else if (selector::changed()) { // ========== Setup Mode ========== // - if (selector::mode() == SETUP && preferences::hidEnabled()) { - preferences::load(); // Reload the settings (in case the main script path changed) - + if ((selector::mode() == SETUP) && preferences::hidEnabled()) { + preferences::load(); // Reload the settings (in case the main script path changed) + // Attack settings keyboard::setLocale(locale::get(preferences::getDefaultLayout().c_str())); duckparser::setDefaultDelay(preferences::getDefaultDelay()); - + attack::start(); // Start keystroke injection attack led::setColor(preferences::getSetupColor()); // Set LED to blue } - // ========== Attack Mode ========== // else if (selector::mode() == ATTACK) { // Only start the attack if run-on-indicator is disabled, or indicator actually changed diff --git a/config.h b/config.h index 779417b..bb88e35 100644 --- a/config.h +++ b/config.h @@ -2,10 +2,10 @@ #pragma once -#define VERSION "1.1.2" +#define VERSION "1.1.3" // ===== DEBUG Settings ===== // -//#define ENABLE_DEBUG +// #define ENABLE_DEBUG #define DEBUG_PORT Serial #define DEBUG_BAUD 115200 @@ -13,10 +13,20 @@ #define READ_BUFFER 2048 // ===== LED Settings ===== // + +#if defined(ARDUINO_ARCH_RP2040) +#define LED_PIN 12 +#else // if defined(ARDUINO_ARCH_RP2040) #define LED_PIN 11 +#endif // if defined(ARDUINO_ARCH_RP2040) // ===== SELECTOR SWITCH ===== // + +#if defined(ARDUINO_ARCH_RP2040) +#define SELECTOR 13 +#else // if defined(ARDUINO_ARCH_RP2040) #define SELECTOR A0 +#endif // if defined(ARDUINO_ARCH_RP2040) // ===== Parser Settings ===== // #define CASE_SENSETIVE false diff --git a/debug.h b/debug.h index 9b1e11a..ab8610f 100644 --- a/debug.h +++ b/debug.h @@ -3,6 +3,7 @@ #pragma once #include +#include "config.h" #ifdef ENABLE_DEBUG diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 0efc6f5..e487d38 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -11,12 +11,13 @@ #include "../attack/attack.h" #include "../msc/msc.h" #include "../../config.h" +#include "../../debug.h" #define BUFFER_SIZE 1024 namespace cli { // ====== PRIVATE ====== // - SimpleCLI cli; + SimpleCLI cli; char buffer[BUFFER_SIZE]; // Copied from https://github.com/SpacehuhnTech/esp8266_deauther/blob/b70dc19579e7af65857726ae45e3e477899942ac/esp8266_deauther/cli.cpp#L1602 @@ -59,38 +60,38 @@ namespace cli { // ====== PUBLIC ====== // void init() { - Serial.begin(115200); - + // Serial.begin(115200); + // error cli.setOnError([](cmd_error* e) { CommandError cmdError(e); - Serial.print("ERROR: "); - Serial.println(cmdError.toString()); + debugF("ERROR: "); + debugln(cmdError.toString()); if (cmdError.hasCommand()) { - Serial.print("Did you mean \""); - Serial.print(cmdError.getCommand().toString()); - Serial.println("\"?"); + debugF("Did you mean \""); + debug(cmdError.getCommand().toString()); + debuglnF("\"?"); } }); // help cli.addCmd("help", [](cmd* c) { - Serial.println("[ = Available Commands =]"); - Serial.print(cli.toString()); - Serial.println("Enter any BadUSB Scripts to run it."); - Serial.println(); + debuglnF("[ = Available Commands =]"); + debug(cli.toString()); + debuglnF("Enter any BadUSB Scripts to run it."); + debugln(); }).setDescription(" Get a list of available commands."); // version cli.addCmd("version", [](cmd* c) { - Serial.println("[ = USB Nova =]"); - Serial.print("Version "); - Serial.println(VERSION); - Serial.println("Source: https://github.com/spacehuhntech/usbnova"); - Serial.println("Made with <3 by Spacehuhn (spacehuhn.com)"); - Serial.println(); + debuglnF("[ = USB Nova =]"); + debugF("Version "); + debugln(VERSION); + debuglnF("Source: https://github.com/spacehuhntech/usbnova"); + debuglnF("Made with <3 by Spacehuhn (spacehuhn.com)"); + debugln(); }).setDescription(" Print the firmware version."); // format @@ -98,25 +99,25 @@ namespace cli { led::setColor(255, 255, 255); msc::format(preferences::getDriveName().c_str()); preferences::save(); - if(selector::mode() == SETUP) { + if (selector::mode() == SETUP) { led::setColor(preferences::getSetupColor()); } else { led::setColor(preferences::getIdleColor()); } - - Serial.println("Done formatting!"); - Serial.println(); + + debuglnF("Done formatting!"); + debugln(); }).setDescription(" Fromat the internal memory."); // reset cli.addCmd("reset", [](cmd* c) { preferences::reset(); preferences::save(); - - Serial.println("Done resetting!"); - Serial.println(); + + debuglnF("Done resetting!"); + debugln(); }).setDescription(" Reset the preferences."); - + // TODO: preferences cli.addSingleArgCmd("preferences", [](cmd* c) { preferences::print(); @@ -132,7 +133,7 @@ namespace cli { Command cmd(c); Argument arg = cmd.getArgument(0); attack::start(arg.getValue().c_str()); - if(selector::mode() == SETUP) { + if (selector::mode() == SETUP) { led::setColor(preferences::getSetupColor()); } else { led::setColor(preferences::getIdleColor()); diff --git a/src/hid/hid.h b/src/hid/hid.h index d946f4f..c2ae56c 100644 --- a/src/hid/hid.h +++ b/src/hid/hid.h @@ -2,14 +2,16 @@ #pragma once +#include "../../config.h" + #include // uint8_t namespace hid { // Report ID enum RID { - KEYBOARD = 0, - MOUSE = 1, - CONSUMER_CONTROL = 2, // Media, volume etc .. + KEYBOARD = 1, + MOUSE = 2, + CONSUMER_CONTROL = 3, // Media, volume etc .. }; void init(); diff --git a/src/msc/format.cpp b/src/msc/format.cpp index 911ab44..8cf550a 100644 --- a/src/msc/format.cpp +++ b/src/msc/format.cpp @@ -19,7 +19,16 @@ namespace format { // ========== PRIVATE ========= // +#if defined(ARDUINO_ARCH_RP2040) + // RP2040 use same flash device that store code for file system. Therefore we + // only need to specify start address and size (no need SPI or SS) + // By default (start=0, size=0), values that match file system setting in + // 'Tools->Flash Size' menu selection will be used. + Adafruit_FlashTransport_RP2040 flashTransport; +#else // if defined(ARDUINO_ARCH_RP2040) Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, EXTERNAL_FLASH_USE_SPI); +#endif // if defined(ARDUINO_ARCH_RP2040) + Adafruit_SPIFlash flash(&flashTransport); // file system object from SdFat diff --git a/src/msc/msc.cpp b/src/msc/msc.cpp index 40a6d35..d08c7ac 100644 --- a/src/msc/msc.cpp +++ b/src/msc/msc.cpp @@ -23,7 +23,16 @@ namespace msc { std::stack file_stack; +#if defined(ARDUINO_ARCH_RP2040) + // RP2040 use same flash device that store code for file system. Therefore we + // only need to specify start address and size (no need SPI or SS) + // By default (start=0, size=0), values that match file system setting in + // 'Tools->Flash Size' menu selection will be used. + Adafruit_FlashTransport_RP2040 flashTransport; +#else // if defined(ARDUINO_ARCH_RP2040) Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, EXTERNAL_FLASH_USE_SPI); +#endif // if defined(ARDUINO_ARCH_RP2040) + Adafruit_SPIFlash flash(&flashTransport); Adafruit_USBD_MSC usb_msc; @@ -69,16 +78,16 @@ namespace msc { // ===== PUBLIC ===== // bool init() { - if(!flash.begin()) { + if (!flash.begin()) { debugln("Couldn't find flash chip!"); return false; } // Try formatting the drive if initialization failed - if(!fatfs.begin(&flash)) { + if (!fatfs.begin(&flash)) { format(); - if(!fatfs.begin(&flash)) { + if (!fatfs.begin(&flash)) { debugln("Couldn't mount flash!"); return false; } @@ -86,30 +95,31 @@ namespace msc { return true; } - + bool format(const char* drive_name) { return format::start(drive_name); } - + void print() { - Serial.println("Available files:"); + debuglnF("Available files:"); // Close file(s) if (file.isOpen()) file.close(); + while (!file_stack.empty()) file_stack.pop(); - + SdFile root; root.open("/"); - - while ( file.openNext(&root, O_RDONLY) ) { + + while (file.openNext(&root, O_RDONLY)) { file.printFileSize(&Serial); - Serial.write(' '); + debugF(" "); file.printName(&Serial); if (file.isDir()) { // Indicate a directory. - Serial.write('/'); + debugF("/"); } - Serial.println(); + debugln(); file.close(); } } @@ -131,7 +141,7 @@ namespace msc { fs_changed = false; return tmp; } - + bool exists(const char* filename) { return fatfs.exists(filename); } @@ -152,7 +162,7 @@ namespace msc { if (file.isOpen()) file.close(); // Create a new file element and push it to the stack - if(add_to_stack) { + if (add_to_stack) { file_element_t file_element; file_element.path = std::string(path); file_element.pos = 0; @@ -261,6 +271,7 @@ namespace msc { size_t write(const char* path, const char* buffer, size_t len) { FatFile wfile; + wfile.open(path, (O_RDWR | O_CREAT)); if (!wfile.isOpen()) return 0;