Merged updated into MalDuino branch
This commit is contained in:
commit
bb93567df1
46
README.md
46
README.md
|
@ -1,13 +1,35 @@
|
|||
# USBNova
|
||||
# USB Nova (MalDuino Port)
|
||||
|
||||
## Arduino-CLI
|
||||
* Install it (Download it and add it to PATH)
|
||||
* Initiate it `arduino-cli config init` (it is saved at `C:\Users\username\AppData\Local\Arduino15\arduino-cli.yaml`)
|
||||
* Update cores `arduino-cli core update-index`
|
||||
* Install core `arduino-cli core install adafruit:samd`
|
||||
* Check your boards `arduino-cli board list`
|
||||
* Compile `arduino-cli compile --profile adafruit_qtpy_m0`
|
||||
* Upload `arduino-cli upload -p COM3`
|
||||
* Compile and upload `arduino-cli compile --fqbn adafruit:samd:adafruit_qtpy_m0:opt=small,usbstack=tinyusb,debug=off -u -p COM3`
|
||||
* Compile export `arduino-cli compile --fqbn adafruit:samd:adafruit_qtpy_m0:opt=small,usbstack=tinyusb,debug=off --output-dir build/`
|
||||
* Convert to uf2 `uf2conv build/USBNova.ino.bin -o build/USBNova.ino.uf2`
|
||||
Get firmware updates on the [release page](https://github.com/SpacehuhnTech/USBNova/releases)
|
||||
|
||||
For documentation, please visit: [usbnova.com](https://usbnova.com/)
|
||||
|
||||
<a href='https://spacehuhn.store/products/usb-nova' target='_blank'>
|
||||
<img height='36' style={{border:0,height:'36px'}} src='https://usbnova.com/img/about/buy.png' border='0' alt='Buy Now' />
|
||||
</a>
|
||||
|
||||
<a href='https://ko-fi.com/G2G75FA4V' target='_blank'>
|
||||
<img height='36' style={{border:0,height:'36px'}} src='https://usbnova.com/img/about/kofi_button.png' border='0' alt='Buy Me a Coffee at ko-fi.com' />
|
||||
</a>
|
||||
|
||||
## Compile using Arduino-CLI
|
||||
Install [Arduino-CLI](https://arduino.github.io/arduino-cli/0.28/installation/).
|
||||
Add `https://adafruit.github.io/arduino-board-index/package_adafruit_index.json` to the additional board manager URLs.
|
||||
Edit boards.txt in `/packages/adafruit/hardware/samd/<version>/` and add [boards.txt](boards.txt).
|
||||
|
||||
Compile and upload:
|
||||
`arduino-cli compile --fqbn adafruit:samd:adafruit_qtpy_m0_nova:usbstack=tinyusb,debug=off -u -p <PORT>`
|
||||
|
||||
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`
|
||||
(To install uf2conv, install rust, then `cargo install uf2conv`)
|
||||
|
||||
---
|
||||
|
||||
For RP2040:
|
||||
`arduino-cli compile --fqbn rp2040:rp2040:generic:flash=16777216_15728640,usbstack=tinyusb --output-dir build/`
|
||||
`elf2uf2-rs build/USBNova.ino.elf build/USBNova.ino.uf2`
|
||||
(To install `cargo install elf2uf2-rs`)
|
65
USBNova.ino
65
USBNova.ino
|
@ -20,7 +20,7 @@ void update() {
|
|||
|
||||
void setup() {
|
||||
led::init();
|
||||
|
||||
|
||||
// Start Serial (for debug)
|
||||
debug_init();
|
||||
|
||||
|
@ -28,33 +28,40 @@ void setup() {
|
|||
if (!msc::init()) {
|
||||
debugln("Couldnt init SD");
|
||||
led::setColor(255, 0, 0, 200);
|
||||
while(true) {
|
||||
taks:update();
|
||||
|
||||
while (true) {
|
||||
tasks::update();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Read mode from selector switch
|
||||
selector::init();
|
||||
|
||||
// Load setting and set USB Device IDs
|
||||
preferences::reset();
|
||||
preferences::load();
|
||||
if (selector::mode() == SETUP) preferences::save();
|
||||
|
||||
if(selector::position() == 2) {
|
||||
hid::setID(preferences::getHid2Vid(), preferences::getHid2Pid(), preferences::getHidRev());
|
||||
if (selector::position() == 1) {
|
||||
hid::setID(preferences::getVID1(), preferences::getPID1(), preferences::getVersion1());
|
||||
hid::setSerial(preferences::getSerial1());
|
||||
hid::setManufacturer(preferences::getManufacturer1());
|
||||
hid::setProduct(preferences::getProduct1());
|
||||
} else {
|
||||
hid::setID(preferences::getHid1Vid(), preferences::getHid1Pid(), preferences::getHidRev());
|
||||
hid::setID(preferences::getVID2(), preferences::getPID2(), preferences::getVersion2());
|
||||
hid::setSerial(preferences::getSerial2());
|
||||
hid::setManufacturer(preferences::getManufacturer2());
|
||||
hid::setProduct(preferences::getProduct2());
|
||||
}
|
||||
|
||||
msc::setID(preferences::getMscVid().c_str(), preferences::getMscPid().c_str(), preferences::getMscRev().c_str());
|
||||
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
|
@ -71,7 +78,7 @@ void setup() {
|
|||
// Attack settings
|
||||
keyboard::setLocale(locale::get(preferences::getDefaultLayout().c_str()));
|
||||
duckparser::setDefaultDelay(preferences::getDefaultDelay());
|
||||
|
||||
|
||||
// Format Flash (if specified in preferences.json)
|
||||
if ((selector::mode() == SETUP) && preferences::getFormat()) {
|
||||
led::setColor(255, 255, 255);
|
||||
|
@ -82,12 +89,12 @@ void setup() {
|
|||
if (!msc::exists(PREFERENCES_PATH)) {
|
||||
preferences::save();
|
||||
}
|
||||
|
||||
|
||||
// Create 1.txt file if it doesn't exist yet
|
||||
if (msc::find(1) == "") {
|
||||
msc::write("1.txt", "# Hello World\n", 14);
|
||||
}
|
||||
|
||||
|
||||
// Create 2.txt file if it doesn't exist yet
|
||||
if (msc::find(2) == "") {
|
||||
msc::write("2.txt", "# Hello World\n", 14);
|
||||
|
@ -100,47 +107,49 @@ 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
|
||||
|
||||
// Don't run again
|
||||
while(true) {
|
||||
while (true) {
|
||||
tasks::update();
|
||||
cli::update();
|
||||
}
|
||||
} 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
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
########################################################################################################################
|
||||
########################################################################################################################
|
||||
########################################################################################################################
|
||||
########################################################################################################################
|
||||
########################################################################################################################
|
||||
########################################################################################################################
|
||||
|
||||
# -----------------------------------
|
||||
# USB Nova
|
||||
# -----------------------------------
|
||||
adafruit_qtpy_m0_nova.name=USB Nova
|
||||
|
||||
# VID/PID for Bootloader, Arduino & CircuitPython
|
||||
adafruit_qtpy_m0_nova.vid.0=0x16D0
|
||||
adafruit_qtpy_m0_nova.pid.0=0x11A4
|
||||
adafruit_qtpy_m0_nova.vid.1=0x16D0
|
||||
adafruit_qtpy_m0_nova.pid.1=0x11A4
|
||||
adafruit_qtpy_m0_nova.vid.2=0x16D0
|
||||
adafruit_qtpy_m0_nova.pid.2=0x11A4
|
||||
|
||||
# Upload
|
||||
adafruit_qtpy_m0_nova.upload.tool=bossac18
|
||||
adafruit_qtpy_m0_nova.upload.protocol=sam-ba
|
||||
adafruit_qtpy_m0_nova.upload.maximum_size=262144
|
||||
adafruit_qtpy_m0_nova.upload.offset=0x2000
|
||||
adafruit_qtpy_m0_nova.upload.use_1200bps_touch=true
|
||||
adafruit_qtpy_m0_nova.upload.wait_for_upload_port=true
|
||||
adafruit_qtpy_m0_nova.upload.native_usb=true
|
||||
|
||||
# Build
|
||||
adafruit_qtpy_m0_nova.build.mcu=cortex-m0plus
|
||||
adafruit_qtpy_m0_nova.build.f_cpu=48000000L
|
||||
adafruit_qtpy_m0_nova.build.usb_product="Nova"
|
||||
adafruit_qtpy_m0_nova.build.usb_manufacturer="Spacehuhn"
|
||||
adafruit_qtpy_m0_nova.build.board=QTPY_M0
|
||||
adafruit_qtpy_m0_nova.build.core=arduino
|
||||
adafruit_qtpy_m0_nova.build.extra_flags=-D__SAMD21E18A__ -DCRYSTALLESS -DADAFRUIT_QTPY_M0 -DARDUINO_SAMD_ZERO -DARM_MATH_CM0PLUS {build.usb_flags}
|
||||
adafruit_qtpy_m0_nova.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
|
||||
adafruit_qtpy_m0_nova.build.openocdscript=openocd_scripts/qtpy_m0.cfg
|
||||
adafruit_qtpy_m0_nova.build.variant=qtpy_m0
|
||||
adafruit_qtpy_m0_nova.build.variant_system_lib=
|
||||
adafruit_qtpy_m0_nova.build.vid=0x16D0
|
||||
adafruit_qtpy_m0_nova.build.pid=0x11A4
|
||||
adafruit_qtpy_m0_nova.bootloader.tool=openocd
|
||||
adafruit_qtpy_m0_nova.bootloader.file=qtpyM0/bootloader-qtpy_m0.bin
|
||||
|
||||
# Menu
|
||||
adafruit_qtpy_m0_nova.menu.opt.small=Small (-Os) (standard)
|
||||
adafruit_qtpy_m0_nova.menu.opt.small.build.flags.optimize=-Os
|
||||
adafruit_qtpy_m0_nova.menu.opt.fast=Fast (-O2)
|
||||
adafruit_qtpy_m0_nova.menu.opt.fast.build.flags.optimize=-O2
|
||||
adafruit_qtpy_m0_nova.menu.opt.faster=Faster (-O3)
|
||||
adafruit_qtpy_m0_nova.menu.opt.faster.build.flags.optimize=-O3
|
||||
adafruit_qtpy_m0_nova.menu.opt.fastest=Fastest (-Ofast)
|
||||
adafruit_qtpy_m0_nova.menu.opt.fastest.build.flags.optimize=-Ofast
|
||||
adafruit_qtpy_m0_nova.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
|
||||
adafruit_qtpy_m0_nova.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
|
||||
adafruit_qtpy_m0_nova.menu.usbstack.arduino=Arduino
|
||||
adafruit_qtpy_m0_nova.menu.usbstack.tinyusb=TinyUSB
|
||||
adafruit_qtpy_m0_nova.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
|
||||
adafruit_qtpy_m0_nova.menu.debug.off=Off
|
||||
adafruit_qtpy_m0_nova.menu.debug.on=On
|
||||
adafruit_qtpy_m0_nova.menu.debug.on.build.flags.debug=-g
|
||||
|
||||
########################################################################################################################
|
||||
########################################################################################################################
|
||||
########################################################################################################################
|
||||
########################################################################################################################
|
||||
########################################################################################################################
|
||||
########################################################################################################################
|
2
config.h
2
config.h
|
@ -2,7 +2,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#define VERSION "0.0.1"
|
||||
#define VERSION "1.2.0"
|
||||
|
||||
// ===== DEBUG Settings ===== //
|
||||
//#define ENABLE_DEBUG
|
||||
|
|
3
debug.h
3
debug.h
|
@ -3,6 +3,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "config.h"
|
||||
|
||||
#ifdef ENABLE_DEBUG
|
||||
|
||||
|
@ -16,7 +17,7 @@
|
|||
|
||||
#else /* ifdef ENABLE_DEBUG */
|
||||
|
||||
#define debug_init() 0
|
||||
#define debug_init() Serial.end();
|
||||
|
||||
#define debugF(...) 0
|
||||
#define debuglnF(...) 0
|
||||
|
|
|
@ -0,0 +1,284 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$ref": "#/$defs/preferences",
|
||||
"$defs": {
|
||||
"color": {
|
||||
"type": "array",
|
||||
"prefixItems": [
|
||||
{
|
||||
"type": "integer",
|
||||
"title": "Red",
|
||||
"description": "From 0 to 255",
|
||||
"minimum": 0,
|
||||
"maximum": 255
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"title": "Green",
|
||||
"description": "From 0 to 255",
|
||||
"minimum": 0,
|
||||
"maximum": 255
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"title": "Blue",
|
||||
"description": "From 0 to 255",
|
||||
"minimum": 0,
|
||||
"maximum": 255
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"title": "Blink-Interval",
|
||||
"description": "The blink interval in milliseconds, 0 means it's not blinking.",
|
||||
"minimum": 0
|
||||
}
|
||||
],
|
||||
"additionalItems": false,
|
||||
"minItems": 4,
|
||||
"maxItems": 4
|
||||
},
|
||||
"preferences": {
|
||||
"title": "Preferences",
|
||||
"description": "Preferences for your USB Nova",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"$schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"enable_msc": {
|
||||
"type": "boolean",
|
||||
"title": "Enable USB mass storage (USB drive) in attack mode",
|
||||
"default": false
|
||||
},
|
||||
"enable_hid": {
|
||||
"type": "boolean",
|
||||
"title": "Enable HID in setup mode",
|
||||
"default": true
|
||||
},
|
||||
"vid1": {
|
||||
"type": "string",
|
||||
"title": "USB Vendor ID",
|
||||
"pattern": "^[0-9A-F]{4}$",
|
||||
"default": "16D0",
|
||||
"examples": [
|
||||
"05AC"
|
||||
],
|
||||
"minLength": 4,
|
||||
"maxLength": 4
|
||||
},
|
||||
"pid1": {
|
||||
"type": "string",
|
||||
"title": "USB Product ID",
|
||||
"pattern": "^[0-9A-F]{4}$",
|
||||
"default": "103F",
|
||||
"examples": [
|
||||
"0250"
|
||||
],
|
||||
"minLength": 4,
|
||||
"maxLength": 4
|
||||
},
|
||||
"version1": {
|
||||
"type": "string",
|
||||
"title": "USB Product Revision (0100 => 1.0)",
|
||||
"default": "0100",
|
||||
"minLength": 4,
|
||||
"maxLength": 4
|
||||
},
|
||||
"serial1": {
|
||||
"type": "string",
|
||||
"title": "USB Serial Number Descriptor",
|
||||
"default": "1337"
|
||||
},
|
||||
"manufacturer1": {
|
||||
"type": "string",
|
||||
"title": "USB Manufacturer Descriptor",
|
||||
"default": "Maltronics"
|
||||
},
|
||||
"product1": {
|
||||
"type": "string",
|
||||
"title": "USB Product Descriptor",
|
||||
"default": "MalDuino"
|
||||
},
|
||||
"vid2": {
|
||||
"type": "string",
|
||||
"title": "USB Vendor ID",
|
||||
"pattern": "^[0-9A-F]{4}$",
|
||||
"default": "16D0",
|
||||
"examples": [
|
||||
"05AC"
|
||||
],
|
||||
"minLength": 4,
|
||||
"maxLength": 4
|
||||
},
|
||||
"pid2": {
|
||||
"type": "string",
|
||||
"title": "USB Product ID",
|
||||
"pattern": "^[0-9A-F]{4}$",
|
||||
"default": "103F",
|
||||
"examples": [
|
||||
"0250"
|
||||
],
|
||||
"minLength": 4,
|
||||
"maxLength": 4
|
||||
},
|
||||
"version2": {
|
||||
"type": "string",
|
||||
"title": "USB Product Revision (0100 => 1.0)",
|
||||
"default": "0100",
|
||||
"minLength": 4,
|
||||
"maxLength": 4
|
||||
},
|
||||
"serial2": {
|
||||
"type": "string",
|
||||
"title": "USB Serial Number Descriptor",
|
||||
"default": "1337"
|
||||
},
|
||||
"manufacturer2": {
|
||||
"type": "string",
|
||||
"title": "USB Manufacturer Descriptor",
|
||||
"default": "Maltronics"
|
||||
},
|
||||
"product2": {
|
||||
"type": "string",
|
||||
"title": "USB Product Descriptor",
|
||||
"default": "MalDuino"
|
||||
},
|
||||
"default_layout": {
|
||||
"type": "string",
|
||||
"title": "Default Keyboard Layout",
|
||||
"enum": [
|
||||
"BE",
|
||||
"BE_MAC",
|
||||
"BG",
|
||||
"BG_MAC",
|
||||
"CA_CM",
|
||||
"CA_FR",
|
||||
"CA_FR_MAC",
|
||||
"CH_DE",
|
||||
"CH_FR",
|
||||
"CH_DE_MAC",
|
||||
"CH_FR_MAC",
|
||||
"CZ",
|
||||
"CZ_MAC",
|
||||
"DE",
|
||||
"DE_MAC",
|
||||
"DK",
|
||||
"DK_MAC",
|
||||
"EE",
|
||||
"EE_MAC",
|
||||
"ES",
|
||||
"ES_MAC",
|
||||
"ES_LA",
|
||||
"ES_LA_MAC",
|
||||
"FI",
|
||||
"FI_MAC",
|
||||
"FR",
|
||||
"FR_MAC",
|
||||
"GB",
|
||||
"GB_MAC",
|
||||
"GR",
|
||||
"GR_MAC",
|
||||
"HU",
|
||||
"HU_MAC",
|
||||
"IE",
|
||||
"IN",
|
||||
"IN_MAC",
|
||||
"IS",
|
||||
"IS_MAC",
|
||||
"IT",
|
||||
"IT_MAC",
|
||||
"LT",
|
||||
"LT_MAC",
|
||||
"LV",
|
||||
"LV_MAC",
|
||||
"NL",
|
||||
"NL_MAC",
|
||||
"NO",
|
||||
"NO_MAC",
|
||||
"PL",
|
||||
"PL_MAC",
|
||||
"PT_BR",
|
||||
"PT_BR_MAC",
|
||||
"PT",
|
||||
"PT_MAC",
|
||||
"RO",
|
||||
"RO_MAC",
|
||||
"RU",
|
||||
"RU_MAC",
|
||||
"SE",
|
||||
"SE_MAC",
|
||||
"SI",
|
||||
"SI_MAC",
|
||||
"SK",
|
||||
"SK_MAC",
|
||||
"TR",
|
||||
"TR_MAC",
|
||||
"UA",
|
||||
"UA_MAC",
|
||||
"US",
|
||||
"US_MAC"
|
||||
],
|
||||
"default": "US"
|
||||
},
|
||||
"default_delay": {
|
||||
"type": "integer",
|
||||
"title": "Default delay between each line",
|
||||
"default": 5,
|
||||
"minimum": 0
|
||||
},
|
||||
"main_script": {
|
||||
"type": "string",
|
||||
"title": "Name of your BadUSB script",
|
||||
"default": "main_script.txt"
|
||||
},
|
||||
"attack_color": {
|
||||
"$ref": "#/$defs/color",
|
||||
"title": "LED color for attack mode",
|
||||
"default": [
|
||||
128,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
"setup_color": {
|
||||
"$ref": "#/$defs/color",
|
||||
"title": "LED color for setup mode",
|
||||
"default": [
|
||||
0,
|
||||
0,
|
||||
20,
|
||||
0
|
||||
]
|
||||
},
|
||||
"idle_color": {
|
||||
"$ref": "#/$defs/color",
|
||||
"title": "LED color for finished attack",
|
||||
"default": [
|
||||
0,
|
||||
30,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
"disable_capslock": {
|
||||
"type": "boolean",
|
||||
"title": "Turn off capslock before starting attack (only work on Windows)",
|
||||
"default": true
|
||||
},
|
||||
"run_on_indicator": {
|
||||
"type": "boolean",
|
||||
"title": "Start script when the user presses capslock, numlock, or another indicator key (only work on Windows)",
|
||||
"default": false
|
||||
},
|
||||
"initial_delay": {
|
||||
"type": "integer",
|
||||
"title": "Startup delay",
|
||||
"default": 1000,
|
||||
"minimum": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
10
sketch.yaml
10
sketch.yaml
|
@ -1,10 +0,0 @@
|
|||
profile:
|
||||
adafruit_qtpy_m0:
|
||||
fqbn: adafruit:samd:adafruit_qtpy_m0:opt=small,usbstack=tinyusb,debug=off
|
||||
platforms:
|
||||
- platform: adafruit:samd (1.7.10)
|
||||
platform_index_url: https://adafruit.github.io/arduino-board-index/package_adafruit_index.json
|
||||
libraries:
|
||||
- SdFat_-_Adafruit_Fork (1.2.4)
|
||||
- Adafruit_NeoPixel (1.10.0)
|
||||
- Adafruit_SPIFlash (3.7.1)
|
|
@ -20,7 +20,7 @@ namespace attack {
|
|||
void start(const char* path) {
|
||||
// If script doesn't exist, don't do anything
|
||||
if (!msc::exists(path)) return;
|
||||
|
||||
|
||||
// Set attack color
|
||||
led::setColor(preferences::getAttackColor());
|
||||
|
||||
|
@ -42,25 +42,26 @@ namespace attack {
|
|||
uint32_t cur_pos = 0;
|
||||
int repeats = 0;
|
||||
|
||||
// For LOOP_START and LOOP_END
|
||||
// For LOOP_BEGIN and LOOP_END
|
||||
uint32_t start_pos = 0;
|
||||
int loops = 0;
|
||||
|
||||
while (true) {
|
||||
debug("Reading line...");
|
||||
debugF("Reading line...");
|
||||
if (!msc::getInLine()) cur_pos = msc::getPosition();
|
||||
len = msc::readLine(buffer, READ_BUFFER);
|
||||
debugln(len);
|
||||
//debugln(std::string(buffer, len-1).c_str());
|
||||
|
||||
// Reached end of file
|
||||
if (len == 0) {
|
||||
debugln("Reached end of file");
|
||||
debuglnF("Reached end of file");
|
||||
if (msc::openNextFile()) continue;
|
||||
else break;
|
||||
}
|
||||
|
||||
debug("Parsing...");
|
||||
debugln(len);
|
||||
debugln(std::string(buffer, len-1).c_str());
|
||||
|
||||
debugF("Parsing...");
|
||||
duckparser::parse(buffer, len);
|
||||
|
||||
// For REPEAT/REPLAY
|
||||
|
@ -77,7 +78,7 @@ namespace attack {
|
|||
|
||||
if (!msc::getInLine()) prev_pos = cur_pos;
|
||||
|
||||
// For LOOP_START/LOOP_STOP
|
||||
// For LOOP_BEGIN/LOOP_END
|
||||
if (duckparser::loopBegin()) {
|
||||
start_pos = msc::getPosition();
|
||||
loops = duckparser::getLoops();
|
||||
|
@ -92,10 +93,9 @@ namespace attack {
|
|||
msc::open(path.c_str());
|
||||
}
|
||||
|
||||
debugln("OK");
|
||||
debuglnF("OK");
|
||||
}
|
||||
|
||||
debugln("Attack finished");
|
||||
debuglnF("Attack finished");
|
||||
}
|
||||
|
||||
void start() {
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
#include "../attack/attack.h"
|
||||
#include "../msc/msc.h"
|
||||
#include "../../config.h"
|
||||
#include "../msc/format.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
|
||||
|
@ -60,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
|
||||
|
@ -99,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();
|
||||
|
@ -133,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());
|
||||
|
|
|
@ -104,7 +104,7 @@ namespace duckparser {
|
|||
else if (compare(str, len, "SHIFT", CASE_SENSETIVE)) keyboard::pressModifier(KEY_MOD_LSHIFT);
|
||||
else if (compare(str, len, "ALT", CASE_SENSETIVE)) keyboard::pressModifier(KEY_MOD_LALT);
|
||||
else if (compare(str, len, "ALTGR", CASE_SENSETIVE)) keyboard::pressModifier(KEY_MOD_RALT);
|
||||
else if (compare(str, len, "WINDOWS", CASE_SENSETIVE) || compare(str, len, "GUI", CASE_SENSETIVE)) keyboard::pressModifier(KEY_MOD_LMETA);
|
||||
else if (compare(str, len, "WINDOWS", CASE_SENSETIVE) || compare(str, len, "GUI", CASE_SENSETIVE) || compare(str, len, "COMMAND", CASE_SENSETIVE)) keyboard::pressModifier(KEY_MOD_LMETA);
|
||||
|
||||
// Numpad Keys
|
||||
|
||||
|
@ -161,12 +161,16 @@ namespace duckparser {
|
|||
if (offset > time) return;
|
||||
else time -= offset;
|
||||
|
||||
sleep_start_time = millis();
|
||||
unsigned long sleep_end_time = sleep_start_time + time;
|
||||
if (time < 50) {
|
||||
delay(time);
|
||||
} else {
|
||||
sleep_start_time = millis();
|
||||
unsigned long sleep_end_time = sleep_start_time + time;
|
||||
|
||||
while (millis() < sleep_end_time) {
|
||||
delay(1);
|
||||
tasks::update();
|
||||
while (millis() < sleep_end_time) {
|
||||
delay(1);
|
||||
tasks::update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,20 +194,21 @@ namespace duckparser {
|
|||
bool ignore_delay;
|
||||
|
||||
while (n) {
|
||||
ignore_delay = false;
|
||||
loop_begin = false;
|
||||
loop_end = false;
|
||||
|
||||
word_list* wl = n->words;
|
||||
word_node* cmd = wl->first;
|
||||
|
||||
// String of the entire line excluding the command keyword (i.e. "STRING ")
|
||||
const char* line_str = cmd->str + cmd->len + 1;
|
||||
size_t line_str_len = n->len - cmd->len - 1;
|
||||
bool has_line_str = cmd->next;
|
||||
const char* line_str = has_line_str ? (cmd->str + cmd->len + 1) : nullptr;
|
||||
size_t line_str_len = has_line_str ? (n->len - cmd->len - 1) : 0;
|
||||
|
||||
char last_char = n->str[n->len];
|
||||
bool line_end = last_char == '\r' || last_char == '\n';
|
||||
|
||||
ignore_delay = false;
|
||||
loop_begin = false;
|
||||
loop_end = false;
|
||||
|
||||
// Check if we're in a multi line comment
|
||||
if (in_ml_comment) {
|
||||
// Check for the end of the comment block
|
||||
|
@ -266,6 +271,24 @@ namespace duckparser {
|
|||
|
||||
in_string = !line_end;
|
||||
}
|
||||
// STRINGLN (-> type each character & press enter)
|
||||
else if (in_string || compare(cmd->str, cmd->len, "STRINGLN", CASE_SENSETIVE)) {
|
||||
// Type the entire line
|
||||
if (in_string) {
|
||||
type(n->str, n->len);
|
||||
}
|
||||
// Type the everything after "STRINGLN "
|
||||
else {
|
||||
type(line_str, line_str_len);
|
||||
}
|
||||
|
||||
if (line_end) {
|
||||
keyboard::pressKey(KEY_ENTER);
|
||||
release();
|
||||
}
|
||||
|
||||
in_string = !line_end;
|
||||
}
|
||||
// REPEAT (-> repeat last command n times)
|
||||
else if (compare(cmd->str, cmd->len, "REPEAT", CASE_SENSETIVE) || compare(cmd->str, cmd->len, "REPLAY", CASE_SENSETIVE)) {
|
||||
repeat_num = to_uint(line_str, line_str_len) + 1;
|
||||
|
@ -290,9 +313,10 @@ namespace duckparser {
|
|||
|
||||
ignore_delay = true;
|
||||
}
|
||||
|
||||
/*
|
||||
// LED
|
||||
else if (compare(cmd->str, cmd->len, "LED", CASE_SENSETIVE)) {
|
||||
// LED
|
||||
else if (compare(cmd->str, cmd->len, "LED", CASE_SENSETIVE)) {
|
||||
// i.e. LED R SOLID
|
||||
if (wl->size == 3) {
|
||||
word_node* w = cmd->next;
|
||||
|
@ -340,8 +364,8 @@ namespace duckparser {
|
|||
}
|
||||
|
||||
ignore_delay = true;
|
||||
}
|
||||
*/
|
||||
}
|
||||
*/
|
||||
// KEYCODE
|
||||
else if (compare(cmd->str, cmd->len, "KEYCODE", CASE_SENSETIVE)) {
|
||||
word_node* w = cmd->next;
|
||||
|
|
|
@ -65,9 +65,9 @@ namespace duckparser {
|
|||
|
||||
// comparison incorrect or string checked until the end and templ_str not checked until the end
|
||||
if (!res || ((a == str_len - 1) &&
|
||||
(templ_str[b + 1] != ',') &&
|
||||
(templ_str[b + 1] != '/') &&
|
||||
(templ_str[b + 1] != '\0'))) {
|
||||
(templ_str[b + 1] != ',') &&
|
||||
(templ_str[b + 1] != '/') &&
|
||||
(templ_str[b + 1] != '\0'))) {
|
||||
// fast forward to next comma
|
||||
while (b < key_len && templ_str[b] != ',') b++;
|
||||
res = 1;
|
||||
|
@ -81,8 +81,8 @@ namespace duckparser {
|
|||
// comparison correct AND string checked until the end AND templ_str checked until the end
|
||||
if (res && (a == str_len) &&
|
||||
((templ_str[b] == ',') ||
|
||||
(templ_str[b] == '/') ||
|
||||
(templ_str[b] == '\0'))) return COMPARE_EQUAL; // res_i
|
||||
(templ_str[b] == '/') ||
|
||||
(templ_str[b] == '\0'))) return COMPARE_EQUAL; // res_i
|
||||
|
||||
return COMPARE_UNEQUAL;
|
||||
}
|
||||
|
@ -295,19 +295,22 @@ namespace duckparser {
|
|||
// in_quotes = (curr == '"' && !escaped) ? !in_quotes : in_quotes;
|
||||
// delimiter = !in_quotes && !escaped && curr == ';' && next == ';';
|
||||
|
||||
linebreak = !in_quotes && (curr == '\r' || curr == '\n');
|
||||
linebreak = /*!in_quotes && */ (curr == '\r' || curr == '\n');
|
||||
|
||||
endofline = stri == len || curr == '\0';
|
||||
// skip \n after \r (windows linebreak)
|
||||
if (/*!in_quotes && */ (curr == '\r') && (next == '\n')) ++stri;
|
||||
|
||||
endofline = (stri == len) || (curr == '\0');
|
||||
|
||||
if (linebreak || endofline || delimiter) {
|
||||
size_t llen = stri - ls; // length of line
|
||||
|
||||
// for every line, parse_words and add to list
|
||||
//if (llen > 0) {
|
||||
if (llen > 0) {
|
||||
n = line_node_create(&str[ls], llen);
|
||||
n->words = parse_words(&str[ls], llen);
|
||||
line_list_push(l, n);
|
||||
//}
|
||||
}
|
||||
|
||||
if (delimiter) ++stri;
|
||||
|
||||
|
|
|
@ -11,10 +11,13 @@ namespace hid {
|
|||
bool indicator_changed = false; // Whether or not any indicator changed since last time
|
||||
bool indicator_read = false; // If initial indicator was read
|
||||
|
||||
std::string serial = "0100";
|
||||
std::string manufacturer = "Maltronics";
|
||||
std::string product = "MalDuino";
|
||||
|
||||
// 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))
|
||||
|
@ -56,7 +59,7 @@ namespace hid {
|
|||
// ====== PUBLIC ====== //
|
||||
void init() {
|
||||
// Notes: following commented-out functions has no affect on ESP32
|
||||
// usb_hid.setBootProtocol(HID_ITF_PROTOCOL_KEYBOARD);
|
||||
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");
|
||||
|
@ -72,6 +75,21 @@ namespace hid {
|
|||
TinyUSBDevice.setDeviceVersion(version);
|
||||
}
|
||||
|
||||
void setSerial(std::string serialstr) {
|
||||
hid::serial = serialstr;
|
||||
TinyUSBDevice.setSerialDescriptor(serial.c_str());
|
||||
}
|
||||
|
||||
void setManufacturer(std::string manufacturerstr) {
|
||||
hid::manufacturer = manufacturerstr;
|
||||
TinyUSBDevice.setManufacturerDescriptor(manufacturer.c_str());
|
||||
}
|
||||
|
||||
void setProduct(std::string productstr) {
|
||||
hid::product = productstr;
|
||||
TinyUSBDevice.setProductDescriptor(product.c_str());
|
||||
}
|
||||
|
||||
bool mounted() {
|
||||
return TinyUSBDevice.mounted();
|
||||
}
|
||||
|
@ -84,25 +102,25 @@ namespace hid {
|
|||
}
|
||||
|
||||
// Wait until ready to send next report
|
||||
while (!usb_hid.ready()){
|
||||
while (!usb_hid.ready()) {
|
||||
delay(1);
|
||||
}
|
||||
|
||||
usb_hid.keyboardReport(RID::KEYBOARD, modifier, keys);
|
||||
}
|
||||
|
||||
|
||||
void sendMouseReport(uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) {
|
||||
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()){
|
||||
while (!usb_hid.ready()) {
|
||||
delay(1);
|
||||
}
|
||||
|
||||
|
||||
usb_hid.mouseReport(RID::MOUSE, buttons, x, y, vertical, horizontal);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,18 +2,25 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../../config.h"
|
||||
|
||||
#include <cstdint> // uint8_t
|
||||
#include <string> // std::string
|
||||
|
||||
namespace hid {
|
||||
// Report ID
|
||||
enum RID {
|
||||
KEYBOARD = 1,
|
||||
MOUSE = 2,
|
||||
KEYBOARD = 1,
|
||||
MOUSE = 2,
|
||||
CONSUMER_CONTROL = 3, // Media, volume etc ..
|
||||
};
|
||||
|
||||
void init();
|
||||
void setID(uint16_t vid, uint16_t pid, uint16_t version);
|
||||
void setSerial(std::string serialstr);
|
||||
void setManufacturer(std::string manufacturerstr);
|
||||
void setProduct(std::string productstr);
|
||||
|
||||
bool mounted();
|
||||
|
||||
void sendKeyboardReport(uint8_t modifier, uint8_t* keys);
|
||||
|
|
|
@ -78,22 +78,22 @@
|
|||
|
||||
namespace locale {
|
||||
// ===== PUBLIC ===== //
|
||||
hid_locale_t *get_default() {
|
||||
hid_locale_t* get_default() {
|
||||
return &locale_us_win;
|
||||
}
|
||||
|
||||
hid_locale_t *get(const char *name) {
|
||||
hid_locale_t* get(const char* name) {
|
||||
if (strncmp(name, "BE_MAC", 6) == 0) return &locale_be_mac;
|
||||
else if (strncmp(name, "BG_MAC", 6) == 0) return &locale_bg_mac;
|
||||
else if (strncmp(name, "CA_FR_MAC", 9) == 0) return &locale_ca_fr_mac;
|
||||
else if (strncmp(name, "CH_DE_MAC", 9) == 0) return &locale_ch_de_mac;
|
||||
else if (strncmp(name, "CH_FR_MAC", 9) == 0) return &locale_ch_fr_mac;
|
||||
else if ((strncmp(name, "CA-FR_MAC", 9) == 0) || (strncmp(name, "CA_FR_MAC", 9) == 0)) return &locale_ca_fr_mac;
|
||||
else if ((strncmp(name, "CH-DE_MAC", 9) == 0) || (strncmp(name, "CH_DE_MAC", 9) == 0)) return &locale_ch_de_mac;
|
||||
else if ((strncmp(name, "CH-FR_MAC", 9) == 0) || (strncmp(name, "CH_FR_MAC", 9) == 0)) return &locale_ch_fr_mac;
|
||||
else if (strncmp(name, "CZ_MAC", 6) == 0) return &locale_cz_mac;
|
||||
else if (strncmp(name, "DE_MAC", 6) == 0) return &locale_de_mac;
|
||||
else if (strncmp(name, "DK_MAC", 6) == 0) return &locale_dk_mac;
|
||||
else if (strncmp(name, "EE_MAC", 6) == 0) return &locale_ee_mac;
|
||||
else if (strncmp(name, "ES_MAC", 6) == 0) return &locale_es_mac;
|
||||
else if (strncmp(name, "ES_LA_MAC", 9) == 0) return &locale_es_la_mac;
|
||||
else if ((strncmp(name, "ES-LA_MAC", 9) == 0) || (strncmp(name, "ES_LA_MAC", 9) == 0)) return &locale_es_la_mac;
|
||||
else if (strncmp(name, "FI_MAC", 6) == 0) return &locale_fi_mac;
|
||||
else if (strncmp(name, "FR_MAC", 6) == 0) return &locale_fr_mac;
|
||||
else if (strncmp(name, "GB_MAC", 6) == 0) return &locale_gb_mac;
|
||||
|
@ -108,7 +108,7 @@ namespace locale {
|
|||
else if (strncmp(name, "NO_MAC", 6) == 0) return &locale_no_mac;
|
||||
else if (strncmp(name, "PL_MAC", 6) == 0) return &locale_pl_mac;
|
||||
else if (strncmp(name, "PT_MAC", 6) == 0) return &locale_pt_mac;
|
||||
else if (strncmp(name, "PT_BR_MAC", 9) == 0) return &locale_pt_br_mac;
|
||||
else if ((strncmp(name, "PT-BR_MAC", 9) == 0) || (strncmp(name, "PT_BR_MAC", 9) == 0)) return &locale_pt_br_mac;
|
||||
else if (strncmp(name, "RO_MAC", 6) == 0) return &locale_ro_mac;
|
||||
else if (strncmp(name, "RU_MAC", 6) == 0) return &locale_ru_mac;
|
||||
else if (strncmp(name, "SE_MAC", 6) == 0) return &locale_se_mac;
|
||||
|
@ -119,15 +119,15 @@ namespace locale {
|
|||
else if (strncmp(name, "US_MAC", 6) == 0) return &locale_us_mac;
|
||||
else if (strncmp(name, "BE", 2) == 0) return &locale_be_win;
|
||||
else if (strncmp(name, "BG", 2) == 0) return &locale_bg_win;
|
||||
else if (strncmp(name, "CA-CMS", 6) == 0) return &locale_ca_cms_win;
|
||||
else if (strncmp(name, "CA-FR", 5) == 0) return &locale_ca_fr_win;
|
||||
else if (strncmp(name, "CH-DE", 5) == 0) return &locale_ch_de_win;
|
||||
else if (strncmp(name, "CH-FR", 5) == 0) return &locale_ch_fr_win;
|
||||
else if ((strncmp(name, "CA-CMS", 6) == 0) || (strncmp(name, "CA_CMS", 6) == 0)) return &locale_ca_cms_win;
|
||||
else if ((strncmp(name, "CA-FR", 5) == 0) || (strncmp(name, "CA_FR", 5) == 0)) return &locale_ca_fr_win;
|
||||
else if ((strncmp(name, "CH-DE", 5) == 0) || (strncmp(name, "CH_DE", 5) == 0)) return &locale_ch_de_win;
|
||||
else if ((strncmp(name, "CH-FR", 5) == 0) || (strncmp(name, "CH_FR", 5) == 0)) return &locale_ch_fr_win;
|
||||
else if (strncmp(name, "CZ", 2) == 0) return &locale_cz_win;
|
||||
else if (strncmp(name, "DE", 2) == 0) return &locale_de_win;
|
||||
else if (strncmp(name, "DK", 2) == 0) return &locale_dk_win;
|
||||
else if (strncmp(name, "EE", 2) == 0) return &locale_ee_win;
|
||||
else if (strncmp(name, "ES-LA", 5) == 0) return &locale_es_la_win;
|
||||
else if ((strncmp(name, "ES-LA", 5) == 0) || (strncmp(name, "ES_LA", 5) == 0)) return &locale_es_la_win;
|
||||
else if (strncmp(name, "ES", 2) == 0) return &locale_es_win;
|
||||
else if (strncmp(name, "FI", 2) == 0) return &locale_fi_win;
|
||||
else if (strncmp(name, "FR", 2) == 0) return &locale_fr_win;
|
||||
|
@ -143,7 +143,7 @@ namespace locale {
|
|||
else if (strncmp(name, "NL", 2) == 0) return &locale_nl_win;
|
||||
else if (strncmp(name, "NO", 2) == 0) return &locale_no_win;
|
||||
else if (strncmp(name, "PL", 2) == 0) return &locale_pl_win;
|
||||
else if (strncmp(name, "PT-BR", 5) == 0) return &locale_pt_br_win;
|
||||
else if ((strncmp(name, "PT-BR", 5) == 0) || (strncmp(name, "PT_BR", 5) == 0)) return &locale_pt_br_win;
|
||||
else if (strncmp(name, "PT", 2) == 0) return &locale_pt_win;
|
||||
else if (strncmp(name, "RO", 2) == 0) return &locale_ro_win;
|
||||
else if (strncmp(name, "RU", 2) == 0) return &locale_ru_win;
|
||||
|
|
|
@ -83,11 +83,11 @@ namespace msc {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool format(const char* drive_name) {
|
||||
return format::start(drive_name);
|
||||
}
|
||||
|
||||
|
||||
void print() {
|
||||
Serial.println("Available files:");
|
||||
|
||||
|
@ -100,23 +100,19 @@ namespace msc {
|
|||
|
||||
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();
|
||||
}
|
||||
|
||||
root.close();
|
||||
}
|
||||
|
||||
void setID(const char* vid, const char* pid, const char* rev) {
|
||||
usb_msc.setID(vid, pid, rev); // Max. 8, 16, 4 characters
|
||||
}
|
||||
|
||||
void enableDrive() {
|
||||
#if SD_FAT_VERSION >= 20000
|
||||
uint32_t block_count = sd.card()->sectorCount();
|
||||
|
@ -136,7 +132,7 @@ namespace msc {
|
|||
fs_changed = false;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
bool exists(const char* filename) {
|
||||
return sd.exists(filename);
|
||||
}
|
||||
|
@ -157,7 +153,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;
|
||||
|
|
|
@ -11,7 +11,6 @@ namespace msc {
|
|||
bool format(const char* drive_name = "MalDuino");
|
||||
void print();
|
||||
|
||||
void setID(const char* vid, const char* pid, const char* rev);
|
||||
void enableDrive();
|
||||
|
||||
bool changed();
|
||||
|
@ -19,7 +18,7 @@ namespace msc {
|
|||
|
||||
bool open(const char* path, bool add_to_stack = true);
|
||||
bool openNextFile();
|
||||
|
||||
|
||||
void close();
|
||||
|
||||
uint32_t getPosition();
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <ArduinoJson.h>
|
||||
#include "../msc/msc.h"
|
||||
|
||||
#define JSON_SIZE 1536
|
||||
#define JSON_SIZE 2048
|
||||
|
||||
/*
|
||||
How to add new settings:
|
||||
|
@ -21,92 +21,116 @@
|
|||
|
||||
namespace preferences {
|
||||
// ========== PRIVATE ========= //
|
||||
bool enable_msc { false };
|
||||
bool enable_led { true };
|
||||
bool enable_hid { true };
|
||||
bool enable_msc;
|
||||
bool enable_led;
|
||||
bool enable_hid;
|
||||
|
||||
std::string hid1_vid { "16D0" };
|
||||
std::string hid1_pid { "103F" };
|
||||
std::string hid2_vid { "16D0" };
|
||||
std::string hid2_pid { "103F" };
|
||||
std::string hid_rev { "0100" };
|
||||
std::string vid1;
|
||||
std::string pid1;
|
||||
std::string version1;
|
||||
std::string serial1;
|
||||
std::string manufacturer1;
|
||||
std::string product1;
|
||||
|
||||
std::string msc_vid { "Maltrncs" }; // max. 8 chars
|
||||
std::string msc_pid { "MalDuino" }; // max. 16 chars
|
||||
std::string msc_rev { "1.0" }; // max. 4 chars
|
||||
std::string vid2;
|
||||
std::string pid2;
|
||||
std::string version2;
|
||||
std::string serial2;
|
||||
std::string manufacturer2;
|
||||
std::string product2;
|
||||
|
||||
std::string default_layout { "US" };
|
||||
int default_delay { 5 };
|
||||
std::string default_layout;
|
||||
int default_delay;
|
||||
|
||||
// std::string main_script { "main.script" };
|
||||
// std::string main_script;
|
||||
|
||||
int attack_color[4] { 255, 0, 0, 1000 };
|
||||
int setup_color[4] { 255, 0, 0, 0 };
|
||||
int idle_color[4] { 0, 0, 0, 0 };
|
||||
int attack_color[4];
|
||||
int setup_color[4];
|
||||
int idle_color[4];
|
||||
|
||||
bool format { false };
|
||||
std::string drive_name { "MalDuino" };
|
||||
bool format;
|
||||
std::string drive_name;
|
||||
|
||||
bool disable_capslock { true };
|
||||
bool run_on_indicator { false };
|
||||
bool disable_capslock;
|
||||
bool run_on_indicator;
|
||||
|
||||
int initial_delay { 1000 };
|
||||
int initial_delay;
|
||||
|
||||
// Array help functions
|
||||
void add_array(JsonDocument& doc, const char* name, int* array, int size) {
|
||||
JsonArray jarr = doc.createNestedArray(name);
|
||||
for(size_t i = 0; i < size; ++i) {
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
jarr.add(array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void toJson(JsonDocument& root) {
|
||||
root["$schema"] = "https://raw.githubusercontent.com/SpacehuhnTech/USBNova/malduino/schema.json";
|
||||
|
||||
root["enable_msc"] = enable_msc;
|
||||
root["enable_led"] = enable_led;
|
||||
root["enable_hid"] = enable_hid;
|
||||
|
||||
root["vid1"] = vid1;
|
||||
root["pid1"] = pid1;
|
||||
root["version1"] = version1;
|
||||
root["serial1"] = serial1;
|
||||
root["manufacturer1"] = manufacturer1;
|
||||
root["product1"] = product1;
|
||||
|
||||
root["vid2"] = vid2;
|
||||
root["pid2"] = pid2;
|
||||
root["version2"] = version2;
|
||||
root["serial2"] = serial2;
|
||||
root["manufacturer2"] = manufacturer2;
|
||||
root["product2"] = product2;
|
||||
|
||||
root["default_layout"] = default_layout;
|
||||
root["default_delay"] = default_delay;
|
||||
|
||||
/*
|
||||
root["main_script"] = main_script;
|
||||
|
||||
add_array(root, "attack_color", attack_color, 4);
|
||||
add_array(root, "setup_color", setup_color, 4);
|
||||
add_array(root, "idle_color", idle_color, 4);
|
||||
*/
|
||||
root["disable_capslock"] = disable_capslock;
|
||||
root["run_on_indicator"] = run_on_indicator;
|
||||
|
||||
root["initial_delay"] = initial_delay;
|
||||
}
|
||||
|
||||
void read_array(JsonDocument& doc, const char* name, int* array, int size) {
|
||||
JsonArray jarr = doc[name].as<JsonArray>();
|
||||
JsonVariant val = doc[name];
|
||||
|
||||
if (val.isNull()) return;
|
||||
|
||||
JsonArray jarr = val.as<JsonArray>();
|
||||
|
||||
for (size_t i = 0; i<jarr.size() && i<size; ++i) {
|
||||
array[i] = jarr[i].as<int>();
|
||||
}
|
||||
}
|
||||
|
||||
void toJson(JsonDocument& root) {
|
||||
root["enable_msc"] = enable_msc;
|
||||
//root["enable_led"] = enable_led;
|
||||
root["enable_hid"] = enable_hid;
|
||||
template<typename T>
|
||||
void read_item(JsonDocument& doc, const char* name, T& val) {
|
||||
JsonVariant new_val = doc[name];
|
||||
|
||||
root["hid1_vid"] = hid1_vid;
|
||||
root["hid1_pid"] = hid1_pid;
|
||||
root["hid2_vid"] = hid2_vid;
|
||||
root["hid2_pid"] = hid2_pid;
|
||||
root["hid_rev"] = hid_rev;
|
||||
|
||||
root["msc_vid"] = msc_vid;
|
||||
root["msc_pid"] = msc_pid;
|
||||
root["msc_rev"] = msc_rev;
|
||||
|
||||
root["default_layout"] = default_layout;
|
||||
root["default_delay"] = default_delay;
|
||||
/*
|
||||
root["main_script"] = main_script;
|
||||
|
||||
add_array(root, "attack_color", attack_color, 4);
|
||||
add_array(root, "setup_color", setup_color, 4);
|
||||
add_array(root, "idle_color", idle_color, 4);
|
||||
*/
|
||||
root["disable_capslock"] = disable_capslock;
|
||||
root["run_on_indicator"] = run_on_indicator;
|
||||
|
||||
root["initial_delay"] = initial_delay;
|
||||
if (new_val.isNull()) return;
|
||||
val = new_val.as<T>();
|
||||
}
|
||||
|
||||
// ======== PUBLIC ======== //
|
||||
void load() {
|
||||
// Read config file
|
||||
char* buffer = (char*)malloc(JSON_SIZE);
|
||||
char* buffer = (char*)calloc(JSON_SIZE, sizeof(char));
|
||||
DynamicJsonDocument config_doc(JSON_SIZE);
|
||||
|
||||
// Open the file and read it into a buffer
|
||||
if (!msc::open(PREFERENCES_PATH), false) return;
|
||||
msc::read(buffer, JSON_SIZE);
|
||||
size_t read = msc::read(buffer, JSON_SIZE);
|
||||
msc::close();
|
||||
|
||||
// Deserialize the JSON document
|
||||
|
@ -121,59 +145,34 @@ namespace preferences {
|
|||
return;
|
||||
}
|
||||
|
||||
// === Add missing values === //
|
||||
if (!config_doc.containsKey("enable_msc")) config_doc["enable_msc"] = enable_msc;
|
||||
//if (!config_doc.containsKey("enable_led")) config_doc["enable_led"] = enable_led;
|
||||
if (!config_doc.containsKey("enable_hid")) config_doc["enable_hid"] = enable_hid;
|
||||
|
||||
if (!config_doc.containsKey("hid1_vid")) config_doc["hid1_vid"] = hid1_vid;
|
||||
if (!config_doc.containsKey("hid1_pid")) config_doc["hid1_pid"] = hid1_pid;
|
||||
if (!config_doc.containsKey("hid2_vid")) config_doc["hid2_vid"] = hid2_vid;
|
||||
if (!config_doc.containsKey("hid2_pid")) config_doc["hid2_pid"] = hid2_pid;
|
||||
if (!config_doc.containsKey("hid_rev")) config_doc["hid_rev"] = hid_rev;
|
||||
|
||||
if (!config_doc.containsKey("msc_vid")) config_doc["msc_vid"] = msc_vid;
|
||||
if (!config_doc.containsKey("msc_pid")) config_doc["msc_pid"] = msc_pid;
|
||||
if (!config_doc.containsKey("msc_rev")) config_doc["msc_rev"] = msc_rev;
|
||||
|
||||
if (!config_doc.containsKey("default_layout")) config_doc["default_layout"] = default_layout;
|
||||
if (!config_doc.containsKey("default_delay")) config_doc["default_delay"] = default_delay;
|
||||
/*
|
||||
if (!config_doc.containsKey("main_script")) config_doc["main_script"] = main_script;
|
||||
|
||||
if (!config_doc.containsKey("attack_color")) add_array(config_doc, "attack_color", attack_color, 4);
|
||||
if (!config_doc.containsKey("setup_color")) add_array(config_doc, "setup_color", setup_color, 4);
|
||||
if (!config_doc.containsKey("idle_color")) add_array(config_doc, "idle_color", idle_color, 4);
|
||||
*/
|
||||
if (!config_doc.containsKey("disable_capslock")) config_doc["disable_capslock"] = disable_capslock;
|
||||
if (!config_doc.containsKey("run_on_indicator")) config_doc["run_on_indicator"] = run_on_indicator;
|
||||
|
||||
if (!config_doc.containsKey("initial_delay")) config_doc["initial_delay"] = initial_delay;
|
||||
|
||||
// === Fetch values === //
|
||||
enable_msc = config_doc["enable_msc"].as<bool>();
|
||||
//enable_led = config_doc["enable_led"].as<bool>();
|
||||
enable_hid = config_doc["enable_hid"].as<bool>();
|
||||
read_item<bool>(config_doc, "enable_msc", enable_msc);
|
||||
read_item<bool>(config_doc, "enable_led", enable_led);
|
||||
read_item<bool>(config_doc, "enable_hid", enable_hid);
|
||||
|
||||
hid1_vid = config_doc["hid1_vid"].as<std::string>();
|
||||
hid1_pid = config_doc["hid1_pid"].as<std::string>();
|
||||
hid2_vid = config_doc["hid2_vid"].as<std::string>();
|
||||
hid2_pid = config_doc["hid2_pid"].as<std::string>();
|
||||
hid_rev = config_doc["hid_rev"].as<std::string>();
|
||||
read_item<std::string>(config_doc, "vid1", vid1);
|
||||
read_item<std::string>(config_doc, "pid1", pid1);
|
||||
read_item<std::string>(config_doc, "version1", version1);
|
||||
read_item<std::string>(config_doc, "serial1", serial1);
|
||||
read_item<std::string>(config_doc, "manufacturer1", manufacturer1);
|
||||
read_item<std::string>(config_doc, "product1", product1);
|
||||
|
||||
msc_vid = config_doc["msc_vid"].as<std::string>();
|
||||
msc_pid = config_doc["msc_pid"].as<std::string>();
|
||||
msc_rev = config_doc["msc_rev"].as<std::string>();
|
||||
read_item<std::string>(config_doc, "vid2", vid2);
|
||||
read_item<std::string>(config_doc, "pid2", pid2);
|
||||
read_item<std::string>(config_doc, "version2", version2);
|
||||
read_item<std::string>(config_doc, "serial2", serial2);
|
||||
read_item<std::string>(config_doc, "manufacturer2", manufacturer2);
|
||||
read_item<std::string>(config_doc, "product2", product2);
|
||||
|
||||
default_layout = config_doc["default_layout"].as<std::string>();
|
||||
default_delay = config_doc["default_delay"].as<int>();
|
||||
/*
|
||||
main_script = config_doc["main_script"].as<std::string>();
|
||||
read_item<std::string>(config_doc, "default_layout", default_layout);
|
||||
read_item<int>(config_doc, "default_delay", default_delay);
|
||||
|
||||
// read_item<std::string>(config_doc, "main_script", main_script);
|
||||
|
||||
// read_array(config_doc, "attack_color", attack_color, 4);
|
||||
// read_array(config_doc, "setup_color", setup_color, 4);
|
||||
// read_array(config_doc, "idle_color", idle_color, 4);
|
||||
|
||||
read_array(config_doc, "attack_color", attack_color, 4);
|
||||
read_array(config_doc, "setup_color", setup_color, 4);
|
||||
read_array(config_doc, "idle_color", idle_color, 4);
|
||||
*/
|
||||
// Format Flash (Drive name/Disk label max 11 characters)
|
||||
format = config_doc.containsKey("format");
|
||||
if (format) {
|
||||
|
@ -181,9 +180,9 @@ namespace preferences {
|
|||
}
|
||||
|
||||
disable_capslock = config_doc["disable_capslock"].as<bool>();
|
||||
run_on_indicator = config_doc["run_on_indicator"].as<bool>();
|
||||
|
||||
initial_delay = config_doc["initial_delay"].as<int>();
|
||||
run_on_indicator = config_doc["run_on_indicator"].as<bool>();
|
||||
|
||||
initial_delay = config_doc["initial_delay"].as<int>();
|
||||
}
|
||||
|
||||
void save() {
|
||||
|
@ -206,31 +205,35 @@ namespace preferences {
|
|||
debug("Saved ");
|
||||
debugln(PREFERENCES_PATH);
|
||||
}
|
||||
|
||||
|
||||
void reset() {
|
||||
enable_msc = false;
|
||||
//enable_led = true;
|
||||
enable_led = true;
|
||||
enable_hid = true;
|
||||
|
||||
hid1_vid = "16D0";
|
||||
hid1_pid = "103F";
|
||||
hid2_vid = "16D0";
|
||||
hid2_pid = "103F";
|
||||
hid_rev = "0100";
|
||||
vid1 = "16D0";
|
||||
pid1 = "103F";
|
||||
version1 = "0100";
|
||||
serial1 = "1337";
|
||||
manufacturer1 = "Maltronics";
|
||||
product1 = "MalDuino";
|
||||
|
||||
msc_vid = "Maltrncs";
|
||||
msc_pid = "MalDuino";
|
||||
msc_rev = "1.0";
|
||||
vid2 = "16D0";
|
||||
pid2 = "103F";
|
||||
version2 = "0100";
|
||||
serial2 = "1337";
|
||||
manufacturer2 = "Maltronics";
|
||||
product2 = "MalDuino";
|
||||
|
||||
default_layout = "US";
|
||||
default_delay = 5;
|
||||
/*
|
||||
main_script = "main.script";
|
||||
default_delay = 5;
|
||||
|
||||
// main_script = "main_script.txt";
|
||||
|
||||
attack_color[0] = 0;
|
||||
attack_color[1] = 0;
|
||||
attack_color[2] = 0;
|
||||
attack_color[3] = 0;
|
||||
attack_color[1] = 0;
|
||||
|
||||
setup_color[0] = 255;
|
||||
setup_color[1] = 0;
|
||||
|
@ -241,16 +244,16 @@ namespace preferences {
|
|||
idle_color[1] = 0;
|
||||
idle_color[2] = 0;
|
||||
idle_color[3] = 0;
|
||||
*/
|
||||
format = false;
|
||||
drive_name = "MalDuino";
|
||||
|
||||
format = false;
|
||||
drive_name = "USB Nova";
|
||||
|
||||
disable_capslock = true;
|
||||
run_on_indicator = false;
|
||||
|
||||
initial_delay = 1000;
|
||||
}
|
||||
|
||||
|
||||
void print() {
|
||||
// Create a new JSON document (and string buffer)
|
||||
DynamicJsonDocument json_doc(JSON_SIZE);
|
||||
|
@ -280,36 +283,52 @@ namespace preferences {
|
|||
return enable_hid;
|
||||
}
|
||||
|
||||
uint16_t getHid1Vid() {
|
||||
return std::stoi(hid1_vid, nullptr, 16);
|
||||
uint16_t getVID1() {
|
||||
return std::stoi(vid1, nullptr, 16);
|
||||
}
|
||||
|
||||
uint16_t getHid1Pid() {
|
||||
return std::stoi(hid1_pid, nullptr, 16);
|
||||
}
|
||||
|
||||
uint16_t getHid2Vid() {
|
||||
return std::stoi(hid2_vid, nullptr, 16);
|
||||
uint16_t getPID1() {
|
||||
return std::stoi(pid1, nullptr, 16);
|
||||
}
|
||||
|
||||
uint16_t getHid2Pid() {
|
||||
return std::stoi(hid2_pid, nullptr, 16);
|
||||
uint16_t getVersion1() {
|
||||
return std::stoi(version1, nullptr, 16);
|
||||
}
|
||||
|
||||
uint16_t getHidRev() {
|
||||
return std::stoi(hid_rev, nullptr, 16);
|
||||
std::string getSerial1() {
|
||||
return serial1;
|
||||
}
|
||||
|
||||
std::string getMscVid() {
|
||||
return msc_vid;
|
||||
std::string getManufacturer1() {
|
||||
return manufacturer1;
|
||||
}
|
||||
|
||||
std::string getMscPid() {
|
||||
return msc_pid;
|
||||
std::string getProduct1() {
|
||||
return product1;
|
||||
}
|
||||
|
||||
std::string getMscRev() {
|
||||
return msc_rev;
|
||||
uint16_t getVID2() {
|
||||
return std::stoi(vid2, nullptr, 16);
|
||||
}
|
||||
|
||||
uint16_t getPID2() {
|
||||
return std::stoi(pid2, nullptr, 16);
|
||||
}
|
||||
|
||||
uint16_t getVersion2() {
|
||||
return std::stoi(version2, nullptr, 16);
|
||||
}
|
||||
|
||||
std::string getSerial2() {
|
||||
return serial2;
|
||||
}
|
||||
|
||||
std::string getManufacturer2() {
|
||||
return manufacturer2;
|
||||
}
|
||||
|
||||
std::string getProduct2() {
|
||||
return product2;
|
||||
}
|
||||
|
||||
std::string getDefaultLayout() {
|
||||
|
@ -319,11 +338,12 @@ namespace preferences {
|
|||
int getDefaultDelay() {
|
||||
return default_delay;
|
||||
}
|
||||
/*
|
||||
std::string getMainScript() {
|
||||
return main_script;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
std::string getMainScript() {
|
||||
return main_script;
|
||||
}
|
||||
*/
|
||||
int* getAttackColor() {
|
||||
return attack_color;
|
||||
}
|
||||
|
@ -351,7 +371,7 @@ namespace preferences {
|
|||
bool getRunOnIndicator() {
|
||||
return run_on_indicator;
|
||||
}
|
||||
|
||||
|
||||
int getInitialDelay() {
|
||||
return initial_delay;
|
||||
}
|
||||
|
|
|
@ -14,20 +14,24 @@ namespace preferences {
|
|||
bool ledEnabled();
|
||||
bool hidEnabled();
|
||||
|
||||
uint16_t getHid1Vid();
|
||||
uint16_t getHid1Pid();
|
||||
uint16_t getHid2Vid();
|
||||
uint16_t getHid2Pid();
|
||||
uint16_t getHidRev();
|
||||
uint16_t getVID1();
|
||||
uint16_t getPID1();
|
||||
uint16_t getVersion1();
|
||||
std::string getSerial1();
|
||||
std::string getManufacturer1();
|
||||
std::string getProduct1();
|
||||
|
||||
std::string getMscVid();
|
||||
std::string getMscPid();
|
||||
std::string getMscRev();
|
||||
uint16_t getVID2();
|
||||
uint16_t getPID2();
|
||||
uint16_t getVersion2();
|
||||
std::string getSerial2();
|
||||
std::string getManufacturer2();
|
||||
std::string getProduct2();
|
||||
|
||||
std::string getDefaultLayout();
|
||||
int getDefaultDelay();
|
||||
|
||||
std::string getMainScript();
|
||||
// std::string getMainScript();
|
||||
|
||||
int* getAttackColor();
|
||||
int* getSetupColor();
|
||||
|
@ -35,7 +39,7 @@ namespace preferences {
|
|||
|
||||
bool getFormat();
|
||||
std::string getDriveName();
|
||||
|
||||
|
||||
bool getDisableCapslock();
|
||||
bool getRunOnIndicator();
|
||||
|
||||
|
|
Loading…
Reference in New Issue